summaryrefslogtreecommitdiffstatsci
path: root/src/vkvg_fonts.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vkvg_fonts.c')
-rw-r--r--src/vkvg_fonts.c306
1 files changed, 177 insertions, 129 deletions
diff --git a/src/vkvg_fonts.c b/src/vkvg_fonts.c
index 2e3dfa3..e8eb465 100644
--- a/src/vkvg_fonts.c
+++ b/src/vkvg_fonts.c
@@ -51,15 +51,26 @@ do { \
}
#define FT_CHECK_RES(f) \
{ \
- FT_Error res = (f); \
- if (res) { \
- char tmp[1024]; \
- ft_face_flags_to_string (face->face->face_flags, tmp, 1024); \
- LOGE("FreeType error is 0x%x in %s at line %d, flags: %s\n", res, __FILE__, __LINE__, tmp);\
- free(font); \
- return (VkvgFont)&_vkvg_status_null_pointer; \
+ FT_Error res = (f); \
+ if (res) { \
+ char tmp[1024]; \
+ ft_face_flags_to_string (face->face->face_flags, tmp, 1024); \
+ LOGE("FreeType error is 0x%x in %s at line %d, flags: %s\n", res, __FILE__, __LINE__, tmp);\
+ free(font); \
+ return (VkvgFont)&_vkvg_status_null_pointer; \
} \
}
+#define FT_CHECK_SIZE(f) \
+{ \
+ FT_Error res = (f); \
+ if (res) { \
+ char tmp[1024]; \
+ ft_face_flags_to_string (face->face->face_flags, tmp, 1024); \
+ LOGE("FreeType error is 0x%x in %s at line %d, flags: %s\n", res, __FILE__, __LINE__, tmp);\
+ free(fntsize); \
+ return false; \
+ } \
+}
#else
#define STBTT_assert(x) ((void)0)
#define STB_TRUETYPE_IMPLEMENTATION
@@ -95,6 +106,7 @@ void _fonts_cache_update_font_descriptor_set (VkvgDevice dev) {
vkUpdateDescriptorSets(dev->vkDev, 1, &writeDescriptorSet, 0, NULL);
}
void _fonts_cache_create(VkvgDevice dev, const char* fontDirs) {
+ LOG(VKVG_LOG_FONT, "Font cache create\n");
font_cache_t* cache = (font_cache_t*)calloc(1, sizeof(font_cache_t));
dev->fontCache = cache;
@@ -233,7 +245,8 @@ void _fonts_cache_create(VkvgDevice dev, const char* fontDirs) {
#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
vkh_device_set_object_name(dev->vkhDev, VK_OBJECT_TYPE_DESCRIPTOR_POOL, (uint64_t)cache->descriptorPool,
"Font cache Descriptor Pool");
- vkh_device_set_object_name(dev->vkhDev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)cache->dsFont, "Cache DescSet FONT");
+ vkh_device_set_object_name(dev->vkhDev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)cache->dsFont, "Font Cache DescSet");
+ vkh_device_set_object_name(dev->vkhDev, VK_OBJECT_TYPE_BUFFER, (uint64_t)cache->buff.buffer, "Font Cache Staging buff");
#endif
}
void _font_buffer_destroy (font_cache_t* cache, FontBuffer fontBuffer) {
@@ -243,10 +256,10 @@ void _font_buffer_destroy (font_cache_t* cache, FontBuffer fontBuffer) {
array_del_FontBuffer(&cache->fontBuffers, fontBuffer);
free(fontBuffer);
}
-void _font_face_destroy (VkvgFont font) {
+void _font_face_destroy (FontSize font) {
FontFace face = font->face;
LOG(VKVG_LOG_FONT, "FontFace destroy: %s\n", get_face_family_name(face));
- array_destroy_VkvgFont(&face->sizes);
+ array_destroy_FontSize(&face->sizes);
array_destroy_uint64_t(&face->queryHashes);
array_del_FontFace(&face->fontBuffer->faces, face);
@@ -264,7 +277,31 @@ void _font_face_destroy (VkvgFont font) {
}
free(face);
}
+void _font_size_destroy (FontSize font) {
+#ifdef VKVG_USE_FREETYPE
+ FT_Done_Size(font->ftSize);
+ if (font->coords)
+ free(font->coords);
+#endif
+
+ for (int i = 0; i < font->texLines.count; ++i) {
+ LOG(VKVG_LOG_FONT, "\treleased line %d of page %d\n", i, font->texLines.elements[i]->pageIdx);
+ font->texLines.elements[i]->released = true;
+ }
+ array_destroy_TexRef(&font->texLines);
+
+ array_del_FontSize(&font->face->sizes , font);
+
+ if (font->face->sizes.count == 0)
+ _font_face_destroy(font);
+ free(font->charLookup);
+
+ vkvg_device_destroy(font->dev);
+ free(font);
+ font = NULL;
+}
void _font_cache_destroy(VkvgDevice dev) {
+ LOG(VKVG_LOG_FONT, "Font cache destroy\n");
font_cache_t* cache = (font_cache_t*)dev->fontCache;
free(cache->hostBuff);
@@ -273,10 +310,10 @@ void _font_cache_destroy(VkvgDevice dev) {
for (int i = 0; i < cache->fontBuffers.count; ++i) {
FontFace* faces = buffs[i]->faces.elements;
for (int j = 0; j < buffs[i]->faces.count; ++j) {
- VkvgFont *fonts = faces[j]->sizes.elements;
+ FontSize *fonts = faces[j]->sizes.elements;
for (int k = 0; k < faces[j]->sizes.count; ++k) {
//while (vkvg_font_get_reference_count(fonts[k]) > 0)
- vkvg_font_destroy(fonts[k]);
+ _font_size_destroy (fonts[k]);
}
}
}
@@ -383,7 +420,7 @@ void _increase_font_tex_array(VkvgDevice dev) {
}
// flush font stagging buffer to cache texture array
// Trigger stagging buffer to be uploaded in font cache. Groupping upload improve performances.
-void _flush_chars_to_tex(VkvgFont f) {
+void _flush_chars_to_tex(FontSize f) {
font_cache_t* cache = f->dev->fontCache;
if (cache->stagingX == 0) // no char in stagging buff to flush
return;
@@ -428,7 +465,7 @@ void _flush_chars_to_tex(VkvgFont f) {
}
/// Start a new line in font cache, increase texture layer count if needed.
-void _init_next_line_in_tex_cache(VkvgFont f) {
+void _init_next_line_in_tex_cache(FontSize f) {
font_cache_t* cache = f->dev->fontCache;
for (int i = 0; i < cache->texPages.count; ++i) {
@@ -478,7 +515,7 @@ void _init_next_line_in_tex_cache(VkvgFont f) {
UNLOCK_FONTCACHE(ctx->dev)
}*/
// create a new char entry and put glyph in stagging buffer, ready for upload.
-glyph_ref _put_glyph_in_cache(VkvgDevice dev, VkvgFont font, uint32_t gindex) {
+glyph_ref _put_glyph_in_cache(VkvgDevice dev, FontSize font, uint32_t gindex) {
#ifdef VKVG_USE_FREETYPE
#if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
FT_CHECK_RESULT(FT_Load_Glyph(f->face, gindex, FT_LOAD_TARGET_NORMAL));
@@ -493,7 +530,7 @@ glyph_ref _put_glyph_in_cache(VkvgDevice dev, VkvgFont font, uint32_t gindex) {
res = FT_Load_Glyph(font->face->face, 0, FT_LOAD_RENDER);
if (res) {
LOGE("Fatal: FT_Load_Glyph error 0x%x for default glyph 0\n", res);
- font->status = VKVG_STATUS_INVALID_FONT;
+ //font->status = VKVG_STATUS_INVALID_FONT;
return (glyph_ref) {0};
}
}
@@ -563,7 +600,7 @@ glyph_ref _put_glyph_in_cache(VkvgDevice dev, VkvgFont font, uint32_t gindex) {
dev->fontCache->stagingX += bmpPixelWidth;
return cr;
}
-vkvg_inline glyph_ref get_cached_glyph (VkvgDevice dev, VkvgFont font, uint32_t gIndex) {
+vkvg_inline glyph_ref get_cached_glyph (VkvgDevice dev, FontSize font, uint32_t gIndex) {
glyph_ref gr;
if (vkvg_unlikely (gIndex > get_face_glyph_count(font->face))) {
LOGW("glyph index out of bounds: idx:%d glyphsCount: %d\n", gIndex, get_face_glyph_count(font->face));
@@ -768,31 +805,112 @@ exit_failed:
#endif
return false;
}
-bool try_get_font_size (FontFace face, uint32_t pt26_6, signed long* coords, VkvgFont *font) {
- *font = NULL;
+
+bool try_get_or_create_font_size (VkvgSurface surf, VkvgFont font) {
+ if (font->curSize != NULL)
+ return true;
+ FontFace face = font->face;
+ uint32_t pxSize = (font->ptSize * surf->vdpi + 2304) / 4608;
+
for (int i = 0; i < face->sizes.count; ++i) {
- VkvgFont f = face->sizes.elements[i];
- if (f->charSize == pt26_6) {
+ FontSize f = face->sizes.elements[i];
+ if (f->pxSize == pxSize) {
#ifdef VKVG_USE_FREETYPE
- if (coords) {
+ /*if (coords) {
for (int axe = 0; axe < face->numAxis; ++axe) {
if (f->coords[axe] != coords[axe])
return false;
}
free(coords);//coords matche, free new coords
- }
+ }*/
#endif
- *font = f;
+ font->curSize = f;
return true;
}
}
- return false;
+
+ FontSize fntsize = (FontSize)calloc(1, sizeof(vkvg_font_size_t));
+ if (!fntsize) {
+ LOGE("Create font size failed, no memory\n");
+ return false;
+ }
+ fntsize->face = face;
+ VkvgDevice dev = surf->dev;
+
+#ifdef VKVG_USE_FREETYPE
+ if (dev->threadAware)
+ mtx_lock(&face->mutex);
+ /* if (face->numAxis && coords)
+ font->coords = coords;*/
+
+ if (!(face->face->face_flags & FT_FACE_FLAG_SCALABLE) || !(face->face->face_flags & FT_FACE_FLAG_SFNT)) {
+ char tmp[1024];
+ ft_face_flags_to_string (face->face->face_flags, tmp, 1024);
+ LOGW("Unsuported font flags: %s\n", tmp);
+ if (dev->threadAware)
+ mtx_lock(&face->mutex);
+ free(fntsize);
+ return false;
+ } else {
+ char tmp[1024];
+ ft_face_flags_to_string (face->face->face_flags, tmp, 1024);
+ LOG(VKVG_LOG_FONT, "loading %s\n\tflags: %s\n", face->face->family_name, tmp);
+ }
+ if (!face->sizes.size)
+ face->sizes = array_create_FontSize(5);//new face,
+
+ FT_CHECK_SIZE(FT_New_Size (face->face, &fntsize->ftSize));
+ FT_CHECK_SIZE(FT_Activate_Size(fntsize->ftSize));
+ //TODO:handle fixed sizes
+ FT_CHECK_SIZE(FT_Set_Pixel_Sizes(face->face, 0, pxSize));
+
+ /*if (font->coords) {
+ FT_Set_Var_Design_Coordinates(face->face, font->face->numAxis, font->coords);
+ font->face->coords = font->coords;
+ }*/
+#ifdef VKVG_USE_HARFBUZZ
+ hb_font_t* hbf = face->hb_font;
+ hb_ft_font_changed(hbf);
+ hb_font_set_ppem(hbf, fntsize->ftSize->metrics.x_ppem, fntsize->ftSize->metrics.y_ppem);
+#endif
+
+ fntsize->charLookup = (glyph_ref*)calloc(face->face->num_glyphs, sizeof(glyph_ref));
+
+ if (FT_IS_SCALABLE(face->face))
+ fntsize->height = face->face->size->metrics.height >> 6;
+ else
+ fntsize->height = face->face->height >> 6;
+
+ fntsize->texLines = array_create_TexRef(2);
+
+ if (dev->threadAware)
+ mtx_lock(&face->mutex);
+#else
+ font->charSize = pointSize;
+ stbtt_GetFontVMetrics(&face->stbInfo, &font->ascent, &font->descent, &font->lineGap);
+ font->charLookup = (glyph_ref*)calloc(face->stbInfo.numGlyphs, sizeof(glyph_ref));
+ font->scale = stbtt_ScaleForMappingEmToPixels(&face->stbInfo, font->charSize * surf->vdpi / 72.f);
+ font->height = roundf(font->scale * (font->ascent - font->descent + font->lineGap));
+ font->ascent = roundf(font->scale * font->ascent);
+ font->descent = roundf(font->scale * font->descent);
+ font->lineGap = roundf(font->scale * font->lineGap);
+#endif
+ array_add_FontSize(&face->sizes, fntsize);
+
+ fntsize->dev = dev;
+ vkvg_device_reference(fntsize->dev);
+
+ _init_next_line_in_tex_cache(fntsize);
+
+ font->curSize = fntsize;
+ return true;
}
+
#ifdef VKVG_USE_HARFBUZZ
// Get harfBuzz buffer for provided text.
hb_buffer_t* _get_hb_buffer(VkvgText textRun, const char* text, int length) {
- VkvgFont font = textRun->font;
+ FontSize font = textRun->font;
hb_buffer_t* buf = hb_buffer_create();
hb_buffer_add_utf8 (buf, text, length, 0, length);
hb_buffer_guess_segment_properties (buf);
@@ -808,7 +926,7 @@ hb_buffer_t* _get_hb_buffer(VkvgText textRun, const char* text, int length) {
return buf;
}
#endif
-void _font_lock_size (VkvgFont font) {
+void _font_lock_size (FontSize font) {
#ifdef VKVG_USE_FREETYPE
FT_Face face = font->face->face;
if (face->size != font->ftSize || font->face->coords != font->coords) {
@@ -829,7 +947,10 @@ void _font_lock_size (VkvgFont font) {
}
// retrieve global font extends of context's current font as defined by FreeType
-void _font_cache_font_extents(VkvgFont font, vkvg_font_extents_t* extents) {
+void _font_cache_font_extents(VkvgContext ctx, vkvg_font_extents_t* extents) {
+ VkvgFont font = ctx->currentFont;
+ if (!try_get_or_create_font_size(ctx->pSurf, font))
+ return;
#ifdef VKVG_USE_FREETYPE
FT_Face face = font->face->face;
/*_font_lock_size(ctx, font);
@@ -839,7 +960,7 @@ void _font_cache_font_extents(VkvgFont font, vkvg_font_extents_t* extents) {
}*/
//FT_BBox* bbox = &face->bbox;
//FT_Size_Metrics* metrics = &face->size->metrics;
- FT_Size_Metrics* metrics = &font->ftSize->metrics;
+ FT_Size_Metrics* metrics = &font->curSize->ftSize->metrics;
extents->ascent = (float)(FT_MulFix(face->ascender, metrics->y_scale) >> 6); // metrics->ascender >> 6;
extents->descent = -(float)(FT_MulFix(face->descender, metrics->y_scale) >> 6); // metrics->descender >> 6;
@@ -867,7 +988,7 @@ void _font_cache_text_extents(VkvgContext ctx, const char* text, int length, vkv
}
vkvg_text_run_t tr = {0};
- text_run_init(&tr, ctx->currentFont, ctx->textDirection, text, length);
+ text_run_init(&tr, ctx, text, length);
if (ctx->status)
return;
@@ -879,7 +1000,7 @@ void _font_cache_text_extents(VkvgContext ctx, const char* text, int length, vkv
// text is expected as utf8 encoded
void _font_cache_show_text(VkvgContext ctx, const char* text) {
vkvg_text_run_t tr = {0};
- text_run_init(&tr, ctx->currentFont, ctx->textDirection, text, -1);
+ text_run_init(&tr, ctx, text, -1);
if (ctx->status)
return;
@@ -890,10 +1011,13 @@ void _font_cache_show_text(VkvgContext ctx, const char* text) {
}
// if length is < 0, text must be null terminated, else it contains glyph count
-void text_run_init(VkvgText textRun, VkvgFont font, vkvg_direction_t textDirection, const char* text, int length) {
- textRun->font = font;
- textRun->textDirection = textDirection;
- vkvg_font_reference (textRun->font);
+void text_run_init(VkvgText textRun, VkvgContext ctx, const char* text, int length) {
+ VkvgFont font = ctx->currentFont;
+
+ try_get_or_create_font_size(ctx->pSurf, font);
+
+ textRun->font = font->curSize;
+ textRun->textDirection = ctx->textDirection;
_font_lock_size(textRun->font);
@@ -959,7 +1083,7 @@ void text_run_term(VkvgText textRun) {
if (textRun->glyph_count > 0)
free(textRun->glyphs);
#endif
- vkvg_font_destroy(textRun->font);
+ //vkvg_font_destroy(textRun->font);
}
void text_run_render(VkvgText tr, VkvgContext ctx) {
@@ -970,7 +1094,7 @@ void text_run_render(VkvgText tr, VkvgContext ctx) {
vkvg_glyph_info_t* glyph_info = tr->glyphs;
glyph_count = tr->glyph_count;
#endif
- VkvgFont f = tr->font;
+ FontSize f = tr->font;
Vertex v = {{0}, ctx->curColor, {0, 0, -1}};
vec2 pen = {0, 0};
@@ -983,8 +1107,8 @@ void text_run_render(VkvgText tr, VkvgContext ctx) {
for (uint32_t i = 0; i < glyph_count; ++i) {
glyph_ref cr = get_cached_glyph(dev, f, glyph_info[i].codepoint);
- if (vkvg_unlikely (f->status))
- break;
+ /*if (vkvg_unlikely (f->status))
+ break;*/
vec2 p0 = {pen.x + cr.bmpDiff.x + (tr->glyphs[i].x_offset >> 6),
pen.y - cr.bmpDiff.y + (tr->glyphs[i].y_offset >> 6)};
@@ -1056,7 +1180,9 @@ void* vkvg_font_get_face(VkvgFont font) {
#endif
}
-VkvgFont _create_font_from_face (VkvgSurface surf, FontFace face, float pointSize, signed long* coords) {
+
+
+VkvgFont _create_font_from_face (VkvgDevice dev, FontFace face, float pointSize, signed long* coords) {
VkvgFont font = (VkvgFont)calloc(1, sizeof(vkvg_font_t));
if (!font) {
LOGE("Create font failed, no memory\n");
@@ -1064,99 +1190,38 @@ VkvgFont _create_font_from_face (VkvgSurface surf, FontFace face, float pointSiz
}
font->face = face;
- VkvgDevice dev = surf->dev;
-
-#ifdef VKVG_USE_FREETYPE
- if (dev->threadAware)
- mtx_lock(&font->face->mutex);
- if (face->numAxis && coords)
- font->coords = coords;
- font->charSize = (uint32_t)(pointSize * 64.f);;
- if (!(face->face->face_flags & FT_FACE_FLAG_SCALABLE) || !(face->face->face_flags & FT_FACE_FLAG_SFNT)) {
- char tmp[1024];
- ft_face_flags_to_string (face->face->face_flags, tmp, 1024);
- LOGW("Unsuported font flags: %s\n", tmp);
- if (dev->threadAware)
- mtx_lock(&font->face->mutex);
- free(font);
- return (VkvgFont)&_vkvg_status_null_pointer;
- } else {
- char tmp[1024];
- ft_face_flags_to_string (face->face->face_flags, tmp, 1024);
- LOG(VKVG_LOG_FONT, "loading %s\n\tflags: %s\n", face->face->family_name, tmp);
- }
- if (!face->sizes.size)
- face->sizes = array_create_VkvgFont(5);//new face,
-
- FT_CHECK_RES(FT_New_Size (face->face, &font->ftSize));
- FT_CHECK_RES(FT_Activate_Size(font->ftSize));
- //TODO:handle fixed sizes
- FT_CHECK_RES(FT_Set_Char_Size(face->face, 0, font->charSize, surf->hdpi, surf->vdpi));
- if (font->coords) {
- FT_Set_Var_Design_Coordinates(face->face, font->face->numAxis, font->coords);
- font->face->coords = font->coords;
- }
-#ifdef VKVG_USE_HARFBUZZ
- hb_font_t* hbf = font->face->hb_font;
- hb_ft_font_changed(hbf);
- hb_font_set_ppem(hbf, font->ftSize->metrics.x_ppem, font->ftSize->metrics.y_ppem);
-#endif
-
- font->charLookup = (glyph_ref*)calloc(face->face->num_glyphs, sizeof(glyph_ref));
-
- if (FT_IS_SCALABLE(face->face))
- font->height = face->face->size->metrics.height >> 6;
- else
- font->height = face->face->height >> 6;
-
- font->texLines = array_create_TexRef(2);
-
- if (dev->threadAware)
- mtx_lock(&font->face->mutex);
-#else
- font->charSize = pointSize;
- stbtt_GetFontVMetrics(&face->stbInfo, &font->ascent, &font->descent, &font->lineGap);
- font->charLookup = (glyph_ref*)calloc(face->stbInfo.numGlyphs, sizeof(glyph_ref));
- font->scale = stbtt_ScaleForMappingEmToPixels(&face->stbInfo, font->charSize * surf->vdpi / 72.f);
- font->height = roundf(font->scale * (font->ascent - font->descent + font->lineGap));
- font->ascent = roundf(font->scale * font->ascent);
- font->descent = roundf(font->scale * font->descent);
- font->lineGap = roundf(font->scale * font->lineGap);
-#endif
- array_add_VkvgFont(&face->sizes, font);
-
font->dev = dev;
+ font->ptSize = (uint32_t)(pointSize * 64.f);
+
vkvg_device_reference(font->dev);
- _init_next_line_in_tex_cache(font);
atomic_init(&font->references, 1);
-
return font;
}
-VkvgFont vkvg_font_create_from_file (VkvgSurface surf, const char* fontFilePath, int faceIndex, float pointSize) {
+VkvgFont vkvg_font_create_from_file (VkvgDevice dev, const char* fontFilePath, int faceIndex, float pointSize) {
FontFace face = NULL;
- if (!try_create_font_face_from_path(surf->dev, fontFilePath, faceIndex, &face) || !face) {
+ if (!try_create_font_face_from_path(dev, fontFilePath, faceIndex, &face) || !face) {
return NULL;
}
- return _create_font_from_face(surf, face, pointSize, NULL);
+ return _create_font_from_face(dev, face, pointSize, NULL);
}
-VkvgFont vkvg_font_create (VkvgSurface surf, const char* query, float pointSize) {
- uint32_t pt26_6 = (uint32_t)(pointSize * 64.f);
+VkvgFont vkvg_font_create (VkvgDevice dev, const char* query, float pointSize) {
+ //uint32_t pt26_6 = (uint32_t)(pointSize * 64.f);
VkvgFont font = NULL;
FontFace face = NULL;
signed long* coords = NULL;
unsigned int numAxis = 0;
- if (try_get_or_create_font_face_from_query(surf->dev, query, &face, &coords)) {
- if (try_get_font_size(face, pt26_6, coords, &font)) {
+ if (try_get_or_create_font_face_from_query(dev, query, &face, &coords)) {
+ /*if (try_get_font_size(face, pt26_6, coords, &font)) {
vkvg_font_reference(font);
return font;
- }
+ }*/
}
if (!face)
return NULL;
- return _create_font_from_face(surf, face, pointSize, coords);
+ return _create_font_from_face(dev, face, pointSize, coords);
}
VkvgFont vkvg_font_reference(VkvgFont font) {
if (!vkvg_font_status(font))
@@ -1175,23 +1240,6 @@ void vkvg_font_destroy(VkvgFont font) {
if (atomic_fetch_sub_explicit(&font->references, 1, memory_order_acq_rel) != 1)
return;
LOG(VKVG_LOG_FONT, "Font destroy: %s\n", get_face_family_name(font->face));
-#ifdef VKVG_USE_FREETYPE
- FT_Done_Size(font->ftSize);
- if (font->coords)
- free(font->coords);
-#endif
-
- for (int i = 0; i < font->texLines.count; ++i) {
- LOG(VKVG_LOG_FONT, "\treleased line %d of page %d\n", i, font->texLines.elements[i]->pageIdx);
- font->texLines.elements[i]->released = true;
- }
- array_destroy_TexRef(&font->texLines);
-
- array_del_VkvgFont(&font->face->sizes , font);
-
- if (font->face->sizes.count == 0)
- _font_face_destroy(font);
- free(font->charLookup);
vkvg_device_destroy(font->dev);
free(font);