Imported Upstream version 1.8.1
[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-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[0
87 #define HB_FONT_FUNC_IMPLEMENT(name) +1
88       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
89 #undef HB_FONT_FUNC_IMPLEMENT
90                 ]) (void);
91   } get;
92 };
93
94
95
96 /*
97  * hb_font_t
98  */
99
100 struct hb_font_t {
101   hb_object_header_t header;
102   ASSERT_POD ();
103
104   hb_bool_t immutable;
105
106   hb_font_t *parent;
107   hb_face_t *face;
108
109   int x_scale;
110   int y_scale;
111
112   unsigned int x_ppem;
113   unsigned int y_ppem;
114
115   float ptem;
116
117   /* Font variation coordinates. */
118   unsigned int num_coords;
119   int *coords;
120
121   hb_font_funcs_t   *klass;
122   void              *user_data;
123   hb_destroy_func_t  destroy;
124
125   struct hb_shaper_data_t shaper_data;
126
127
128   /* Convert from font-space to user-space */
129   inline int dir_scale (hb_direction_t direction)
130   { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
131   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
132   inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
133   inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
134   inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
135   inline float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
136   inline float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
137   inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
138   { return em_scale (v, dir_scale (direction)); }
139
140   /* Convert from parent-font user-space to our user-space */
141   inline hb_position_t parent_scale_x_distance (hb_position_t v) {
142     if (unlikely (parent && parent->x_scale != x_scale))
143       return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
144     return v;
145   }
146   inline hb_position_t parent_scale_y_distance (hb_position_t v) {
147     if (unlikely (parent && parent->y_scale != y_scale))
148       return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
149     return v;
150   }
151   inline hb_position_t parent_scale_x_position (hb_position_t v) {
152     return parent_scale_x_distance (v);
153   }
154   inline hb_position_t parent_scale_y_position (hb_position_t v) {
155     return parent_scale_y_distance (v);
156   }
157
158   inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
159     *x = parent_scale_x_distance (*x);
160     *y = parent_scale_y_distance (*y);
161   }
162   inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
163     *x = parent_scale_x_position (*x);
164     *y = parent_scale_y_position (*y);
165   }
166
167
168   /* Public getters */
169
170   HB_INTERNAL bool has_func (unsigned int i);
171
172   /* has_* ... */
173 #define HB_FONT_FUNC_IMPLEMENT(name) \
174   bool \
175   has_##name##_func (void) \
176   { \
177     hb_font_funcs_t *funcs = this->klass; \
178     unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
179     return has_func (i); \
180   }
181   HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
182 #undef HB_FONT_FUNC_IMPLEMENT
183
184   inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
185   {
186     memset (extents, 0, sizeof (*extents));
187     return klass->get.f.font_h_extents (this, user_data,
188                                         extents,
189                                         klass->user_data.font_h_extents);
190   }
191   inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
192   {
193     memset (extents, 0, sizeof (*extents));
194     return klass->get.f.font_v_extents (this, user_data,
195                                         extents,
196                                         klass->user_data.font_v_extents);
197   }
198
199   inline bool has_glyph (hb_codepoint_t unicode)
200   {
201     hb_codepoint_t glyph;
202     return get_nominal_glyph (unicode, &glyph);
203   }
204
205   inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
206                                       hb_codepoint_t *glyph)
207   {
208     *glyph = 0;
209     return klass->get.f.nominal_glyph (this, user_data,
210                                        unicode, glyph,
211                                        klass->user_data.nominal_glyph);
212   }
213
214   inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
215                                         hb_codepoint_t *glyph)
216   {
217     *glyph = 0;
218     return klass->get.f.variation_glyph (this, user_data,
219                                          unicode, variation_selector, glyph,
220                                          klass->user_data.variation_glyph);
221   }
222
223   inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
224   {
225     return klass->get.f.glyph_h_advance (this, user_data,
226                                          glyph,
227                                          klass->user_data.glyph_h_advance);
228   }
229
230   inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
231   {
232     return klass->get.f.glyph_v_advance (this, user_data,
233                                          glyph,
234                                          klass->user_data.glyph_v_advance);
235   }
236
237   inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
238                                        hb_position_t *x, hb_position_t *y)
239   {
240     *x = *y = 0;
241     return klass->get.f.glyph_h_origin (this, user_data,
242                                         glyph, x, y,
243                                         klass->user_data.glyph_h_origin);
244   }
245
246   inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
247                                        hb_position_t *x, hb_position_t *y)
248   {
249     *x = *y = 0;
250     return klass->get.f.glyph_v_origin (this, user_data,
251                                         glyph, x, y,
252                                         klass->user_data.glyph_v_origin);
253   }
254
255   inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
256   {
257     return klass->get.f.glyph_h_kerning (this, user_data,
258                                          left_glyph, right_glyph,
259                                          klass->user_data.glyph_h_kerning);
260   }
261
262   inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
263   {
264     return klass->get.f.glyph_v_kerning (this, user_data,
265                                          top_glyph, bottom_glyph,
266                                          klass->user_data.glyph_v_kerning);
267   }
268
269   inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
270                                       hb_glyph_extents_t *extents)
271   {
272     memset (extents, 0, sizeof (*extents));
273     return klass->get.f.glyph_extents (this, user_data,
274                                        glyph,
275                                        extents,
276                                        klass->user_data.glyph_extents);
277   }
278
279   inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
280                                             hb_position_t *x, hb_position_t *y)
281   {
282     *x = *y = 0;
283     return klass->get.f.glyph_contour_point (this, user_data,
284                                              glyph, point_index,
285                                              x, y,
286                                              klass->user_data.glyph_contour_point);
287   }
288
289   inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
290                                    char *name, unsigned int size)
291   {
292     if (size) *name = '\0';
293     return klass->get.f.glyph_name (this, user_data,
294                                     glyph,
295                                     name, size,
296                                     klass->user_data.glyph_name);
297   }
298
299   inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
300                                         hb_codepoint_t *glyph)
301   {
302     *glyph = 0;
303     if (len == -1) len = strlen (name);
304     return klass->get.f.glyph_from_name (this, user_data,
305                                          name, len,
306                                          glyph,
307                                          klass->user_data.glyph_from_name);
308   }
309
310
311   /* A bit higher-level, and with fallback */
312
313   inline void get_h_extents_with_fallback (hb_font_extents_t *extents)
314   {
315     if (!get_font_h_extents (extents))
316     {
317       extents->ascender = y_scale * .8;
318       extents->descender = extents->ascender - y_scale;
319       extents->line_gap = 0;
320     }
321   }
322   inline void get_v_extents_with_fallback (hb_font_extents_t *extents)
323   {
324     if (!get_font_v_extents (extents))
325     {
326       extents->ascender = x_scale / 2;
327       extents->descender = extents->ascender - x_scale;
328       extents->line_gap = 0;
329     }
330   }
331
332   inline void get_extents_for_direction (hb_direction_t direction,
333                                          hb_font_extents_t *extents)
334   {
335     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
336       get_h_extents_with_fallback (extents);
337     else
338       get_v_extents_with_fallback (extents);
339   }
340
341   inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
342                                                hb_direction_t direction,
343                                                hb_position_t *x, hb_position_t *y)
344   {
345     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
346       *x = get_glyph_h_advance (glyph);
347       *y = 0;
348     } else {
349       *x = 0;
350       *y = get_glyph_v_advance (glyph);
351     }
352   }
353
354   inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
355                                              hb_position_t *x, hb_position_t *y)
356   {
357     *x = get_glyph_h_advance (glyph) / 2;
358
359     /* TODO cache this somehow?! */
360     hb_font_extents_t extents;
361     get_h_extents_with_fallback (&extents);
362     *y = extents.ascender;
363   }
364
365   inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
366                                                 hb_position_t *x, hb_position_t *y)
367   {
368     if (!get_glyph_h_origin (glyph, x, y) &&
369          get_glyph_v_origin (glyph, x, y))
370     {
371       hb_position_t dx, dy;
372       guess_v_origin_minus_h_origin (glyph, &dx, &dy);
373       *x -= dx; *y -= dy;
374     }
375   }
376   inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
377                                                 hb_position_t *x, hb_position_t *y)
378   {
379     if (!get_glyph_v_origin (glyph, x, y) &&
380          get_glyph_h_origin (glyph, x, y))
381     {
382       hb_position_t dx, dy;
383       guess_v_origin_minus_h_origin (glyph, &dx, &dy);
384       *x += dx; *y += dy;
385     }
386   }
387
388   inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
389                                               hb_direction_t direction,
390                                               hb_position_t *x, hb_position_t *y)
391   {
392     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
393       get_glyph_h_origin_with_fallback (glyph, x, y);
394     else
395       get_glyph_v_origin_with_fallback (glyph, x, y);
396   }
397
398   inline void add_glyph_h_origin (hb_codepoint_t glyph,
399                                   hb_position_t *x, hb_position_t *y)
400   {
401     hb_position_t origin_x, origin_y;
402
403     get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
404
405     *x += origin_x;
406     *y += origin_y;
407   }
408   inline void add_glyph_v_origin (hb_codepoint_t glyph,
409                                   hb_position_t *x, hb_position_t *y)
410   {
411     hb_position_t origin_x, origin_y;
412
413     get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
414
415     *x += origin_x;
416     *y += origin_y;
417   }
418   inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
419                                               hb_direction_t direction,
420                                               hb_position_t *x, hb_position_t *y)
421   {
422     hb_position_t origin_x, origin_y;
423
424     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
425
426     *x += origin_x;
427     *y += origin_y;
428   }
429
430   inline void subtract_glyph_h_origin (hb_codepoint_t glyph,
431                                        hb_position_t *x, hb_position_t *y)
432   {
433     hb_position_t origin_x, origin_y;
434
435     get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
436
437     *x -= origin_x;
438     *y -= origin_y;
439   }
440   inline void subtract_glyph_v_origin (hb_codepoint_t glyph,
441                                        hb_position_t *x, hb_position_t *y)
442   {
443     hb_position_t origin_x, origin_y;
444
445     get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
446
447     *x -= origin_x;
448     *y -= origin_y;
449   }
450   inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
451                                                    hb_direction_t direction,
452                                                    hb_position_t *x, hb_position_t *y)
453   {
454     hb_position_t origin_x, origin_y;
455
456     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
457
458     *x -= origin_x;
459     *y -= origin_y;
460   }
461
462   inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
463                                                hb_direction_t direction,
464                                                hb_position_t *x, hb_position_t *y)
465   {
466     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
467       *x = get_glyph_h_kerning (first_glyph, second_glyph);
468       *y = 0;
469     } else {
470       *x = 0;
471       *y = get_glyph_v_kerning (first_glyph, second_glyph);
472     }
473   }
474
475   inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
476                                                  hb_direction_t direction,
477                                                  hb_glyph_extents_t *extents)
478   {
479     hb_bool_t ret = get_glyph_extents (glyph, extents);
480
481     if (ret)
482       subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
483
484     return ret;
485   }
486
487   inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
488                                                        hb_direction_t direction,
489                                                        hb_position_t *x, hb_position_t *y)
490   {
491     hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
492
493     if (ret)
494       subtract_glyph_origin_for_direction (glyph, direction, x, y);
495
496     return ret;
497   }
498
499   /* Generates gidDDD if glyph has no name. */
500   inline void
501   glyph_to_string (hb_codepoint_t glyph,
502                    char *s, unsigned int size)
503   {
504     if (get_glyph_name (glyph, s, size)) return;
505
506     if (size && snprintf (s, size, "gid%u", glyph) < 0)
507       *s = '\0';
508   }
509
510   /* Parses gidDDD and uniUUUU strings automatically. */
511   inline hb_bool_t
512   glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
513                      hb_codepoint_t *glyph)
514   {
515     if (get_glyph_from_name (s, len, glyph)) return true;
516
517     if (len == -1) len = strlen (s);
518
519     /* Straight glyph index. */
520     if (hb_codepoint_parse (s, len, 10, glyph))
521       return true;
522
523     if (len > 3)
524     {
525       /* gidDDD syntax for glyph indices. */
526       if (0 == strncmp (s, "gid", 3) &&
527           hb_codepoint_parse (s + 3, len - 3, 10, glyph))
528         return true;
529
530       /* uniUUUU and other Unicode character indices. */
531       hb_codepoint_t unichar;
532       if (0 == strncmp (s, "uni", 3) &&
533           hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
534           get_nominal_glyph (unichar, glyph))
535         return true;
536     }
537
538     return false;
539   }
540
541   inline hb_position_t em_scale (int16_t v, int scale)
542   {
543     int upem = face->get_upem ();
544     int64_t scaled = v * (int64_t) scale;
545     scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
546     return (hb_position_t) (scaled / upem);
547   }
548   inline hb_position_t em_scalef (float v, int scale)
549   {
550     return (hb_position_t) round (v * scale / face->get_upem ());
551   }
552   inline float em_fscale (int16_t v, int scale)
553   {
554     return (float) v * scale / face->get_upem ();
555   }
556 };
557
558 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
559 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
560 #include "hb-shaper-list.hh"
561 #undef HB_SHAPER_IMPLEMENT
562 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
563
564
565 #endif /* HB_FONT_PRIVATE_HH */