• 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-face-private.hh"
37 #include "hb-shaper-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 /*
89  * hb_font_t
90  */
91 
92 struct hb_font_t {
93   hb_object_header_t header;
94   ASSERT_POD ();
95 
96   hb_bool_t immutable;
97 
98   hb_font_t *parent;
99   hb_face_t *face;
100 
101   int x_scale;
102   int y_scale;
103 
104   unsigned int x_ppem;
105   unsigned int y_ppem;
106 
107   hb_font_funcs_t   *klass;
108   void              *user_data;
109   hb_destroy_func_t  destroy;
110 
111   struct hb_shaper_data_t shaper_data;
112 
113 
114   /* Convert from font-space to user-space */
em_scale_xhb_font_t115   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
em_scale_yhb_font_t116   inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
117 
118   /* Convert from parent-font user-space to our user-space */
parent_scale_x_distancehb_font_t119   inline hb_position_t parent_scale_x_distance (hb_position_t v) {
120     if (unlikely (parent && parent->x_scale != x_scale))
121       return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
122     return v;
123   }
parent_scale_y_distancehb_font_t124   inline hb_position_t parent_scale_y_distance (hb_position_t v) {
125     if (unlikely (parent && parent->y_scale != y_scale))
126       return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
127     return v;
128   }
parent_scale_x_positionhb_font_t129   inline hb_position_t parent_scale_x_position (hb_position_t v) {
130     return parent_scale_x_distance (v);
131   }
parent_scale_y_positionhb_font_t132   inline hb_position_t parent_scale_y_position (hb_position_t v) {
133     return parent_scale_y_distance (v);
134   }
135 
parent_scale_distancehb_font_t136   inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
137     *x = parent_scale_x_distance (*x);
138     *y = parent_scale_y_distance (*y);
139   }
parent_scale_positionhb_font_t140   inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
141     *x = parent_scale_x_position (*x);
142     *y = parent_scale_y_position (*y);
143   }
144 
145 
146   /* Public getters */
147 
get_glyphhb_font_t148   inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
149 			      hb_codepoint_t *glyph)
150   {
151     *glyph = 0;
152     return klass->get.glyph (this, user_data,
153 			     unicode, variation_selector, glyph,
154 			     klass->user_data.glyph);
155   }
156 
get_glyph_h_advancehb_font_t157   inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
158   {
159     return klass->get.glyph_h_advance (this, user_data,
160 				       glyph,
161 				       klass->user_data.glyph_h_advance);
162   }
163 
get_glyph_v_advancehb_font_t164   inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
165   {
166     return klass->get.glyph_v_advance (this, user_data,
167 				       glyph,
168 				       klass->user_data.glyph_v_advance);
169   }
170 
get_glyph_h_originhb_font_t171   inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
172 				       hb_position_t *x, hb_position_t *y)
173   {
174     *x = *y = 0;
175     return klass->get.glyph_h_origin (this, user_data,
176 				      glyph, x, y,
177 				      klass->user_data.glyph_h_origin);
178   }
179 
get_glyph_v_originhb_font_t180   inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
181 				       hb_position_t *x, hb_position_t *y)
182   {
183     *x = *y = 0;
184     return klass->get.glyph_v_origin (this, user_data,
185 				      glyph, x, y,
186 				      klass->user_data.glyph_v_origin);
187   }
188 
get_glyph_h_kerninghb_font_t189   inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
190   {
191     return klass->get.glyph_h_kerning (this, user_data,
192 				       left_glyph, right_glyph,
193 				       klass->user_data.glyph_h_kerning);
194   }
195 
get_glyph_v_kerninghb_font_t196   inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
197   {
198     return klass->get.glyph_v_kerning (this, user_data,
199 				       top_glyph, bottom_glyph,
200 				       klass->user_data.glyph_v_kerning);
201   }
202 
get_glyph_extentshb_font_t203   inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
204 				      hb_glyph_extents_t *extents)
205   {
206     memset (extents, 0, sizeof (*extents));
207     return klass->get.glyph_extents (this, user_data,
208 				     glyph,
209 				     extents,
210 				     klass->user_data.glyph_extents);
211   }
212 
get_glyph_contour_pointhb_font_t213   inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
214 					    hb_position_t *x, hb_position_t *y)
215   {
216     *x = *y = 0;
217     return klass->get.glyph_contour_point (this, user_data,
218 					   glyph, point_index,
219 					   x, y,
220 					   klass->user_data.glyph_contour_point);
221   }
222 
get_glyph_namehb_font_t223   inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
224 				   char *name, unsigned int size)
225   {
226     if (size) *name = '\0';
227     return klass->get.glyph_name (this, user_data,
228 				  glyph,
229 				  name, size,
230 				  klass->user_data.glyph_name);
231   }
232 
get_glyph_from_namehb_font_t233   inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
234 					hb_codepoint_t *glyph)
235   {
236     *glyph = 0;
237     if (len == -1) len = strlen (name);
238     return klass->get.glyph_from_name (this, user_data,
239 				       name, len,
240 				       glyph,
241 				       klass->user_data.glyph_from_name);
242   }
243 
244 
245   /* A bit higher-level, and with fallback */
246 
get_glyph_advance_for_directionhb_font_t247   inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
248 					       hb_direction_t direction,
249 					       hb_position_t *x, hb_position_t *y)
250   {
251     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
252       *x = get_glyph_h_advance (glyph);
253       *y = 0;
254     } else {
255       *x = 0;
256       *y = get_glyph_v_advance (glyph);
257     }
258   }
259 
260   /* Internal only */
guess_v_origin_minus_h_originhb_font_t261   inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
262 					     hb_position_t *x, hb_position_t *y)
263   {
264     *x = get_glyph_h_advance (glyph) / 2;
265 
266     /* TODO use font_metics.ascent */
267     *y = y_scale;
268   }
269 
get_glyph_origin_for_directionhb_font_t270   inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
271 					      hb_direction_t direction,
272 					      hb_position_t *x, hb_position_t *y)
273   {
274     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
275     {
276       if (!get_glyph_h_origin (glyph, x, y) &&
277 	   get_glyph_v_origin (glyph, x, y))
278       {
279 	hb_position_t dx, dy;
280 	guess_v_origin_minus_h_origin (glyph, &dx, &dy);
281 	*x -= dx; *y -= dy;
282       }
283     }
284     else
285     {
286       if (!get_glyph_v_origin (glyph, x, y) &&
287 	   get_glyph_h_origin (glyph, x, y))
288       {
289 	hb_position_t dx, dy;
290 	guess_v_origin_minus_h_origin (glyph, &dx, &dy);
291 	*x += dx; *y += dy;
292       }
293     }
294   }
295 
add_glyph_origin_for_directionhb_font_t296   inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
297 					      hb_direction_t direction,
298 					      hb_position_t *x, hb_position_t *y)
299   {
300     hb_position_t origin_x, origin_y;
301 
302     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
303 
304     *x += origin_x;
305     *y += origin_y;
306   }
307 
subtract_glyph_origin_for_directionhb_font_t308   inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
309 						   hb_direction_t direction,
310 						   hb_position_t *x, hb_position_t *y)
311   {
312     hb_position_t origin_x, origin_y;
313 
314     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
315 
316     *x -= origin_x;
317     *y -= origin_y;
318   }
319 
get_glyph_kerning_for_directionhb_font_t320   inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
321 					       hb_direction_t direction,
322 					       hb_position_t *x, hb_position_t *y)
323   {
324     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
325       *x = get_glyph_h_kerning (first_glyph, second_glyph);
326       *y = 0;
327     } else {
328       *x = 0;
329       *y = get_glyph_v_kerning (first_glyph, second_glyph);
330     }
331   }
332 
get_glyph_extents_for_originhb_font_t333   inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
334 						 hb_direction_t direction,
335 						 hb_glyph_extents_t *extents)
336   {
337     hb_bool_t ret = get_glyph_extents (glyph, extents);
338 
339     if (ret)
340       subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
341 
342     return ret;
343   }
344 
get_glyph_contour_point_for_originhb_font_t345   inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
346 						       hb_direction_t direction,
347 						       hb_position_t *x, hb_position_t *y)
348   {
349     hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
350 
351     if (ret)
352       subtract_glyph_origin_for_direction (glyph, direction, x, y);
353 
354     return ret;
355   }
356 
357   /* Generates gidDDD if glyph has no name. */
358   inline void
glyph_to_stringhb_font_t359   glyph_to_string (hb_codepoint_t glyph,
360 		   char *s, unsigned int size)
361   {
362     if (get_glyph_name (glyph, s, size)) return;
363 
364     if (size && snprintf (s, size, "gid%u", glyph) < 0)
365       *s = '\0';
366   }
367 
368   /* Parses gidDDD and uniUUUU strings automatically. */
369   inline hb_bool_t
glyph_from_stringhb_font_t370   glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
371 		     hb_codepoint_t *glyph)
372   {
373     if (get_glyph_from_name (s, len, glyph)) return true;
374 
375     if (len == -1) len = strlen (s);
376 
377     /* Straight glyph index. */
378     if (hb_codepoint_parse (s, len, 10, glyph))
379       return true;
380 
381     if (len > 3)
382     {
383       /* gidDDD syntax for glyph indices. */
384       if (0 == strncmp (s, "gid", 3) &&
385 	  hb_codepoint_parse (s + 3, len - 3, 10, glyph))
386 	return true;
387 
388       /* uniUUUU and other Unicode character indices. */
389       hb_codepoint_t unichar;
390       if (0 == strncmp (s, "uni", 3) &&
391 	  hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
392 	  get_glyph (unichar, 0, glyph))
393 	return true;
394     }
395 
396     return false;
397   }
398 
399   private:
em_scalehb_font_t400   inline hb_position_t em_scale (int16_t v, int scale) { return (hb_position_t) (v * (int64_t) scale / face->get_upem ()); }
401 };
402 
403 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
404 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
405 #include "hb-shaper-list.hh"
406 #undef HB_SHAPER_IMPLEMENT
407 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
408 
409 
410 #endif /* HB_FONT_PRIVATE_HH */
411