Hi everyone, I have been trying to use FreeType to render emojis. The goal was to see how FreeType handles CBDT based fonts (by stepping through the code in GDB) in the hope that it'd give me a better idea of how it'll handle OT-SVG fonts. However, I couldn't make it work. Following is a description of the whole issue. The code necessary to reproduce the case is attached.
*What am I trying to do here?* I am trying to render emojis from a font called `joypixels-android'. You can get the font file here <https://www.joypixels.com/download>. It's `JoyPixels 4.5 Free' and I am using the font file that can be found in the `Android' folder of the zip that you'll download from the site. *How am I trying to do it?* You can find the code in `hello.c' and compile it using `Makefile'. After getting through the boiler plate, all I am doing is using `FT_Get_First_Char' and `FT_Get_Next_Char' to get all the `charcodes' and their corresponding `glyph indexes'. For each such pair, I am calling `FT_Load_Glyph' and then `FT_Render_Glyph'. In the code you'll see that I am calling `FT_Set_Char_Size' to set the size. Not sure if it makes any sense with `CBDT' fonts, but I have tried removing it. The problem stays! *What's the problem?* If I call `FT_Set_Char_Size' in the program, it returns error code 0x17 which is `Invalid Pixel Size'. Secondly, `FT_Load_Glyph' returns error code 0x24 which is `Invalid Size Handle'. `FT_Load_Glyph' returns the same even if I don't call `FT_Set_Char_Size' at all. *Where are the errors coming from?* The error 0x17, `Invalid Pixel Size' coming from `FT_Set_Char_Size' comes from the function `FT_Match_Size' which is in `./src/base/ftobjs.c:2924'. The trace message: "FT_Match_Size: no matching bitmap strike" also comes up. The error 0x24, `Invalid Size Handle' comes from `TT_Load_Glyph' which is in `./src/truetype/ttgload.c:2718'. More specifically from the following lines: > 2831 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ > 2832 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid > ) > 2833 { > 2834 error = FT_THROW( Invalid_Size_Handle ); > 2835 goto Exit; > 2836 } > 2837 *My guess, so far?* Something that really seems suspicious is that the my code doesn't make into this `if' statement, while the comment indicates it should. The snippet is from `TT_Load_Glyph' which is in `./src/truetype/ttgload.c:2718': > 2733 /* try to load embedded bitmap (if any) */ > 2734 if ( size->strike_index != 0xFFFFFFFFUL && > 2735 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && > 2736 IS_DEFAULT_INSTANCE ) > 2737 { The reason why it doesn't do this is `size->strike_index' has the value `0x 0xFFFFFFFFUL'. So I tried to follow the code to see why strike index was being set to this value. Turns out, it's set to this value at the time when the `face->size' object is created. My guess is, some code in between calling `FT_New_Face' and `FT_Load_Glyph' is supposed to set this strike index. Maybe this should have happened in `FT_Set_Char_Size' but it also runs into an error before reaching that point, as I have already mentioned. *Files attached* 1. *hello.c:* The main code 2. *Makefile: *The Makefile for linking it to the FreeType I have installed on my machine 3. *Makefile-debug: *The Makefile I am using to link it with a gdb debuggable build of FreeType with tracing enabled. 4. *trace.txt: *Contains a very verbose trace of the program. I have removed the last lines because they were simple repetitions (due to the while loop). *Notes:* 1. I am linking against `FreeType 2.10.0' 2. I am getting the same issue with any other emoji font I can find. Please feel free to ask me for more details. :) Thank you, Moazin
FT_Open_Face: Requesting face 0 FT_Stream_Open: opened `joypixels-android.ttf' (19316880 bytes) successfully TTF driver SFNT driver sfnt_open_font: synthesize TTC sfnt_init_face: 0x56509a668ce0 (index 0) tt_face_load_font_dir: 0x56509a668ce0 FT_Stream_EnterFrame: 8 bytes FT_Stream_ExitFrame -- Number of tables: 13 -- Format version: 0x00010000 FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 16 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 208 bytes tag offset length checksum ---------------------------------- CBDT 0000319c 0125e938 5ce48f7b CBLC 01261ad4 00002a34 4d89db91 GSUB 01264508 0000669a e1dde4fc OS/2 00000158 00000060 760467d7 cmap 00002090 00000e15 91b90627 head 000000dc 00000036 0f49bed9 hhea 00000114 00000024 11640d0f hmtx 000001b8 00001ed8 2c020000 maxp 00000138 00000020 0aa40039 name 00002ea8 000002d2 3af3706e post 0000317c 00000020 fb270084 vhea 0126aba4 00000024 0e5e04cc vmtx 0126abc8 000014c6 13880000 FT_Stream_ExitFrame table directory loaded tt_face_lookup_table: 0x56509a668ce0, `fvar' -- could not find table tt_face_lookup_table: 0x56509a668ce0, `glyf' -- could not find table tt_face_lookup_table: 0x56509a668ce0, `CFF2' -- could not find table tt_face_lookup_table: 0x56509a668ce0, `CFF ' -- could not find table sfnt_load_face: 0x56509a668ce0 tt_face_lookup_table: 0x56509a668ce0, `glyf' -- could not find table tt_face_lookup_table: 0x56509a668ce0, `CFF ' -- could not find table tt_face_lookup_table: 0x56509a668ce0, `CFF2' -- could not find table tt_face_lookup_table: 0x56509a668ce0, `sbix' -- could not find table `bhed' --> tt_face_lookup_table: 0x56509a668ce0, `bhed' -- could not find table missing `head' --> tt_face_lookup_table: 0x56509a668ce0, `head' -- found table. FT_Stream_EnterFrame: 54 bytes FT_Stream_ExitFrame Units per EM: 2048 IndexToLoc: 0 loaded tt_face_lookup_table: 0x56509a668ce0, `CBLC' -- found table. tt_face_lookup_table: 0x56509a668ce0, `CBDT' -- found table. `maxp' --> tt_face_lookup_table: 0x56509a668ce0, `maxp' -- found table. FT_Stream_EnterFrame: 6 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 26 bytes FT_Stream_ExitFrame numGlyphs: 2656 loaded `cmap' --> tt_face_lookup_table: 0x56509a668ce0, `cmap' -- found table. FT_Stream_EnterFrame: 3605 bytes loaded `name' --> tt_face_lookup_table: 0x56509a668ce0, `name' -- found table. FT_Stream_EnterFrame: 6 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 180 bytes FT_Stream_ExitFrame loaded `post' --> tt_face_lookup_table: 0x56509a668ce0, `post' -- found table. FT_Stream_EnterFrame: 32 bytes FT_Stream_ExitFrame FormatType: 0x30000 isFixedPitch: yes loaded `hhea' --> tt_face_lookup_table: 0x56509a668ce0, `hhea' -- found table. FT_Stream_EnterFrame: 36 bytes FT_Stream_ExitFrame Ascender: 1900 Descender: -500 number_Of_Metrics: 1292 loaded `hmtx' --> tt_face_lookup_table: 0x56509a668ce0, `hmtx' -- found table. loaded `vertical hhea' --> tt_face_lookup_table: 0x56509a668ce0, `vhea' -- found table. FT_Stream_EnterFrame: 36 bytes FT_Stream_ExitFrame Ascender: 1275 Descender: -1275 number_Of_Metrics: 3 loaded `vertical hmtx' --> tt_face_lookup_table: 0x56509a668ce0, `vmtx' -- found table. loaded `os2' --> tt_face_lookup_table: 0x56509a668ce0, `OS/2' -- found table. FT_Stream_EnterFrame: 78 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 8 bytes FT_Stream_ExitFrame FT_Stream_EnterFrame: 10 bytes FT_Stream_ExitFrame sTypoAscender: 1900 sTypoDescender: -500 usWinAscent: 1900 usWinDescent: 500 fsSelection: 0x40 loaded `eblc' --> tt_face_lookup_table: 0x56509a668ce0, `CBLC' -- found table. FT_Stream_EnterFrame: 10804 bytes tt_face_load_sbit_strikes: found 1 strikes tt_face_lookup_table: 0x56509a668ce0, `CBDT' -- found table. loaded `cpal' --> tt_face_lookup_table: 0x56509a668ce0, `CPAL' -- could not find table missing `colr' --> failed to load `pclt' --> tt_face_lookup_table: 0x56509a668ce0, `PCLT' -- could not find table missing `gasp' --> tt_face_lookup_table: 0x56509a668ce0, `gasp' -- could not find table missing `kern' --> tt_face_lookup_table: 0x56509a668ce0, `kern' -- could not find table missing sfnt_load_face: done tt_face_lookup_table: 0x56509a668ce0, `hdmx' -- could not find table FT_Open_Face: New face object, adding to list FT_Open_Face: Creating glyph slot FT_New_GlyphSlot: Creating new slot object FT_New_GlyphSlot: Return 0x0 FT_Open_Face: Creating size object FT_Open_Face: Return 0x0 FT_Match_Size: no matching bitmap strike FT_Request_Size (truetype driver): x scale: 65536 (1.000000) y scale: 65536 (1.000000) ascender: 0.000000 descender: 0.000000 height: 0.000000 max advance: 0.000000 x ppem: 0 y ppem: 0 TT_Load_Glyph: glyph index 1 failed (error code 0x24) TT_Load_Glyph: glyph index 2 failed (error code 0x24) TT_Load_Glyph: glyph index 3 failed (error code 0x24) TT_Load_Glyph: glyph index 4 failed (error code 0x24) TT_Load_Glyph: glyph index 5 failed (error code 0x24) TT_Load_Glyph: glyph index 6 failed (error code 0x24) TT_Load_Glyph: glyph index 7 failed (error code 0x24) TT_Load_Glyph: glyph index 8 failed (error code 0x24) TT_Load_Glyph: glyph index 9 failed (error code 0x24) TT_Load_Glyph: glyph index 10 failed (error code 0x24) [...]
Makefile
Description: Binary data
Makefile-debug
Description: Binary data
#include <stdio.h> #include <string.h> #include <ft2build.h> #include FT_FREETYPE_H int main(void){ FT_Library ft; if(FT_Init_FreeType(&ft)){ printf("Error"); return 1; } FT_Face face; if(FT_New_Face(ft, "joypixels-android.ttf", 0, &face)) { printf("Error"); return 1; } FT_Error err = FT_Set_Char_Size(face, 0, 16*64, 300, 300); printf("%d\n", err); FT_ULong charcode; FT_UInt gindex; charcode = FT_Get_First_Char(face, &gindex); while(gindex != 0){ printf("(%lu, %u)\n", charcode, gindex); FT_Error err = FT_Load_Glyph(face, gindex, FT_LOAD_DEFAULT|FT_LOAD_COLOR); printf("%d\n", err); FT_GlyphSlot g = face->glyph; err = FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL); /* Do everything with the glyph here */ charcode = FT_Get_Next_Char(face, charcode, &gindex); } return 0; }
_______________________________________________ Freetype-devel mailing list Freetype-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/freetype-devel