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