48fbb0ee54931990bc8089e7791500bac2fcdd4b
[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   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
113   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
127   inline unsigned int get_upem (void) const
128   {
129     if (unlikely (!upem))
130       load_upem ();
131     return upem;
132   }
133
134   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 */
180   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
181   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 */
184   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   }
189   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   }
194   inline hb_position_t parent_scale_x_position (hb_position_t v) {
195     return parent_scale_x_distance (v);
196   }
197   inline hb_position_t parent_scale_y_position (hb_position_t v) {
198     return parent_scale_y_distance (v);
199   }
200
201   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   }
205   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
213   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
222   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
229   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
236   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
245   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
254   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
261   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
268   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
278   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
288   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
298   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
312   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 */
326   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
335   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
356   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
368   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
380   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
393   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
405   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
419   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
429   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:
459   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 */