• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2009  Red Hat, Inc.
3  * Copyright © 2011  Google, Inc.
4  *
5  *  This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * 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  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * 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  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Red Hat Author(s): Behdad Esfahbod
26  * Google Author(s): Behdad Esfahbod
27  */
28 
29 #ifndef HB_FONT_PRIVATE_HH
30 #define HB_FONT_PRIVATE_HH
31 
32 #include "hb-private.hh"
33 
34 #include "hb-object-private.hh"
35 #include "hb-face-private.hh"
36 #include "hb-shaper-private.hh"
37 
38 
39 
40 /*
41  * hb_font_funcs_t
42  */
43 
44 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
45   HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
46   HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
47   HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
48   HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
49   HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
50   HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
51   HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
52   HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
53   HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
54   HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
55   HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
56   HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
57   HB_FONT_FUNC_IMPLEMENT (glyph_name) \
58   HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
59   /* ^--- Add new callbacks here */
60 
61 struct hb_font_funcs_t {
62   hb_object_header_t header;
63   ASSERT_POD ();
64 
65   hb_bool_t immutable;
66 
67   struct {
68 #define HB_FONT_FUNC_IMPLEMENT(name) void *name;
69     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
70 #undef HB_FONT_FUNC_IMPLEMENT
71   } user_data;
72 
73   struct {
74 #define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
75     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
76 #undef HB_FONT_FUNC_IMPLEMENT
77   } destroy;
78 
79   /* Don't access these directly.  Call font->get_*() instead. */
80   union get_t {
81     struct get_funcs_t {
82 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
83       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
84 #undef HB_FONT_FUNC_IMPLEMENT
85     } f;
86     void (*array[VAR]) (void);
87   } get;
88 };
89 
90 
91 
92 /*
93  * hb_font_t
94  */
95 
96 struct hb_font_t {
97   hb_object_header_t header;
98   ASSERT_POD ();
99 
100   hb_bool_t immutable;
101 
102   hb_font_t *parent;
103   hb_face_t *face;
104 
105   int x_scale;
106   int y_scale;
107 
108   unsigned int x_ppem;
109   unsigned int y_ppem;
110 
111   /* Font variation coordinates. */
112   unsigned int num_coords;
113   int *coords;
114 
115   hb_font_funcs_t   *klass;
116   void              *user_data;
117   hb_destroy_func_t  destroy;
118 
119   struct hb_shaper_data_t shaper_data;
120 
121 
122   /* Convert from font-space to user-space */
dir_scalehb_font_t123   inline int dir_scale (hb_direction_t direction)
124   { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
em_scale_xhb_font_t125   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
em_scale_yhb_font_t126   inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
em_scalef_xhb_font_t127   inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
em_scalef_yhb_font_t128   inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
em_scale_dirhb_font_t129   inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
130   { return em_scale (v, dir_scale (direction)); }
131 
132   /* Convert from parent-font user-space to our user-space */
parent_scale_x_distancehb_font_t133   inline hb_position_t parent_scale_x_distance (hb_position_t v) {
134     if (unlikely (parent && parent->x_scale != x_scale))
135       return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
136     return v;
137   }
parent_scale_y_distancehb_font_t138   inline hb_position_t parent_scale_y_distance (hb_position_t v) {
139     if (unlikely (parent && parent->y_scale != y_scale))
140       return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
141     return v;
142   }
parent_scale_x_positionhb_font_t143   inline hb_position_t parent_scale_x_position (hb_position_t v) {
144     return parent_scale_x_distance (v);
145   }
parent_scale_y_positionhb_font_t146   inline hb_position_t parent_scale_y_position (hb_position_t v) {
147     return parent_scale_y_distance (v);
148   }
149 
parent_scale_distancehb_font_t150   inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
151     *x = parent_scale_x_distance (*x);
152     *y = parent_scale_y_distance (*y);
153   }
parent_scale_positionhb_font_t154   inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
155     *x = parent_scale_x_position (*x);
156     *y = parent_scale_y_position (*y);
157   }
158 
159 
160   /* Public getters */
161 
162   HB_INTERNAL bool has_func (unsigned int i);
163 
164   /* has_* ... */
165 #define HB_FONT_FUNC_IMPLEMENT(name) \
166   bool \
167   has_##name##_func (void) \
168   { \
169     hb_font_funcs_t *funcs = this->klass; \
170     unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
171     return has_func (i); \
172   }
173   HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
174 #undef HB_FONT_FUNC_IMPLEMENT
175 
get_font_h_extentshb_font_t176   inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
177   {
178     memset (extents, 0, sizeof (*extents));
179     return klass->get.f.font_h_extents (this, user_data,
180 					extents,
181 					klass->user_data.font_h_extents);
182   }
get_font_v_extentshb_font_t183   inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
184   {
185     memset (extents, 0, sizeof (*extents));
186     return klass->get.f.font_v_extents (this, user_data,
187 					extents,
188 					klass->user_data.font_v_extents);
189   }
190 
has_glyphhb_font_t191   inline bool has_glyph (hb_codepoint_t unicode)
192   {
193     hb_codepoint_t glyph;
194     return get_nominal_glyph (unicode, &glyph);
195   }
196 
get_nominal_glyphhb_font_t197   inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
198 				      hb_codepoint_t *glyph)
199   {
200     *glyph = 0;
201     return klass->get.f.nominal_glyph (this, user_data,
202 				       unicode, glyph,
203 				       klass->user_data.nominal_glyph);
204   }
205 
get_variation_glyphhb_font_t206   inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
207 					hb_codepoint_t *glyph)
208   {
209     *glyph = 0;
210     return klass->get.f.variation_glyph (this, user_data,
211 					 unicode, variation_selector, glyph,
212 					 klass->user_data.variation_glyph);
213   }
214 
get_glyph_h_advancehb_font_t215   inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
216   {
217     return klass->get.f.glyph_h_advance (this, user_data,
218 					 glyph,
219 					 klass->user_data.glyph_h_advance);
220   }
221 
get_glyph_v_advancehb_font_t222   inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
223   {
224     return klass->get.f.glyph_v_advance (this, user_data,
225 					 glyph,
226 					 klass->user_data.glyph_v_advance);
227   }
228 
get_glyph_h_originhb_font_t229   inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
230 				       hb_position_t *x, hb_position_t *y)
231   {
232     *x = *y = 0;
233     return klass->get.f.glyph_h_origin (this, user_data,
234 					glyph, x, y,
235 					klass->user_data.glyph_h_origin);
236   }
237 
get_glyph_v_originhb_font_t238   inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
239 				       hb_position_t *x, hb_position_t *y)
240   {
241     *x = *y = 0;
242     return klass->get.f.glyph_v_origin (this, user_data,
243 					glyph, x, y,
244 					klass->user_data.glyph_v_origin);
245   }
246 
get_glyph_h_kerninghb_font_t247   inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
248   {
249     return klass->get.f.glyph_h_kerning (this, user_data,
250 					 left_glyph, right_glyph,
251 					 klass->user_data.glyph_h_kerning);
252   }
253 
get_glyph_v_kerninghb_font_t254   inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
255   {
256     return klass->get.f.glyph_v_kerning (this, user_data,
257 					 top_glyph, bottom_glyph,
258 					 klass->user_data.glyph_v_kerning);
259   }
260 
get_glyph_extentshb_font_t261   inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
262 				      hb_glyph_extents_t *extents)
263   {
264     memset (extents, 0, sizeof (*extents));
265     return klass->get.f.glyph_extents (this, user_data,
266 				       glyph,
267 				       extents,
268 				       klass->user_data.glyph_extents);
269   }
270 
get_glyph_contour_pointhb_font_t271   inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
272 					    hb_position_t *x, hb_position_t *y)
273   {
274     *x = *y = 0;
275     return klass->get.f.glyph_contour_point (this, user_data,
276 					     glyph, point_index,
277 					     x, y,
278 					     klass->user_data.glyph_contour_point);
279   }
280 
get_glyph_namehb_font_t281   inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
282 				   char *name, unsigned int size)
283   {
284     if (size) *name = '\0';
285     return klass->get.f.glyph_name (this, user_data,
286 				    glyph,
287 				    name, size,
288 				    klass->user_data.glyph_name);
289   }
290 
get_glyph_from_namehb_font_t291   inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
292 					hb_codepoint_t *glyph)
293   {
294     *glyph = 0;
295     if (len == -1) len = strlen (name);
296     return klass->get.f.glyph_from_name (this, user_data,
297 					 name, len,
298 					 glyph,
299 					 klass->user_data.glyph_from_name);
300   }
301 
302 
303   /* A bit higher-level, and with fallback */
304 
get_h_extents_with_fallbackhb_font_t305   inline void get_h_extents_with_fallback (hb_font_extents_t *extents)
306   {
307     if (!get_font_h_extents (extents))
308     {
309       extents->ascender = y_scale * .8;
310       extents->descender = extents->ascender - y_scale;
311       extents->line_gap = 0;
312     }
313   }
get_v_extents_with_fallbackhb_font_t314   inline void get_v_extents_with_fallback (hb_font_extents_t *extents)
315   {
316     if (!get_font_v_extents (extents))
317     {
318       extents->ascender = x_scale / 2;
319       extents->descender = extents->ascender - x_scale;
320       extents->line_gap = 0;
321     }
322   }
323 
get_extents_for_directionhb_font_t324   inline void get_extents_for_direction (hb_direction_t direction,
325 					 hb_font_extents_t *extents)
326   {
327     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
328       get_h_extents_with_fallback (extents);
329     else
330       get_v_extents_with_fallback (extents);
331   }
332 
get_glyph_advance_for_directionhb_font_t333   inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
334 					       hb_direction_t direction,
335 					       hb_position_t *x, hb_position_t *y)
336   {
337     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
338       *x = get_glyph_h_advance (glyph);
339       *y = 0;
340     } else {
341       *x = 0;
342       *y = get_glyph_v_advance (glyph);
343     }
344   }
345 
guess_v_origin_minus_h_originhb_font_t346   inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
347 					     hb_position_t *x, hb_position_t *y)
348   {
349     *x = get_glyph_h_advance (glyph) / 2;
350 
351     /* TODO cache this somehow?! */
352     hb_font_extents_t extents;
353     get_h_extents_with_fallback (&extents);
354     *y = extents.ascender;
355   }
356 
get_glyph_h_origin_with_fallbackhb_font_t357   inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
358 						hb_position_t *x, hb_position_t *y)
359   {
360     if (!get_glyph_h_origin (glyph, x, y) &&
361 	 get_glyph_v_origin (glyph, x, y))
362     {
363       hb_position_t dx, dy;
364       guess_v_origin_minus_h_origin (glyph, &dx, &dy);
365       *x -= dx; *y -= dy;
366     }
367   }
get_glyph_v_origin_with_fallbackhb_font_t368   inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
369 						hb_position_t *x, hb_position_t *y)
370   {
371     if (!get_glyph_v_origin (glyph, x, y) &&
372 	 get_glyph_h_origin (glyph, x, y))
373     {
374       hb_position_t dx, dy;
375       guess_v_origin_minus_h_origin (glyph, &dx, &dy);
376       *x += dx; *y += dy;
377     }
378   }
379 
get_glyph_origin_for_directionhb_font_t380   inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
381 					      hb_direction_t direction,
382 					      hb_position_t *x, hb_position_t *y)
383   {
384     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
385       get_glyph_h_origin_with_fallback (glyph, x, y);
386     else
387       get_glyph_v_origin_with_fallback (glyph, x, y);
388   }
389 
add_glyph_h_originhb_font_t390   inline void add_glyph_h_origin (hb_codepoint_t glyph,
391 				  hb_position_t *x, hb_position_t *y)
392   {
393     hb_position_t origin_x, origin_y;
394 
395     get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
396 
397     *x += origin_x;
398     *y += origin_y;
399   }
add_glyph_v_originhb_font_t400   inline void add_glyph_v_origin (hb_codepoint_t glyph,
401 				  hb_position_t *x, hb_position_t *y)
402   {
403     hb_position_t origin_x, origin_y;
404 
405     get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
406 
407     *x += origin_x;
408     *y += origin_y;
409   }
add_glyph_origin_for_directionhb_font_t410   inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
411 					      hb_direction_t direction,
412 					      hb_position_t *x, hb_position_t *y)
413   {
414     hb_position_t origin_x, origin_y;
415 
416     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
417 
418     *x += origin_x;
419     *y += origin_y;
420   }
421 
subtract_glyph_h_originhb_font_t422   inline void subtract_glyph_h_origin (hb_codepoint_t glyph,
423 				       hb_position_t *x, hb_position_t *y)
424   {
425     hb_position_t origin_x, origin_y;
426 
427     get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
428 
429     *x -= origin_x;
430     *y -= origin_y;
431   }
subtract_glyph_v_originhb_font_t432   inline void subtract_glyph_v_origin (hb_codepoint_t glyph,
433 				       hb_position_t *x, hb_position_t *y)
434   {
435     hb_position_t origin_x, origin_y;
436 
437     get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
438 
439     *x -= origin_x;
440     *y -= origin_y;
441   }
subtract_glyph_origin_for_directionhb_font_t442   inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
443 						   hb_direction_t direction,
444 						   hb_position_t *x, hb_position_t *y)
445   {
446     hb_position_t origin_x, origin_y;
447 
448     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
449 
450     *x -= origin_x;
451     *y -= origin_y;
452   }
453 
get_glyph_kerning_for_directionhb_font_t454   inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
455 					       hb_direction_t direction,
456 					       hb_position_t *x, hb_position_t *y)
457   {
458     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
459       *x = get_glyph_h_kerning (first_glyph, second_glyph);
460       *y = 0;
461     } else {
462       *x = 0;
463       *y = get_glyph_v_kerning (first_glyph, second_glyph);
464     }
465   }
466 
get_glyph_extents_for_originhb_font_t467   inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
468 						 hb_direction_t direction,
469 						 hb_glyph_extents_t *extents)
470   {
471     hb_bool_t ret = get_glyph_extents (glyph, extents);
472 
473     if (ret)
474       subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
475 
476     return ret;
477   }
478 
get_glyph_contour_point_for_originhb_font_t479   inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
480 						       hb_direction_t direction,
481 						       hb_position_t *x, hb_position_t *y)
482   {
483     hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
484 
485     if (ret)
486       subtract_glyph_origin_for_direction (glyph, direction, x, y);
487 
488     return ret;
489   }
490 
491   /* Generates gidDDD if glyph has no name. */
492   inline void
glyph_to_stringhb_font_t493   glyph_to_string (hb_codepoint_t glyph,
494 		   char *s, unsigned int size)
495   {
496     if (get_glyph_name (glyph, s, size)) return;
497 
498     if (size && snprintf (s, size, "gid%u", glyph) < 0)
499       *s = '\0';
500   }
501 
502   /* Parses gidDDD and uniUUUU strings automatically. */
503   inline hb_bool_t
glyph_from_stringhb_font_t504   glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
505 		     hb_codepoint_t *glyph)
506   {
507     if (get_glyph_from_name (s, len, glyph)) return true;
508 
509     if (len == -1) len = strlen (s);
510 
511     /* Straight glyph index. */
512     if (hb_codepoint_parse (s, len, 10, glyph))
513       return true;
514 
515     if (len > 3)
516     {
517       /* gidDDD syntax for glyph indices. */
518       if (0 == strncmp (s, "gid", 3) &&
519 	  hb_codepoint_parse (s + 3, len - 3, 10, glyph))
520 	return true;
521 
522       /* uniUUUU and other Unicode character indices. */
523       hb_codepoint_t unichar;
524       if (0 == strncmp (s, "uni", 3) &&
525 	  hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
526 	  get_nominal_glyph (unichar, glyph))
527 	return true;
528     }
529 
530     return false;
531   }
532 
em_scalehb_font_t533   inline hb_position_t em_scale (int16_t v, int scale)
534   {
535     int upem = face->get_upem ();
536     int64_t scaled = v * (int64_t) scale;
537     scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
538     return (hb_position_t) (scaled / upem);
539   }
em_scalefhb_font_t540   inline hb_position_t em_scalef (float v, int scale)
541   {
542     return (hb_position_t) (v * scale / face->get_upem ());
543   }
544 };
545 
546 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
547 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
548 #include "hb-shaper-list.hh"
549 #undef HB_SHAPER_IMPLEMENT
550 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
551 
552 
553 #endif /* HB_FONT_PRIVATE_HH */
554