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