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