mirror of https://github.com/bjornbytes/lovr.git
Compare commits
3 Commits
fa2bd2b05c
...
1f8d37a160
Author | SHA1 | Date |
---|---|---|
bjorn | 1f8d37a160 | |
bjorn | 078b54a7a5 | |
bjorn | 7711fe8b65 |
|
@ -142,6 +142,7 @@ struct Blob;
|
|||
struct Image;
|
||||
struct Blob* luax_readblob(struct lua_State* L, int index, const char* debug);
|
||||
struct Image* luax_checkimage(struct lua_State* L, int index);
|
||||
uint32_t luax_checkcodepoint(struct lua_State* L, int index);
|
||||
#endif
|
||||
|
||||
#ifndef LOVR_DISABLE_EVENT
|
||||
|
@ -156,9 +157,11 @@ void* luax_readfile(const char* filename, size_t* bytesRead);
|
|||
|
||||
#ifndef LOVR_DISABLE_GRAPHICS
|
||||
struct Buffer;
|
||||
struct ColoredString;
|
||||
void luax_readbufferfield(struct lua_State* L, int index, int type, void* data);
|
||||
void luax_readbufferdata(struct lua_State* L, int index, struct Buffer* buffer, char* data);
|
||||
uint32_t luax_checkcomparemode(struct lua_State* L, int index);
|
||||
struct ColoredString* luax_checkcoloredstrings(struct lua_State* L, int index, uint32_t* count, struct ColoredString* stack);
|
||||
#endif
|
||||
|
||||
#ifndef LOVR_DISABLE_MATH
|
||||
|
|
|
@ -6,6 +6,20 @@
|
|||
#include <lauxlib.h>
|
||||
#include <math.h>
|
||||
|
||||
uint32_t luax_checkcodepoint(lua_State* L, int index) {
|
||||
size_t length;
|
||||
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_lovrRasterizerGetFontSize(lua_State* L) {
|
||||
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
||||
float size = lovrRasterizerGetFontSize(rasterizer);
|
||||
|
@ -67,20 +81,6 @@ static int l_lovrRasterizerGetLeading(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t luax_checkcodepoint(lua_State* L, int index) {
|
||||
size_t length;
|
||||
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_lovrRasterizerGetAdvance(lua_State* L) {
|
||||
Rasterizer* rasterizer = luax_checktype(L, 1, Rasterizer);
|
||||
uint32_t codepoint = luax_checkcodepoint(L, 2);
|
||||
|
|
|
@ -4,6 +4,28 @@
|
|||
#include "util.h"
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
ColoredString* luax_checkcoloredstrings(lua_State* L, int index, uint32_t* count, ColoredString* stack) {
|
||||
if (lua_istable(L, index)) {
|
||||
*count = luax_len(L, index) / 2;
|
||||
ColoredString* strings = malloc(*count * sizeof(*strings));
|
||||
lovrAssert(strings, "Out of memory");
|
||||
for (uint32_t i = 0; i < *count; i++) {
|
||||
lua_rawgeti(L, index, i * 2 + 1);
|
||||
lua_rawgeti(L, index, i * 2 + 2);
|
||||
luax_optcolor(L, -2, strings[i].color);
|
||||
lovrCheck(lua_isstring(L, -1), "Expected a string to print");
|
||||
strings[i].string = luaL_checklstring(L, -1, &strings[i].length);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
return strings;
|
||||
} else {
|
||||
stack->string = luaL_checklstring(L, index, &stack->length);
|
||||
stack->color[0] = stack->color[1] = stack->color[2] = stack->color[3] = 1.f;
|
||||
return *count = 1, stack;
|
||||
}
|
||||
}
|
||||
|
||||
static int l_lovrFontGetRasterizer(lua_State* L) {
|
||||
Font* font = luax_checktype(L, 1, Font);
|
||||
|
@ -67,6 +89,35 @@ static int l_lovrFontGetHeight(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrFontGetKerning(lua_State* L) {
|
||||
Font* font = luax_checktype(L, 1, Font);
|
||||
uint32_t left = luax_checkcodepoint(L, 2);
|
||||
uint32_t right = luax_checkcodepoint(L, 3);
|
||||
float kerning = lovrFontGetKerning(font, left, right);
|
||||
float density = lovrFontGetPixelDensity(font);
|
||||
lua_pushnumber(L, kerning / density);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void online(void* context, const char* string, size_t length) {
|
||||
lua_State* L = context;
|
||||
int index = luax_len(L, -1) + 1;
|
||||
lua_pushlstring(L, string, length);
|
||||
lua_rawseti(L, -2, index);
|
||||
}
|
||||
|
||||
static int l_lovrFontGetWrap(lua_State* L) {
|
||||
Font* font = luax_checktype(L, 1, Font);
|
||||
uint32_t count;
|
||||
ColoredString stack;
|
||||
ColoredString* strings = luax_checkcoloredstrings(L, 2, &count, &stack);
|
||||
float wrap = luax_checkfloat(L, 3);
|
||||
lua_newtable(L);
|
||||
lovrFontGetWrap(font, strings, 1, wrap, online, L);
|
||||
if (strings != &stack) free(strings);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrFont[] = {
|
||||
{ "getRasterizer", l_lovrFontGetRasterizer },
|
||||
{ "getPixelDensity", l_lovrFontGetPixelDensity },
|
||||
|
@ -76,5 +127,7 @@ const luaL_Reg lovrFont[] = {
|
|||
{ "getAscent", l_lovrFontGetAscent },
|
||||
{ "getDescent", l_lovrFontGetDescent },
|
||||
{ "getHeight", l_lovrFontGetHeight },
|
||||
{ "getKerning", l_lovrFontGetKerning },
|
||||
{ "getWrap", l_lovrFontGetWrap },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -556,35 +556,16 @@ static int l_lovrPassText(lua_State* L) {
|
|||
Pass* pass = luax_checktype(L, 1, Pass);
|
||||
Font* font = luax_totype(L, 2, Font);
|
||||
int index = font ? 3 : 2;
|
||||
uint32_t count = 0;
|
||||
ColoredString string;
|
||||
ColoredString* strings = &string;
|
||||
if (lua_istable(L, index)) {
|
||||
count = luax_len(L, index) / 2;
|
||||
strings = malloc(count * sizeof(*strings));
|
||||
lovrAssert(strings, "Out of memory");
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
lua_rawgeti(L, index, i * 2 + 1);
|
||||
lua_rawgeti(L, index, i * 2 + 2);
|
||||
luax_optcolor(L, -2, strings[i].color);
|
||||
lovrCheck(lua_isstring(L, -1), "Expected a string to print");
|
||||
strings[i].string = luaL_checklstring(L, -1, &strings[i].length);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
index++;
|
||||
} else {
|
||||
strings[0].string = luaL_checklstring(L, index, &strings[0].length);
|
||||
strings[0].color[0] = strings[0].color[1] = strings[0].color[2] = strings[0].color[3] = 1.f;
|
||||
count = 1;
|
||||
index++;
|
||||
}
|
||||
uint32_t count;
|
||||
ColoredString stack;
|
||||
ColoredString* strings = luax_checkcoloredstrings(L, index++, &count, &stack);
|
||||
float transform[16];
|
||||
index = luax_readmat4(L, index++, transform, 1);
|
||||
float wrap = luax_optfloat(L, index++, 0.);
|
||||
HorizontalAlign halign = luax_checkenum(L, index++, HorizontalAlign, "center");
|
||||
VerticalAlign valign = luax_checkenum(L, index++, VerticalAlign, "middle");
|
||||
lovrPassText(pass, font, strings, count, transform, wrap, halign, valign);
|
||||
if (strings != &string) free(strings);
|
||||
if (strings != &stack) free(strings);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1826,11 +1826,12 @@ void lovrFontSetLineSpacing(Font* font, float spacing) {
|
|||
font->lineSpacing = spacing;
|
||||
}
|
||||
|
||||
static Glyph* lovrFontGetGlyph(Font* font, uint32_t codepoint) {
|
||||
static Glyph* lovrFontGetGlyph(Font* font, uint32_t codepoint, bool* resized) {
|
||||
uint64_t hash = hash64(&codepoint, 4);
|
||||
uint64_t index = map_get(&font->glyphLookup, hash);
|
||||
|
||||
if (index != MAP_NIL) {
|
||||
if (resized) *resized = false;
|
||||
return &font->glyphs.data[index];
|
||||
}
|
||||
|
||||
|
@ -1843,6 +1844,7 @@ static Glyph* lovrFontGetGlyph(Font* font, uint32_t codepoint) {
|
|||
|
||||
if (lovrRasterizerIsGlyphEmpty(font->info.rasterizer, codepoint)) {
|
||||
memset(glyph->box, 0, sizeof(glyph->box));
|
||||
if (resized) *resized = false;
|
||||
return glyph;
|
||||
}
|
||||
|
||||
|
@ -1884,17 +1886,9 @@ static Glyph* lovrFontGetGlyph(Font* font, uint32_t codepoint) {
|
|||
font->atlasX += pixelWidth;
|
||||
font->rowHeight = MAX(font->rowHeight, pixelHeight);
|
||||
|
||||
return glyph;
|
||||
}
|
||||
|
||||
static void lovrFontUploadNewGlyphs(Font* font, uint32_t start, ColoredString* strings, uint32_t count, GlyphVertex* vertices) {
|
||||
if (start >= font->glyphs.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Atlas resize
|
||||
if (!font->atlas || font->atlasWidth > font->atlas->info.width || font->atlasHeight > font->atlas->info.height) {
|
||||
lovrCheck(font->atlasWidth <= 65536, "Font atlas is too big!");
|
||||
lovrCheck(font->atlasWidth <= 65536, "Font atlas is way too big!");
|
||||
|
||||
Texture* atlas = lovrTextureCreate(&(TextureInfo) {
|
||||
.type = TEXTURE_2D,
|
||||
|
@ -1942,96 +1936,138 @@ static void lovrFontUploadNewGlyphs(Font* font, uint32_t start, ColoredString* s
|
|||
|
||||
// Recompute all glyph uvs after atlas resize
|
||||
for (size_t i = 0; i < font->glyphs.length; i++) {
|
||||
Glyph* glyph = &font->glyphs.data[i];
|
||||
glyph->uv[0] = (uint16_t) ((float) glyph->x / font->atlasWidth * 65535.f + .5f);
|
||||
glyph->uv[1] = (uint16_t) ((float) glyph->y / font->atlasHeight * 65535.f + .5f);
|
||||
glyph->uv[2] = (uint16_t) ((float) (glyph->x + glyph->box[2] - glyph->box[0]) / font->atlasWidth * 65535.f + .5f);
|
||||
glyph->uv[3] = (uint16_t) ((float) (glyph->y + glyph->box[3] - glyph->box[1]) / font->atlasHeight * 65535.f + .5f);
|
||||
Glyph* g = &font->glyphs.data[i];
|
||||
g->uv[0] = (uint16_t) ((float) g->x / font->atlasWidth * 65535.f + .5f);
|
||||
g->uv[1] = (uint16_t) ((float) g->y / font->atlasHeight * 65535.f + .5f);
|
||||
g->uv[2] = (uint16_t) ((float) (g->x + g->box[2] - g->box[0]) / font->atlasWidth * 65535.f + .5f);
|
||||
g->uv[3] = (uint16_t) ((float) (g->y + g->box[3] - g->box[1]) / font->atlasHeight * 65535.f + .5f);
|
||||
}
|
||||
|
||||
// Adjust current vertex uvs
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
size_t bytes;
|
||||
uint32_t codepoint;
|
||||
const char* str = strings[i].string;
|
||||
const char* end = strings[i].string + strings[i].length;
|
||||
while ((bytes = utf8_decode(str, end, &codepoint)) > 0) {
|
||||
if (codepoint == ' ' || codepoint == '\n' || codepoint == '\r' || codepoint== '\t') {
|
||||
str += bytes;
|
||||
continue;
|
||||
}
|
||||
|
||||
Glyph* glyph = lovrFontGetGlyph(font, codepoint);
|
||||
if (glyph->box[2] - glyph->box[0] != 0.f) {
|
||||
vertices[0].uv.u = glyph->uv[0];
|
||||
vertices[0].uv.v = glyph->uv[1];
|
||||
vertices[1].uv.u = glyph->uv[2];
|
||||
vertices[1].uv.v = glyph->uv[1];
|
||||
vertices[2].uv.u = glyph->uv[0];
|
||||
vertices[2].uv.v = glyph->uv[3];
|
||||
vertices[3].uv.u = glyph->uv[2];
|
||||
vertices[3].uv.v = glyph->uv[3];
|
||||
vertices += 4;
|
||||
}
|
||||
str += bytes;
|
||||
}
|
||||
}
|
||||
if (resized) *resized = true;
|
||||
}
|
||||
|
||||
gpu_buffer* scratchpad = tempAlloc(gpu_sizeof_buffer());
|
||||
|
||||
for (uint32_t i = start; i < font->glyphs.length; i++) {
|
||||
Glyph* glyph = &font->glyphs.data[i];
|
||||
|
||||
float width = glyph->box[2] - glyph->box[0];
|
||||
float height = glyph->box[3] - glyph->box[1];
|
||||
|
||||
if (width == 0.f || height == 0.f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t w = 2 * font->padding + ceilf(width);
|
||||
uint32_t h = 2 * font->padding + ceilf(height);
|
||||
|
||||
uint32_t stack = tempPush();
|
||||
float* pixels = tempAlloc(w * h * 4 * sizeof(float));
|
||||
|
||||
lovrRasterizerGetPixels(font->info.rasterizer, glyph->codepoint, pixels, w, h, font->info.spread);
|
||||
uint8_t* dst = gpu_map(scratchpad, w * h * 4 * sizeof(uint8_t), 4, GPU_MAP_WRITE);
|
||||
|
||||
float* src = pixels;
|
||||
for (uint32_t y = 0; y < h; y++) {
|
||||
for (uint32_t x = 0; x < w; x++) {
|
||||
for (uint32_t c = 0; c < 4; c++) {
|
||||
float f = *src++; // CLAMP evaluates multiple times
|
||||
*dst++ = (uint8_t) (CLAMP(f, 0.f, 1.f) * 255.f + .5f);
|
||||
}
|
||||
uint32_t stack = tempPush();
|
||||
float* pixels = tempAlloc(pixelWidth * pixelHeight * 4 * sizeof(float));
|
||||
lovrRasterizerGetPixels(font->info.rasterizer, glyph->codepoint, pixels, pixelWidth, pixelHeight, font->info.spread);
|
||||
uint8_t* dst = gpu_map(scratchpad, pixelWidth * pixelHeight * 4 * sizeof(uint8_t), 4, GPU_MAP_WRITE);
|
||||
float* src = pixels;
|
||||
for (uint32_t y = 0; y < pixelHeight; y++) {
|
||||
for (uint32_t x = 0; x < pixelWidth; x++) {
|
||||
for (uint32_t c = 0; c < 4; c++) {
|
||||
float f = *src++; // CLAMP would evaluate this multiple times
|
||||
*dst++ = (uint8_t) (CLAMP(f, 0.f, 1.f) * 255.f + .5f);
|
||||
}
|
||||
}
|
||||
|
||||
tempPop(stack);
|
||||
|
||||
uint32_t dstOffset[4] = { glyph->x - font->padding, glyph->y - font->padding, 0, 0 };
|
||||
uint32_t extent[3] = { w, h, 1 };
|
||||
gpu_copy_buffer_texture(state.stream, scratchpad, font->atlas->gpu, 0, dstOffset, extent);
|
||||
}
|
||||
uint32_t dstOffset[4] = { glyph->x - font->padding, glyph->y - font->padding, 0, 0 };
|
||||
uint32_t extent[3] = { pixelWidth, pixelHeight, 1 };
|
||||
gpu_copy_buffer_texture(state.stream, scratchpad, font->atlas->gpu, 0, dstOffset, extent);
|
||||
tempPop(stack);
|
||||
|
||||
state.hasGlyphUpload = true;
|
||||
return glyph;
|
||||
}
|
||||
|
||||
static float lovrFontGetKerning(Font* font, uint32_t previous, uint32_t codepoint) {
|
||||
uint32_t codepoints[] = { previous, codepoint };
|
||||
float lovrFontGetKerning(Font* font, uint32_t left, uint32_t right) {
|
||||
uint32_t codepoints[] = { left, right };
|
||||
uint64_t hash = hash64(codepoints, sizeof(codepoints));
|
||||
union { float f32; uint64_t u64; } kerning = { .u64 = map_get(&font->kerning, hash) };
|
||||
|
||||
if (kerning.u64 == MAP_NIL) {
|
||||
kerning.f32 = lovrRasterizerGetKerning(font->info.rasterizer, previous, codepoint);
|
||||
kerning.f32 = lovrRasterizerGetKerning(font->info.rasterizer, left, right);
|
||||
map_set(&font->kerning, hash, kerning.u64);
|
||||
}
|
||||
|
||||
return kerning.f32;
|
||||
}
|
||||
|
||||
void lovrFontGetWrap(Font* font, ColoredString* strings, uint32_t count, float wrap, void (*callback)(void* context, const char* string, size_t length), void* context) {
|
||||
size_t totalLength = 0;
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
totalLength += strings[i].length;
|
||||
}
|
||||
|
||||
uint32_t stack = tempPush();
|
||||
char* string = tempAlloc(totalLength + 1);
|
||||
string[totalLength] = '\0';
|
||||
|
||||
for (uint32_t i = 0, cursor = 0; i < count; i++, cursor += strings[i].length) {
|
||||
memcpy(string + cursor, strings[i].string, strings[i].length);
|
||||
}
|
||||
|
||||
float x = 0.f;
|
||||
float nextWordStartX = 0.f;
|
||||
wrap *= font->pixelDensity;
|
||||
|
||||
size_t bytes;
|
||||
uint32_t codepoint;
|
||||
uint32_t previous = '\0';
|
||||
const char* lineStart = string;
|
||||
const char* wordStart = string;
|
||||
const char* end = string + totalLength;
|
||||
Glyph* space = lovrFontGetGlyph(font, ' ', NULL);
|
||||
while ((bytes = utf8_decode(string, end, &codepoint)) > 0) {
|
||||
if (codepoint == ' ' || codepoint == '\t') {
|
||||
x += codepoint == '\t' ? space->advance * 4.f : space->advance;
|
||||
nextWordStartX = x;
|
||||
previous = '\0';
|
||||
string += bytes;
|
||||
wordStart = string;
|
||||
continue;
|
||||
} else if (codepoint == '\n') {
|
||||
size_t length = string - lineStart;
|
||||
while (string[length] == ' ' || string[length] == '\t') length--;
|
||||
callback(context, lineStart, length);
|
||||
nextWordStartX = 0.f;
|
||||
x = 0.f;
|
||||
previous = '\0';
|
||||
string += bytes;
|
||||
lineStart = string;
|
||||
wordStart = string;
|
||||
continue;
|
||||
} else if (codepoint == '\r') {
|
||||
string += bytes;
|
||||
continue;
|
||||
}
|
||||
|
||||
Glyph* glyph = lovrFontGetGlyph(font, codepoint, NULL);
|
||||
|
||||
// Keming
|
||||
if (previous) x += lovrFontGetKerning(font, previous, codepoint);
|
||||
previous = codepoint;
|
||||
|
||||
// Ignore bearing for the first character on a line (questionable)
|
||||
if (string == lineStart) {
|
||||
x -= glyph->box[0];
|
||||
} else if (string == wordStart) {
|
||||
nextWordStartX += glyph->box[0]; // So wrapping accounts for bearing of first glyph
|
||||
}
|
||||
|
||||
// Wrap
|
||||
if (wordStart != lineStart && x + glyph->box[2] > wrap) {
|
||||
size_t length = wordStart - lineStart;
|
||||
while (string[length] == ' ' || string[length] == '\t') length--;
|
||||
callback(context, lineStart, length);
|
||||
lineStart = wordStart;
|
||||
x -= nextWordStartX;
|
||||
nextWordStartX = 0.f;
|
||||
previous = '\0';
|
||||
}
|
||||
|
||||
// Advance
|
||||
x += glyph->advance;
|
||||
string += bytes;
|
||||
}
|
||||
|
||||
if (end - lineStart > 0) {
|
||||
callback(context, lineStart, end - lineStart);
|
||||
}
|
||||
|
||||
tempPop(stack);
|
||||
}
|
||||
|
||||
// Pass
|
||||
|
||||
Pass* lovrGraphicsGetPass(PassInfo* info) {
|
||||
|
@ -3412,14 +3448,15 @@ static void aline(GlyphVertex* vertices, uint32_t head, uint32_t tail, Horizonta
|
|||
|
||||
void lovrPassText(Pass* pass, Font* font, ColoredString* strings, uint32_t count, float* transform, float wrap, HorizontalAlign halign, VerticalAlign valign) {
|
||||
font = font ? font : lovrGraphicsGetDefaultFont();
|
||||
uint32_t originalGlyphCount = font->glyphs.length;
|
||||
Glyph* space = lovrFontGetGlyph(font, ' ', NULL);
|
||||
|
||||
uint32_t maxGlyphCount = 0;
|
||||
size_t totalLength = 0;
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
maxGlyphCount += strings[i].length;
|
||||
totalLength += strings[i].length;
|
||||
}
|
||||
|
||||
GlyphVertex* vertices = tempAlloc(maxGlyphCount * 4 * sizeof(GlyphVertex));
|
||||
uint32_t stack = tempPush();
|
||||
GlyphVertex* vertices = tempAlloc(totalLength * 4 * sizeof(GlyphVertex));
|
||||
uint32_t vertexCount = 0;
|
||||
uint32_t glyphCount = 0;
|
||||
uint32_t lineCount = 1;
|
||||
|
@ -3446,9 +3483,8 @@ void lovrPassText(Pass* pass, Font* font, ColoredString* strings, uint32_t count
|
|||
|
||||
while ((bytes = utf8_decode(str, end, &codepoint)) > 0) {
|
||||
if (codepoint == ' ' || codepoint == '\t') {
|
||||
Glyph* glyph = lovrFontGetGlyph(font, ' ');
|
||||
wordStart = vertexCount;
|
||||
x += codepoint == '\t' ? glyph->advance * 4.f : glyph->advance;
|
||||
x += codepoint == '\t' ? space->advance * 4.f : space->advance;
|
||||
previous = '\0';
|
||||
str += bytes;
|
||||
continue;
|
||||
|
@ -3467,7 +3503,14 @@ void lovrPassText(Pass* pass, Font* font, ColoredString* strings, uint32_t count
|
|||
continue;
|
||||
}
|
||||
|
||||
Glyph* glyph = lovrFontGetGlyph(font, codepoint);
|
||||
bool resized;
|
||||
Glyph* glyph = lovrFontGetGlyph(font, codepoint, &resized);
|
||||
|
||||
if (resized) {
|
||||
tempPop(stack);
|
||||
lovrPassText(pass, font, strings, count, transform, wrap, halign, valign);
|
||||
return;
|
||||
}
|
||||
|
||||
// Keming
|
||||
if (previous) x += lovrFontGetKerning(font, previous, codepoint);
|
||||
|
@ -3491,7 +3534,7 @@ void lovrPassText(Pass* pass, Font* font, ColoredString* strings, uint32_t count
|
|||
y -= dy;
|
||||
}
|
||||
|
||||
// Ignore bearing for the first character on a line so it lines up perfectly (questionable)
|
||||
// Ignore bearing for the first character on a line (questionable)
|
||||
if (vertexCount == lineStart) {
|
||||
x -= glyph->box[0];
|
||||
}
|
||||
|
@ -3514,9 +3557,6 @@ void lovrPassText(Pass* pass, Font* font, ColoredString* strings, uint32_t count
|
|||
// Align last line
|
||||
aline(vertices, lineStart, vertexCount, halign);
|
||||
|
||||
// Resize atlas, rasterize new glyphs, upload them into atlas, recreate material
|
||||
lovrFontUploadNewGlyphs(font, originalGlyphCount, strings, count, vertices);
|
||||
|
||||
mat4_scale(transform, scale, scale, scale);
|
||||
mat4_translate(transform, 0.f, -ascent + valign / 2.f * (leading * lineCount), 0.f);
|
||||
|
||||
|
@ -3538,6 +3578,8 @@ void lovrPassText(Pass* pass, Font* font, ColoredString* strings, uint32_t count
|
|||
memcpy(indices, quad, sizeof(quad));
|
||||
indices += COUNTOF(quad);
|
||||
}
|
||||
|
||||
tempPop(stack);
|
||||
}
|
||||
|
||||
void lovrPassFill(Pass* pass, Texture* texture) {
|
||||
|
|
|
@ -328,7 +328,7 @@ typedef struct {
|
|||
double spread;
|
||||
} FontInfo;
|
||||
|
||||
typedef struct {
|
||||
typedef struct ColoredString {
|
||||
float color[4];
|
||||
const char* string;
|
||||
size_t length;
|
||||
|
@ -353,6 +353,8 @@ float lovrFontGetPixelDensity(Font* font);
|
|||
void lovrFontSetPixelDensity(Font* font, float pixelDensity);
|
||||
float lovrFontGetLineSpacing(Font* font);
|
||||
void lovrFontSetLineSpacing(Font* font, float spacing);
|
||||
float lovrFontGetKerning(Font* font, uint32_t left, uint32_t right);
|
||||
void lovrFontGetWrap(Font* font, ColoredString* strings, uint32_t count, float wrap, void (*callback)(void* context, const char* string, size_t length), void* context);
|
||||
|
||||
// Pass
|
||||
|
||||
|
|
Loading…
Reference in New Issue