From: Jean-Philippe Bruyère Date: Sat, 25 Dec 2021 11:11:55 +0000 (+0100) Subject: optional fontconfig and harfbuzz X-Git-Tag: v0.3.0-beta~70 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=2daa950835ace12d5f090cb60a17abe8875b144e;p=jp%2Fvkvg.git optional fontconfig and harfbuzz --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c2c816..4209246 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,10 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.21) SET(LANG "CXX") +SET(CMAKE_C_STANDARD 11) SET(CMAKE_CXX_STANDARD 11) -PROJECT(vkvg VERSION 0.2.0 DESCRIPTION "Vulkan Vector Graphic") +PROJECT(vkvg VERSION 0.3.0 DESCRIPTION "Vulkan Vector Graphic") ADD_COMPILE_DEFINITIONS( "VKVG_VERSION_MAJOR=${vkvg_VERSION_MAJOR}" @@ -91,11 +92,32 @@ IF (ENABLE_DBG_UTILS) ADD_DEFINITIONS (-DVKVG_DBG_UTILS) ENDIF () +OPTION(VKVG_USE_FONTCONFIG "use FontConfig to resolve font names" ON) FIND_PACKAGE(Vulkan REQUIRED) FIND_PACKAGE(Freetype REQUIRED) -FIND_PACKAGE(Fontconfig REQUIRED) -FIND_PACKAGE(HarfBuzz REQUIRED) + +FIND_PACKAGE(Fontconfig) +IF (Fontconfig_FOUND) + OPTION(VKVG_USE_FONTCONFIG "use FontConfig to resolve font names" ON) +ELSE () + OPTION(VKVG_USE_FONTCONFIG "use FontConfig to resolve font names" OFF) + UNSET(VKVG_USE_FONTCONFIG CACHE) +ENDIF () +IF (VKVG_USE_FONTCONFIG) + ADD_DEFINITIONS (-DVKVG_USE_FONTCONFIG) +ENDIF () + +FIND_PACKAGE(HarfBuzz) +IF (HarfBuzz_FOUND) + OPTION(VKVG_USE_HARFBUZZ "use Harbuzz for text layouting" ON) +ELSE () + OPTION(VKVG_USE_HARFBUZZ "use Harbuzz for text layouting" OFF) + UNSET(VKVG_USE_HARFBUZZ CACHE) +ENDIF () +IF (VKVG_USE_HARFBUZZ) + ADD_DEFINITIONS (-DVKVG_USE_HARFBUZZ) +ENDIF () FIND_PACKAGE(GLFW3) FIND_PACKAGE(Doxygen) @@ -180,7 +202,7 @@ FUNCTION (setup_lib LibName) VERSION ${vkvg_VERSION_MAJOR}.${vkvg_VERSION_MINOR} SOVERSION ${vkvg_VERSION_MAJOR} C_STANDARD 11 - C_EXTENSIONS OFF + #C_EXTENSIONS OFF PUBLIC_HEADER "${VKVG_PUBLIC_HEADERS}" ) @@ -201,6 +223,15 @@ FUNCTION (setup_lib LibName) ${Fontconfig_LIBRARIES} vkh_static ) + IF (VKVG_USE_FONTCONFIG) + TARGET_INCLUDE_DIRECTORIES(${LibName} PRIVATE + ${Fontconfig_INCLUDE_DIRS} + ) + TARGET_LINK_LIBRARIES(${LibName} + ${Fontconfig_LIBRARIES} + ) + ENDIF () + INSTALL(TARGETS ${LibName} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -275,9 +306,6 @@ IF (VKVG_BUILD_DOCS) ENDIF () ENDIF (VKVG_BUILD_DOCS) -MESSAGE(STATUS "VKVG_PUBLIC_HEADERS = ${VKVG_PUBLIC_HEADERS}") -MESSAGE(STATUS "Vulkan_LIBRARIES = ${Vulkan_LIBRARIES}") - MESSAGE(STATUS "VKVG version\t\t= ${vkvg_VERSION_MAJOR}.${vkvg_VERSION_MINOR}.${vkvg_VERSION_PATCH}") MESSAGE(STATUS "comp flags\t\t= ${CMAKE_${LANG}_FLAGS}") @@ -314,6 +342,16 @@ IF (VKVG_PREMULT_ALPHA) ELSE () MESSAGE(STATUS "Premult Alpha\t= disabled.") ENDIF () +IF (VKVG_USE_FONTCONFIG) + MESSAGE(STATUS "FontConfig\t\t= enabled.") +ELSE () + MESSAGE(STATUS "FontConfig\t\t= disabled.") +ENDIF () +IF (VKVG_USE_HARFBUZZ) + MESSAGE(STATUS "Harfbuzz\t\t= enabled.") +ELSE () + MESSAGE(STATUS "Harfbuzz\t\t= disabled.") +ENDIF () IF (VKVG_LCD_FONT_FILTER) MESSAGE(STATUS "Font filtering\t= LCD.") ELSE () diff --git a/appveyor.yml b/appveyor.yml index b31862d..369028b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.1.{build} +version: 0.3.{build} image: - Visual Studio 2019 @@ -55,7 +55,7 @@ for: - cpack after_build: - cd .. - - appveyor PushArtifact build/vkvg_0.2.0.deb + - appveyor PushArtifact build/vkvg_0.3.0.deb diff --git a/cmake/FindFontconfig.cmake b/cmake/FindFontconfig.cmake deleted file mode 100644 index a6f0180..0000000 --- a/cmake/FindFontconfig.cmake +++ /dev/null @@ -1,101 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -FindFontconfig --------------- - -Find Fontconfig headers and library. - -Imported Targets -^^^^^^^^^^^^^^^^ - -``Fontconfig::Fontconfig`` - The Fontconfig library, if found. - -Result Variables -^^^^^^^^^^^^^^^^ - -This will define the following variables in your project: - -``Fontconfig_FOUND`` - true if (the requested version of) Fontconfig is available. -``Fontconfig_VERSION`` - the version of Fontconfig. -``Fontconfig_LIBRARIES`` - the libraries to link against to use Fontconfig. -``Fontconfig_INCLUDE_DIRS`` - where to find the Fontconfig headers. -``Fontconfig_COMPILE_OPTIONS`` - this should be passed to target_compile_options(), if the - target is not used for linking - -#]=======================================================================] - - -# use pkg-config to get the directories and then use these values -# in the FIND_PATH() and FIND_LIBRARY() calls -find_package(PkgConfig QUIET) -pkg_check_modules(PKG_FONTCONFIG QUIET fontconfig) -set(Fontconfig_COMPILE_OPTIONS ${PKG_FONTCONFIG_CFLAGS_OTHER}) -set(Fontconfig_VERSION ${PKG_FONTCONFIG_VERSION}) - -find_path( Fontconfig_INCLUDE_DIR - NAMES - fontconfig/fontconfig.h - HINTS - ${PKG_FONTCONFIG_INCLUDE_DIRS} - /usr/X11/include -) - -find_library( Fontconfig_LIBRARY - NAMES - fontconfig - PATHS - ${PKG_FONTCONFIG_LIBRARY_DIRS} -) - -if (Fontconfig_INCLUDE_DIR AND NOT Fontconfig_VERSION) - file(STRINGS ${Fontconfig_INCLUDE_DIR}/fontconfig/fontconfig.h _contents REGEX "^#define[ \t]+FC_[A-Z]+[ \t]+[0-9]+$") - unset(Fontconfig_VERSION) - foreach(VPART MAJOR MINOR REVISION) - foreach(VLINE ${_contents}) - if(VLINE MATCHES "^#define[\t ]+FC_${VPART}[\t ]+([0-9]+)$") - set(Fontconfig_VERSION_PART "${CMAKE_MATCH_1}") - if(Fontconfig_VERSION) - string(APPEND Fontconfig_VERSION ".${Fontconfig_VERSION_PART}") - else() - set(Fontconfig_VERSION "${Fontconfig_VERSION_PART}") - endif() - endif() - endforeach() - endforeach() -endif () - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Fontconfig - FOUND_VAR - Fontconfig_FOUND - REQUIRED_VARS - Fontconfig_LIBRARY - Fontconfig_INCLUDE_DIR - VERSION_VAR - Fontconfig_VERSION -) - - -if(Fontconfig_FOUND AND NOT TARGET Fontconfig::Fontconfig) - add_library(Fontconfig::Fontconfig UNKNOWN IMPORTED) - set_target_properties(Fontconfig::Fontconfig PROPERTIES - IMPORTED_LOCATION "${Fontconfig_LIBRARY}" - INTERFACE_COMPILE_OPTIONS "${Fontconfig_COMPILE_OPTIONS}" - INTERFACE_INCLUDE_DIRECTORIES "${Fontconfig_INCLUDE_DIR}" - ) -endif() - -mark_as_advanced(Fontconfig_LIBRARY Fontconfig_INCLUDE_DIR) - -if(Fontconfig_FOUND) - set(Fontconfig_LIBRARIES ${Fontconfig_LIBRARY}) - set(Fontconfig_INCLUDE_DIRS ${Fontconfig_INCLUDE_DIR}) -endif() diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h index 644be23..a5e6fcd 100644 --- a/src/vkvg_context_internal.h +++ b/src/vkvg_context_internal.h @@ -170,7 +170,7 @@ typedef struct _vkvg_context_t { char* selectedFontName; //_vkvg_font_t selectedFont; //hold current face and size before cache addition _vkvg_font_identity_t* currentFont; //font pointing to cached fonts identity - _vkvg_font_t* currentFontSize; //font structure by size ready for lookup + _vkvg_font_t* currentFontSize; //font structure by size ready for lookup vkvg_direction_t textDirection; push_constants pushConsts; diff --git a/src/vkvg_fonts.c b/src/vkvg_fonts.c index 24b3036..1bfee07 100644 --- a/src/vkvg_fonts.c +++ b/src/vkvg_fonts.c @@ -27,17 +27,23 @@ #include "vkh.h" +#include +#include +#include + static int defaultFontCharSize = 12<<6; void _init_fonts_cache (VkvgDevice dev){ _font_cache_t* cache = (_font_cache_t*)calloc(1, sizeof(_font_cache_t)); +#ifdef VKVG_USE_FONTCONFIG cache->config = FcInitLoadConfigAndFonts(); if (!cache->config) { fprintf(stderr, "Font config initialisation failed, consider using 'FONTCONFIG_PATH' and 'FONTCONFIG_FILE' environmane\ variables to point to 'fonts.conf' needed for FontConfig startup"); assert(cache->config); } +#endif FT_CHECK_RESULT(FT_Init_FreeType(&cache->library)); @@ -175,7 +181,9 @@ void _destroy_font_cache (VkvgDevice dev){ free(s->charLookup[g]); } FT_Done_Face (s->face); +#ifdef VKVG_USE_HARFBUZZ hb_font_destroy (s->hb_font); +#endif free(s->charLookup); } @@ -197,8 +205,10 @@ void _destroy_font_cache (VkvgDevice dev){ vkDestroyFence (dev->vkDev,cache->uploadFence,NULL); FT_Done_FreeType(cache->library); +#ifdef VKVG_USE_FONTCONFIG FcConfigDestroy(cache->config); FcFini(); +#endif free (dev->fontCache); @@ -309,14 +319,15 @@ _char_ref* _prepare_char (VkvgDevice dev, _vkvg_font_t* f, FT_UInt gindex){ _char_ref* cr = (_char_ref*)malloc(sizeof(_char_ref)); vec4 uvBounds = { - (float)(penX + f->curLine.penX) / (float)FONT_PAGE_SIZE, - (float)f->curLine.penY / (float)FONT_PAGE_SIZE, - (float)bmpWidth, - (float)bmp.rows}; - cr->bounds = uvBounds; - cr->pageIdx = f->curLine.pageIdx; - cr->bmpDiff.x = (int16_t)slot->bitmap_left; - cr->bmpDiff.y = (int16_t)slot->bitmap_top; + {(float)(penX + f->curLine.penX) / (float)FONT_PAGE_SIZE}, + {(float)f->curLine.penY / (float)FONT_PAGE_SIZE}, + {(float)bmpWidth}, + {(float)bmp.rows}}; + cr->bounds = uvBounds; + cr->pageIdx = f->curLine.pageIdx; + cr->bmpDiff.x = (int16_t)slot->bitmap_left; + cr->bmpDiff.y = (int16_t)slot->bitmap_top; + cr->advance = slot->advance; f->charLookup[gindex] = cr; dev->fontCache->stagingX += bmpWidth; @@ -333,12 +344,13 @@ void _select_font_face (VkvgContext ctx, const char* name){ ctx->currentFont = NULL; ctx->currentFontSize = NULL; } -void _font_add_fc_name (_vkvg_font_identity_t* font, const char* fcname) { +void _font_add_fc_name (_vkvg_font_identity_t* font, const char* fcname, int nameLength) { if (++font->fcNamesCount == 1) font->fcNames = (char**) malloc (sizeof(char*)); else font->fcNames = (char**) realloc (font->fcNames, font->fcNamesCount * sizeof(char*)); - font->fcNames[font->fcNamesCount-1] = (char*)calloc(FONT_NAME_MAX_SIZE, sizeof (char)); + + font->fcNames[font->fcNamesCount-1] = (char*)calloc(nameLength, sizeof (char)); strcpy (font->fcNames[font->fcNamesCount-1], fcname); } _vkvg_font_t* _find_or_create_font_size (VkvgContext ctx, _vkvg_font_identity_t* font, FT_F26Dot6 charSize) { @@ -358,12 +370,16 @@ _vkvg_font_t* _find_or_create_font_size (VkvgContext ctx, _vkvg_font_identity_t* FT_CHECK_RESULT(FT_New_Face(cache->library, font->fontFile, 0, &newSize.face)); FT_CHECK_RESULT(FT_Set_Char_Size(newSize.face, 0, newSize.charSize, dev->hdpi, dev->vdpi )); + +#ifdef VKVG_USE_HARFBUZZ newSize.hb_font = hb_ft_font_create(newSize.face, NULL); +#endif + newSize.charLookup = (_char_ref**)calloc(newSize.face->num_glyphs,sizeof(_char_ref*)); //nf.curLine.height = (nf.face->bbox.xMax - nf.face->bbox.xMin) >> 6; if (FT_IS_SCALABLE(newSize.face)) - newSize.curLine.height = FT_MulFix(newSize.face->height, newSize.face->size->metrics.y_scale) >> 6;// nf.face->size->metrics.height >> 6; + newSize.curLine.height = FT_MulFix(newSize.face->height, newSize.face->size->metrics.y_scale) >> 6; else newSize.curLine.height = newSize.face->height >> 6; @@ -374,66 +390,74 @@ _vkvg_font_t* _find_or_create_font_size (VkvgContext ctx, _vkvg_font_identity_t* } //try find font already resolved with fontconfig by font name -_vkvg_font_identity_t* _tryFindFontByName (VkvgContext ctx, const char* fontName){ +_vkvg_font_identity_t* _tryFindFontByName (VkvgContext ctx){ _font_cache_t* cache = (_font_cache_t*)ctx->pSurf->dev->fontCache; for (int i = 0; i < cache->fontsCount; ++i) { for (uint32_t j = 0; j < cache->fonts[i].fcNamesCount; j++) { - if (strcmp (cache->fonts[i].fcNames[j], fontName) == 0) + if (strcmp (cache->fonts[i].fcNames[j], ctx->selectedFontName) == 0) return &cache->fonts[i]; } } return NULL; } -_vkvg_font_identity_t* _tryResolveFontNameWithFontConfig (VkvgContext ctx, const char* fontName) { +_vkvg_font_identity_t* _tryResolveFontNameWithFontConfig (VkvgContext ctx) { _vkvg_font_identity_t* resolvedFont = NULL; _font_cache_t* cache = (_font_cache_t*)ctx->pSurf->dev->fontCache; + char* fontFile = NULL; + +#ifdef VKVG_USE_FONTCONFIG FcPattern* pat = FcNameParse((const FcChar8*)ctx->selectedFontName); FcConfigSubstitute(cache->config, pat, FcMatchPattern); FcDefaultSubstitute(pat); FcResult result; FcPattern* font = FcFontMatch(cache->config, pat, &result); - char* fontFile; - if (font) { - if (FcPatternGetString(font, FC_FILE, 0, (FcChar8 **)&fontFile) == FcResultMatch) { - //try find font in cache by path - for (int i = 0; i < cache->fontsCount; ++i) { - if (strcmp (cache->fonts[i].fontFile, fontFile) == 0) { - _font_add_fc_name (&cache->fonts[i], ctx->selectedFontName); - resolvedFont = &cache->fonts[i]; - break;; - } + if (font) + FcPatternGetString(font, FC_FILE, 0, (FcChar8 **)&fontFile); +#endif + if (fontFile) { + //try find font in cache by path + for (int i = 0; i < cache->fontsCount; ++i) { + if (strcmp (cache->fonts[i].fontFile, fontFile) == 0) { + int fflength = strlen(fontFile) + 1; + _font_add_fc_name (&cache->fonts[i], ctx->selectedFontName, fflength); + resolvedFont = &cache->fonts[i]; + break;; } - if (!resolvedFont) { - //if not found, create a new vkvg_font - cache->fontsCount++; + } + if (!resolvedFont) { + //if not found, create a new vkvg_font + cache->fontsCount++; - if (cache->fontsCount == 1) - cache->fonts = (_vkvg_font_identity_t*) malloc (cache->fontsCount * sizeof(_vkvg_font_identity_t)); - else - cache->fonts = (_vkvg_font_identity_t*) realloc (cache->fonts, cache->fontsCount * sizeof(_vkvg_font_identity_t)); + if (cache->fontsCount == 1) + cache->fonts = (_vkvg_font_identity_t*) malloc (cache->fontsCount * sizeof(_vkvg_font_identity_t)); + else + cache->fonts = (_vkvg_font_identity_t*) realloc (cache->fonts, cache->fontsCount * sizeof(_vkvg_font_identity_t)); - _vkvg_font_identity_t nf = {0}; + _vkvg_font_identity_t nf = {0}; - nf.fontFile = (char*)malloc (FONT_FILE_NAME_MAX_SIZE * sizeof(char)); - memcpy (nf.fontFile, fontFile, FONT_FILE_NAME_MAX_SIZE); - _font_add_fc_name (&nf, ctx->selectedFontName); + int fflength = strlen(fontFile) + 1; + nf.fontFile = (char*)malloc (fflength * sizeof(char)); + strcpy (nf.fontFile, fontFile); + _font_add_fc_name (&nf, ctx->selectedFontName, fflength); - cache->fonts[cache->fontsCount-1] = nf; - resolvedFont = &cache->fonts[cache->fontsCount-1]; - } + cache->fonts[cache->fontsCount-1] = nf; + resolvedFont = &cache->fonts[cache->fontsCount-1]; } } + +#ifdef VKVG_USE_FONTCONFIG FcPatternDestroy(pat); FcPatternDestroy(font); +#endif return resolvedFont; } //try to find font in cache with same font file path and font size as selected in context. _vkvg_font_identity_t* _find_or_create_font (VkvgContext ctx){ - _vkvg_font_identity_t* resolvedFont = _tryFindFontByName(ctx, ctx->selectedFontName); + _vkvg_font_identity_t* resolvedFont = _tryFindFontByName(ctx); if (!resolvedFont) - resolvedFont = _tryResolveFontNameWithFontConfig(ctx, ctx->selectedFontName); + resolvedFont = _tryResolveFontNameWithFontConfig(ctx); return resolvedFont; } //try to find corresponding font in cache (defined by context selectedFont) and create a new font entry if not found. @@ -446,6 +470,8 @@ void _update_current_font (VkvgContext ctx) { ctx->currentFontSize = _find_or_create_font_size (ctx, ctx->currentFont, ctx->selectedCharSize); } } + +#ifdef VKVG_USE_HARFBUZZ //Get harfBuzz buffer for provided text. hb_buffer_t * _get_hb_buffer (_vkvg_font_t* font, const char* text) { hb_buffer_t *buf = hb_buffer_create(); @@ -464,6 +490,8 @@ hb_buffer_t * _get_hb_buffer (_vkvg_font_t* font, const char* text) { hb_shape (font->hb_font, buf, NULL, 0); return buf; } +#endif + //retrieve global font extends of context's current font as defined by FreeType void _font_extents (VkvgContext ctx, vkvg_font_extents_t *extents) { _update_current_font (ctx); @@ -508,31 +536,67 @@ void _create_text_run (VkvgContext ctx, const char* text, VkvgText textRun) { if (ctx->status) return; - textRun->hbBuf = _get_hb_buffer (ctx->currentFontSize, text); textRun->font = ctx->currentFontSize; textRun->dev = ctx->pSurf->dev; - textRun->glyph_pos = hb_buffer_get_glyph_positions (textRun->hbBuf, &textRun->glyph_count); +#ifdef VKVG_USE_HARFBUZZ + textRun->hbBuf = _get_hb_buffer (ctx->currentFontSize, text); + textRun->glyphs = hb_buffer_get_glyph_positions (textRun->hbBuf, &textRun->glyph_count); +#else + int textByteLength = strlen (text); + if (textByteLength > 0) { + size_t wsize = mbstowcs(NULL, text, 0); + wchar_t *tmp = (wchar_t*)malloc((wsize+1) * sizeof (wchar_t)); + textRun->glyph_count = mbstowcs (tmp, text, wsize); + textRun->glyphs = (vkvg_glyph_info_t*)malloc(textRun->glyph_count * sizeof (vkvg_glyph_info_t)); + for (unsigned int i=0; iglyph_count; i++) { + FT_UInt gindex = FT_Get_Char_Index( textRun->font->face, tmp[i]); + _char_ref* cr = textRun->font->charLookup[gindex]; + if (cr==NULL) + cr = _prepare_char(textRun->dev, textRun->font, gindex); + textRun->glyphs[i].codepoint = gindex; + textRun->glyphs[i].x_advance = cr->advance.x; + textRun->glyphs[i].y_advance = cr->advance.y; + textRun->glyphs[i].x_offset = 0; + textRun->glyphs[i].y_offset = 0; + /*textRun->glyphs[i].x_offset = cr->bmpDiff.x; + textRun->glyphs[i].y_offset = cr->bmpDiff.y;*/ + } + free (tmp); + } +#endif unsigned int string_width_in_pixels = 0; for (uint32_t i=0; i < textRun->glyph_count; ++i) - string_width_in_pixels += textRun->glyph_pos[i].x_advance >> 6; + string_width_in_pixels += textRun->glyphs[i].x_advance >> 6; FT_Size_Metrics* metrics = &ctx->currentFontSize->face->size->metrics; textRun->extents.x_advance = (float)string_width_in_pixels; - textRun->extents.y_advance = (float)(textRun->glyph_pos[textRun->glyph_count-1].y_advance >> 6); - textRun->extents.x_bearing = -(float)(textRun->glyph_pos[0].x_offset >> 6); - textRun->extents.y_bearing = -(float)(textRun->glyph_pos[0].y_offset >> 6); + if (textRun->glyph_count > 0) { + textRun->extents.y_advance = (float)(textRun->glyphs[textRun->glyph_count-1].y_advance >> 6); + textRun->extents.x_bearing = -(float)(textRun->glyphs[0].x_offset >> 6); + textRun->extents.y_bearing = -(float)(textRun->glyphs[0].y_offset >> 6); + } textRun->extents.height = (float)(FT_MulFix(ctx->currentFontSize->face->height, metrics->y_scale) >> 6);// (metrics->ascender + metrics->descender) >> 6; textRun->extents.width = textRun->extents.x_advance; } void _destroy_text_run (VkvgText textRun) { +#ifdef VKVG_USE_HARFBUZZ hb_buffer_destroy (textRun->hbBuf); +#else + if (textRun->glyph_count > 0) + free (textRun->glyphs); +#endif } void _show_text_run (VkvgContext ctx, VkvgText tr) { unsigned int glyph_count; +#ifdef VKVG_USE_HARFBUZZ hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos (tr->hbBuf, &glyph_count); +#else + vkvg_glyph_info_t* glyph_info = tr->glyphs; + glyph_count = tr->glyph_count; +#endif Vertex v = {{0},ctx->curColor,{0,0,-1}}; vec2 pen = {0,0}; @@ -550,8 +614,8 @@ void _show_text_run (VkvgContext ctx, VkvgText tr) { if (cr!=NULL){ float uvWidth = cr->bounds.width / (float)FONT_PAGE_SIZE; float uvHeight = cr->bounds.height / (float)FONT_PAGE_SIZE; - vec2 p0 = {pen.x + cr->bmpDiff.x + (tr->glyph_pos[i].x_offset >> 6), - pen.y - cr->bmpDiff.y + (tr->glyph_pos[i].y_offset >> 6)}; + vec2 p0 = {pen.x + cr->bmpDiff.x + (tr->glyphs[i].x_offset >> 6), + pen.y - cr->bmpDiff.y + (tr->glyphs[i].y_offset >> 6)}; v.pos = p0; VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset); @@ -579,8 +643,8 @@ void _show_text_run (VkvgContext ctx, VkvgText tr) { _add_tri_indices_for_rect (ctx, firstIdx); } - pen.x += (tr->glyph_pos[i].x_advance >> 6); - pen.y -= (tr->glyph_pos[i].y_advance >> 6); + pen.x += (tr->glyphs[i].x_advance >> 6); + pen.y -= (tr->glyphs[i].y_advance >> 6); } vkvg_move_to(ctx, pen.x, pen.y); diff --git a/src/vkvg_fonts.h b/src/vkvg_fonts.h index 5c88447..02b0a7f 100644 --- a/src/vkvg_fonts.h +++ b/src/vkvg_fonts.h @@ -31,11 +31,15 @@ #if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING) #include #endif - +#ifdef VKVG_USE_HARFBUZZ #include #include +#else +#endif +#ifdef VKVG_USE_FONTCONFIG #include +#endif #define FONT_PAGE_SIZE 1024 #define FONT_CACHE_INIT_LAYERS 1 @@ -60,9 +64,10 @@ //texture coordinates of one character in font cache array texture. typedef struct { - vec4 bounds; /* normalized float bounds of character bitmap in font cache texture. */ - vec2i16 bmpDiff; /* Difference in pixel between char bitmap top left corner and char glyph*/ - uint8_t pageIdx; /* Page index in font cache texture array */ + vec4 bounds; /* normalized float bounds of character bitmap in font cache texture. */ + vec2i16 bmpDiff; /* Difference in pixel between char bitmap top left corner and char glyph*/ + uint8_t pageIdx; /* Page index in font cache texture array */ + FT_Vector advance; /* horizontal or vertical advance */ }_char_ref; // Current location in font cache texture array for new character addition. Each font holds such structure to locate // where to upload new chars. @@ -76,11 +81,14 @@ typedef struct { typedef struct { FT_F26Dot6 charSize; /* Font size*/ FT_Face face; /* FreeType face*/ +#ifdef VKVG_USE_HARFBUZZ hb_font_t* hb_font; /* HarfBuzz font instance*/ +#endif _char_ref** charLookup; /* Lookup table of characteres in cache, if not found, upload is queued*/ _tex_ref_t curLine; /* tex coord where to add new char bmp's */ }_vkvg_font_t; + /* Font identification structure */ typedef struct { char** fcNames; /* Resolved Input names to this font by fontConfig */ @@ -93,7 +101,9 @@ typedef struct { // Font cache global structure, entry point for all font related operations. typedef struct { FT_Library library; /* FreeType library*/ +#ifdef VKVG_USE_FONTCONFIG FcConfig* config; /* Font config, used to find font files by font names*/ +#endif int stagingX; /* x pen in host buffer */ uint8_t* hostBuff; /* host memory where bitmaps are first loaded */ @@ -107,18 +117,31 @@ typedef struct { int* pensY; /* array of current y pen positions for each texture in cache 2d array */ VkFence uploadFence; /* Signaled when upload is finished */ - _vkvg_font_identity_t* fonts; /* Loaded fonts structure array */ + _vkvg_font_identity_t* fonts; /* Loaded fonts structure array */ int32_t fontsCount; /* Loaded fonts array count*/ }_font_cache_t; +#ifndef VKVG_USE_HARFBUZZ +typedef struct _glyph_info_t { + int32_t x_advance; + int32_t y_advance; + int32_t x_offset; + int32_t y_offset; + FT_UInt codepoint;//should be named glyphIndex, but for harfbuzz compatibility... +} vkvg_glyph_info_t; +#endif // Precompute everything necessary to draw one line of text, usefull to draw the same text multiple times. typedef struct _vkvg_text_run_t { - hb_buffer_t* hbBuf; /* HarfBuzz buffer of text */ _vkvg_font_t* font; /* vkvg font structure pointer */ VkvgDevice dev; /* vkvg device associated with this text run */ vkvg_text_extents_t extents; /* store computed text extends */ const char* text; /* utf8 char array of text*/ unsigned int glyph_count;/* Total glyph count */ - hb_glyph_position_t *glyph_pos; /* HarfBuzz computed glyph positions array */ +#ifdef VKVG_USE_HARFBUZZ + hb_buffer_t* hbBuf; /* HarfBuzz buffer of text */ + hb_glyph_position_t *glyphs; /* HarfBuzz computed glyph positions array */ +#else + vkvg_glyph_info_t *glyphs; /* computed glyph positions array */ +#endif } vkvg_text_run_t; //Create font cache. void _init_fonts_cache (VkvgDevice dev);