Imported Upstream version 0.9.3
[platform/upstream/harfbuzz.git] / src / hb-font-private.hh
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
104   struct hb_shaper_data_t shaper_data;
105
106   struct plan_node_t {
107     hb_shape_plan_t *shape_plan;
108     plan_node_t *next;
109   } *shape_plans;
110
111
112   inline hb_blob_t *reference_table (hb_tag_t tag) const
113   {
114     hb_blob_t *blob;
115
116     if (unlikely (!this || !reference_table_func))
117       return hb_blob_get_empty ();
118
119     blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
120     if (unlikely (!blob))
121       return hb_blob_get_empty ();
122
123     return blob;
124   }
125
126   inline unsigned int get_upem (void) const
127   {
128     if (unlikely (!upem))
129       load_upem ();
130     return upem;
131   }
132
133   private:
134   HB_INTERNAL void load_upem (void) const;
135 };
136
137 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
138 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);
139 #include "hb-shaper-list.hh"
140 #undef HB_SHAPER_IMPLEMENT
141 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
142
143
144 /*
145  * hb_font_t
146  */
147
148 struct hb_font_t {
149   hb_object_header_t header;
150   ASSERT_POD ();
151
152   hb_bool_t immutable;
153
154   hb_font_t *parent;
155   hb_face_t *face;
156
157   int x_scale;
158   int y_scale;
159
160   unsigned int x_ppem;
161   unsigned int y_ppem;
162
163   hb_font_funcs_t   *klass;
164   void              *user_data;
165   hb_destroy_func_t  destroy;
166
167   struct hb_shaper_data_t shaper_data;
168
169
170   /* Convert from font-space to user-space */
171   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
172   inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
173
174   /* Convert from parent-font user-space to our user-space */
175   inline hb_position_t parent_scale_x_distance (hb_position_t v) {
176     if (unlikely (parent && parent->x_scale != x_scale))
177       return v * (int64_t) this->x_scale / this->parent->x_scale;
178     return v;
179   }
180   inline hb_position_t parent_scale_y_distance (hb_position_t v) {
181     if (unlikely (parent && parent->y_scale != y_scale))
182       return v * (int64_t) this->y_scale / this->parent->y_scale;
183     return v;
184   }
185   inline hb_position_t parent_scale_x_position (hb_position_t v) {
186     return parent_scale_x_distance (v);
187   }
188   inline hb_position_t parent_scale_y_position (hb_position_t v) {
189     return parent_scale_y_distance (v);
190   }
191
192   inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
193     *x = parent_scale_x_distance (*x);
194     *y = parent_scale_y_distance (*y);
195   }
196   inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
197     *x = parent_scale_x_position (*x);
198     *y = parent_scale_y_position (*y);
199   }
200
201
202   /* Public getters */
203
204   inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
205                               hb_codepoint_t *glyph)
206   {
207     *glyph = 0;
208     return klass->get.glyph (this, user_data,
209                              unicode, variation_selector, glyph,
210                              klass->user_data.glyph);
211   }
212
213   inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
214   {
215     return klass->get.glyph_h_advance (this, user_data,
216                                        glyph,
217                                        klass->user_data.glyph_h_advance);
218   }
219
220   inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
221   {
222     return klass->get.glyph_v_advance (this, user_data,
223                                        glyph,
224                                        klass->user_data.glyph_v_advance);
225   }
226
227   inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
228                                        hb_position_t *x, hb_position_t *y)
229   {
230     *x = *y = 0;
231     return klass->get.glyph_h_origin (this, user_data,
232                                       glyph, x, y,
233                                       klass->user_data.glyph_h_origin);
234   }
235
236   inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
237                                        hb_position_t *x, hb_position_t *y)
238   {
239     *x = *y = 0;
240     return klass->get.glyph_v_origin (this, user_data,
241                                       glyph, x, y,
242                                       klass->user_data.glyph_v_origin);
243   }
244
245   inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
246   {
247     return klass->get.glyph_h_kerning (this, user_data,
248                                        left_glyph, right_glyph,
249                                        klass->user_data.glyph_h_kerning);
250   }
251
252   inline hb_position_t get_glyph_v_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
253   {
254     return klass->get.glyph_v_kerning (this, user_data,
255                                        left_glyph, right_glyph,
256                                        klass->user_data.glyph_v_kerning);
257   }
258
259   inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
260                                       hb_glyph_extents_t *extents)
261   {
262     memset (extents, 0, sizeof (*extents));
263     return klass->get.glyph_extents (this, user_data,
264                                      glyph,
265                                      extents,
266                                      klass->user_data.glyph_extents);
267   }
268
269   inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
270                                             hb_position_t *x, hb_position_t *y)
271   {
272     *x = *y = 0;
273     return klass->get.glyph_contour_point (this, user_data,
274                                            glyph, point_index,
275                                            x, y,
276                                            klass->user_data.glyph_contour_point);
277   }
278
279   inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
280                                    char *name, unsigned int size)
281   {
282     if (size) *name = '\0';
283     return klass->get.glyph_name (this, user_data,
284                                   glyph,
285                                   name, size,
286                                   klass->user_data.glyph_name);
287   }
288
289   inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
290                                         hb_codepoint_t *glyph)
291   {
292     *glyph = 0;
293     if (len == -1) len = strlen (name);
294     return klass->get.glyph_from_name (this, user_data,
295                                        name, len,
296                                        glyph,
297                                        klass->user_data.glyph_from_name);
298   }
299
300
301   /* A bit higher-level, and with fallback */
302
303   inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
304                                                hb_direction_t direction,
305                                                hb_position_t *x, hb_position_t *y)
306   {
307     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
308       *x = get_glyph_h_advance (glyph);
309       *y = 0;
310     } else {
311       *x = 0;
312       *y = get_glyph_v_advance (glyph);
313     }
314   }
315
316   /* Internal only */
317   inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
318                                              hb_position_t *x, hb_position_t *y)
319   {
320     *x = get_glyph_h_advance (glyph) / 2;
321
322     /* TODO use font_metics.ascent */
323     *y = y_scale;
324   }
325
326   inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
327                                               hb_direction_t direction,
328                                               hb_position_t *x, hb_position_t *y)
329   {
330     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
331       hb_bool_t ret = get_glyph_h_origin (glyph, x, y);
332       if (!ret && (ret = get_glyph_v_origin (glyph, x, y))) {
333         hb_position_t dx, dy;
334         guess_v_origin_minus_h_origin (glyph, &dx, &dy);
335         *x -= dx; *y -= dy;
336       }
337     } else {
338       hb_bool_t ret = get_glyph_v_origin (glyph, x, y);
339       if (!ret && (ret = get_glyph_h_origin (glyph, x, y))) {
340         hb_position_t dx, dy;
341         guess_v_origin_minus_h_origin (glyph, &dx, &dy);
342         *x += dx; *y += dy;
343       }
344     }
345   }
346
347   inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
348                                               hb_direction_t direction,
349                                               hb_position_t *x, hb_position_t *y)
350   {
351     hb_position_t origin_x, origin_y;
352
353     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
354
355     *x += origin_x;
356     *y += origin_y;
357   }
358
359   inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
360                                                    hb_direction_t direction,
361                                                    hb_position_t *x, hb_position_t *y)
362   {
363     hb_position_t origin_x, origin_y;
364
365     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
366
367     *x -= origin_x;
368     *y -= origin_y;
369   }
370
371   inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
372                                                hb_direction_t direction,
373                                                hb_position_t *x, hb_position_t *y)
374   {
375     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
376       *x = get_glyph_h_kerning (first_glyph, second_glyph);
377       *y = 0;
378     } else {
379       *x = 0;
380       *y = get_glyph_v_kerning (first_glyph, second_glyph);
381     }
382   }
383
384   inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
385                                                  hb_direction_t direction,
386                                                  hb_glyph_extents_t *extents)
387   {
388     hb_bool_t ret = get_glyph_extents (glyph, extents);
389
390     if (ret)
391       subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
392
393     return ret;
394   }
395
396   inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
397                                                        hb_direction_t direction,
398                                                        hb_position_t *x, hb_position_t *y)
399   {
400     hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
401
402     if (ret)
403       subtract_glyph_origin_for_direction (glyph, direction, x, y);
404
405     return ret;
406   }
407
408   /* Generates gidDDD if glyph has no name. */
409   inline void
410   glyph_to_string (hb_codepoint_t glyph,
411                    char *s, unsigned int size)
412   {
413     if (get_glyph_name (glyph, s, size)) return;
414
415     snprintf (s, size, "gid%u", glyph);
416   }
417
418   /* Parses gidDDD and uniUUUU strings automatically. */
419   inline hb_bool_t
420   glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
421                      hb_codepoint_t *glyph)
422   {
423     if (get_glyph_from_name (s, len, glyph)) return true;
424
425     if (len == -1) len = strlen (s);
426
427     /* Straight glyph index. */
428     if (hb_codepoint_parse (s, len, 10, glyph))
429       return true;
430
431     if (len > 3)
432     {
433       /* gidDDD syntax for glyph indices. */
434       if (0 == strncmp (s, "gid", 3) &&
435           hb_codepoint_parse (s + 3, len - 3, 10, glyph))
436         return true;
437
438       /* uniUUUU and other Unicode character indices. */
439       hb_codepoint_t unichar;
440       if (0 == strncmp (s, "uni", 3) &&
441           hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
442           get_glyph (unichar, 0, glyph))
443         return true;
444     }
445
446     return false;
447   }
448
449   private:
450   inline hb_position_t em_scale (int16_t v, int scale) { return v * (int64_t) scale / hb_face_get_upem (this->face); }
451 };
452
453 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
454 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
455 #include "hb-shaper-list.hh"
456 #undef HB_SHAPER_IMPLEMENT
457 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
458
459
460 #endif /* HB_FONT_PRIVATE_HH */