mirror of https://github.com/bjornbytes/lovr.git
Start updating Rasterizer;
This commit is contained in:
parent
cb121d3d36
commit
717f95f6bd
|
@ -4,78 +4,202 @@
|
|||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
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 }
|
||||
};
|
||||
|
|
|
@ -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 <msdfgen-c.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue