Rasterizer:getGlyphImage;

This commit is contained in:
bjorn 2022-06-20 18:24:12 -07:00
parent fe31431016
commit 7625ef9bd8
3 changed files with 111 additions and 23 deletions

View File

@ -1,8 +1,10 @@
#include "api.h"
#include "data/rasterizer.h"
#include "data/image.h"
#include "util.h"
#include <lua.h>
#include <lauxlib.h>
#include <math.h>
static int l_lovrRasterizerGetFontSize(lua_State* L) {
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
@ -11,17 +13,6 @@ static int l_lovrRasterizerGetFontSize(lua_State* L) {
return 1;
}
static int l_lovrRasterizerGetBoundingBox(lua_State* L) {
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
float box[4];
lovrRasterizerGetBoundingBox(rasterizer, box);
lua_pushnumber(L, box[0]);
lua_pushnumber(L, box[1]);
lua_pushnumber(L, box[2]);
lua_pushnumber(L, box[3]);
return 4;
}
static int l_lovrRasterizerGetGlyphCount(lua_State* L) {
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
uint32_t count = lovrRasterizerGetGlyphCount(rasterizer);
@ -124,27 +115,39 @@ static int l_lovrRasterizerGetGlyphBearing(lua_State* L) {
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);
if (lua_isnoneornil(L, 2)) {
lovrRasterizerGetBoundingBox(rasterizer, box);
} else {
uint32_t codepoint = luax_checkcodepoint(L, 2);
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);
if (lua_isnoneornil(L, 2)) {
lovrRasterizerGetBoundingBox(rasterizer, box);
} else {
uint32_t codepoint = luax_checkcodepoint(L, 2);
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);
if (lua_isnoneornil(L, 2)) {
lovrRasterizerGetBoundingBox(rasterizer, box);
} else {
uint32_t codepoint = luax_checkcodepoint(L, 2);
lovrRasterizerGetGlyphBoundingBox(rasterizer, codepoint, box);
}
lua_pushnumber(L, box[2] - box[0]);
lua_pushnumber(L, box[3] - box[1]);
return 2;
@ -152,9 +155,13 @@ static int l_lovrRasterizerGetGlyphDimensions(lua_State* L) {
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);
if (lua_isnoneornil(L, 2)) {
lovrRasterizerGetBoundingBox(rasterizer, box);
} else {
uint32_t codepoint = luax_checkcodepoint(L, 2);
lovrRasterizerGetGlyphBoundingBox(rasterizer, codepoint, box);
}
lua_pushnumber(L, box[0]);
lua_pushnumber(L, box[1]);
lua_pushnumber(L, box[2]);
@ -196,9 +203,23 @@ static int l_lovrRasterizerGetGlyphCurves(lua_State* L) {
return 1;
}
static int l_lovrRasterizerGetGlyphImage(lua_State* L) {
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
uint32_t codepoint = luax_checkcodepoint(L, 2);
float box[4];
lovrRasterizerGetGlyphBoundingBox(rasterizer, codepoint, box);
uint32_t width = 2 + (uint32_t) ceilf(box[2] - box[0]);
uint32_t height = 2 + (uint32_t) ceilf(box[3] - box[1]);
Image* image = lovrImageCreateRaw(width, height, FORMAT_RGBA32F);
void* pixels = lovrImageGetLayerData(image, 0, 0);
lovrRasterizerGetGlyphPixels(rasterizer, codepoint, pixels, width, height, 4.);
luax_pushtype(L, Image, image);
lovrRelease(image, lovrImageDestroy);
return 1;
}
const luaL_Reg lovrRasterizer[] = {
{ "getFontSize", l_lovrRasterizerGetFontSize },
{ "getBoundingBox", l_lovrRasterizerGetBoundingBox },
{ "getGlyphCount", l_lovrRasterizerGetGlyphCount },
{ "hasGlyphs", l_lovrRasterizerHasGlyphs },
{ "getAscent", l_lovrRasterizerGetAscent },
@ -213,5 +234,6 @@ const luaL_Reg lovrRasterizer[] = {
{ "getGlyphDimensions", l_lovrRasterizerGetGlyphDimensions },
{ "getGlyphBoundingBox", l_lovrRasterizerGetGlyphBoundingBox },
{ "getGlyphCurves", l_lovrRasterizerGetGlyphCurves },
{ "getGlyphImage", l_lovrRasterizerGetGlyphImage },
{ NULL, NULL }
};

View File

@ -5,6 +5,7 @@
#include "lib/stb/stb_truetype.h"
#include <msdfgen-c.h>
#include <stdlib.h>
#include <math.h>
struct Rasterizer {
uint32_t ref;
@ -129,11 +130,11 @@ 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) {
bool 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;
return false;
}
stbtt_vertex* vertices;
@ -168,4 +169,68 @@ void lovrRasterizerGetGlyphCurves(Rasterizer* rasterizer, uint32_t codepoint, vo
}
stbtt_FreeShape(&rasterizer->font, vertices);
return true;
}
#include <stdio.h>
bool lovrRasterizerGetGlyphPixels(Rasterizer* rasterizer, uint32_t codepoint, float* pixels, uint32_t width, uint32_t height, double spread) {
int id = stbtt_FindGlyphIndex(&rasterizer->font, codepoint);
if (stbtt_IsGlyphEmpty(&rasterizer->font, id)) {
return false;
}
stbtt_vertex* vertices;
int count = stbtt_GetGlyphShape(&rasterizer->font, id, &vertices);
msShape* shape = msShapeCreate();
msContour* contour = NULL;
float x = 0.f;
float y = 0.f;
for (int i = 0; i < count; i++) {
stbtt_vertex vertex = vertices[i];
float x2 = vertex.x;
float y2 = vertex.y;
if (vertex.type == STBTT_vmove) {
contour = msShapeAddContour(shape);
} else if (vertex.type == STBTT_vline) {
msContourAddLinearEdge(contour, x, y, x2, y2);
} else if (vertex.type == STBTT_vcurve) {
float cx = vertex.cx;
float cy = vertex.cy;
msContourAddQuadraticEdge(contour, x, y, cx, cy, x2, y2);
} else if (vertex.type == STBTT_vcubic) {
float cx1 = vertex.cx;
float cy1 = vertex.cy;
float cx2 = vertex.cx1;
float cy2 = vertex.cy1;
msContourAddCubicEdge(contour, x, y, cx1, cy1, cx2, cy2, x2, y2);
}
x = x2;
y = y2;
}
stbtt_FreeShape(&rasterizer->font, vertices);
int x0, y0, x1, y1;
stbtt_GetGlyphBox(&rasterizer->font, id, &x0, &y0, &x1, &y1);
double unused;
float scale = rasterizer->scale;
float centerOffsetX = (1.f - modf((x1 - x0) * scale, &unused)) / 2.f;
float centerOffsetY = (1.f - modf((y1 - y0) * scale, &unused)) / 2.f;
uint32_t padding = 1;
float offsetX = -x0 + ((padding + centerOffsetX) / rasterizer->scale);
float offsetY = -y1 - ((padding + centerOffsetY) / rasterizer->scale);
msShapeNormalize(shape);
msEdgeColoringSimple(shape, 3., 0);
msGenerateMTSDF(pixels, width, height, shape, spread / rasterizer->scale, scale, -scale, offsetX, offsetY);
msShapeDestroy(shape);
return true;
}

View File

@ -24,4 +24,5 @@ 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);
bool lovrRasterizerGetGlyphCurves(Rasterizer* rasterizer, uint32_t codepoint, void (*fn)(void* context, uint32_t degree, float* points), void* context);
bool lovrRasterizerGetGlyphPixels(Rasterizer* rasterizer, uint32_t codepoint, float* pixels, uint32_t width, uint32_t height, double spread);