From 717f95f6bd12f5f0681e3e0d6613c772a28bec05 Mon Sep 17 00:00:00 2001 From: bjorn Date: Fri, 17 Jun 2022 17:43:58 -0700 Subject: [PATCH] Start updating Rasterizer; --- src/api/l_data_rasterizer.c | 220 ++++++++++++++++++++++++------- src/modules/data/rasterizer.c | 240 ++++++++++++---------------------- src/modules/data/rasterizer.h | 38 ++---- 3 files changed, 267 insertions(+), 231 deletions(-) diff --git a/src/api/l_data_rasterizer.c b/src/api/l_data_rasterizer.c index af10c2ea..9cd1d946 100644 --- a/src/api/l_data_rasterizer.c +++ b/src/api/l_data_rasterizer.c @@ -4,78 +4,202 @@ #include #include -static int l_lovrRasterizerGetHeight(lua_State* L) { +static int l_lovrRasterizerGetFontSize(lua_State* L) { Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); - lua_pushinteger(L, lovrRasterizerGetHeight(rasterizer)); - return 1; -} - -static int l_lovrRasterizerGetAdvance(lua_State* L) { - Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); - lua_pushinteger(L, lovrRasterizerGetAdvance(rasterizer)); - return 1; -} - -static int l_lovrRasterizerGetAscent(lua_State* L) { - Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); - lua_pushinteger(L, lovrRasterizerGetAscent(rasterizer)); - return 1; -} - -static int l_lovrRasterizerGetDescent(lua_State* L) { - Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); - lua_pushinteger(L, lovrRasterizerGetDescent(rasterizer)); - return 1; -} - -static int l_lovrRasterizerGetLineHeight(lua_State* L) { - Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); - lua_pushinteger(L, lovrRasterizerGetHeight(rasterizer) * 1.25f); + float size = lovrRasterizerGetFontSize(rasterizer); + lua_pushnumber(L, size); return 1; } static int l_lovrRasterizerGetGlyphCount(lua_State* L) { Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); - lua_pushinteger(L, lovrRasterizerGetGlyphCount(rasterizer)); + 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); - bool hasGlyphs = true; for (int i = 2; i <= lua_gettop(L); i++) { - if (lua_type(L, i) == LUA_TSTRING) { - hasGlyphs &= lovrRasterizerHasGlyphs(rasterizer, lua_tostring(L, i)); - } else { - hasGlyphs &= lovrRasterizerHasGlyph(rasterizer, luax_checku32(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, hasGlyphs); + lua_pushboolean(L, true); return 1; } -static int l_lovrRasterizerGetWidth(lua_State* L) { +static int l_lovrRasterizerGetAscent(lua_State* L) { Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + float ascent = lovrRasterizerGetAscent(rasterizer); + lua_pushnumber(L, ascent); + return 1; +} + +static int l_lovrRasterizerGetDescent(lua_State* L) { + Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + float descent = lovrRasterizerGetDescent(rasterizer); + lua_pushnumber(L, descent); + return 1; +} + +static int l_lovrRasterizerGetLineGap(lua_State* L) { + Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + float lineGap = lovrRasterizerGetLineGap(rasterizer); + lua_pushnumber(L, lineGap); + return 1; +} + +static int l_lovrRasterizerGetLeading(lua_State* L) { + Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + float leading = lovrRasterizerGetLeading(rasterizer); + lua_pushnumber(L, leading); + return 1; +} + +static uint32_t luax_checkcodepoint(lua_State* L, int index) { size_t length; - const char* string = luaL_checklstring(L, 2, &length); - float wrap = luax_optfloat(L, 4, 0.f); - float width, lastLineWidth, height; - uint32_t lineCount, glyphCount; - lovrRasterizerMeasure(rasterizer, string, length, wrap, &width, &lastLineWidth, &height, &lineCount, &glyphCount); - lua_pushnumber(L, width); - lua_pushnumber(L, lineCount + 1); - lua_pushnumber(L, lastLineWidth); + 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; + } +} + +static int l_lovrRasterizerGetKerning(lua_State* L) { + Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + uint32_t prev = luax_checkcodepoint(L, 2); + uint32_t next = luax_checkcodepoint(L, 3); + float kerning = lovrRasterizerGetKerning(rasterizer, prev, next); + lua_pushnumber(L, kerning); + return 1; +} + +static int l_lovrRasterizerGetGlyphAdvance(lua_State* L) { + Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + uint32_t codepoint = luax_checkcodepoint(L, 2); + float advance = lovrRasterizerGetGlyphAdvance(rasterizer, codepoint); + lua_pushnumber(L, advance); + return 1; +} + +static int l_lovrRasterizerGetGlyphBearing(lua_State* L) { + Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + uint32_t codepoint = luax_checkcodepoint(L, 2); + float bearing = lovrRasterizerGetGlyphBearing(rasterizer, codepoint); + lua_pushnumber(L, bearing); + return 1; +} + +static int l_lovrRasterizerGetGlyphWidth(lua_State* L) { + Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + uint32_t codepoint = luax_checkcodepoint(L, 2); + float box[4]; + lovrRasterizerGetGlyphBoundingBox(rasterizer, codepoint, box); + lua_pushnumber(L, box[2] - box[0]); + return 1; +} + +static int l_lovrRasterizerGetGlyphHeight(lua_State* L) { + Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + uint32_t codepoint = luax_checkcodepoint(L, 2); + float box[4]; + lovrRasterizerGetGlyphBoundingBox(rasterizer, codepoint, box); + lua_pushnumber(L, box[3] - box[1]); + return 1; +} + +static int l_lovrRasterizerGetGlyphDimensions(lua_State* L) { + Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + uint32_t codepoint = luax_checkcodepoint(L, 2); + float box[4]; + lovrRasterizerGetGlyphBoundingBox(rasterizer, codepoint, box); + lua_pushnumber(L, box[2] - box[0]); + lua_pushnumber(L, box[3] - box[1]); return 2; } +static int l_lovrRasterizerGetGlyphBoundingBox(lua_State* L) { + Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + uint32_t codepoint = luax_checkcodepoint(L, 2); + float box[4]; + lovrRasterizerGetGlyphBoundingBox(rasterizer, codepoint, box); + 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); +} + +static int l_lovrRasterizerGetGlyphCurves(lua_State* L) { + Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer); + uint32_t codepoint = luax_checkcodepoint(L, 2); + bool three = lua_toboolean(L, 3); + lua_newtable(L); + lovrRasterizerGetGlyphCurves(rasterizer, codepoint, three ? onCurve3D : onCurve2D, L); + return 1; +} + const luaL_Reg lovrRasterizer[] = { - { "getHeight", l_lovrRasterizerGetHeight }, - { "getAdvance", l_lovrRasterizerGetAdvance }, - { "getAscent", l_lovrRasterizerGetAscent }, - { "getDescent", l_lovrRasterizerGetDescent }, - { "getLineHeight", l_lovrRasterizerGetLineHeight }, + { "getFontSize", l_lovrRasterizerGetFontSize }, { "getGlyphCount", l_lovrRasterizerGetGlyphCount }, { "hasGlyphs", l_lovrRasterizerHasGlyphs }, - { "getWidth", l_lovrRasterizerGetWidth }, + { "getAscent", l_lovrRasterizerGetAscent }, + { "getDescent", l_lovrRasterizerGetDescent }, + { "getLineGap", l_lovrRasterizerGetLineGap }, + { "getLeading", l_lovrRasterizerGetLeading }, + { "getKerning", l_lovrRasterizerGetKerning }, + { "getGlyphAdvance", l_lovrRasterizerGetGlyphAdvance }, + { "getGlyphBearing", l_lovrRasterizerGetGlyphBearing }, + { "getGlyphWidth", l_lovrRasterizerGetGlyphWidth }, + { "getGlyphHeight", l_lovrRasterizerGetGlyphHeight }, + { "getGlyphDimensions", l_lovrRasterizerGetGlyphDimensions }, + { "getGlyphBoundingBox", l_lovrRasterizerGetGlyphBoundingBox }, + { "getGlyphCurves", l_lovrRasterizerGetGlyphCurves }, { NULL, NULL } }; diff --git a/src/modules/data/rasterizer.c b/src/modules/data/rasterizer.c index b3e79c9b..264f924b 100644 --- a/src/modules/data/rasterizer.c +++ b/src/modules/data/rasterizer.c @@ -1,25 +1,21 @@ #include "data/rasterizer.h" #include "data/blob.h" -#include "data/image.h" #include "util.h" #include "VarelaRound.ttf.h" #include "lib/stb/stb_truetype.h" #include #include -#include -#include struct Rasterizer { uint32_t ref; - stbtt_fontinfo font; struct Blob* blob; float size; float scale; - int glyphCount; - int height; - int advance; - int ascent; - int descent; + float ascent; + float descent; + float lineGap; + float leading; + stbtt_fontinfo font; }; Rasterizer* lovrRasterizerCreate(Blob* blob, float size) { @@ -37,17 +33,13 @@ Rasterizer* lovrRasterizerCreate(Blob* blob, float size) { rasterizer->blob = blob; rasterizer->size = size; rasterizer->scale = stbtt_ScaleForMappingEmToPixels(font, size); - rasterizer->glyphCount = font->numGlyphs; - int ascent, descent, linegap; - stbtt_GetFontVMetrics(font, &ascent, &descent, &linegap); - rasterizer->ascent = roundf(ascent * rasterizer->scale); - rasterizer->descent = roundf(descent * rasterizer->scale); - rasterizer->height = roundf((ascent - descent + linegap) * rasterizer->scale); - - int x0, y0, x1, y1; - stbtt_GetFontBoundingBox(font, &x0, &y0, &x1, &y1); - rasterizer->advance = roundf(x1 * rasterizer->scale); + int ascent, descent, lineGap; + stbtt_GetFontVMetrics(font, &ascent, &descent, &lineGap); + rasterizer->ascent = ascent * rasterizer->scale; + rasterizer->descent = descent * rasterizer->scale; + rasterizer->lineGap = lineGap * rasterizer->scale; + rasterizer->leading = (ascent - descent + lineGap) * rasterizer->scale; return rasterizer; } @@ -58,96 +50,108 @@ void lovrRasterizerDestroy(void* ref) { free(rasterizer); } -float lovrRasterizerGetSize(Rasterizer* rasterizer) { +float lovrRasterizerGetFontSize(Rasterizer* rasterizer) { return rasterizer->size; } -int lovrRasterizerGetGlyphCount(Rasterizer* rasterizer) { - return rasterizer->glyphCount; +uint32_t lovrRasterizerGetGlyphCount(Rasterizer* rasterizer) { + return rasterizer->font.numGlyphs; } -int lovrRasterizerGetHeight(Rasterizer* rasterizer) { - return rasterizer->height; +bool lovrRasterizerHasGlyph(Rasterizer* rasterizer, uint32_t codepoint) { + return stbtt_FindGlyphIndex(&rasterizer->font, codepoint) != 0; } -int lovrRasterizerGetAdvance(Rasterizer* rasterizer) { - return rasterizer->advance; +bool lovrRasterizerHasGlyphs(Rasterizer* rasterizer, const char* str, size_t length) { + size_t bytes; + uint32_t codepoint; + const char* end = str + length; + while ((bytes = utf8_decode(str, end, &codepoint)) > 0) { + if (!lovrRasterizerHasGlyph(rasterizer, codepoint)) { + return false; + } + str += bytes; + } + return true; } -int lovrRasterizerGetAscent(Rasterizer* rasterizer) { +float lovrRasterizerGetAscent(Rasterizer* rasterizer) { return rasterizer->ascent; } -int lovrRasterizerGetDescent(Rasterizer* rasterizer) { +float lovrRasterizerGetDescent(Rasterizer* rasterizer) { return rasterizer->descent; } -bool lovrRasterizerHasGlyph(Rasterizer* rasterizer, uint32_t character) { - return stbtt_FindGlyphIndex(&rasterizer->font, character) != 0; +float lovrRasterizerGetLineGap(Rasterizer* rasterizer) { + return rasterizer->lineGap; } -bool lovrRasterizerHasGlyphs(Rasterizer* rasterizer, const char* str) { - const char* end = str + strlen(str); - unsigned int codepoint; - size_t bytes; - - bool hasGlyphs = true; - while ((bytes = utf8_decode(str, end, &codepoint)) > 0) { - hasGlyphs &= lovrRasterizerHasGlyph(rasterizer, codepoint); - str += bytes; - } - return hasGlyphs; +float lovrRasterizerGetLeading(Rasterizer* rasterizer) { + return rasterizer->leading; } -void lovrRasterizerLoadGlyph(Rasterizer* rasterizer, uint32_t character, uint32_t padding, double spread, Glyph* glyph) { - int glyphIndex = stbtt_FindGlyphIndex(&rasterizer->font, character); +float lovrRasterizerGetKerning(Rasterizer* rasterizer, uint32_t prev, uint32_t next) { + return stbtt_GetCodepointKernAdvance(&rasterizer->font, prev, next) * rasterizer->scale; +} +float lovrRasterizerGetGlyphAdvance(Rasterizer* rasterizer, uint32_t codepoint) { int advance, bearing; - stbtt_GetGlyphHMetrics(&rasterizer->font, glyphIndex, &advance, &bearing); + stbtt_GetCodepointHMetrics(&rasterizer->font, codepoint, &advance, &bearing); + return advance * rasterizer->scale; +} - if (stbtt_IsGlyphEmpty(&rasterizer->font, glyphIndex)) { - memset(glyph, 0, sizeof(Glyph)); - glyph->advance = roundf(advance * rasterizer->scale); +float lovrRasterizerGetGlyphBearing(Rasterizer* rasterizer, uint32_t codepoint) { + int advance, bearing; + stbtt_GetCodepointHMetrics(&rasterizer->font, codepoint, &advance, &bearing); + return bearing * rasterizer->scale; +} + +void lovrRasterizerGetGlyphBoundingBox(Rasterizer* rasterizer, uint32_t codepoint, float box[4]) { + int x0, y0, x1, y1; + stbtt_GetCodepointBox(&rasterizer->font, codepoint, &x0, &y0, &x1, &y1); + box[0] = x0 * rasterizer->scale; + box[1] = y0 * rasterizer->scale; + box[2] = x1 * rasterizer->scale; + box[3] = y1 * rasterizer->scale; +} + +bool lovrRasterizerIsGlyphEmpty(Rasterizer* rasterizer, uint32_t codepoint) { + return stbtt_IsGlyphEmpty(&rasterizer->font, stbtt_FindGlyphIndex(&rasterizer->font, codepoint)); +} + +void lovrRasterizerGetGlyphCurves(Rasterizer* rasterizer, uint32_t codepoint, void (*fn)(void* context, uint32_t degree, float* points), void* context) { + uint32_t id = stbtt_FindGlyphIndex(&rasterizer->font, codepoint); + + if (stbtt_IsGlyphEmpty(&rasterizer->font, id)) { return; } - // Trace glyph outline stbtt_vertex* vertices; - int vertexCount = stbtt_GetGlyphShape(&rasterizer->font, glyphIndex, &vertices); - msShape* shape = msShapeCreate(); - msContour* contour = NULL; + uint32_t count = stbtt_GetGlyphShape(&rasterizer->font, id, &vertices); + float x = 0.f; float y = 0.f; - - for (int i = 0; i < vertexCount; i++) { + for (uint32_t i = 0; i < count; i++) { stbtt_vertex vertex = vertices[i]; float x2 = vertex.x * rasterizer->scale; float y2 = vertex.y * rasterizer->scale; - switch (vertex.type) { - case STBTT_vmove: - contour = msShapeAddContour(shape); - break; - - case STBTT_vline: - msContourAddLinearEdge(contour, x, y, x2, y2); - break; - - case STBTT_vcurve: { - float cx = vertex.cx * rasterizer->scale; - float cy = vertex.cy * rasterizer->scale; - msContourAddQuadraticEdge(contour, x, y, cx, cy, x2, y2); - break; - } - - case STBTT_vcubic: { - float cx1 = vertex.cx * rasterizer->scale; - float cy1 = vertex.cy * rasterizer->scale; - float cx2 = vertex.cx1 * rasterizer->scale; - float cy2 = vertex.cy1 * rasterizer->scale; - msContourAddCubicEdge(contour, x, y, cx1, cy1, cx2, cy2, x2, y2); - break; - } + if (vertex.type == STBTT_vline) { + float points[4] = { x, y, x2, y2 }; + fn(context, 1, points); + } else if (vertex.type == STBTT_vcurve) { + float cx = vertex.cx * rasterizer->scale; + float cy = vertex.cy * rasterizer->scale; + float points[6] = { x, y, cx, cy, x2, y2 }; + fn(context, 2, points); + } else if (vertex.type == STBTT_vcubic) { + float cx1 = vertex.cx * rasterizer->scale; + float cy1 = vertex.cy * rasterizer->scale; + float cx2 = vertex.cx1 * rasterizer->scale; + float cy2 = vertex.cy1 * rasterizer->scale; + float points[8] = { x, y, cx1, cy1, cx2, cy2, x2, y2 }; + fn(context, 3, points); } x = x2; @@ -155,86 +159,4 @@ void lovrRasterizerLoadGlyph(Rasterizer* rasterizer, uint32_t character, uint32_ } stbtt_FreeShape(&rasterizer->font, vertices); - - int x0, y0, x1, y1; - stbtt_GetGlyphBox(&rasterizer->font, glyphIndex, &x0, &y0, &x1, &y1); - - // Initialize glyph data - glyph->x = 0; - glyph->y = 0; - glyph->w = ceilf((x1 - x0) * rasterizer->scale); - glyph->h = ceilf((y1 - y0) * rasterizer->scale); - glyph->tw = glyph->w + 2 * padding; - glyph->th = glyph->h + 2 * padding; - glyph->dx = roundf(bearing * rasterizer->scale); - glyph->dy = roundf(y1 * rasterizer->scale); - glyph->advance = roundf(advance * rasterizer->scale); - glyph->data = lovrImageCreateRaw(glyph->tw, glyph->th, FORMAT_RGBA32F); - - // Render SDF - float tx = (float) padding + -glyph->dx; - float ty = (float) padding + (float) glyph->h - glyph->dy; - msShapeNormalize(shape); - msEdgeColoringSimple(shape, 3., 0); - msGenerateMTSDF(lovrImageGetBlob(glyph->data)->data, glyph->tw, glyph->th, shape, spread, 1.f, 1.f, tx, ty); - msShapeDestroy(shape); -} - -int32_t lovrRasterizerGetKerning(Rasterizer* rasterizer, uint32_t left, uint32_t right) { - return stbtt_GetCodepointKernAdvance(&rasterizer->font, left, right) * rasterizer->scale; -} - -void lovrRasterizerMeasure(Rasterizer* rasterizer, const char* str, size_t length, float wrap, float* width, float* lastLineWidth, float* height, uint32_t* lineCount, uint32_t* glyphCount) { - float x = 0.f; - const char* end = str + length; - size_t bytes; - unsigned int previous = '\0'; - unsigned int codepoint; - *width = 0.f; - *lastLineWidth = 0.f; - *lineCount = 0; - *glyphCount = 0; - - while ((bytes = utf8_decode(str, end, &codepoint)) > 0) { - if (codepoint == '\n' || (wrap && x > wrap && (codepoint == ' ' || previous == ' '))) { - *width = MAX(*width, x); - (*lineCount)++; - x = 0.f; - previous = '\0'; - if (codepoint == ' ' || codepoint == '\n') { - str += bytes; - continue; - } - } - - // Tabs - if (codepoint == '\t') { - int glyphIndex = stbtt_FindGlyphIndex(&rasterizer->font, ' '); - int advance, bearing; - stbtt_GetGlyphHMetrics(&rasterizer->font, glyphIndex, &advance, &bearing); - x += advance * 4.f; - str += bytes; - continue; - } - - int glyphIndex = stbtt_FindGlyphIndex(&rasterizer->font, codepoint); - int advance, bearing; - stbtt_GetGlyphHMetrics(&rasterizer->font, glyphIndex, &advance, &bearing); - int x0, y0, x1, y1; - if (stbtt_GetGlyphBox(&rasterizer->font, glyphIndex, &x0, &y0, &x1, &y1)) { - float w = ceilf((x1 - x0) * rasterizer->scale); - float h = ceilf((y1 - y0) * rasterizer->scale); - if (w > 0 && h > 0) { - (*glyphCount)++; - } - } - - x += roundf(advance * rasterizer->scale) + lovrRasterizerGetKerning(rasterizer, previous, codepoint); - previous = codepoint; - str += bytes; - } - - *width = MAX(*width, x); - *lastLineWidth = x; - *height = ((*lineCount + 1) * lovrRasterizerGetHeight(rasterizer)); } diff --git a/src/modules/data/rasterizer.h b/src/modules/data/rasterizer.h index 405a1315..cdf7bf88 100644 --- a/src/modules/data/rasterizer.h +++ b/src/modules/data/rasterizer.h @@ -7,30 +7,20 @@ struct Blob; struct Image; -typedef struct { - uint32_t x; - uint32_t y; - uint32_t w; - uint32_t h; - uint32_t tw; - uint32_t th; - int32_t dx; - int32_t dy; - int32_t advance; - struct Image* data; -} Glyph; - typedef struct Rasterizer Rasterizer; Rasterizer* lovrRasterizerCreate(struct Blob* blob, float size); void lovrRasterizerDestroy(void* ref); -float lovrRasterizerGetSize(Rasterizer* rasterizer); -int lovrRasterizerGetGlyphCount(Rasterizer* rasterizer); -int lovrRasterizerGetHeight(Rasterizer* rasterizer); -int lovrRasterizerGetAdvance(Rasterizer* rasterizer); -int lovrRasterizerGetAscent(Rasterizer* rasterizer); -int lovrRasterizerGetDescent(Rasterizer* rasterizer); -bool lovrRasterizerHasGlyph(Rasterizer* fontData, uint32_t character); -bool lovrRasterizerHasGlyphs(Rasterizer* fontData, const char* str); -void lovrRasterizerLoadGlyph(Rasterizer* fontData, uint32_t character, uint32_t padding, double spread, Glyph* glyph); -int32_t lovrRasterizerGetKerning(Rasterizer* fontData, uint32_t left, uint32_t right); -void lovrRasterizerMeasure(Rasterizer* rasterizer, const char* str, size_t length, float wrap, float* width, float* lastLineWidth, float* height, uint32_t* lineCount, uint32_t* glyphCount); +float lovrRasterizerGetFontSize(Rasterizer* rasterizer); +uint32_t lovrRasterizerGetGlyphCount(Rasterizer* rasterizer); +bool lovrRasterizerHasGlyph(Rasterizer* rasterizer, uint32_t codepoint); +bool lovrRasterizerHasGlyphs(Rasterizer* rasterizer, const char* str, size_t length); +float lovrRasterizerGetAscent(Rasterizer* rasterizer); +float lovrRasterizerGetDescent(Rasterizer* rasterizer); +float lovrRasterizerGetLineGap(Rasterizer* rasterizer); +float lovrRasterizerGetLeading(Rasterizer* rasterizer); +float lovrRasterizerGetKerning(Rasterizer* rasterizer, uint32_t prev, uint32_t next); +float lovrRasterizerGetGlyphAdvance(Rasterizer* rasterizer, uint32_t codepoint); +float lovrRasterizerGetGlyphBearing(Rasterizer* rasterizer, uint32_t codepoint); +void lovrRasterizerGetGlyphBoundingBox(Rasterizer* rasterizer, uint32_t codepoint, float box[4]); +bool lovrRasterizerIsGlyphEmpty(Rasterizer* rasterizer, uint32_t codepoint); +void lovrRasterizerGetGlyphCurves(Rasterizer* rasterizer, uint32_t codepoint, void (*fn)(void* context, uint32_t degree, float* points), void* context);