OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2009 Red Hat, Inc. | 2 * Copyright © 2009 Red Hat, Inc. |
3 * Copyright © 2009 Keith Stribley | 3 * Copyright © 2009 Keith Stribley |
| 4 * Copyright © 2015 Google, Inc. |
4 * | 5 * |
5 * This is part of HarfBuzz, a text shaping library. | 6 * This is part of HarfBuzz, a text shaping library. |
6 * | 7 * |
7 * Permission is hereby granted, without written agreement and without | 8 * Permission is hereby granted, without written agreement and without |
8 * license or royalty fees, to use, copy, modify, and distribute this | 9 * license or royalty fees, to use, copy, modify, and distribute this |
9 * software and its documentation for any purpose, provided that the | 10 * software and its documentation for any purpose, provided that the |
10 * above copyright notice and the following two paragraphs appear in | 11 * above copyright notice and the following two paragraphs appear in |
11 * all copies of this software. | 12 * all copies of this software. |
12 * | 13 * |
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 14 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | 15 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN | 16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | 17 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
17 * DAMAGE. | 18 * DAMAGE. |
18 * | 19 * |
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | 20 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | 21 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS | 22 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO | 23 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 24 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
24 * | 25 * |
25 * Red Hat Author(s): Behdad Esfahbod | 26 * Red Hat Author(s): Behdad Esfahbod |
| 27 * Google Author(s): Behdad Esfahbod |
26 */ | 28 */ |
27 | 29 |
28 #include "hb-private.hh" | 30 #include "hb-private.hh" |
29 | 31 |
30 #include "hb-ft.h" | 32 #include "hb-ft.h" |
31 | 33 |
32 #include "hb-font-private.hh" | 34 #include "hb-font-private.hh" |
33 | 35 |
34 #include FT_ADVANCES_H | 36 #include FT_ADVANCES_H |
35 #include FT_TRUETYPE_TABLES_H | 37 #include FT_TRUETYPE_TABLES_H |
36 | 38 |
37 | 39 |
38 | 40 |
39 #ifndef HB_DEBUG_FT | 41 #ifndef HB_DEBUG_FT |
40 #define HB_DEBUG_FT (HB_DEBUG+0) | 42 #define HB_DEBUG_FT (HB_DEBUG+0) |
41 #endif | 43 #endif |
42 | 44 |
43 | 45 |
44 /* TODO: | 46 /* TODO: |
45 * | 47 * |
46 * In general, this file does a fine job of what it's supposed to do. | 48 * In general, this file does a fine job of what it's supposed to do. |
47 * There are, however, things that need more work: | 49 * There are, however, things that need more work: |
48 * | 50 * |
49 * - We don't handle any load_flags. That definitely has API implications. :( | 51 * - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be bugg
y. |
50 * I believe hb_ft_font_create() should take load_flags input. | 52 * Have not investigated. |
51 * In particular, FT_Get_Advance() without the NO_HINTING flag seems to be | |
52 * buggy. | |
53 * | 53 * |
54 * FreeType works in 26.6 mode. Clients can decide to use that mode, and ev
erything | 54 * - FreeType works in 26.6 mode. Clients can decide to use that mode, and ev
erything |
55 * would work fine. However, we also abuse this API for performing in font-
space, | 55 * would work fine. However, we also abuse this API for performing in font-
space, |
56 * but don't pass the correct flags to FreeType. We just abuse the no-hinti
ng mode | 56 * but don't pass the correct flags to FreeType. We just abuse the no-hinti
ng mode |
57 * for that, such that no rounding etc happens. As such, we don't set ppem,
and | 57 * for that, such that no rounding etc happens. As such, we don't set ppem,
and |
58 * pass NO_HINTING around. This seems to work best, until we go ahead and a
dd a full | 58 * pass NO_HINTING as load_flags. Would be much better to use NO_SCALE, and
scale |
59 * load_flags API. | 59 * ourselves, like we do in uniscribe, etc. |
60 * | 60 * |
61 * - We don't handle / allow for emboldening / obliqueing. | 61 * - We don't handle / allow for emboldening / obliqueing. |
62 * | 62 * |
63 * - In the future, we should add constructors to create fonts in font space? | 63 * - In the future, we should add constructors to create fonts in font space? |
64 * | 64 * |
65 * - FT_Load_Glyph() is exteremely costly. Do something about it? | 65 * - FT_Load_Glyph() is exteremely costly. Do something about it? |
66 */ | 66 */ |
67 | 67 |
68 | 68 |
| 69 struct hb_ft_font_t |
| 70 { |
| 71 FT_Face ft_face; |
| 72 int load_flags; |
| 73 bool unref; /* Whether to destroy ft_face when done. */ |
| 74 }; |
| 75 |
| 76 static hb_ft_font_t * |
| 77 _hb_ft_font_create (FT_Face ft_face, bool unref) |
| 78 { |
| 79 hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); |
| 80 |
| 81 if (unlikely (!ft_font)) |
| 82 return NULL; |
| 83 |
| 84 ft_font->ft_face = ft_face; |
| 85 ft_font->unref = unref; |
| 86 |
| 87 ft_font->load_flags = FT_LOAD_DEFAULT; |
| 88 |
| 89 return ft_font; |
| 90 } |
| 91 |
| 92 static void |
| 93 _hb_ft_font_destroy (hb_ft_font_t *ft_font) |
| 94 { |
| 95 if (ft_font->unref) |
| 96 FT_Done_Face (ft_font->ft_face); |
| 97 |
| 98 free (ft_font); |
| 99 } |
| 100 |
| 101 /** |
| 102 * hb_ft_font_set_load_flags: |
| 103 * @font: |
| 104 * @load_flags: |
| 105 * |
| 106 * |
| 107 * |
| 108 * Since: 1.0.5 |
| 109 **/ |
| 110 void |
| 111 hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) |
| 112 { |
| 113 if (font->immutable) |
| 114 return; |
| 115 |
| 116 if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) |
| 117 return; |
| 118 |
| 119 hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data; |
| 120 |
| 121 ft_font->load_flags = load_flags; |
| 122 } |
| 123 |
| 124 /** |
| 125 * hb_ft_font_get_load_flags: |
| 126 * @font: |
| 127 * |
| 128 * |
| 129 * |
| 130 * Return value: |
| 131 * Since: 1.0.5 |
| 132 **/ |
| 133 int |
| 134 hb_ft_font_get_load_flags (hb_font_t *font) |
| 135 { |
| 136 if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) |
| 137 return 0; |
| 138 |
| 139 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; |
| 140 |
| 141 return ft_font->load_flags; |
| 142 } |
| 143 |
| 144 FT_Face |
| 145 hb_ft_font_get_face (hb_font_t *font) |
| 146 { |
| 147 if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) |
| 148 return NULL; |
| 149 |
| 150 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; |
| 151 |
| 152 return ft_font->ft_face; |
| 153 } |
| 154 |
| 155 |
| 156 |
69 static hb_bool_t | 157 static hb_bool_t |
70 hb_ft_get_glyph (hb_font_t *font HB_UNUSED, | 158 hb_ft_get_glyph (hb_font_t *font HB_UNUSED, |
71 void *font_data, | 159 void *font_data, |
72 hb_codepoint_t unicode, | 160 hb_codepoint_t unicode, |
73 hb_codepoint_t variation_selector, | 161 hb_codepoint_t variation_selector, |
74 hb_codepoint_t *glyph, | 162 hb_codepoint_t *glyph, |
75 void *user_data HB_UNUSED) | 163 void *user_data HB_UNUSED) |
76 | 164 |
77 { | 165 { |
| 166 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
78 unsigned int g; | 167 unsigned int g; |
79 FT_Face ft_face = (FT_Face) font_data; | |
80 | 168 |
81 if (likely (!variation_selector)) | 169 if (likely (!variation_selector)) |
82 g = FT_Get_Char_Index (ft_face, unicode); | 170 g = FT_Get_Char_Index (ft_font->ft_face, unicode); |
83 else | 171 else |
84 g = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector); | 172 g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_select
or); |
85 | 173 |
86 if (unlikely (!g)) | 174 if (unlikely (!g)) |
87 return false; | 175 return false; |
88 | 176 |
89 *glyph = g; | 177 *glyph = g; |
90 return true; | 178 return true; |
91 } | 179 } |
92 | 180 |
93 static hb_position_t | 181 static hb_position_t |
94 hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED, | 182 hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED, |
95 void *font_data, | 183 void *font_data, |
96 hb_codepoint_t glyph, | 184 hb_codepoint_t glyph, |
97 void *user_data HB_UNUSED) | 185 void *user_data HB_UNUSED) |
98 { | 186 { |
99 FT_Face ft_face = (FT_Face) font_data; | 187 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
100 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; | |
101 FT_Fixed v; | 188 FT_Fixed v; |
102 | 189 |
103 if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) | 190 if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v
))) |
104 return 0; | 191 return 0; |
105 | 192 |
106 if (font->x_scale < 0) | 193 if (font->x_scale < 0) |
107 v = -v; | 194 v = -v; |
108 | 195 |
109 return (v + (1<<9)) >> 10; | 196 return (v + (1<<9)) >> 10; |
110 } | 197 } |
111 | 198 |
112 static hb_position_t | 199 static hb_position_t |
113 hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED, | 200 hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED, |
114 void *font_data, | 201 void *font_data, |
115 hb_codepoint_t glyph, | 202 hb_codepoint_t glyph, |
116 void *user_data HB_UNUSED) | 203 void *user_data HB_UNUSED) |
117 { | 204 { |
118 FT_Face ft_face = (FT_Face) font_data; | 205 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
119 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING | FT_LOAD_VERTICAL_LAYOU
T; | |
120 FT_Fixed v; | 206 FT_Fixed v; |
121 | 207 |
122 if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) | 208 if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | F
T_LOAD_VERTICAL_LAYOUT, &v))) |
123 return 0; | 209 return 0; |
124 | 210 |
125 if (font->y_scale < 0) | 211 if (font->y_scale < 0) |
126 v = -v; | 212 v = -v; |
127 | 213 |
128 /* Note: FreeType's vertical metrics grows downward while other FreeType coord
inates | 214 /* Note: FreeType's vertical metrics grows downward while other FreeType coord
inates |
129 * have a Y growing upward. Hence the extra negation. */ | 215 * have a Y growing upward. Hence the extra negation. */ |
130 return (-v + (1<<9)) >> 10; | 216 return (-v + (1<<9)) >> 10; |
131 } | 217 } |
132 | 218 |
(...skipping 10 matching lines...) Expand all Loading... |
143 } | 229 } |
144 | 230 |
145 static hb_bool_t | 231 static hb_bool_t |
146 hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED, | 232 hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED, |
147 void *font_data, | 233 void *font_data, |
148 hb_codepoint_t glyph, | 234 hb_codepoint_t glyph, |
149 hb_position_t *x, | 235 hb_position_t *x, |
150 hb_position_t *y, | 236 hb_position_t *y, |
151 void *user_data HB_UNUSED) | 237 void *user_data HB_UNUSED) |
152 { | 238 { |
153 FT_Face ft_face = (FT_Face) font_data; | 239 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
154 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; | 240 FT_Face ft_face = ft_font->ft_face; |
155 | 241 |
156 if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) | 242 if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) |
157 return false; | 243 return false; |
158 | 244 |
159 /* Note: FreeType's vertical metrics grows downward while other FreeType coord
inates | 245 /* Note: FreeType's vertical metrics grows downward while other FreeType coord
inates |
160 * have a Y growing upward. Hence the extra negation. */ | 246 * have a Y growing upward. Hence the extra negation. */ |
161 *x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBear
ingX; | 247 *x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBear
ingX; |
162 *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBear
ingY); | 248 *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBear
ingY); |
163 | 249 |
164 if (font->x_scale < 0) | 250 if (font->x_scale < 0) |
165 *x = -*x; | 251 *x = -*x; |
166 if (font->y_scale < 0) | 252 if (font->y_scale < 0) |
167 *y = -*y; | 253 *y = -*y; |
168 | 254 |
169 return true; | 255 return true; |
170 } | 256 } |
171 | 257 |
172 static hb_position_t | 258 static hb_position_t |
173 hb_ft_get_glyph_h_kerning (hb_font_t *font, | 259 hb_ft_get_glyph_h_kerning (hb_font_t *font, |
174 void *font_data, | 260 void *font_data, |
175 hb_codepoint_t left_glyph, | 261 hb_codepoint_t left_glyph, |
176 hb_codepoint_t right_glyph, | 262 hb_codepoint_t right_glyph, |
177 void *user_data HB_UNUSED) | 263 void *user_data HB_UNUSED) |
178 { | 264 { |
179 FT_Face ft_face = (FT_Face) font_data; | 265 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
180 FT_Vector kerningv; | 266 FT_Vector kerningv; |
181 | 267 |
182 FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED
; | 268 FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED
; |
183 if (FT_Get_Kerning (ft_face, left_glyph, right_glyph, mode, &kerningv)) | 269 if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv
)) |
184 return 0; | 270 return 0; |
185 | 271 |
186 return kerningv.x; | 272 return kerningv.x; |
187 } | 273 } |
188 | 274 |
189 static hb_position_t | 275 static hb_position_t |
190 hb_ft_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, | 276 hb_ft_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, |
191 void *font_data HB_UNUSED, | 277 void *font_data HB_UNUSED, |
192 hb_codepoint_t top_glyph HB_UNUSED, | 278 hb_codepoint_t top_glyph HB_UNUSED, |
193 hb_codepoint_t bottom_glyph HB_UNUSED, | 279 hb_codepoint_t bottom_glyph HB_UNUSED, |
194 void *user_data HB_UNUSED) | 280 void *user_data HB_UNUSED) |
195 { | 281 { |
196 /* FreeType API doesn't support vertical kerning */ | 282 /* FreeType API doesn't support vertical kerning */ |
197 return 0; | 283 return 0; |
198 } | 284 } |
199 | 285 |
200 static hb_bool_t | 286 static hb_bool_t |
201 hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED, | 287 hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED, |
202 void *font_data, | 288 void *font_data, |
203 hb_codepoint_t glyph, | 289 hb_codepoint_t glyph, |
204 hb_glyph_extents_t *extents, | 290 hb_glyph_extents_t *extents, |
205 void *user_data HB_UNUSED) | 291 void *user_data HB_UNUSED) |
206 { | 292 { |
207 FT_Face ft_face = (FT_Face) font_data; | 293 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
208 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; | 294 FT_Face ft_face = ft_font->ft_face; |
209 | 295 |
210 if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) | 296 if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) |
211 return false; | 297 return false; |
212 | 298 |
213 extents->x_bearing = ft_face->glyph->metrics.horiBearingX; | 299 extents->x_bearing = ft_face->glyph->metrics.horiBearingX; |
214 extents->y_bearing = ft_face->glyph->metrics.horiBearingY; | 300 extents->y_bearing = ft_face->glyph->metrics.horiBearingY; |
215 extents->width = ft_face->glyph->metrics.width; | 301 extents->width = ft_face->glyph->metrics.width; |
216 extents->height = -ft_face->glyph->metrics.height; | 302 extents->height = -ft_face->glyph->metrics.height; |
217 return true; | 303 return true; |
218 } | 304 } |
219 | 305 |
220 static hb_bool_t | 306 static hb_bool_t |
221 hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED, | 307 hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED, |
222 void *font_data, | 308 void *font_data, |
223 hb_codepoint_t glyph, | 309 hb_codepoint_t glyph, |
224 unsigned int point_index, | 310 unsigned int point_index, |
225 hb_position_t *x, | 311 hb_position_t *x, |
226 hb_position_t *y, | 312 hb_position_t *y, |
227 void *user_data HB_UNUSED) | 313 void *user_data HB_UNUSED) |
228 { | 314 { |
229 FT_Face ft_face = (FT_Face) font_data; | 315 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
230 int load_flags = FT_LOAD_DEFAULT; | 316 FT_Face ft_face = ft_font->ft_face; |
231 | 317 |
232 if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) | 318 if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) |
233 return false; | 319 return false; |
234 | 320 |
235 if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)) | 321 if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)) |
236 return false; | 322 return false; |
237 | 323 |
238 if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points)) | 324 if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points)) |
239 return false; | 325 return false; |
240 | 326 |
241 *x = ft_face->glyph->outline.points[point_index].x; | 327 *x = ft_face->glyph->outline.points[point_index].x; |
242 *y = ft_face->glyph->outline.points[point_index].y; | 328 *y = ft_face->glyph->outline.points[point_index].y; |
243 | 329 |
244 return true; | 330 return true; |
245 } | 331 } |
246 | 332 |
247 static hb_bool_t | 333 static hb_bool_t |
248 hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED, | 334 hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED, |
249 void *font_data, | 335 void *font_data, |
250 hb_codepoint_t glyph, | 336 hb_codepoint_t glyph, |
251 char *name, unsigned int size, | 337 char *name, unsigned int size, |
252 void *user_data HB_UNUSED) | 338 void *user_data HB_UNUSED) |
253 { | 339 { |
254 FT_Face ft_face = (FT_Face) font_data; | 340 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
255 | 341 |
256 hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size); | 342 hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size); |
257 if (ret && (size && !*name)) | 343 if (ret && (size && !*name)) |
258 ret = false; | 344 ret = false; |
259 | 345 |
260 return ret; | 346 return ret; |
261 } | 347 } |
262 | 348 |
263 static hb_bool_t | 349 static hb_bool_t |
264 hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED, | 350 hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED, |
265 void *font_data, | 351 void *font_data, |
266 const char *name, int len, /* -1 means nul-terminated
*/ | 352 const char *name, int len, /* -1 means nul-terminated
*/ |
267 hb_codepoint_t *glyph, | 353 hb_codepoint_t *glyph, |
268 void *user_data HB_UNUSED) | 354 void *user_data HB_UNUSED) |
269 { | 355 { |
270 FT_Face ft_face = (FT_Face) font_data; | 356 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
| 357 FT_Face ft_face = ft_font->ft_face; |
271 | 358 |
272 if (len < 0) | 359 if (len < 0) |
273 *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name); | 360 *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name); |
274 else { | 361 else { |
275 /* Make a nul-terminated version. */ | 362 /* Make a nul-terminated version. */ |
276 char buf[128]; | 363 char buf[128]; |
277 len = MIN (len, (int) sizeof (buf) - 1); | 364 len = MIN (len, (int) sizeof (buf) - 1); |
278 strncpy (buf, name, len); | 365 strncpy (buf, name, len); |
279 buf[len] = '\0'; | 366 buf[len] = '\0'; |
280 *glyph = FT_Get_Name_Index (ft_face, buf); | 367 *glyph = FT_Get_Name_Index (ft_face, buf); |
281 } | 368 } |
282 | 369 |
283 if (*glyph == 0) | 370 if (*glyph == 0) |
284 { | 371 { |
285 /* Check whether the given name was actually the name of glyph 0. */ | 372 /* Check whether the given name was actually the name of glyph 0. */ |
286 char buf[128]; | 373 char buf[128]; |
287 if (!FT_Get_Glyph_Name(ft_face, 0, buf, sizeof (buf)) && | 374 if (!FT_Get_Glyph_Name(ft_face, 0, buf, sizeof (buf)) && |
288 len < 0 ? !strcmp (buf, name) : !strncmp (buf, name, len)) | 375 len < 0 ? !strcmp (buf, name) : !strncmp (buf, name, len)) |
289 return true; | 376 return true; |
290 } | 377 } |
291 | 378 |
292 return *glyph != 0; | 379 return *glyph != 0; |
293 } | 380 } |
294 | 381 |
295 | 382 |
296 static hb_font_funcs_t * | 383 static void |
297 _hb_ft_get_font_funcs (void) | 384 _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref) |
298 { | 385 { |
299 static const hb_font_funcs_t ft_ffuncs = { | 386 static const hb_font_funcs_t ft_ffuncs = { |
300 HB_OBJECT_HEADER_STATIC, | 387 HB_OBJECT_HEADER_STATIC, |
301 | 388 |
302 true, /* immutable */ | 389 true, /* immutable */ |
303 | 390 |
304 { | 391 { |
305 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name, | 392 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name, |
306 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS | 393 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS |
307 #undef HB_FONT_FUNC_IMPLEMENT | 394 #undef HB_FONT_FUNC_IMPLEMENT |
308 } | 395 } |
309 }; | 396 }; |
310 | 397 |
311 return const_cast<hb_font_funcs_t *> (&ft_ffuncs); | 398 hb_font_set_funcs (font, |
| 399 » » const_cast<hb_font_funcs_t *> (&ft_ffuncs), |
| 400 » » _hb_ft_font_create (ft_face, unref), |
| 401 » » (hb_destroy_func_t) _hb_ft_font_destroy); |
312 } | 402 } |
313 | 403 |
314 | 404 |
315 static hb_blob_t * | 405 static hb_blob_t * |
316 reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) | 406 reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) |
317 { | 407 { |
318 FT_Face ft_face = (FT_Face) user_data; | 408 FT_Face ft_face = (FT_Face) user_data; |
319 FT_Byte *buffer; | 409 FT_Byte *buffer; |
320 FT_ULong length = 0; | 410 FT_ULong length = 0; |
321 FT_Error error; | 411 FT_Error error; |
(...skipping 18 matching lines...) Expand all Loading... |
340 } | 430 } |
341 | 431 |
342 /** | 432 /** |
343 * hb_ft_face_create: | 433 * hb_ft_face_create: |
344 * @ft_face: (destroy destroy) (scope notified): | 434 * @ft_face: (destroy destroy) (scope notified): |
345 * @destroy: | 435 * @destroy: |
346 * | 436 * |
347 * | 437 * |
348 * | 438 * |
349 * Return value: (transfer full): | 439 * Return value: (transfer full): |
350 * Since: 1.0 | 440 * Since: 0.9.2 |
351 **/ | 441 **/ |
352 hb_face_t * | 442 hb_face_t * |
353 hb_ft_face_create (FT_Face ft_face, | 443 hb_ft_face_create (FT_Face ft_face, |
354 hb_destroy_func_t destroy) | 444 hb_destroy_func_t destroy) |
355 { | 445 { |
356 hb_face_t *face; | 446 hb_face_t *face; |
357 | 447 |
358 if (ft_face->stream->read == NULL) { | 448 if (ft_face->stream->read == NULL) { |
359 hb_blob_t *blob; | 449 hb_blob_t *blob; |
360 | 450 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 hb_face_destroy ((hb_face_t *) ft_face->generic.data); | 486 hb_face_destroy ((hb_face_t *) ft_face->generic.data); |
397 } | 487 } |
398 | 488 |
399 /** | 489 /** |
400 * hb_ft_face_create_cached: | 490 * hb_ft_face_create_cached: |
401 * @ft_face: | 491 * @ft_face: |
402 * | 492 * |
403 * | 493 * |
404 * | 494 * |
405 * Return value: (transfer full): | 495 * Return value: (transfer full): |
406 * Since: 1.0 | 496 * Since: 0.9.2 |
407 **/ | 497 **/ |
408 hb_face_t * | 498 hb_face_t * |
409 hb_ft_face_create_cached (FT_Face ft_face) | 499 hb_ft_face_create_cached (FT_Face ft_face) |
410 { | 500 { |
411 if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Gene
ric_Finalizer) hb_ft_face_finalize)) | 501 if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Gene
ric_Finalizer) hb_ft_face_finalize)) |
412 { | 502 { |
413 if (ft_face->generic.finalizer) | 503 if (ft_face->generic.finalizer) |
414 ft_face->generic.finalizer (ft_face); | 504 ft_face->generic.finalizer (ft_face); |
415 | 505 |
416 ft_face->generic.data = hb_ft_face_create (ft_face, NULL); | 506 ft_face->generic.data = hb_ft_face_create (ft_face, NULL); |
417 ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize; | 507 ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize; |
418 } | 508 } |
419 | 509 |
420 return hb_face_reference ((hb_face_t *) ft_face->generic.data); | 510 return hb_face_reference ((hb_face_t *) ft_face->generic.data); |
421 } | 511 } |
422 | 512 |
423 static void | |
424 _do_nothing (void) | |
425 { | |
426 } | |
427 | |
428 | 513 |
429 /** | 514 /** |
430 * hb_ft_font_create: | 515 * hb_ft_font_create: |
431 * @ft_face: (destroy destroy) (scope notified): | 516 * @ft_face: (destroy destroy) (scope notified): |
432 * @destroy: | 517 * @destroy: |
433 * | 518 * |
434 * | 519 * |
435 * | 520 * |
436 * Return value: (transfer full): | 521 * Return value: (transfer full): |
437 * Since: 1.0 | 522 * Since: 0.9.2 |
438 **/ | 523 **/ |
439 hb_font_t * | 524 hb_font_t * |
440 hb_ft_font_create (FT_Face ft_face, | 525 hb_ft_font_create (FT_Face ft_face, |
441 hb_destroy_func_t destroy) | 526 hb_destroy_func_t destroy) |
442 { | 527 { |
443 hb_font_t *font; | 528 hb_font_t *font; |
444 hb_face_t *face; | 529 hb_face_t *face; |
445 | 530 |
446 face = hb_ft_face_create (ft_face, destroy); | 531 face = hb_ft_face_create (ft_face, destroy); |
447 font = hb_font_create (face); | 532 font = hb_font_create (face); |
448 hb_face_destroy (face); | 533 hb_face_destroy (face); |
449 hb_font_set_funcs (font, | 534 _hb_ft_font_set_funcs (font, ft_face, false); |
450 » » _hb_ft_get_font_funcs (), | |
451 » » ft_face, (hb_destroy_func_t) _do_nothing); | |
452 hb_font_set_scale (font, | 535 hb_font_set_scale (font, |
453 (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16), | 536 (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16), |
454 (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16)); | 537 (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16)); |
455 #if 0 /* hb-ft works in no-hinting model */ | 538 #if 0 /* hb-ft works in no-hinting model */ |
456 hb_font_set_ppem (font, | 539 hb_font_set_ppem (font, |
457 ft_face->size->metrics.x_ppem, | 540 ft_face->size->metrics.x_ppem, |
458 ft_face->size->metrics.y_ppem); | 541 ft_face->size->metrics.y_ppem); |
459 #endif | 542 #endif |
460 | 543 |
461 return font; | 544 return font; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 if (font->x_scale < 0 || font->y_scale < 0) | 638 if (font->x_scale < 0 || font->y_scale < 0) |
556 { | 639 { |
557 FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, | 640 FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, |
558 0, font->y_scale < 0 ? -1 : +1}; | 641 0, font->y_scale < 0 ? -1 : +1}; |
559 FT_Set_Transform (ft_face, &matrix, NULL); | 642 FT_Set_Transform (ft_face, &matrix, NULL); |
560 } | 643 } |
561 | 644 |
562 ft_face->generic.data = blob; | 645 ft_face->generic.data = blob; |
563 ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; | 646 ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; |
564 | 647 |
565 hb_font_set_funcs (font, | 648 _hb_ft_font_set_funcs (font, ft_face, true); |
566 » » _hb_ft_get_font_funcs (), | 649 hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING); |
567 » » ft_face, | |
568 » » (hb_destroy_func_t) FT_Done_Face); | |
569 } | 650 } |
570 | |
571 FT_Face | |
572 hb_ft_font_get_face (hb_font_t *font) | |
573 { | |
574 if (font->destroy == (hb_destroy_func_t) FT_Done_Face || | |
575 font->destroy == (hb_destroy_func_t) _do_nothing) | |
576 return (FT_Face) font->user_data; | |
577 | |
578 return NULL; | |
579 } | |
OLD | NEW |