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 |