From 7077d89a22ef51e75e74611eb984acaa195d551f Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 16 Mar 2017 01:12:32 -0700 Subject: [PATCH] Font metrics; --- src/api/types/font.c | 37 +++++++++++++++++++++++++++++++++++++ src/graphics/font.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/graphics/font.h | 5 +++++ src/loaders/font.c | 2 ++ src/loaders/font.h | 2 ++ src/math/math.h | 4 ++-- 6 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/api/types/font.c b/src/api/types/font.c index faa0f99c..6ad42fdc 100644 --- a/src/api/types/font.c +++ b/src/api/types/font.c @@ -1,6 +1,38 @@ #include "api/lovr.h" #include "graphics/font.h" +int l_lovrFontGetWidth(lua_State* L) { + Font* font = luax_checktype(L, 1, Font); + const char* string = luaL_checkstring(L, 2); + float wrap = luaL_optnumber(L, 3, 0); + lua_pushnumber(L, lovrFontGetWidth(font, string, wrap)); + return 1; +} + +int l_lovrFontGetHeight(lua_State* L) { + Font* font = luax_checktype(L, 1, Font); + lua_pushnumber(L, lovrFontGetHeight(font)); + return 1; +} + +int l_lovrFontGetAscent(lua_State* L) { + Font* font = luax_checktype(L, 1, Font); + lua_pushnumber(L, lovrFontGetAscent(font)); + return 1; +} + +int l_lovrFontGetDescent(lua_State* L) { + Font* font = luax_checktype(L, 1, Font); + lua_pushnumber(L, lovrFontGetDescent(font)); + return 1; +} + +int l_lovrFontGetBaseline(lua_State* L) { + Font* font = luax_checktype(L, 1, Font); + lua_pushnumber(L, lovrFontGetBaseline(font)); + return 1; +} + int l_lovrFontGetLineHeight(lua_State* L) { Font* font = luax_checktype(L, 1, Font); lua_pushinteger(L, lovrFontGetLineHeight(font)); @@ -28,6 +60,11 @@ int l_lovrFontSetPixelDensity(lua_State* L) { } const luaL_Reg lovrFont[] = { + { "getWidth", l_lovrFontGetWidth }, + { "getHeight", l_lovrFontGetHeight }, + { "getAscent", l_lovrFontGetAscent }, + { "getDescent", l_lovrFontGetDescent }, + { "getBaseline", l_lovrFontGetBaseline }, { "getLineHeight", l_lovrFontGetLineHeight }, { "setLineHeight", l_lovrFontSetLineHeight }, { "getPixelDensity", l_lovrFontGetPixelDensity }, diff --git a/src/graphics/font.c b/src/graphics/font.c index 4392de44..b89a5256 100644 --- a/src/graphics/font.c +++ b/src/graphics/font.c @@ -170,6 +170,49 @@ void lovrFontPrint(Font* font, const char* str, mat4 transform, float wrap, Hori lovrGraphicsPop(); } +float lovrFontGetWidth(Font* font, const char* str, float wrap) { + float width = 0; + float x = 0; + const char* end = str + strlen(str); + size_t bytes; + unsigned int previous = '\0'; + unsigned int codepoint; + float scale = 1 / font->pixelDensity; + + while ((bytes = utf8_decode(str, end, &codepoint)) > 0) { + if (codepoint == '\n' || (wrap && x * scale > wrap && codepoint == ' ')) { + width = MAX(width, x) / font->pixelDensity; + x = 0; + previous = '\0'; + str += bytes; + continue; + } + + Glyph* glyph = lovrFontGetGlyph(font, codepoint); + x += glyph->advance + lovrFontGetKerning(font, previous, codepoint); + previous = codepoint; + str += bytes; + } + + return MAX(x, width) * scale; +} + +float lovrFontGetHeight(Font* font) { + return font->fontData->height / font->pixelDensity; +} + +float lovrFontGetAscent(Font* font) { + return font->fontData->ascent / font->pixelDensity; +} + +float lovrFontGetDescent(Font* font) { + return font->fontData->descent / font->pixelDensity; +} + +float lovrFontGetBaseline(Font* font) { + return font->fontData->height * .8 / font->pixelDensity; +} + float lovrFontGetLineHeight(Font* font) { return font->lineHeight; } diff --git a/src/graphics/font.h b/src/graphics/font.h index 66c30d20..eb653555 100644 --- a/src/graphics/font.h +++ b/src/graphics/font.h @@ -44,6 +44,11 @@ typedef struct { Font* lovrFontCreate(FontData* fontData); void lovrFontDestroy(const Ref* ref); void lovrFontPrint(Font* font, const char* str, mat4 transform, float wrap, HorizontalAlign halign, VerticalAlign valign); +float lovrFontGetWidth(Font* font, const char* string, float wrap); +float lovrFontGetHeight(Font* font); +float lovrFontGetAscent(Font* font); +float lovrFontGetDescent(Font* font); +float lovrFontGetBaseline(Font* font); float lovrFontGetLineHeight(Font* font); void lovrFontSetLineHeight(Font* font, float lineHeight); int lovrFontGetKerning(Font* font, unsigned int a, unsigned int b); diff --git a/src/loaders/font.c b/src/loaders/font.c index 23f3a705..32e91316 100644 --- a/src/loaders/font.c +++ b/src/loaders/font.c @@ -32,6 +32,8 @@ FontData* lovrFontDataCreate(void* data, int size, int height) { FT_Size_Metrics metrics = face->size->metrics; fontData->height = metrics.height >> 6; + fontData->ascent = metrics.ascender >> 6; + fontData->descent = metrics.descender >> 6; return fontData; } diff --git a/src/loaders/font.h b/src/loaders/font.h index 47438f2f..38a1f7cb 100644 --- a/src/loaders/font.h +++ b/src/loaders/font.h @@ -7,6 +7,8 @@ typedef struct { void* rasterizer; int size; int height; + int ascent; + int descent; } FontData; typedef struct { diff --git a/src/math/math.h b/src/math/math.h index efba86fb..5857cb50 100644 --- a/src/math/math.h +++ b/src/math/math.h @@ -2,8 +2,8 @@ #pragma once -#define MAX(a, b) a > b ? a : b -#define MIN(a, b) a < b ? a : b +#define MAX(a, b) (a > b ? a : b) +#define MIN(a, b) (a < b ? a : b) typedef float* vec3; typedef float* quat;