68 |
68 |
69 struct hb_ft_font_t |
69 struct hb_ft_font_t |
70 { |
70 { |
71 FT_Face ft_face; |
71 FT_Face ft_face; |
72 int load_flags; |
72 int load_flags; |
|
73 bool symbol; /* Whether selected cmap is symbol cmap. */ |
73 bool unref; /* Whether to destroy ft_face when done. */ |
74 bool unref; /* Whether to destroy ft_face when done. */ |
74 }; |
75 }; |
75 |
76 |
76 static hb_ft_font_t * |
77 static hb_ft_font_t * |
77 _hb_ft_font_create (FT_Face ft_face, bool unref) |
78 _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) |
78 { |
79 { |
79 hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); |
80 hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); |
80 |
81 |
81 if (unlikely (!ft_font)) |
82 if (unlikely (!ft_font)) |
82 return NULL; |
83 return NULL; |
83 |
84 |
84 ft_font->ft_face = ft_face; |
85 ft_font->ft_face = ft_face; |
|
86 ft_font->symbol = symbol; |
85 ft_font->unref = unref; |
87 ft_font->unref = unref; |
86 |
88 |
87 ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; |
89 ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; |
88 |
90 |
89 return ft_font; |
91 return ft_font; |
|
92 } |
|
93 |
|
94 static void |
|
95 _hb_ft_face_destroy (FT_Face ft_face) |
|
96 { |
|
97 FT_Done_Face (ft_face); |
90 } |
98 } |
91 |
99 |
92 static void |
100 static void |
93 _hb_ft_font_destroy (hb_ft_font_t *ft_font) |
101 _hb_ft_font_destroy (hb_ft_font_t *ft_font) |
94 { |
102 { |
95 if (ft_font->unref) |
103 if (ft_font->unref) |
96 FT_Done_Face (ft_font->ft_face); |
104 _hb_ft_face_destroy (ft_font->ft_face); |
97 |
105 |
98 free (ft_font); |
106 free (ft_font); |
99 } |
107 } |
100 |
108 |
101 /** |
109 /** |
153 } |
161 } |
154 |
162 |
155 |
163 |
156 |
164 |
157 static hb_bool_t |
165 static hb_bool_t |
158 hb_ft_get_glyph (hb_font_t *font HB_UNUSED, |
166 hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED, |
159 void *font_data, |
167 void *font_data, |
160 hb_codepoint_t unicode, |
168 hb_codepoint_t unicode, |
161 hb_codepoint_t variation_selector, |
169 hb_codepoint_t *glyph, |
162 hb_codepoint_t *glyph, |
170 void *user_data HB_UNUSED) |
163 void *user_data HB_UNUSED) |
171 { |
164 |
172 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
165 { |
173 unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode); |
166 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
174 |
167 unsigned int g; |
175 if (unlikely (!g)) |
168 |
176 { |
169 if (likely (!variation_selector)) |
177 if (unlikely (ft_font->symbol) && unicode <= 0x00FFu) |
170 g = FT_Get_Char_Index (ft_font->ft_face, unicode); |
178 { |
171 else |
179 /* For symbol-encoded OpenType fonts, we duplicate the |
172 g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector); |
180 * U+F000..F0FF range at U+0000..U+00FF. That's what |
|
181 * Windows seems to do, and that's hinted about at: |
|
182 * http://www.microsoft.com/typography/otspec/recom.htm |
|
183 * under "Non-Standard (Symbol) Fonts". */ |
|
184 g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode); |
|
185 if (!g) |
|
186 return false; |
|
187 } |
|
188 else |
|
189 return false; |
|
190 } |
|
191 |
|
192 *glyph = g; |
|
193 return true; |
|
194 } |
|
195 |
|
196 static hb_bool_t |
|
197 hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED, |
|
198 void *font_data, |
|
199 hb_codepoint_t unicode, |
|
200 hb_codepoint_t variation_selector, |
|
201 hb_codepoint_t *glyph, |
|
202 void *user_data HB_UNUSED) |
|
203 { |
|
204 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
|
205 unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector); |
173 |
206 |
174 if (unlikely (!g)) |
207 if (unlikely (!g)) |
175 return false; |
208 return false; |
176 |
209 |
177 *glyph = g; |
210 *glyph = g; |
212 v = -v; |
245 v = -v; |
213 |
246 |
214 /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates |
247 /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates |
215 * have a Y growing upward. Hence the extra negation. */ |
248 * have a Y growing upward. Hence the extra negation. */ |
216 return (-v + (1<<9)) >> 10; |
249 return (-v + (1<<9)) >> 10; |
217 } |
|
218 |
|
219 static hb_bool_t |
|
220 hb_ft_get_glyph_h_origin (hb_font_t *font HB_UNUSED, |
|
221 void *font_data HB_UNUSED, |
|
222 hb_codepoint_t glyph HB_UNUSED, |
|
223 hb_position_t *x HB_UNUSED, |
|
224 hb_position_t *y HB_UNUSED, |
|
225 void *user_data HB_UNUSED) |
|
226 { |
|
227 /* We always work in the horizontal coordinates. */ |
|
228 return true; |
|
229 } |
250 } |
230 |
251 |
231 static hb_bool_t |
252 static hb_bool_t |
232 hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED, |
253 hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED, |
233 void *font_data, |
254 void *font_data, |
298 |
308 |
299 extents->x_bearing = ft_face->glyph->metrics.horiBearingX; |
309 extents->x_bearing = ft_face->glyph->metrics.horiBearingX; |
300 extents->y_bearing = ft_face->glyph->metrics.horiBearingY; |
310 extents->y_bearing = ft_face->glyph->metrics.horiBearingY; |
301 extents->width = ft_face->glyph->metrics.width; |
311 extents->width = ft_face->glyph->metrics.width; |
302 extents->height = -ft_face->glyph->metrics.height; |
312 extents->height = -ft_face->glyph->metrics.height; |
|
313 if (font->x_scale < 0) |
|
314 { |
|
315 extents->x_bearing = -extents->x_bearing; |
|
316 extents->width = -extents->width; |
|
317 } |
|
318 if (font->y_scale < 0) |
|
319 { |
|
320 extents->y_bearing = -extents->y_bearing; |
|
321 extents->height = -extents->height; |
|
322 } |
303 return true; |
323 return true; |
304 } |
324 } |
305 |
325 |
306 static hb_bool_t |
326 static hb_bool_t |
307 hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED, |
327 hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED, |
377 } |
397 } |
378 |
398 |
379 return *glyph != 0; |
399 return *glyph != 0; |
380 } |
400 } |
381 |
401 |
|
402 static hb_bool_t |
|
403 hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED, |
|
404 void *font_data, |
|
405 hb_font_extents_t *metrics, |
|
406 void *user_data HB_UNUSED) |
|
407 { |
|
408 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
|
409 FT_Face ft_face = ft_font->ft_face; |
|
410 metrics->ascender = ft_face->size->metrics.ascender; |
|
411 metrics->descender = ft_face->size->metrics.descender; |
|
412 metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender); |
|
413 if (font->y_scale < 0) |
|
414 { |
|
415 metrics->ascender = -metrics->ascender; |
|
416 metrics->descender = -metrics->descender; |
|
417 metrics->line_gap = -metrics->line_gap; |
|
418 } |
|
419 return true; |
|
420 } |
|
421 |
|
422 static hb_font_funcs_t *static_ft_funcs = NULL; |
|
423 |
|
424 #ifdef HB_USE_ATEXIT |
|
425 static |
|
426 void free_static_ft_funcs (void) |
|
427 { |
|
428 hb_font_funcs_destroy (static_ft_funcs); |
|
429 } |
|
430 #endif |
382 |
431 |
383 static void |
432 static void |
384 _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref) |
433 _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref) |
385 { |
434 { |
386 static const hb_font_funcs_t ft_ffuncs = { |
435 retry: |
387 HB_OBJECT_HEADER_STATIC, |
436 hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs); |
388 |
437 |
389 true, /* immutable */ |
438 if (unlikely (!funcs)) |
390 |
439 { |
391 { |
440 funcs = hb_font_funcs_create (); |
392 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name, |
441 |
393 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS |
442 hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, NULL, NULL); |
394 #undef HB_FONT_FUNC_IMPLEMENT |
443 //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, NULL, NULL); |
|
444 hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, NULL, NULL); |
|
445 hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, NULL, NULL); |
|
446 hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL); |
|
447 hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL); |
|
448 //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL); |
|
449 hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, NULL, NULL); |
|
450 hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, NULL, NULL); |
|
451 //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL); |
|
452 hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, NULL, NULL); |
|
453 hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, NULL, NULL); |
|
454 hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, NULL, NULL); |
|
455 hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, NULL, NULL); |
|
456 |
|
457 hb_font_funcs_make_immutable (funcs); |
|
458 |
|
459 if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, NULL, funcs)) { |
|
460 hb_font_funcs_destroy (funcs); |
|
461 goto retry; |
395 } |
462 } |
|
463 |
|
464 #ifdef HB_USE_ATEXIT |
|
465 atexit (free_static_ft_funcs); /* First person registers atexit() callback. */ |
|
466 #endif |
396 }; |
467 }; |
397 |
468 |
|
469 bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL; |
|
470 |
398 hb_font_set_funcs (font, |
471 hb_font_set_funcs (font, |
399 const_cast<hb_font_funcs_t *> (&ft_ffuncs), |
472 funcs, |
400 _hb_ft_font_create (ft_face, unref), |
473 _hb_ft_font_create (ft_face, symbol, unref), |
401 (hb_destroy_func_t) _hb_ft_font_destroy); |
474 (hb_destroy_func_t) _hb_ft_font_destroy); |
402 } |
475 } |
403 |
476 |
404 |
477 |
405 static hb_blob_t * |
478 static hb_blob_t * |