From 530c80c63c1559c1d9bc754fbb188e45cc3f5d0c Mon Sep 17 00:00:00 2001 From: bjorn Date: Tue, 7 Feb 2017 22:11:20 -0800 Subject: [PATCH] Kerning; --- src/graphics/font.c | 34 +++++++++++++++++++++++++++++++--- src/graphics/font.h | 2 ++ src/loaders/font.c | 9 +++++++++ src/loaders/font.h | 3 ++- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/graphics/font.c b/src/graphics/font.c index 27f7fb17..5386d8bf 100644 --- a/src/graphics/font.c +++ b/src/graphics/font.c @@ -15,6 +15,7 @@ Font* lovrFontCreate(FontData* fontData) { font->fontData = fontData; vec_init(&font->vertices); + map_init(&font->kerning); // Atlas int padding = 1; @@ -40,6 +41,7 @@ void lovrFontDestroy(const Ref* ref) { lovrFontDataDestroy(font->fontData); lovrRelease(&font->texture->ref); map_deinit(&font->atlas.glyphs); + map_deinit(&font->kerning); vec_deinit(&font->vertices); free(font); } @@ -55,29 +57,40 @@ void lovrFontPrint(Font* font, const char* str) { int length = strlen(str); const char* end = str + length; size_t bytes; + unsigned int previous = '\0'; unsigned int codepoint; vec_reserve(&font->vertices, length * 30); vec_clear(&font->vertices); while ((bytes = utf8_decode(str, end, &codepoint)) > 0) { + + // Newlines if (codepoint == '\n') { x = 0; y -= font->fontData->size; + previous = '\0'; str += bytes; continue; } - Glyph* glyph = lovrFontGetGlyph(font, codepoint); + // Kerning + x += lovrFontGetKerning(font, previous, codepoint); + previous = codepoint; + // Glyph geometry + Glyph* glyph = lovrFontGetGlyph(font, codepoint); int gx = glyph->x; int gy = glyph->y; int gw = glyph->w; int gh = glyph->h; + int dx = glyph->dx; + int dy = glyph->dy; + // Triangles if (gw > 0 && gh > 0) { - float x1 = x + glyph->dx; - float y1 = y + glyph->dy; + float x1 = x + dx; + float y1 = y + dy; float x2 = x1 + gw; float y2 = y1 - gh; float s1 = gx / u; @@ -97,6 +110,7 @@ void lovrFontPrint(Font* font, const char* str) { vec_pusharr(&font->vertices, v, 30); } + // Advance cursor x += glyph->advance; str += bytes; } @@ -117,6 +131,20 @@ int lovrFontGetDescent(Font* font) { return font->fontData->descent; } +int lovrFontGetKerning(Font* font, unsigned int left, unsigned int right) { + char key[12]; + snprintf(key, 12, "%d,%d", left, right); + + int* entry = map_get(&font->kerning, key); + if (entry) { + return *entry; + } + + int kerning = lovrFontDataGetKerning(font->fontData, left, right); + map_set(&font->kerning, key, kerning); + return kerning; +} + Glyph* lovrFontGetGlyph(Font* font, uint32_t codepoint) { char key[6]; snprintf(key, 6, "%d", codepoint); diff --git a/src/graphics/font.h b/src/graphics/font.h index e535e881..af7fce8c 100644 --- a/src/graphics/font.h +++ b/src/graphics/font.h @@ -42,6 +42,7 @@ typedef struct { FontData* fontData; Texture* texture; FontAtlas atlas; + map_int_t kerning; vec_float_t vertices; } Font; @@ -51,6 +52,7 @@ void lovrFontPrint(Font* font, const char* str); int lovrFontGetHeight(Font* font); int lovrFontGetAscent(Font* font); int lovrFontGetDescent(Font* font); +int lovrFontGetKerning(Font* font, unsigned int a, unsigned int b); Glyph* lovrFontGetGlyph(Font* font, uint32_t codepoint); void lovrFontAddGlyph(Font* font, Glyph* glyph); void lovrFontExpandTexture(Font* font); diff --git a/src/loaders/font.c b/src/loaders/font.c index 0a526821..f3a2512c 100644 --- a/src/loaders/font.c +++ b/src/loaders/font.c @@ -81,3 +81,12 @@ void lovrFontDataLoadGlyph(FontData* fontData, uint32_t character, Glyph* glyph) FT_Done_Glyph(slot); } + +int lovrFontDataGetKerning(FontData* fontData, uint32_t left, uint32_t right) { + FT_Face face = fontData->rasterizer; + FT_Vector kerning; + left = FT_Get_Char_Index(face, left); + right = FT_Get_Char_Index(face, right); + FT_Get_Kerning(face, left, right, FT_KERNING_DEFAULT, &kerning); + return kerning.x >> 6; +} diff --git a/src/loaders/font.h b/src/loaders/font.h index 820fb45e..1398a69f 100644 --- a/src/loaders/font.h +++ b/src/loaders/font.h @@ -3,4 +3,5 @@ FontData* lovrFontDataCreate(void* data, int size, int height); void lovrFontDataDestroy(FontData* fontData); -void lovrFontDataLoadGlyph(FontData* fontData, uint32_t characer, Glyph* glyph); +void lovrFontDataLoadGlyph(FontData* fontData, uint32_t character, Glyph* glyph); +int lovrFontDataGetKerning(FontData* fontData, uint32_t left, uint32_t right);