mirror of https://github.com/bjornbytes/lovr.git
Move text measuring to Rasterizer
This commit is contained in:
parent
0a2f968850
commit
09cc73a988
|
@ -54,6 +54,19 @@ static int l_lovrRasterizerHasGlyphs(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrRasterizerGetWidth(lua_State* L) {
|
||||
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
||||
size_t length;
|
||||
const char* string = luaL_checklstring(L, 2, &length);
|
||||
float wrap = luax_optfloat(L, 4, 0.f);
|
||||
float width, height;
|
||||
uint32_t lineCount, glyphCount;
|
||||
lovrRasterizerMeasure(rasterizer, string, length, wrap, &width, &height, &lineCount, &glyphCount);
|
||||
lua_pushnumber(L, width);
|
||||
lua_pushnumber(L, lineCount + 1);
|
||||
return 2;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrRasterizer[] = {
|
||||
{ "getHeight", l_lovrRasterizerGetHeight },
|
||||
{ "getAdvance", l_lovrRasterizerGetAdvance },
|
||||
|
@ -62,5 +75,6 @@ const luaL_Reg lovrRasterizer[] = {
|
|||
{ "getLineHeight", l_lovrRasterizerGetLineHeight },
|
||||
{ "getGlyphCount", l_lovrRasterizerGetGlyphCount },
|
||||
{ "hasGlyphs", l_lovrRasterizerHasGlyphs },
|
||||
{ "getWidth", l_lovrRasterizerGetWidth },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -184,3 +184,54 @@ void lovrRasterizerLoadGlyph(Rasterizer* rasterizer, uint32_t character, uint32_
|
|||
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* 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;
|
||||
*lineCount = 0;
|
||||
*glyphCount = 0;
|
||||
|
||||
while ((bytes = utf8_decode(str, end, &codepoint)) > 0) {
|
||||
if (codepoint == '\n' || (wrap && x > wrap && codepoint == ' ')) {
|
||||
*width = MAX(*width, x);
|
||||
(*lineCount)++;
|
||||
x = 0.f;
|
||||
previous = '\0';
|
||||
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;
|
||||
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);
|
||||
*height = ((*lineCount + 1) * lovrRasterizerGetHeight(rasterizer));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
|
@ -32,3 +33,4 @@ 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* height, uint32_t* lineCount, uint32_t* glyphCount);
|
||||
|
|
|
@ -200,47 +200,10 @@ void lovrFontRender(Font* font, const char* str, size_t length, float wrap, Hori
|
|||
}
|
||||
|
||||
void lovrFontMeasure(Font* font, const char* str, size_t length, float wrap, float* width, 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;
|
||||
float scale = 1.f / font->pixelDensity;
|
||||
*width = 0.f;
|
||||
*lineCount = 0;
|
||||
*glyphCount = 0;
|
||||
|
||||
while ((bytes = utf8_decode(str, end, &codepoint)) > 0) {
|
||||
if (codepoint == '\n' || (wrap && x * scale > wrap && codepoint == ' ')) {
|
||||
*width = MAX(*width, x * scale);
|
||||
(*lineCount)++;
|
||||
x = 0.f;
|
||||
previous = '\0';
|
||||
str += bytes;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Tabs
|
||||
if (codepoint == '\t') {
|
||||
Glyph* space = lovrFontGetGlyph(font, ' ');
|
||||
x += space->advance * 4.f;
|
||||
str += bytes;
|
||||
continue;
|
||||
}
|
||||
|
||||
Glyph* glyph = lovrFontGetGlyph(font, codepoint);
|
||||
|
||||
if (glyph->w > 0 && glyph->h > 0) {
|
||||
(*glyphCount)++;
|
||||
}
|
||||
|
||||
x += glyph->advance + lovrFontGetKerning(font, previous, codepoint);
|
||||
previous = codepoint;
|
||||
str += bytes;
|
||||
}
|
||||
|
||||
*width = MAX(*width, x * scale);
|
||||
*height = ((*lineCount + 1) * lovrRasterizerGetHeight(font->rasterizer) * font->lineHeight) * (font->flip ? -1 : 1);
|
||||
wrap *= font->pixelDensity;
|
||||
lovrRasterizerMeasure(font->rasterizer, str, length, wrap, width, height, lineCount, glyphCount);
|
||||
*width /= font->pixelDensity;
|
||||
*height *= font->lineHeight * (font->flip ? -1 : 1);
|
||||
}
|
||||
|
||||
uint32_t lovrFontGetPadding(Font* font) {
|
||||
|
|
Loading…
Reference in New Issue