• 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-font.h"
35 #include "hb-object-private.hh"
36 #include "hb-shaper-private.hh"
37 #include "hb-shape-plan-private.hh"
38 
39 
40 
41 /*
42  * hb_font_funcs_t
43  */
44 
45 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
46   HB_FONT_FUNC_IMPLEMENT (glyph) \
47   HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
48   HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
49   HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
50   HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
51   HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
52   HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
53   HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
54   HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
55   HB_FONT_FUNC_IMPLEMENT (glyph_name) \
56   HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
57   /* ^--- Add new callbacks here */
58 
59 struct hb_font_funcs_t {
60   hb_object_header_t header;
61   ASSERT_POD ();
62 
63   hb_bool_t immutable;
64 
65   /* Don't access these directly.  Call hb_font_get_*() instead. */
66 
67   struct {
68 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
69     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
70 #undef HB_FONT_FUNC_IMPLEMENT
71   } get;
72 
73   struct {
74 #define HB_FONT_FUNC_IMPLEMENT(name) void *name;
75     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
76 #undef HB_FONT_FUNC_IMPLEMENT
77   } user_data;
78 
79   struct {
80 #define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
81     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
82 #undef HB_FONT_FUNC_IMPLEMENT
83   } destroy;
84 };
85 
86 
87 /*
88  * hb_face_t
89  */
90 
91 struct hb_face_t {
92   hb_object_header_t header;
93   ASSERT_POD ();
94 
95   hb_bool_t immutable;
96 
97   hb_reference_table_func_t  reference_table_func;
98   void                      *user_data;
99   hb_destroy_func_t          destroy;
100 
101   unsigned int index;
102   mutable unsigned int upem;
103   mutable unsigned int num_glyphs;
104 
105   struct hb_shaper_data_t shaper_data;
106 
107   struct plan_node_t {
108     hb_shape_plan_t *shape_plan;
109     plan_node_t *next;
110   } *shape_plans;
111 
112 
reference_tablehb_face_t113   inline hb_blob_t *reference_table (hb_tag_t tag) const
114   {
115     hb_blob_t *blob;
116 
117     if (unlikely (!this || !reference_table_func))
118       return hb_blob_get_empty ();
119 
120     blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
121     if (unlikely (!blob))
122       return hb_blob_get_empty ();
123 
124     return blob;
125   }
126 
get_upemhb_face_t127   inline unsigned int get_upem (void) const
128   {
129     if (unlikely (!upem))
130       load_upem ();
131     return upem;
132   }
133 
get_num_glyphshb_face_t134   inline unsigned int get_num_glyphs (void) const
135   {
136     if (unlikely (num_glyphs == (unsigned int) -1))
137       load_num_glyphs ();
138     return num_glyphs;
139   }
140 
141   private:
142   HB_INTERNAL void load_upem (void) const;
143   HB_INTERNAL void load_num_glyphs (void) const;
144 };
145 
146 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
147 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);
148 #include "hb-shaper-list.hh"
149 #undef HB_SHAPER_IMPLEMENT
150 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
151 
152 
153 /*
154  * hb_font_t
155  */
156 
157 struct hb_font_t {
158   hb_object_header_t header;
159   ASSERT_POD ();
160 
161   hb_bool_t immutable;
162 
163   hb_font_t *parent;
164   hb_face_t *face;
165 
166   int x_scale;
167   int y_scale;
168 
169   unsigned int x_ppem;
170   unsigned int y_ppem;
171 
172   hb_font_funcs_t   *klass;
173   void              *user_data;
174   hb_destroy_func_t  destroy;
175 
176   struct hb_shaper_data_t shaper_data;
177 
178 
179   /* Convert from font-space to user-space */
em_scale_xhb_font_t180   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
em_scale_yhb_font_t181   inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
182 
183   /* Convert from parent-font user-space to our user-space */
parent_scale_x_distancehb_font_t184   inline hb_position_t parent_scale_x_distance (hb_position_t v) {
185     if (unlikely (parent && parent->x_scale != x_scale))
186       return v * (int64_t) this->x_scale / this->parent->x_scale;
187     return v;
188   }
parent_scale_y_distancehb_font_t189   inline hb_position_t parent_scale_y_distance (hb_position_t v) {
190     if (unlikely (parent && parent->y_scale != y_scale))
191       return v * (int64_t) this->y_scale / this->parent->y_scale;
192     return v;
193   }
parent_scale_x_positionhb_font_t194   inline hb_position_t parent_scale_x_position (hb_position_t v) {
195     return parent_scale_x_distance (v);
196   }
parent_scale_y_positionhb_font_t197   inline hb_position_t parent_scale_y_position (hb_position_t v) {
198     return parent_scale_y_distance (v);
199   }
200 
parent_scale_distancehb_font_t201   inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
202     *x = parent_scale_x_distance (*x);
203     *y = parent_scale_y_distance (*y);
204   }
parent_scale_positionhb_font_t205   inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
206     *x = parent_scale_x_position (*x);
207     *y = parent_scale_y_position (*y);
208   }
209 
210 
211   /* Public getters */
212 
get_glyphhb_font_t213   inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
214 			      hb_codepoint_t *glyph)
215   {
216     *glyph = 0;
217     return klass->get.glyph (this, user_data,
218 			     unicode, variation_selector, glyph,
219 			     klass->user_data.glyph);
220   }
221 
get_glyph_h_advancehb_font_t222   inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
223   {
224     return klass->get.glyph_h_advance (this, user_data,
225 				       glyph,
226 				       klass->user_data.glyph_h_advance);
227   }
228 
get_glyph_v_advancehb_font_t229   inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
230   {
231     return klass->get.glyph_v_advance (this, user_data,
232 				       glyph,
233 				       klass->user_data.glyph_v_advance);
234   }
235 
get_glyph_h_originhb_font_t236   inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
237 				       hb_position_t *x, hb_position_t *y)
238   {
239     *x = *y = 0;
240     return klass->get.glyph_h_origin (this, user_data,
241 				      glyph, x, y,
242 				      klass->user_data.glyph_h_origin);
243   }
244 
get_glyph_v_originhb_font_t245   inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
246 				       hb_position_t *x, hb_position_t *y)
247   {
248     *x = *y = 0;
249     return klass->get.glyph_v_origin (this, user_data,
250 				      glyph, x, y,
251 				      klass->user_data.glyph_v_origin);
252   }
253 
get_glyph_h_kerninghb_font_t254   inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
255   {
256     return klass->get.glyph_h_kerning (this, user_data,
257 				       left_glyph, right_glyph,
258 				       klass->user_data.glyph_h_kerning);
259   }
260 
get_glyph_v_kerninghb_font_t261   inline hb_position_t get_glyph_v_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
262   {
263     return klass->get.glyph_v_kerning (this, user_data,
264 				       left_glyph, right_glyph,
265 				       klass->user_data.glyph_v_kerning);
266   }
267 
get_glyph_extentshb_font_t268   inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
269 				      hb_glyph_extents_t *extents)
270   {
271     memset (extents, 0, sizeof (*extents));
272     return klass->get.glyph_extents (this, user_data,
273 				     glyph,
274 				     extents,
275 				     klass->user_data.glyph_extents);
276   }
277 
get_glyph_contour_pointhb_font_t278   inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
279 					    hb_position_t *x, hb_position_t *y)
280   {
281     *x = *y = 0;
282     return klass->get.glyph_contour_point (this, user_data,
283 					   glyph, point_index,
284 					   x, y,
285 					   klass->user_data.glyph_contour_point);
286   }
287 
get_glyph_namehb_font_t288   inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
289 				   char *name, unsigned int size)
290   {
291     if (size) *name = '\0';
292     return klass->get.glyph_name (this, user_data,
293 				  glyph,
294 				  name, size,
295 				  klass->user_data.glyph_name);
296   }
297 
get_glyph_from_namehb_font_t298   inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
299 					hb_codepoint_t *glyph)
300   {
301     *glyph = 0;
302     if (len == -1) len = strlen (name);
303     return klass->get.glyph_from_name (this, user_data,
304 				       name, len,
305 				       glyph,
306 				       klass->user_data.glyph_from_name);
307   }
308 
309 
310   /* A bit higher-level, and with fallback */
311 
get_glyph_advance_for_directionhb_font_t312   inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
313 					       hb_direction_t direction,
314 					       hb_position_t *x, hb_position_t *y)
315   {
316     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
317       *x = get_glyph_h_advance (glyph);
318       *y = 0;
319     } else {
320       *x = 0;
321       *y = get_glyph_v_advance (glyph);
322     }
323   }
324 
325   /* Internal only */
guess_v_origin_minus_h_originhb_font_t326   inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
327 					     hb_position_t *x, hb_position_t *y)
328   {
329     *x = get_glyph_h_advance (glyph) / 2;
330 
331     /* TODO use font_metics.ascent */
332     *y = y_scale;
333   }
334 
get_glyph_origin_for_directionhb_font_t335   inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
336 					      hb_direction_t direction,
337 					      hb_position_t *x, hb_position_t *y)
338   {
339     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
340       hb_bool_t ret = get_glyph_h_origin (glyph, x, y);
341       if (!ret && (ret = get_glyph_v_origin (glyph, x, y))) {
342 	hb_position_t dx, dy;
343 	guess_v_origin_minus_h_origin (glyph, &dx, &dy);
344 	*x -= dx; *y -= dy;
345       }
346     } else {
347       hb_bool_t ret = get_glyph_v_origin (glyph, x, y);
348       if (!ret && (ret = get_glyph_h_origin (glyph, x, y))) {
349 	hb_position_t dx, dy;
350 	guess_v_origin_minus_h_origin (glyph, &dx, &dy);
351 	*x += dx; *y += dy;
352       }
353     }
354   }
355 
add_glyph_origin_for_directionhb_font_t356   inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
357 					      hb_direction_t direction,
358 					      hb_position_t *x, hb_position_t *y)
359   {
360     hb_position_t origin_x, origin_y;
361 
362     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
363 
364     *x += origin_x;
365     *y += origin_y;
366   }
367 
subtract_glyph_origin_for_directionhb_font_t368   inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
369 						   hb_direction_t direction,
370 						   hb_position_t *x, hb_position_t *y)
371   {
372     hb_position_t origin_x, origin_y;
373 
374     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
375 
376     *x -= origin_x;
377     *y -= origin_y;
378   }
379 
get_glyph_kerning_for_directionhb_font_t380   inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_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       *x = get_glyph_h_kerning (first_glyph, second_glyph);
386       *y = 0;
387     } else {
388       *x = 0;
389       *y = get_glyph_v_kerning (first_glyph, second_glyph);
390     }
391   }
392 
get_glyph_extents_for_originhb_font_t393   inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
394 						 hb_direction_t direction,
395 						 hb_glyph_extents_t *extents)
396   {
397     hb_bool_t ret = get_glyph_extents (glyph, extents);
398 
399     if (ret)
400       subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
401 
402     return ret;
403   }
404 
get_glyph_contour_point_for_originhb_font_t405   inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
406 						       hb_direction_t direction,
407 						       hb_position_t *x, hb_position_t *y)
408   {
409     hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
410 
411     if (ret)
412       subtract_glyph_origin_for_direction (glyph, direction, x, y);
413 
414     return ret;
415   }
416 
417   /* Generates gidDDD if glyph has no name. */
418   inline void
glyph_to_stringhb_font_t419   glyph_to_string (hb_codepoint_t glyph,
420 		   char *s, unsigned int size)
421   {
422     if (get_glyph_name (glyph, s, size)) return;
423 
424     snprintf (s, size, "gid%u", glyph);
425   }
426 
427   /* Parses gidDDD and uniUUUU strings automatically. */
428   inline hb_bool_t
glyph_from_stringhb_font_t429   glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
430 		     hb_codepoint_t *glyph)
431   {
432     if (get_glyph_from_name (s, len, glyph)) return true;
433 
434     if (len == -1) len = strlen (s);
435 
436     /* Straight glyph index. */
437     if (hb_codepoint_parse (s, len, 10, glyph))
438       return true;
439 
440     if (len > 3)
441     {
442       /* gidDDD syntax for glyph indices. */
443       if (0 == strncmp (s, "gid", 3) &&
444 	  hb_codepoint_parse (s + 3, len - 3, 10, glyph))
445 	return true;
446 
447       /* uniUUUU and other Unicode character indices. */
448       hb_codepoint_t unichar;
449       if (0 == strncmp (s, "uni", 3) &&
450 	  hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
451 	  get_glyph (unichar, 0, glyph))
452 	return true;
453     }
454 
455     return false;
456   }
457 
458   private:
em_scalehb_font_t459   inline hb_position_t em_scale (int16_t v, int scale) { return v * (int64_t) scale / hb_face_get_upem (this->face); }
460 };
461 
462 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
463 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
464 #include "hb-shaper-list.hh"
465 #undef HB_SHAPER_IMPLEMENT
466 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
467 
468 
469 #endif /* HB_FONT_PRIVATE_HH */
470