]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - ft2.c
build: minor adjustments
[xonotic/darkplaces.git] / ft2.c
diff --git a/ft2.c b/ft2.c
index db3021c0e3a327c9a78a2c620d60e83f2a8525ad..64efe9a674c93a4834458e55fb7c96710b26673c 100644 (file)
--- a/ft2.c
+++ b/ft2.c
@@ -32,11 +32,11 @@ static int img_fontmap[256] = {
  *     http://www.unicode.org/Public/UNIDATA/Blocks.txt
  *
  * Let's call these "bigblocks".
- * These appears in a text in a "spreaded" way, ordinary maps will 
+ * These characters are "spreaded", and ordinary maps will 
  *     waste huge amount of resources rendering/caching unused glyphs.
  *
- * So, another matter is invented to counter this: incremental maps,
- *     in which only used glyphs may present.
+ * So, a new design is introduced to solve the problem:
+ *     incremental maps, in which only used glyphs are stored.
  */
 static const Uchar unicode_bigblocks[] = {
        0x3400, 0x4DBF,         //   6592  CJK Unified Ideographs Extension A
@@ -53,10 +53,9 @@ CVars introduced with the freetype extension
 */
 
 cvar_t r_font_disable_freetype = {CF_CLIENT | CF_ARCHIVE, "r_font_disable_freetype", "0", "disable freetype support for fonts entirely"};
-cvar_t r_font_use_alpha_textures = {CF_CLIENT | CF_ARCHIVE, "r_font_use_alpha_textures", "0", "use alpha-textures for font rendering, this should safe memory"};
 cvar_t r_font_size_snapping = {CF_CLIENT | CF_ARCHIVE, "r_font_size_snapping", "1", "stick to good looking font sizes whenever possible - bad when the mod doesn't support it!"};
 cvar_t r_font_kerning = {CF_CLIENT | CF_ARCHIVE, "r_font_kerning", "1", "Use kerning if available"};
-cvar_t r_font_diskcache = {CF_CLIENT | CF_ARCHIVE, "r_font_diskcache", "0", "(deprecated and non-functional) save font textures to disk for future loading rather than generating them every time"};
+cvar_t r_font_diskcache = {CF_CLIENT | CF_ARCHIVE, "r_font_diskcache", "0", "[deprecated, not effective] save font textures to disk for future loading rather than generating them every time"};
 cvar_t r_font_compress = {CF_CLIENT | CF_ARCHIVE, "r_font_compress", "0", "use texture compression on font textures to save video memory"};
 cvar_t r_font_nonpoweroftwo = {CF_CLIENT | CF_ARCHIVE, "r_font_nonpoweroftwo", "1", "use nonpoweroftwo textures for font (saves memory, potentially slower)"};
 cvar_t developer_font = {CF_CLIENT | CF_ARCHIVE, "developer_font", "0", "prints debug messages about fonts"};
@@ -289,7 +288,7 @@ static const unsigned char *fontfilecache_LoadFile(const char *path, qbool quiet
                for(i = 0; i < MAX_FONTFILES; ++i)
                        if(fontfiles[i].refcount <= 0)
                        {
-                               strlcpy(fontfiles[i].path, path, sizeof(fontfiles[i].path));
+                               dp_strlcpy(fontfiles[i].path, path, sizeof(fontfiles[i].path));
                                fontfiles[i].len = *filesizepointer;
                                fontfiles[i].buf = buf;
                                fontfiles[i].refcount = 1;
@@ -445,7 +444,6 @@ void Font_Init(void)
 {
        Cvar_RegisterVariable(&r_font_nonpoweroftwo);
        Cvar_RegisterVariable(&r_font_disable_freetype);
-       Cvar_RegisterVariable(&r_font_use_alpha_textures);
        Cvar_RegisterVariable(&r_font_size_snapping);
        Cvar_RegisterVariable(&r_font_kerning);
        Cvar_RegisterVariable(&r_font_diskcache);
@@ -549,7 +547,7 @@ qbool Font_LoadFont(const char *name, dp_font_t *dpfnt)
                        Mem_Free(ft2);
                        return false;
                }
-               strlcpy(ft2->name, name, sizeof(ft2->name));
+               dp_strlcpy(ft2->name, name, sizeof(ft2->name));
                ft2->image_font = true;
                ft2->has_kerning = false;
        }
@@ -726,7 +724,7 @@ static qbool Font_LoadFile(const char *name, int _face, ft2_settings_t *settings
                        Con_Printf(CON_ERROR "Failed to add attachment %u to %s\n", (unsigned)i, font->name);
        }
 
-       strlcpy(font->name, name, sizeof(font->name));
+       dp_strlcpy(font->name, name, sizeof(font->name));
        font->image_font = false;
        font->has_kerning = !!(((FT_Face)(font->face))->face_flags & FT_FACE_FLAG_KERNING);
        return true;
@@ -1248,50 +1246,12 @@ static float Font_SearchSize(ft2_font_t *font, FT_Face fontface, float size)
        }
 }
 
-// some color transforming functions I made in attempt to fix font_diskcache
-// until the point I realize it's not worthwhile anymore
-
-static inline void rgba_to_bgra(unsigned char *source, unsigned char *target, int source_size)
-{
-       int x;
-       for (x = 0; x < source_size; x += 4)
-       {
-               target[0] = source[2];
-               target[1] = source[1];
-               target[2] = source[0];
-               target[3] = source[3];
-       }
-}
-static inline void rgba_to_alpha(unsigned char *source, unsigned char *target, int source_size)
-{
-       int x, i;
-       for (x = 0, i = 0; x < source_size; x += 4)
-       {
-               target[i++] = (
-                       source[x+0] * 0.2125 +      // r
-                       source[x+1] * 0.7154 +          // g
-                       source[x+2] * 0.0721            // b
-               ) / 3 * (source[x+3] / 256);    // a
-       }
-}
-static inline void alpha_to_rgba(unsigned char *source, unsigned char *target, int source_size)
-{
-       int x, i;
-       for (x = 0, i = 0; x < source_size; x += 4)
-       {
-               target[x+0] = target[x+1] = target[x+2] = 0xff - source[i];
-               target[x+3] = source[i++];
-       }
-}
-#define alpha_to_bgra alpha_to_rgba
-
-// helper inline functions for incmap_post_process
+// helper inline functions for incmap_post_process:
 
 static inline void update_pic_for_fontmap(ft2_font_map_t *fontmap, const char *identifier,
                int width, int height, unsigned char *data)
 {
-       fontmap->pic = Draw_NewPic(identifier, width, height, data,
-               r_font_use_alpha_textures.integer ? TEXTYPE_ALPHA : TEXTYPE_RGBA,
+       fontmap->pic = Draw_NewPic(identifier, width, height, data, TEXTYPE_RGBA,
                TEXF_ALPHA | TEXF_CLAMP | (r_font_compress.integer > 0 ? TEXF_COMPRESS : 0));
 }
 
@@ -1323,60 +1283,24 @@ static inline void merge_single_map(ft2_font_map_t *targetmap, int targetindex,
 static inline void incmap_post_process(font_incmap_t *incmap, Uchar ch,
                unsigned char *data, ft2_font_map_t **outmap, int *outmapch)
 {
+       #define bytes_per_pixel 4
+
        int index, targetmap_at;
        // where will the next `data` be placed
        int tier1_data_index, tier2_data_index;
        // metrics of data to manipulate
-       int width, height, bytes_per_pixel, pitch, datasize;
+       int width, height, pitch, datasize;
        int i, j, x, y;
        unsigned char *newdata, *chunk;
        ft2_font_map_t *startmap, *targetmap, *currentmap;
        #define M FONT_CHARS_PER_LINE
        #define N FONT_CHAR_LINES
 
-       bytes_per_pixel = r_font_use_alpha_textures.integer ? 1 : 4;
-
        startmap = incmap->fontmap;
        index = incmap->charcount;
        tier1_data_index = index % M;
        tier2_data_index = incmap->tier1_merged;
 
-       if (bytes_per_pixel != incmap->bytes_per_pixel)
-       {
-               // should it really happen...
-               int olddata_size;
-               calc_data_arguments(1, 1);
-               olddata_size = datasize / bytes_per_pixel * incmap->bytes_per_pixel;
-               for (i = 0; i < M; ++i)
-               {
-                       chunk = incmap->data_tier1[i];
-                       if (chunk == NULL) break;
-                       newdata = (unsigned char *)Mem_Alloc(font_mempool, datasize);
-                       if (bytes_per_pixel == 1)
-                               rgba_to_alpha(chunk, newdata, olddata_size);
-                       else if (bytes_per_pixel == 4)
-                               alpha_to_rgba(chunk, newdata, olddata_size);
-                       Mem_Free(chunk);
-                       incmap->data_tier1[i] = newdata;
-               }
-               chunk = NULL;
-               olddata_size *= M;
-               for (i = 0; i < N; ++i)
-               {
-                       chunk = incmap->data_tier2[i];
-                       if (chunk == NULL) break;
-                       newdata = (unsigned char *)Mem_Alloc(font_mempool, datasize);
-                       if (bytes_per_pixel == 1)
-                               rgba_to_alpha(chunk, newdata, olddata_size);
-                       else if (bytes_per_pixel == 4)
-                               alpha_to_rgba(chunk, newdata, olddata_size);
-                       Mem_Free(chunk);
-                       incmap->data_tier2[i] = newdata;
-               }
-               chunk = NULL;
-               incmap->bytes_per_pixel = bytes_per_pixel;
-       }
-       
        incmap->data_tier1[tier1_data_index] = data;
 
        if (index % M == M - 1)
@@ -1412,7 +1336,7 @@ static inline void incmap_post_process(font_incmap_t *incmap, Uchar ch,
                incmap->newmap_start = INCMAP_START + targetmap_at + 1;
                // then give this merged map
                *outmap = targetmap;
-               *outmapch = i;
+               *outmapch = FONT_CHARS_PER_LINE - 1;
        }
        if (index % (M * N) == M * N - 1)
        {
@@ -1448,7 +1372,7 @@ static inline void incmap_post_process(font_incmap_t *incmap, Uchar ch,
                incmap->newmap_start = INCMAP_START + targetmap_at + 1;
                // then give this merged map
                *outmap = targetmap;
-               *outmapch = i * M + j;
+               *outmapch = FONT_CHARS_PER_MAP - 1;
        }
 
        ++incmap->charcount;
@@ -1461,6 +1385,8 @@ static inline void incmap_post_process(font_incmap_t *incmap, Uchar ch,
 static qbool Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _ch,
                ft2_font_map_t **outmap, int *outmapch, qbool use_incmap)
 {
+       #define bytes_per_pixel 4
+
        char map_identifier[MAX_QPATH];
        unsigned long map_startglyph = _ch / FONT_CHARS_PER_MAP * FONT_CHARS_PER_MAP;
        unsigned char *data = NULL;
@@ -1471,7 +1397,6 @@ static qbool Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _ch,
        int gpad_l, gpad_r, gpad_t, gpad_b;
 
        int pitch;
-       int bytes_per_pixel;
        int width, height, datasize;
        int glyph_row, glyph_column;
 
@@ -1485,8 +1410,6 @@ static qbool Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _ch,
 
        FT_Face fontface;
 
-       bytes_per_pixel = r_font_use_alpha_textures.integer ? 1 : 4;
-
        incmap = mapstart->incmap;
        if (use_incmap)
        {
@@ -1580,7 +1503,7 @@ static qbool Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _ch,
        map = (ft2_font_map_t *)Mem_Alloc(font_mempool, sizeof(ft2_font_map_t));
        if (!map)
        {
-               Con_Printf(CON_ERROR "ERROR: Out of memory when allowcating fontmap for %s\n", font->name);
+               Con_Printf(CON_ERROR "ERROR: Out of memory when allocating fontmap for %s\n", font->name);
                return false;
        }
 
@@ -1602,8 +1525,16 @@ static qbool Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _ch,
                // add pointer as a unique part to avoid earlier incmaps' state being trashed
                use_incmap ? (unsigned long)mapstart : 0x0);
        */
-       dpsnprintf(map_identifier, sizeof(map_identifier), "%s_%g_%lx_%u",
-                       font->name, mapstart->intSize, (unsigned long) mapstart, (unsigned) map_startglyph);
+       /*
+        * note 1: it appears that different font instances may have the same metrics, causing this pic being overwritten
+        *         will use startmap's pointer as a unique part to avoid earlier incmaps' dynamic pics being trashed
+        * note 2: if this identifier is made too long, significient performance drop will take place
+        * note 3: blur/outline/shadow are per-font settings, so a pointer to startmap & map size
+        *         already made these unique, hence they are omitted
+        * note 4: font_diskcache is removed, this name can be less meaningful
+        */
+       dpsnprintf(map_identifier, sizeof(map_identifier), "%s_%g_%p_%u",
+                       font->name, mapstart->intSize, mapstart, (unsigned) map_startglyph);
 
        // create a cachepic_t from the data now, or reuse an existing one
        if (developer_font.integer)
@@ -1638,13 +1569,12 @@ static qbool Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _ch,
                        incmap = mapstart->incmap = (font_incmap_t *)Mem_Alloc(font_mempool, sizeof(font_incmap_t));
                        if (!incmap)
                        {
-                               Con_Printf(CON_ERROR "ERROR: Out of memory when allowcating incremental fontmap for %s\n", font->name);
+                               Con_Printf(CON_ERROR "ERROR: Out of memory when allocating incremental fontmap for %s\n", font->name);
                                return false;
                        }
                        // this will be the startmap of incmap
                        incmap->fontmap = map;
                        incmap->newmap_start = INCMAP_START;
-                       incmap->bytes_per_pixel = bytes_per_pixel;
                }
                else
                {
@@ -1926,27 +1856,6 @@ static qbool Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _ch,
        // update the pic returned by Draw_CachePic_Flags earlier to contain our texture
        update_pic_for_fontmap(map, map_identifier, width, height, data);
 
-       // diskcache deprecated for being complicated to fix and not worthwhile anymore
-#if 0
-       if (r_font_diskcache.integer >= 1 && bytes_per_pixel == 4 && !use_incmap)
-       {
-                       // swap to BGRA for tga writing...
-                       int x;
-                       int b;
-                       for (x = 0;x < datasize;x++)
-                       {
-                               b = data[x*4+0];
-                               data[x*4+0] = data[x*4+2];
-                               data[x*4+2] = b;
-                       }
-                       Image_WriteTGABGRA(va(vabuf, sizeof(vabuf), "%s.tga", map_identifier), width, height, data);
-#ifndef USE_GLES2
-               if (r_font_compress.integer && Draw_IsPicLoaded(map->pic))
-                       R_SaveTextureDDSFile(Draw_GetPicTexture(map->pic), va(vabuf, sizeof(vabuf), "dds/%s.dds", map_identifier), r_texture_dds_save.integer < 2, true);
-#endif
-       }
-#endif
-
        if (!Draw_IsPicLoaded(map->pic))
        {
                // if the first try isn't successful, keep it with a broken texture
@@ -1998,7 +1907,7 @@ qbool Font_LoadMapForIndex(ft2_font_t *font, int map_index, Uchar ch, ft2_font_m
        return Font_LoadMap(font, font->font_maps[map_index], ch, outmap, NULL, false);
 }
 
-// legacy font API, please use `Font_GetMapForChar` instead
+// legacy font API. please use `Font_GetMapForChar` instead
 ft2_font_map_t *FontMap_FindForChar(ft2_font_map_t *start, Uchar ch)
 {
        ft2_font_map_t *map = start;