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-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 */
    470