mirror of https://github.com/bjornbytes/lovr.git
Rasterizer:getGlyphImage;
This commit is contained in:
parent
fe31431016
commit
7625ef9bd8
|
@ -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 }
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue