]> O.S.I.I.S - jp/vkvg.git/commitdiff
split font identity and size structure, the second holding face, hb, and lookup objects
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 19 Jul 2021 16:41:34 +0000 (18:41 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 19 Jul 2021 16:41:34 +0000 (18:41 +0200)
src/vkvg_context.c
src/vkvg_context_internal.h
src/vkvg_fonts.c
src/vkvg_fonts.h

index e87c3b7e1e9e1965e052e6f938f1f85621293598..0ec252efd1f4d8f2890e9d852a99e3e5b09d5e30 100644 (file)
@@ -973,8 +973,12 @@ void vkvg_select_font_path (VkvgContext ctx, const char* path){
 void vkvg_set_font_size (VkvgContext ctx, uint32_t size){
        if (ctx->status)
                return;
-       ctx->selectedCharSize = size << 6;
+       FT_F26Dot6 newSize = size << 6;
+       if (ctx->selectedCharSize == newSize)
+               return;
+       ctx->selectedCharSize = newSize;
        ctx->currentFont = NULL;
+       ctx->currentFontSize = NULL;
 }
 
 void vkvg_set_text_direction (vkvg_context* ctx, vkvg_direction_t direction){
index 6c874854af96ea1b73ae920af45d7dd1fc9caba1..592bc1f166155a6d2438da82abf0be8ebb8a7f3a 100644 (file)
@@ -89,8 +89,8 @@ typedef struct _vkvg_context_save_t{
 
        FT_F26Dot6                      selectedCharSize; /* Font size*/
        char*                           selectedFontName;
-       _vkvg_font_t        selectedFont;     //hold current face and size before cache addition
-       _vkvg_font_t*       currentFont;      //font ready for lookup
+       _vkvg_font_identity_t        selectedFont;     //hold current face and size before cache addition
+       _vkvg_font_identity_t*       currentFont;      //font ready for lookup
        vkvg_direction_t    textDirection;
        push_constants      pushConsts;
        VkvgPattern         pattern;
@@ -169,7 +169,8 @@ typedef struct _vkvg_context_t {
        FT_F26Dot6                      selectedCharSize; /* Font size*/
        char*                           selectedFontName;
        //_vkvg_font_t        selectedFont;     //hold current face and size before cache addition
-       _vkvg_font_t*       currentFont;      //font pointing to cached fonts ready for lookup
+       _vkvg_font_identity_t*       currentFont;               //font pointing to cached fonts identity
+       _vkvg_font_t*   currentFontSize;        //font structure by size ready for lookup
        vkvg_direction_t    textDirection;
 
        push_constants      pushConsts;
index 4ac2fe2579d420f396fbb5425efe85456c9c7efb..96fed15ddcc07c6d6433b092bcce99593be932eb 100644 (file)
@@ -167,17 +167,19 @@ void _destroy_font_cache (VkvgDevice dev){
        free (cache->hostBuff);
 
        for (int i = 0; i < cache->fontsCount; ++i) {
-               _vkvg_font_t* f = &cache->fonts[i];
+               _vkvg_font_identity_t* f = &cache->fonts[i];
+               for (uint32_t j = 0; j < f->sizeCount; j++) {
+                       _vkvg_font_t* s = &f->sizes[j];
+                       for (int g = 0; g < s->face->num_glyphs; ++g) {
+                               if (s->charLookup[g]!=NULL)
+                                       free(s->charLookup[g]);
+                       }
+                       FT_Done_Face (s->face);
+                       hb_font_destroy (s->hb_font);
 
-               for (int g = 0; g < f->face->num_glyphs; ++g) {
-                       if (f->charLookup[g]!=NULL)
-                               free(f->charLookup[g]);
+                       free(s->charLookup);
                }
-
-               FT_Done_Face (f->face);
-               hb_font_destroy (f->hb_font);
-
-               free(f->charLookup);
+               free (f->sizes);
                free(f->fontFile);
                for (uint32_t j = 0; j < f->fcNamesCount; j++)
                        free (f->fcNames[j]);
@@ -325,9 +327,13 @@ void _select_font_path (VkvgContext ctx, const char* fontFile){
 }
 //select current font for context
 void _select_font_face (VkvgContext ctx, const char* name){
+       if (strcmp(ctx->selectedFontName, name) == 0)
+               return;
        strcpy (ctx->selectedFontName, name);
+       ctx->currentFont = NULL;
+       ctx->currentFontSize = NULL;
 }
-void _font_add_fc_name (_vkvg_font_t* font, const char* fcname) {
+void _font_add_fc_name (_vkvg_font_identity_t* font, const char* fcname) {
        if (++font->fcNamesCount == 1)
                font->fcNames = (char**) malloc (sizeof(char*));
        else
@@ -335,92 +341,110 @@ void _font_add_fc_name (_vkvg_font_t* font, const char* fcname) {
        font->fcNames[font->fcNamesCount-1] = (char*)calloc(FONT_NAME_MAX_SIZE, 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) {
+       for (uint32_t i = 0; i < font->sizeCount; ++i) {
+               if (font->sizes[i].charSize == charSize)
+                       return &font->sizes[i];
+       }
+       //if not found, create a new font size structure
+       _font_cache_t*  cache = (_font_cache_t*)ctx->pSurf->dev->fontCache;
+       VkvgDevice dev = ctx->pSurf->dev;
 
-//try to find font in cache with same font file path and font size as selected in context.
-_vkvg_font_t* _tryFindVkvgFont (VkvgContext ctx){
+       if (++font->sizeCount == 1)
+               font->sizes = (_vkvg_font_t*) malloc (sizeof(_vkvg_font_t));
+       else
+               font->sizes = (_vkvg_font_t*) realloc (font->sizes, font->sizeCount * sizeof(_vkvg_font_t));
+       _vkvg_font_t newSize = {.charSize = charSize};
+
+       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 ));
+       newSize.hb_font = hb_ft_font_create(newSize.face, NULL);
+       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;
+       else
+               newSize.curLine.height = newSize.face->height >> 6;
+
+       _init_next_line_in_tex_cache (dev, &newSize);
+
+       font->sizes[font->sizeCount-1] = newSize;
+       return &font->sizes[font->sizeCount-1];
+}
+
+//try find font already resolved with fontconfig by font name
+_vkvg_font_identity_t* _tryFindFontByName (VkvgContext ctx, const char* fontName){
        _font_cache_t*  cache = (_font_cache_t*)ctx->pSurf->dev->fontCache;
-       //try find font already resolved with fontconfig by font name
        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], ctx->selectedFontName) == 0 && cache->fonts[i].charSize == ctx->selectedCharSize)
+                       if (strcmp (cache->fonts[i].fcNames[j], fontName) == 0)
                                return &cache->fonts[i];
                }
        }
-       //try resolve name with fontconfig
+       return NULL;
+}
+_vkvg_font_identity_t* _tryResolveFontNameWithFontConfig (VkvgContext ctx, const char* fontName) {
+       _vkvg_font_identity_t* resolvedFont = NULL;
+       _font_cache_t*  cache = (_font_cache_t*)ctx->pSurf->dev->fontCache;
        FcPattern* pat = FcNameParse((const FcChar8*)ctx->selectedFontName);
        FcConfigSubstitute(cache->config, pat, FcMatchPattern);
        FcDefaultSubstitute(pat);
-       // find the font
        FcResult result;
        FcPattern* font = FcFontMatch(cache->config, pat, &result);
-       if (font)
-       {
-               char* fontFile;
+       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 && cache->fonts[i].charSize == ctx->selectedCharSize) {
+                               if (strcmp (cache->fonts[i].fontFile, fontFile) == 0) {
                                        _font_add_fc_name (&cache->fonts[i], ctx->selectedFontName);
-                                       FcPatternDestroy(pat);
-                                       FcPatternDestroy(font);
-                                       return &cache->fonts[i];
+                                       resolvedFont = &cache->fonts[i];
+                                       break;;
                                }
                        }
-                       //if not found, create a new vkvg_font
-                       cache->fontsCount++;
-
-                       if (cache->fontsCount == 1)
-                               cache->fonts = (_vkvg_font_t*) malloc (cache->fontsCount * sizeof(_vkvg_font_t));
-                       else
-                               cache->fonts = (_vkvg_font_t*) realloc (cache->fonts, cache->fontsCount * sizeof(_vkvg_font_t));
-
-                       _vkvg_font_t* nf = &cache->fonts[cache->fontsCount-1];
-                       memset (nf, 0, sizeof(_vkvg_font_t));
-
-                       nf->charSize = ctx->selectedCharSize;
-                       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);
-                       FcPatternDestroy(pat);
-                       FcPatternDestroy(font);
-                       return nf;
+                       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));
+
+                               _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);
+
+                               cache->fonts[cache->fontsCount-1] = nf;
+                               resolvedFont = &cache->fonts[cache->fontsCount-1];
+                       }
                }
        }
        FcPatternDestroy(pat);
        FcPatternDestroy(font);
+       return resolvedFont;
+}
 
 
-       return NULL;
+//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);
+       if (!resolvedFont)
+               resolvedFont = _tryResolveFontNameWithFontConfig(ctx, ctx->selectedFontName);
+       return resolvedFont;
 }
 //try to find corresponding font in cache (defined by context selectedFont) and create a new font entry if not found.
 void _update_current_font (VkvgContext ctx) {
-       VkvgDevice dev = ctx->pSurf->dev;
-
        if (ctx->currentFont == NULL){
                if (ctx->selectedFontName[0] == 0)
                        _select_font_face (ctx, "sans");
 
-               ctx->currentFont = _tryFindVkvgFont (ctx);
-
-               if (ctx->currentFont->face == NULL){
-                       //create new font in cache
-                       _font_cache_t*  cache = dev->fontCache;
-
-
-                       FT_CHECK_RESULT(FT_New_Face(cache->library, ctx->currentFont->fontFile, 0, &ctx->currentFont->face));
-                       FT_CHECK_RESULT(FT_Set_Char_Size(ctx->currentFont->face, 0, ctx->currentFont->charSize, dev->hdpi, dev->vdpi ));
-                       ctx->currentFont->hb_font = hb_ft_font_create(ctx->currentFont->face, NULL);
-                       ctx->currentFont->charLookup = (_char_ref**)calloc(ctx->currentFont->face->num_glyphs,sizeof(_char_ref*));
-
-                       //nf.curLine.height = (nf.face->bbox.xMax - nf.face->bbox.xMin) >> 6;
-                       if (FT_IS_SCALABLE(ctx->currentFont->face))
-                               ctx->currentFont->curLine.height = FT_MulFix(ctx->currentFont->face->height, ctx->currentFont->face->size->metrics.y_scale) >> 6;// nf.face->size->metrics.height >> 6;
-                       else
-                               ctx->currentFont->curLine.height = ctx->currentFont->face->height >> 6;
-
-                       _init_next_line_in_tex_cache (dev, ctx->currentFont);
-               }
-       }
+               ctx->currentFont = _find_or_create_font (ctx);
+               ctx->currentFontSize = _find_or_create_font_size (ctx, ctx->currentFont, ctx->selectedCharSize);
+       }       
 }
 //Get harfBuzz buffer for provided text.
 hb_buffer_t * _get_hb_buffer (_vkvg_font_t* font, const char* text) {
@@ -448,11 +472,13 @@ void _font_extents (VkvgContext ctx, vkvg_font_extents_t *extents) {
                return;
 
        //TODO: ensure correct metrics are returned (scalled/unscalled, etc..)
-       FT_BBox* bbox = &ctx->currentFont->face->bbox;
-       FT_Size_Metrics* metrics = &ctx->currentFont->face->size->metrics;
-       extents->ascent = (float)(FT_MulFix(ctx->currentFont->face->ascender, metrics->y_scale) >> 6);//metrics->ascender >> 6;
-       extents->descent= -(float)(FT_MulFix(ctx->currentFont->face->descender, metrics->y_scale) >> 6);//metrics->descender >> 6;
-       extents->height = (float)(FT_MulFix(ctx->currentFont->face->height, metrics->y_scale) >> 6);//metrics->height >> 6;
+       _vkvg_font_t* font = ctx->currentFontSize;
+
+       FT_BBox* bbox = &font->face->bbox;
+       FT_Size_Metrics* metrics = &font->face->size->metrics;
+       extents->ascent = (float)(FT_MulFix(font->face->ascender, metrics->y_scale) >> 6);//metrics->ascender >> 6;
+       extents->descent= -(float)(FT_MulFix(font->face->descender, metrics->y_scale) >> 6);//metrics->descender >> 6;
+       extents->height = (float)(FT_MulFix(font->face->height, metrics->y_scale) >> 6);//metrics->height >> 6;
        extents->max_x_advance = (float)(bbox->xMax >> 6);
        extents->max_y_advance = (float)(bbox->yMax >> 6);
 }
@@ -477,8 +503,8 @@ void _create_text_run (VkvgContext ctx, const char* text, VkvgText textRun) {
        if (ctx->status)
                return;
 
-       textRun->hbBuf = _get_hb_buffer (ctx->currentFont, text);
-       textRun->font = ctx->currentFont;
+       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);
@@ -487,13 +513,13 @@ void _create_text_run (VkvgContext ctx, const char* text, VkvgText textRun) {
        for (uint32_t i=0; i < textRun->glyph_count; ++i)
                string_width_in_pixels += textRun->glyph_pos[i].x_advance >> 6;
 
-       FT_Size_Metrics* metrics = &ctx->currentFont->face->size->metrics;
+       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);
 
-       textRun->extents.height = (float)(FT_MulFix(ctx->currentFont->face->height, metrics->y_scale) >> 6);// (metrics->ascender + metrics->descender) >> 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) {
index 11f9434bdf8da2202e01a699135b8e07f3d70f02..ce06786ab4b0959f46b4b759f35aa000da30ff3c 100644 (file)
@@ -71,18 +71,24 @@ typedef struct {
        int         penY;               /* Current Y in cache for next char addition */
        int         height;             /* Height of current line pointed by this structure */
 }_tex_ref_t;
-// Loaded font structure, holds informations for glyphes upload in cache and the lookup table of characters.
+// Loaded font structure, one per size, holds informations for glyphes upload in cache and the lookup table of characters.
 typedef struct {
-       char**          fcNames;                        /* Resolved Input names to this font by fontConfig */
-       uint32_t        fcNamesCount;           /* Count of resolved names by fontConfig */
-       char*       fontFile;           /* Font file full path*/
        FT_F26Dot6  charSize;           /* Font size*/
-       hb_font_t*  hb_font;            /* HarfBuzz font instance*/
        FT_Face     face;               /* FreeType face*/
+       hb_font_t*  hb_font;            /* HarfBuzz font instance*/
        _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 */
+       uint32_t                        fcNamesCount;   /* Count of resolved names by fontConfig */
+       char*                           fontFile;               /* Font file full path*/
+       uint32_t                        sizeCount;              /* available font size loaded */
+       _vkvg_font_t*           sizes                   /* loaded font size array */
+}_vkvg_font_identity_t;
+
 // Font cache global structure, entry point for all font related operations.
 typedef struct {
        FT_Library              library;        /* FreeType library*/
@@ -100,17 +106,17 @@ 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_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;
 // 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 */
+       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 */
+       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 */
 } vkvg_text_run_t;
 //Create font cache.