1 #include <stdint.h> 2 3 #include <ft2build.h> 4 #include FT_FREETYPE_H 5 #include FT_TRUETYPE_TABLES_H 6 7 #if 0 8 #include <freetype/freetype.h> 9 #include <freetype/tttables.h> 10 #endif 11 12 #include <harfbuzz-shaper.h> 13 #include "harfbuzz-unicode.h" 14 15 static HB_Bool 16 hb_freetype_string_to_glyphs(HB_Font font, 17 const HB_UChar16 *chars, hb_uint32 len, 18 HB_Glyph *glyphs, hb_uint32 *numGlyphs, 19 HB_Bool is_rtl) { 20 FT_Face face = (FT_Face) font->userData; 21 if (len > *numGlyphs) 22 return 0; 23 24 size_t i = 0, j = 0; 25 while (i < len) { 26 const uint32_t cp = utf16_to_code_point(chars, len, &i); 27 glyphs[j++] = FT_Get_Char_Index(face, cp); 28 } 29 30 *numGlyphs = j; 31 32 return 1; 33 } 34 35 static void 36 hb_freetype_advances_get(HB_Font font, const HB_Glyph *glyphs, hb_uint32 len, 37 HB_Fixed *advances, int flags) { 38 FT_Face face = (FT_Face) font->userData; 39 40 hb_uint32 i; 41 for (i = 0; i < len; ++i) { 42 const FT_Error error = FT_Load_Glyph(face, glyphs[i], FT_LOAD_DEFAULT); 43 if (error) { 44 advances[i] = 0; 45 continue; 46 } 47 48 advances[i] = face->glyph->advance.x; 49 } 50 } 51 52 static HB_Bool 53 hb_freetype_can_render(HB_Font font, const HB_UChar16 *chars, hb_uint32 len) { 54 FT_Face face = (FT_Face)font->userData; 55 56 size_t i = 0; 57 while (i < len) { 58 const uint32_t cp = utf16_to_code_point(chars, len, &i); 59 if (FT_Get_Char_Index(face, cp) == 0) 60 return 0; 61 } 62 63 return 1; 64 } 65 66 static HB_Error 67 hb_freetype_outline_point_get(HB_Font font, HB_Glyph glyph, int flags, 68 hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, 69 hb_uint32 *n_points) { 70 HB_Error error = HB_Err_Ok; 71 FT_Face face = (FT_Face) font->userData; 72 73 int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT; 74 75 if ((error = (HB_Error) FT_Load_Glyph(face, glyph, load_flags))) 76 return error; 77 78 if (face->glyph->format != ft_glyph_format_outline) 79 return (HB_Error)HB_Err_Invalid_SubTable; 80 81 *n_points = face->glyph->outline.n_points; 82 if (!(*n_points)) 83 return HB_Err_Ok; 84 85 if (point > *n_points) 86 return (HB_Error)HB_Err_Invalid_SubTable; 87 88 *xpos = face->glyph->outline.points[point].x; 89 *ypos = face->glyph->outline.points[point].y; 90 91 return HB_Err_Ok; 92 } 93 94 static void 95 hb_freetype_glyph_metrics_get(HB_Font font, HB_Glyph glyph, 96 HB_GlyphMetrics *metrics) { 97 FT_Face face = (FT_Face) font->userData; 98 99 const FT_Error error = FT_Load_Glyph(face, glyph, FT_LOAD_DEFAULT); 100 if (error) { 101 metrics->x = metrics->y = metrics->width = metrics->height = 0; 102 metrics->xOffset = metrics->yOffset = 0; 103 return; 104 } 105 106 const FT_Glyph_Metrics *ftmetrics = &face->glyph->metrics; 107 metrics->width = ftmetrics->width; 108 metrics->height = ftmetrics->height; 109 metrics->x = ftmetrics->horiAdvance; 110 metrics->y = 0; // unclear what this is 111 metrics->xOffset = ftmetrics->horiBearingX; 112 metrics->yOffset = ftmetrics->horiBearingY; 113 } 114 115 static HB_Fixed 116 hb_freetype_font_metric_get(HB_Font font, HB_FontMetric metric) { 117 FT_Face face = (FT_Face) font->userData; 118 119 switch (metric) { 120 case HB_FontAscent: 121 // Note that we aren't scanning the VDMX table which we probably would in 122 // an ideal world. 123 return face->ascender; 124 default: 125 return 0; 126 } 127 } 128 129 const HB_FontClass hb_freetype_class = { 130 hb_freetype_string_to_glyphs, 131 hb_freetype_advances_get, 132 hb_freetype_can_render, 133 hb_freetype_outline_point_get, 134 hb_freetype_glyph_metrics_get, 135 hb_freetype_font_metric_get, 136 }; 137 138 HB_Error 139 hb_freetype_table_sfnt_get(void *voidface, const HB_Tag tag, HB_Byte *buffer, HB_UInt *len) { 140 FT_Face face = (FT_Face) voidface; 141 FT_ULong ftlen = *len; 142 143 if (!FT_IS_SFNT(face)) 144 return HB_Err_Invalid_Argument; 145 146 const FT_Error error = FT_Load_Sfnt_Table(face, tag, 0, buffer, &ftlen); 147 *len = ftlen; 148 return (HB_Error) error; 149 } 150