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 (glyph) \
     46   HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
     47   HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
     48   HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
     49   HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
     50   HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
     51   HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
     52   HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
     53   HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
     54   HB_FONT_FUNC_IMPLEMENT (glyph_name) \
     55   HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
     56   /* ^--- Add new callbacks here */
     57 
     58 struct hb_font_funcs_t {
     59   hb_object_header_t header;
     60   ASSERT_POD ();
     61 
     62   hb_bool_t immutable;
     63 
     64   /* Don't access these directly.  Call hb_font_get_*() instead. */
     65 
     66   struct {
     67 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
     68     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
     69 #undef HB_FONT_FUNC_IMPLEMENT
     70   } get;
     71 
     72   struct {
     73 #define HB_FONT_FUNC_IMPLEMENT(name) void *name;
     74     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
     75 #undef HB_FONT_FUNC_IMPLEMENT
     76   } user_data;
     77 
     78   struct {
     79 #define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
     80     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
     81 #undef HB_FONT_FUNC_IMPLEMENT
     82   } destroy;
     83 };
     84 
     85 
     86 
     87 /*
     88  * hb_font_t
     89  */
     90 
     91 struct hb_font_t {
     92   hb_object_header_t header;
     93   ASSERT_POD ();
     94 
     95   hb_bool_t immutable;
     96 
     97   hb_font_t *parent;
     98   hb_face_t *face;
     99 
    100   int x_scale;
    101   int y_scale;
    102 
    103   unsigned int x_ppem;
    104   unsigned int y_ppem;
    105 
    106   hb_font_funcs_t   *klass;
    107   void              *user_data;
    108   hb_destroy_func_t  destroy;
    109 
    110   struct hb_shaper_data_t shaper_data;
    111 
    112 
    113   /* Convert from font-space to user-space */
    114   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
    115   inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
    116 
    117   /* Convert from parent-font user-space to our user-space */
    118   inline hb_position_t parent_scale_x_distance (hb_position_t v) {
    119     if (unlikely (parent && parent->x_scale != x_scale))
    120       return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
    121     return v;
    122   }
    123   inline hb_position_t parent_scale_y_distance (hb_position_t v) {
    124     if (unlikely (parent && parent->y_scale != y_scale))
    125       return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
    126     return v;
    127   }
    128   inline hb_position_t parent_scale_x_position (hb_position_t v) {
    129     return parent_scale_x_distance (v);
    130   }
    131   inline hb_position_t parent_scale_y_position (hb_position_t v) {
    132     return parent_scale_y_distance (v);
    133   }
    134 
    135   inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
    136     *x = parent_scale_x_distance (*x);
    137     *y = parent_scale_y_distance (*y);
    138   }
    139   inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
    140     *x = parent_scale_x_position (*x);
    141     *y = parent_scale_y_position (*y);
    142   }
    143 
    144 
    145   /* Public getters */
    146 
    147   inline hb_bool_t has_glyph (hb_codepoint_t unicode)
    148   {
    149     hb_codepoint_t glyph;
    150     return get_glyph (unicode, 0, &glyph);
    151   }
    152 
    153   inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
    154 			      hb_codepoint_t *glyph)
    155   {
    156     *glyph = 0;
    157     return klass->get.glyph (this, user_data,
    158 			     unicode, variation_selector, glyph,
    159 			     klass->user_data.glyph);
    160   }
    161 
    162   inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
    163   {
    164     return klass->get.glyph_h_advance (this, user_data,
    165 				       glyph,
    166 				       klass->user_data.glyph_h_advance);
    167   }
    168 
    169   inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
    170   {
    171     return klass->get.glyph_v_advance (this, user_data,
    172 				       glyph,
    173 				       klass->user_data.glyph_v_advance);
    174   }
    175 
    176   inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
    177 				       hb_position_t *x, hb_position_t *y)
    178   {
    179     *x = *y = 0;
    180     return klass->get.glyph_h_origin (this, user_data,
    181 				      glyph, x, y,
    182 				      klass->user_data.glyph_h_origin);
    183   }
    184 
    185   inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
    186 				       hb_position_t *x, hb_position_t *y)
    187   {
    188     *x = *y = 0;
    189     return klass->get.glyph_v_origin (this, user_data,
    190 				      glyph, x, y,
    191 				      klass->user_data.glyph_v_origin);
    192   }
    193 
    194   inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
    195   {
    196     return klass->get.glyph_h_kerning (this, user_data,
    197 				       left_glyph, right_glyph,
    198 				       klass->user_data.glyph_h_kerning);
    199   }
    200 
    201   inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
    202   {
    203     return klass->get.glyph_v_kerning (this, user_data,
    204 				       top_glyph, bottom_glyph,
    205 				       klass->user_data.glyph_v_kerning);
    206   }
    207 
    208   inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
    209 				      hb_glyph_extents_t *extents)
    210   {
    211     memset (extents, 0, sizeof (*extents));
    212     return klass->get.glyph_extents (this, user_data,
    213 				     glyph,
    214 				     extents,
    215 				     klass->user_data.glyph_extents);
    216   }
    217 
    218   inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
    219 					    hb_position_t *x, hb_position_t *y)
    220   {
    221     *x = *y = 0;
    222     return klass->get.glyph_contour_point (this, user_data,
    223 					   glyph, point_index,
    224 					   x, y,
    225 					   klass->user_data.glyph_contour_point);
    226   }
    227 
    228   inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
    229 				   char *name, unsigned int size)
    230   {
    231     if (size) *name = '\0';
    232     return klass->get.glyph_name (this, user_data,
    233 				  glyph,
    234 				  name, size,
    235 				  klass->user_data.glyph_name);
    236   }
    237 
    238   inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
    239 					hb_codepoint_t *glyph)
    240   {
    241     *glyph = 0;
    242     if (len == -1) len = strlen (name);
    243     return klass->get.glyph_from_name (this, user_data,
    244 				       name, len,
    245 				       glyph,
    246 				       klass->user_data.glyph_from_name);
    247   }
    248 
    249 
    250   /* A bit higher-level, and with fallback */
    251 
    252   inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
    253 					       hb_direction_t direction,
    254 					       hb_position_t *x, hb_position_t *y)
    255   {
    256     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
    257       *x = get_glyph_h_advance (glyph);
    258       *y = 0;
    259     } else {
    260       *x = 0;
    261       *y = get_glyph_v_advance (glyph);
    262     }
    263   }
    264 
    265   /* Internal only */
    266   inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
    267 					     hb_position_t *x, hb_position_t *y)
    268   {
    269     *x = get_glyph_h_advance (glyph) / 2;
    270 
    271     /* TODO use font_metics.ascent */
    272     *y = y_scale;
    273   }
    274 
    275   inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
    276 					      hb_direction_t direction,
    277 					      hb_position_t *x, hb_position_t *y)
    278   {
    279     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
    280     {
    281       if (!get_glyph_h_origin (glyph, x, y) &&
    282 	   get_glyph_v_origin (glyph, x, y))
    283       {
    284 	hb_position_t dx, dy;
    285 	guess_v_origin_minus_h_origin (glyph, &dx, &dy);
    286 	*x -= dx; *y -= dy;
    287       }
    288     }
    289     else
    290     {
    291       if (!get_glyph_v_origin (glyph, x, y) &&
    292 	   get_glyph_h_origin (glyph, x, y))
    293       {
    294 	hb_position_t dx, dy;
    295 	guess_v_origin_minus_h_origin (glyph, &dx, &dy);
    296 	*x += dx; *y += dy;
    297       }
    298     }
    299   }
    300 
    301   inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
    302 					      hb_direction_t direction,
    303 					      hb_position_t *x, hb_position_t *y)
    304   {
    305     hb_position_t origin_x, origin_y;
    306 
    307     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
    308 
    309     *x += origin_x;
    310     *y += origin_y;
    311   }
    312 
    313   inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
    314 						   hb_direction_t direction,
    315 						   hb_position_t *x, hb_position_t *y)
    316   {
    317     hb_position_t origin_x, origin_y;
    318 
    319     get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
    320 
    321     *x -= origin_x;
    322     *y -= origin_y;
    323   }
    324 
    325   inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
    326 					       hb_direction_t direction,
    327 					       hb_position_t *x, hb_position_t *y)
    328   {
    329     if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
    330       *x = get_glyph_h_kerning (first_glyph, second_glyph);
    331       *y = 0;
    332     } else {
    333       *x = 0;
    334       *y = get_glyph_v_kerning (first_glyph, second_glyph);
    335     }
    336   }
    337 
    338   inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
    339 						 hb_direction_t direction,
    340 						 hb_glyph_extents_t *extents)
    341   {
    342     hb_bool_t ret = get_glyph_extents (glyph, extents);
    343 
    344     if (ret)
    345       subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
    346 
    347     return ret;
    348   }
    349 
    350   inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
    351 						       hb_direction_t direction,
    352 						       hb_position_t *x, hb_position_t *y)
    353   {
    354     hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
    355 
    356     if (ret)
    357       subtract_glyph_origin_for_direction (glyph, direction, x, y);
    358 
    359     return ret;
    360   }
    361 
    362   /* Generates gidDDD if glyph has no name. */
    363   inline void
    364   glyph_to_string (hb_codepoint_t glyph,
    365 		   char *s, unsigned int size)
    366   {
    367     if (get_glyph_name (glyph, s, size)) return;
    368 
    369     if (size && snprintf (s, size, "gid%u", glyph) < 0)
    370       *s = '\0';
    371   }
    372 
    373   /* Parses gidDDD and uniUUUU strings automatically. */
    374   inline hb_bool_t
    375   glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
    376 		     hb_codepoint_t *glyph)
    377   {
    378     if (get_glyph_from_name (s, len, glyph)) return true;
    379 
    380     if (len == -1) len = strlen (s);
    381 
    382     /* Straight glyph index. */
    383     if (hb_codepoint_parse (s, len, 10, glyph))
    384       return true;
    385 
    386     if (len > 3)
    387     {
    388       /* gidDDD syntax for glyph indices. */
    389       if (0 == strncmp (s, "gid", 3) &&
    390 	  hb_codepoint_parse (s + 3, len - 3, 10, glyph))
    391 	return true;
    392 
    393       /* uniUUUU and other Unicode character indices. */
    394       hb_codepoint_t unichar;
    395       if (0 == strncmp (s, "uni", 3) &&
    396 	  hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
    397 	  get_glyph (unichar, 0, glyph))
    398 	return true;
    399     }
    400 
    401     return false;
    402   }
    403 
    404   private:
    405   inline hb_position_t em_scale (int16_t v, int scale) { return (hb_position_t) (v * (int64_t) scale / face->get_upem ()); }
    406 };
    407 
    408 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
    409 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
    410 #include "hb-shaper-list.hh"
    411 #undef HB_SHAPER_IMPLEMENT
    412 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
    413 
    414 
    415 #endif /* HB_FONT_PRIVATE_HH */
    416