2018-01-22 16:40:47 +00:00
|
|
|
#include "api.h"
|
2018-01-23 02:49:45 +00:00
|
|
|
#include "data/rasterizer.h"
|
2022-06-21 01:24:12 +00:00
|
|
|
#include "data/image.h"
|
2022-03-22 07:13:21 +00:00
|
|
|
#include "util.h"
|
2022-06-21 01:24:12 +00:00
|
|
|
#include <math.h>
|
2018-01-23 02:49:45 +00:00
|
|
|
|
2022-06-30 04:49:55 +00:00
|
|
|
uint32_t luax_checkcodepoint(lua_State* L, int index) {
|
|
|
|
size_t length;
|
|
|
|
const char* str;
|
|
|
|
uint32_t codepoint;
|
|
|
|
switch (lua_type(L, index)) {
|
|
|
|
case LUA_TSTRING:
|
|
|
|
str = lua_tolstring(L, index, &length);
|
|
|
|
return utf8_decode(str, str + length, &codepoint) ? codepoint : 0;
|
|
|
|
case LUA_TNUMBER:
|
|
|
|
return luax_checku32(L, index);
|
|
|
|
default: return luax_typeerror(L, index, "string or number"), 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-18 00:43:58 +00:00
|
|
|
static int l_lovrRasterizerGetFontSize(lua_State* L) {
|
2018-01-23 02:49:45 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
2022-06-18 00:43:58 +00:00
|
|
|
float size = lovrRasterizerGetFontSize(rasterizer);
|
|
|
|
lua_pushnumber(L, size);
|
2018-01-23 02:49:45 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-06-18 00:43:58 +00:00
|
|
|
static int l_lovrRasterizerGetGlyphCount(lua_State* L) {
|
2018-01-23 02:49:45 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
2022-06-18 00:43:58 +00:00
|
|
|
uint32_t count = lovrRasterizerGetGlyphCount(rasterizer);
|
|
|
|
lua_pushinteger(L, count);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int l_lovrRasterizerHasGlyphs(lua_State* L) {
|
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
|
|
|
for (int i = 2; i <= lua_gettop(L); i++) {
|
|
|
|
size_t length;
|
|
|
|
const char* str;
|
|
|
|
switch (lua_type(L, i)) {
|
|
|
|
case LUA_TSTRING:
|
|
|
|
str = lua_tolstring(L, i, &length);
|
|
|
|
if (!lovrRasterizerHasGlyphs(rasterizer, str, length)) {
|
|
|
|
lua_pushboolean(L, false);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LUA_TNUMBER:
|
|
|
|
if (!lovrRasterizerHasGlyph(rasterizer, luax_checku32(L, i))) {
|
|
|
|
lua_pushboolean(L, false);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default: return luax_typeerror(L, i, "string or number");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lua_pushboolean(L, true);
|
2018-01-23 02:49:45 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-02-17 22:52:22 +00:00
|
|
|
static int l_lovrRasterizerGetAscent(lua_State* L) {
|
2018-01-23 02:49:45 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
2022-06-18 00:43:58 +00:00
|
|
|
float ascent = lovrRasterizerGetAscent(rasterizer);
|
|
|
|
lua_pushnumber(L, ascent);
|
2018-01-23 02:49:45 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-02-17 22:52:22 +00:00
|
|
|
static int l_lovrRasterizerGetDescent(lua_State* L) {
|
2018-01-23 02:49:45 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
2022-06-18 00:43:58 +00:00
|
|
|
float descent = lovrRasterizerGetDescent(rasterizer);
|
|
|
|
lua_pushnumber(L, descent);
|
2018-01-23 02:49:45 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-06-18 00:43:58 +00:00
|
|
|
static int l_lovrRasterizerGetLeading(lua_State* L) {
|
2018-01-23 02:49:45 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
2022-06-18 00:43:58 +00:00
|
|
|
float leading = lovrRasterizerGetLeading(rasterizer);
|
|
|
|
lua_pushnumber(L, leading);
|
2018-01-23 02:49:45 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-06-29 03:18:45 +00:00
|
|
|
static int l_lovrRasterizerGetAdvance(lua_State* L) {
|
2021-10-11 22:31:43 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
2022-06-18 00:43:58 +00:00
|
|
|
uint32_t codepoint = luax_checkcodepoint(L, 2);
|
2022-06-29 03:18:45 +00:00
|
|
|
float advance = lovrRasterizerGetAdvance(rasterizer, codepoint);
|
2022-06-18 00:43:58 +00:00
|
|
|
lua_pushnumber(L, advance);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-06-29 03:18:45 +00:00
|
|
|
static int l_lovrRasterizerGetBearing(lua_State* L) {
|
2022-06-18 00:43:58 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
|
|
|
uint32_t codepoint = luax_checkcodepoint(L, 2);
|
2022-06-29 03:18:45 +00:00
|
|
|
float bearing = lovrRasterizerGetBearing(rasterizer, codepoint);
|
2022-06-18 00:43:58 +00:00
|
|
|
lua_pushnumber(L, bearing);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-06-29 03:18:45 +00:00
|
|
|
static int l_lovrRasterizerGetKerning(lua_State* L) {
|
2022-06-18 00:43:58 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
2022-07-04 22:22:54 +00:00
|
|
|
uint32_t first = luax_checkcodepoint(L, 2);
|
|
|
|
uint32_t second = luax_checkcodepoint(L, 3);
|
|
|
|
float kerning = lovrRasterizerGetKerning(rasterizer, first, second);
|
2022-06-29 03:18:45 +00:00
|
|
|
lua_pushnumber(L, kerning);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void luax_getboundingbox(lua_State* L, int index, Rasterizer* rasterizer, float box[4]) {
|
|
|
|
if (lua_isnoneornil(L, index)) {
|
2022-06-21 01:24:12 +00:00
|
|
|
lovrRasterizerGetBoundingBox(rasterizer, box);
|
|
|
|
} else {
|
2022-06-29 03:18:45 +00:00
|
|
|
uint32_t codepoint = luax_checkcodepoint(L, index);
|
2022-06-21 01:24:12 +00:00
|
|
|
lovrRasterizerGetGlyphBoundingBox(rasterizer, codepoint, box);
|
|
|
|
}
|
2022-06-29 03:18:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int l_lovrRasterizerGetWidth(lua_State* L) {
|
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
|
|
|
float box[4];
|
|
|
|
luax_getboundingbox(L, 2, rasterizer, box);
|
2022-06-18 00:43:58 +00:00
|
|
|
lua_pushnumber(L, box[2] - box[0]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-06-29 03:18:45 +00:00
|
|
|
static int l_lovrRasterizerGetHeight(lua_State* L) {
|
2022-06-18 00:43:58 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
|
|
|
float box[4];
|
2022-06-29 03:18:45 +00:00
|
|
|
luax_getboundingbox(L, 2, rasterizer, box);
|
2022-06-18 00:43:58 +00:00
|
|
|
lua_pushnumber(L, box[3] - box[1]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-06-29 03:18:45 +00:00
|
|
|
static int l_lovrRasterizerGetDimensions(lua_State* L) {
|
2022-06-18 00:43:58 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
|
|
|
float box[4];
|
2022-06-29 03:18:45 +00:00
|
|
|
luax_getboundingbox(L, 2, rasterizer, box);
|
2022-06-18 00:43:58 +00:00
|
|
|
lua_pushnumber(L, box[2] - box[0]);
|
|
|
|
lua_pushnumber(L, box[3] - box[1]);
|
2021-10-11 22:31:43 +00:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2022-06-29 03:18:45 +00:00
|
|
|
static int l_lovrRasterizerGetBoundingBox(lua_State* L) {
|
2022-06-18 00:43:58 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
|
|
|
float box[4];
|
2022-06-29 03:18:45 +00:00
|
|
|
luax_getboundingbox(L, 2, rasterizer, box);
|
2022-06-18 00:43:58 +00:00
|
|
|
lua_pushnumber(L, box[0]);
|
|
|
|
lua_pushnumber(L, box[1]);
|
|
|
|
lua_pushnumber(L, box[2]);
|
|
|
|
lua_pushnumber(L, box[3]);
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void onCurve2D(void* context, uint32_t degree, float* points) {
|
|
|
|
lua_State* L = context;
|
|
|
|
uint32_t count = (degree + 1) * 2;
|
|
|
|
lua_createtable(L, count, 0);
|
|
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
|
|
lua_pushnumber(L, points[i]);
|
|
|
|
lua_rawseti(L, -2, i + 1);
|
|
|
|
}
|
|
|
|
lua_rawseti(L, -2, luax_len(L, -2) + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void onCurve3D(void* context, uint32_t degree, float* points) {
|
|
|
|
lua_State* L = context;
|
|
|
|
lua_createtable(L, (degree + 1) * 3, 0);
|
|
|
|
for (uint32_t i = 0; i < degree + 1; i++) {
|
|
|
|
lua_pushnumber(L, points[2 * i + 0]);
|
|
|
|
lua_rawseti(L, -2, 3 * i + 1);
|
|
|
|
lua_pushnumber(L, points[2 * i + 1]);
|
|
|
|
lua_rawseti(L, -2, 3 * i + 2);
|
|
|
|
lua_pushnumber(L, 0.);
|
|
|
|
lua_rawseti(L, -2, 3 * i + 3);
|
|
|
|
}
|
|
|
|
lua_rawseti(L, -2, luax_len(L, -2) + 1);
|
|
|
|
}
|
|
|
|
|
2022-06-29 03:18:45 +00:00
|
|
|
static int l_lovrRasterizerGetCurves(lua_State* L) {
|
2022-06-18 00:43:58 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
|
|
|
uint32_t codepoint = luax_checkcodepoint(L, 2);
|
|
|
|
bool three = lua_toboolean(L, 3);
|
|
|
|
lua_newtable(L);
|
2022-06-29 03:18:45 +00:00
|
|
|
lovrRasterizerGetCurves(rasterizer, codepoint, three ? onCurve3D : onCurve2D, L);
|
2022-06-18 00:43:58 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-06-29 03:18:45 +00:00
|
|
|
static int l_lovrRasterizerNewImage(lua_State* L) {
|
2022-06-21 01:24:12 +00:00
|
|
|
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
|
|
|
uint32_t codepoint = luax_checkcodepoint(L, 2);
|
2022-06-29 03:18:45 +00:00
|
|
|
double spread = luaL_optnumber(L, 3, 4.);
|
|
|
|
uint32_t padding = (uint32_t) ceil(spread / 2.);
|
2022-06-21 01:24:12 +00:00
|
|
|
float box[4];
|
|
|
|
lovrRasterizerGetGlyphBoundingBox(rasterizer, codepoint, box);
|
2022-06-29 03:18:45 +00:00
|
|
|
uint32_t width = 2 * padding + (uint32_t) ceilf(box[2] - box[0]);
|
|
|
|
uint32_t height = 2 * padding + (uint32_t) ceilf(box[3] - box[1]);
|
2023-11-02 20:38:21 +00:00
|
|
|
Image* image = lovrImageCreateRaw(width, height, FORMAT_RGBA32F, false);
|
2022-06-21 01:24:12 +00:00
|
|
|
void* pixels = lovrImageGetLayerData(image, 0, 0);
|
2022-06-29 03:18:45 +00:00
|
|
|
lovrRasterizerGetPixels(rasterizer, codepoint, pixels, width, height, spread);
|
2022-06-21 01:24:12 +00:00
|
|
|
luax_pushtype(L, Image, image);
|
|
|
|
lovrRelease(image, lovrImageDestroy);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-01-22 16:40:47 +00:00
|
|
|
const luaL_Reg lovrRasterizer[] = {
|
2022-06-18 00:43:58 +00:00
|
|
|
{ "getFontSize", l_lovrRasterizerGetFontSize },
|
2018-01-23 02:49:45 +00:00
|
|
|
{ "getGlyphCount", l_lovrRasterizerGetGlyphCount },
|
|
|
|
{ "hasGlyphs", l_lovrRasterizerHasGlyphs },
|
2022-06-18 00:43:58 +00:00
|
|
|
{ "getAscent", l_lovrRasterizerGetAscent },
|
|
|
|
{ "getDescent", l_lovrRasterizerGetDescent },
|
|
|
|
{ "getLeading", l_lovrRasterizerGetLeading },
|
2022-06-29 03:18:45 +00:00
|
|
|
{ "getAdvance", l_lovrRasterizerGetAdvance },
|
|
|
|
{ "getBearing", l_lovrRasterizerGetBearing },
|
2022-06-18 00:43:58 +00:00
|
|
|
{ "getKerning", l_lovrRasterizerGetKerning },
|
2022-06-29 03:18:45 +00:00
|
|
|
{ "getWidth", l_lovrRasterizerGetWidth },
|
|
|
|
{ "getHeight", l_lovrRasterizerGetHeight },
|
|
|
|
{ "getDimensions", l_lovrRasterizerGetDimensions },
|
|
|
|
{ "getBoundingBox", l_lovrRasterizerGetBoundingBox },
|
|
|
|
{ "getCurves", l_lovrRasterizerGetCurves },
|
|
|
|
{ "newImage", l_lovrRasterizerNewImage },
|
2018-01-22 16:40:47 +00:00
|
|
|
{ NULL, NULL }
|
|
|
|
};
|