Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  2007,2008,2009  Red Hat, Inc.
      3  * Copyright  2010,2011,2012  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_OT_LAYOUT_GDEF_TABLE_HH
     30 #define HB_OT_LAYOUT_GDEF_TABLE_HH
     31 
     32 #include "hb-ot-layout-common-private.hh"
     33 
     34 #include "hb-font-private.hh"
     35 
     36 
     37 namespace OT {
     38 
     39 
     40 /*
     41  * Attachment List Table
     42  */
     43 
     44 typedef ArrayOf<UINT16> AttachPoint;	/* Array of contour point indices--in
     45 					 * increasing numerical order */
     46 
     47 struct AttachList
     48 {
     49   inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
     50 					 unsigned int start_offset,
     51 					 unsigned int *point_count /* IN/OUT */,
     52 					 unsigned int *point_array /* OUT */) const
     53   {
     54     unsigned int index = (this+coverage).get_coverage (glyph_id);
     55     if (index == NOT_COVERED)
     56     {
     57       if (point_count)
     58 	*point_count = 0;
     59       return 0;
     60     }
     61 
     62     const AttachPoint &points = this+attachPoint[index];
     63 
     64     if (point_count) {
     65       const UINT16 *array = points.sub_array (start_offset, point_count);
     66       unsigned int count = *point_count;
     67       for (unsigned int i = 0; i < count; i++)
     68 	point_array[i] = array[i];
     69     }
     70 
     71     return points.len;
     72   }
     73 
     74   inline bool sanitize (hb_sanitize_context_t *c) const
     75   {
     76     TRACE_SANITIZE (this);
     77     return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
     78   }
     79 
     80   protected:
     81   OffsetTo<Coverage>
     82 		coverage;		/* Offset to Coverage table -- from
     83 					 * beginning of AttachList table */
     84   OffsetArrayOf<AttachPoint>
     85 		attachPoint;		/* Array of AttachPoint tables
     86 					 * in Coverage Index order */
     87   public:
     88   DEFINE_SIZE_ARRAY (4, attachPoint);
     89 };
     90 
     91 /*
     92  * Ligature Caret Table
     93  */
     94 
     95 struct CaretValueFormat1
     96 {
     97   friend struct CaretValue;
     98 
     99   private:
    100   inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
    101   {
    102     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
    103   }
    104 
    105   inline bool sanitize (hb_sanitize_context_t *c) const
    106   {
    107     TRACE_SANITIZE (this);
    108     return_trace (c->check_struct (this));
    109   }
    110 
    111   protected:
    112   UINT16	caretValueFormat;	/* Format identifier--format = 1 */
    113   INT16		coordinate;		/* X or Y value, in design units */
    114   public:
    115   DEFINE_SIZE_STATIC (4);
    116 };
    117 
    118 struct CaretValueFormat2
    119 {
    120   friend struct CaretValue;
    121 
    122   private:
    123   inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
    124   {
    125     hb_position_t x, y;
    126     if (font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y))
    127       return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
    128     else
    129       return 0;
    130   }
    131 
    132   inline bool sanitize (hb_sanitize_context_t *c) const
    133   {
    134     TRACE_SANITIZE (this);
    135     return_trace (c->check_struct (this));
    136   }
    137 
    138   protected:
    139   UINT16	caretValueFormat;	/* Format identifier--format = 2 */
    140   UINT16	caretValuePoint;	/* Contour point index on glyph */
    141   public:
    142   DEFINE_SIZE_STATIC (4);
    143 };
    144 
    145 struct CaretValueFormat3
    146 {
    147   friend struct CaretValue;
    148 
    149   inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VariationStore &var_store) const
    150   {
    151     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
    152            font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
    153            font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
    154   }
    155 
    156   inline bool sanitize (hb_sanitize_context_t *c) const
    157   {
    158     TRACE_SANITIZE (this);
    159     return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
    160   }
    161 
    162   protected:
    163   UINT16	caretValueFormat;	/* Format identifier--format = 3 */
    164   INT16		coordinate;		/* X or Y value, in design units */
    165   OffsetTo<Device>
    166 		deviceTable;		/* Offset to Device table for X or Y
    167 					 * value--from beginning of CaretValue
    168 					 * table */
    169   public:
    170   DEFINE_SIZE_STATIC (6);
    171 };
    172 
    173 struct CaretValue
    174 {
    175   inline hb_position_t get_caret_value (hb_font_t *font,
    176 					hb_direction_t direction,
    177 					hb_codepoint_t glyph_id,
    178 					const VariationStore &var_store) const
    179   {
    180     switch (u.format) {
    181     case 1: return u.format1.get_caret_value (font, direction);
    182     case 2: return u.format2.get_caret_value (font, direction, glyph_id);
    183     case 3: return u.format3.get_caret_value (font, direction, var_store);
    184     default:return 0;
    185     }
    186   }
    187 
    188   inline bool sanitize (hb_sanitize_context_t *c) const
    189   {
    190     TRACE_SANITIZE (this);
    191     if (!u.format.sanitize (c)) return_trace (false);
    192     switch (u.format) {
    193     case 1: return_trace (u.format1.sanitize (c));
    194     case 2: return_trace (u.format2.sanitize (c));
    195     case 3: return_trace (u.format3.sanitize (c));
    196     default:return_trace (true);
    197     }
    198   }
    199 
    200   protected:
    201   union {
    202   UINT16		format;		/* Format identifier */
    203   CaretValueFormat1	format1;
    204   CaretValueFormat2	format2;
    205   CaretValueFormat3	format3;
    206   } u;
    207   public:
    208   DEFINE_SIZE_UNION (2, format);
    209 };
    210 
    211 struct LigGlyph
    212 {
    213   inline unsigned int get_lig_carets (hb_font_t *font,
    214 				      hb_direction_t direction,
    215 				      hb_codepoint_t glyph_id,
    216 				      const VariationStore &var_store,
    217 				      unsigned int start_offset,
    218 				      unsigned int *caret_count /* IN/OUT */,
    219 				      hb_position_t *caret_array /* OUT */) const
    220   {
    221     if (caret_count) {
    222       const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
    223       unsigned int count = *caret_count;
    224       for (unsigned int i = 0; i < count; i++)
    225 	caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store);
    226     }
    227 
    228     return carets.len;
    229   }
    230 
    231   inline bool sanitize (hb_sanitize_context_t *c) const
    232   {
    233     TRACE_SANITIZE (this);
    234     return_trace (carets.sanitize (c, this));
    235   }
    236 
    237   protected:
    238   OffsetArrayOf<CaretValue>
    239 		carets;			/* Offset array of CaretValue tables
    240 					 * --from beginning of LigGlyph table
    241 					 * --in increasing coordinate order */
    242   public:
    243   DEFINE_SIZE_ARRAY (2, carets);
    244 };
    245 
    246 struct LigCaretList
    247 {
    248   inline unsigned int get_lig_carets (hb_font_t *font,
    249 				      hb_direction_t direction,
    250 				      hb_codepoint_t glyph_id,
    251 				      const VariationStore &var_store,
    252 				      unsigned int start_offset,
    253 				      unsigned int *caret_count /* IN/OUT */,
    254 				      hb_position_t *caret_array /* OUT */) const
    255   {
    256     unsigned int index = (this+coverage).get_coverage (glyph_id);
    257     if (index == NOT_COVERED)
    258     {
    259       if (caret_count)
    260 	*caret_count = 0;
    261       return 0;
    262     }
    263     const LigGlyph &lig_glyph = this+ligGlyph[index];
    264     return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
    265   }
    266 
    267   inline bool sanitize (hb_sanitize_context_t *c) const
    268   {
    269     TRACE_SANITIZE (this);
    270     return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
    271   }
    272 
    273   protected:
    274   OffsetTo<Coverage>
    275 		coverage;		/* Offset to Coverage table--from
    276 					 * beginning of LigCaretList table */
    277   OffsetArrayOf<LigGlyph>
    278 		ligGlyph;		/* Array of LigGlyph tables
    279 					 * in Coverage Index order */
    280   public:
    281   DEFINE_SIZE_ARRAY (4, ligGlyph);
    282 };
    283 
    284 
    285 struct MarkGlyphSetsFormat1
    286 {
    287   inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
    288   { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
    289 
    290   inline bool sanitize (hb_sanitize_context_t *c) const
    291   {
    292     TRACE_SANITIZE (this);
    293     return_trace (coverage.sanitize (c, this));
    294   }
    295 
    296   protected:
    297   UINT16	format;			/* Format identifier--format = 1 */
    298   ArrayOf<LOffsetTo<Coverage> >
    299 		coverage;		/* Array of long offsets to mark set
    300 					 * coverage tables */
    301   public:
    302   DEFINE_SIZE_ARRAY (4, coverage);
    303 };
    304 
    305 struct MarkGlyphSets
    306 {
    307   inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
    308   {
    309     switch (u.format) {
    310     case 1: return u.format1.covers (set_index, glyph_id);
    311     default:return false;
    312     }
    313   }
    314 
    315   inline bool sanitize (hb_sanitize_context_t *c) const
    316   {
    317     TRACE_SANITIZE (this);
    318     if (!u.format.sanitize (c)) return_trace (false);
    319     switch (u.format) {
    320     case 1: return_trace (u.format1.sanitize (c));
    321     default:return_trace (true);
    322     }
    323   }
    324 
    325   protected:
    326   union {
    327   UINT16		format;		/* Format identifier */
    328   MarkGlyphSetsFormat1	format1;
    329   } u;
    330   public:
    331   DEFINE_SIZE_UNION (2, format);
    332 };
    333 
    334 
    335 /*
    336  * GDEF -- The Glyph Definition Table
    337  */
    338 
    339 struct GDEF
    340 {
    341   static const hb_tag_t tableTag	= HB_OT_TAG_GDEF;
    342 
    343   enum GlyphClasses {
    344     UnclassifiedGlyph	= 0,
    345     BaseGlyph		= 1,
    346     LigatureGlyph	= 2,
    347     MarkGlyph		= 3,
    348     ComponentGlyph	= 4
    349   };
    350 
    351   inline bool has_glyph_classes (void) const { return glyphClassDef != 0; }
    352   inline unsigned int get_glyph_class (hb_codepoint_t glyph) const
    353   { return (this+glyphClassDef).get_class (glyph); }
    354   inline void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
    355   { (this+glyphClassDef).add_class (glyphs, klass); }
    356 
    357   inline bool has_mark_attachment_types (void) const { return markAttachClassDef != 0; }
    358   inline unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
    359   { return (this+markAttachClassDef).get_class (glyph); }
    360 
    361   inline bool has_attach_points (void) const { return attachList != 0; }
    362   inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
    363 					 unsigned int start_offset,
    364 					 unsigned int *point_count /* IN/OUT */,
    365 					 unsigned int *point_array /* OUT */) const
    366   { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
    367 
    368   inline bool has_lig_carets (void) const { return ligCaretList != 0; }
    369   inline unsigned int get_lig_carets (hb_font_t *font,
    370 				      hb_direction_t direction,
    371 				      hb_codepoint_t glyph_id,
    372 				      unsigned int start_offset,
    373 				      unsigned int *caret_count /* IN/OUT */,
    374 				      hb_position_t *caret_array /* OUT */) const
    375   { return (this+ligCaretList).get_lig_carets (font,
    376 					       direction, glyph_id, get_var_store(),
    377 					       start_offset, caret_count, caret_array); }
    378 
    379   inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
    380   inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
    381   { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); }
    382 
    383   inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; }
    384   inline const VariationStore &get_var_store (void) const
    385   { return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); }
    386 
    387   inline bool sanitize (hb_sanitize_context_t *c) const
    388   {
    389     TRACE_SANITIZE (this);
    390     return_trace (version.sanitize (c) &&
    391 		  likely (version.major == 1) &&
    392 		  glyphClassDef.sanitize (c, this) &&
    393 		  attachList.sanitize (c, this) &&
    394 		  ligCaretList.sanitize (c, this) &&
    395 		  markAttachClassDef.sanitize (c, this) &&
    396 		  (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
    397 		  (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
    398   }
    399 
    400   /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
    401    * glyph class and other bits, and high 8-bit gthe mark attachment type (if any).
    402    * Not to be confused with lookup_props which is very similar. */
    403   inline unsigned int get_glyph_props (hb_codepoint_t glyph) const
    404   {
    405     unsigned int klass = get_glyph_class (glyph);
    406 
    407     static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), "");
    408     static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), "");
    409     static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), "");
    410 
    411     switch (klass) {
    412     default:			return 0;
    413     case BaseGlyph:		return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
    414     case LigatureGlyph:		return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
    415     case MarkGlyph:
    416 	  klass = get_mark_attachment_type (glyph);
    417 	  return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8);
    418     }
    419   }
    420 
    421 
    422   protected:
    423   FixedVersion<>version;		/* Version of the GDEF table--currently
    424 					 * 0x00010003u */
    425   OffsetTo<ClassDef>
    426 		glyphClassDef;		/* Offset to class definition table
    427 					 * for glyph type--from beginning of
    428 					 * GDEF header (may be Null) */
    429   OffsetTo<AttachList>
    430 		attachList;		/* Offset to list of glyphs with
    431 					 * attachment points--from beginning
    432 					 * of GDEF header (may be Null) */
    433   OffsetTo<LigCaretList>
    434 		ligCaretList;		/* Offset to list of positioning points
    435 					 * for ligature carets--from beginning
    436 					 * of GDEF header (may be Null) */
    437   OffsetTo<ClassDef>
    438 		markAttachClassDef;	/* Offset to class definition table for
    439 					 * mark attachment type--from beginning
    440 					 * of GDEF header (may be Null) */
    441   OffsetTo<MarkGlyphSets>
    442 		markGlyphSetsDef;	/* Offset to the table of mark set
    443 					 * definitions--from beginning of GDEF
    444 					 * header (may be NULL).  Introduced
    445 					 * in version 0x00010002. */
    446   LOffsetTo<VariationStore>
    447 		varStore;		/* Offset to the table of Item Variation
    448 					 * Store--from beginning of GDEF
    449 					 * header (may be NULL).  Introduced
    450 					 * in version 0x00010003. */
    451   public:
    452   DEFINE_SIZE_MIN (12);
    453 };
    454 
    455 
    456 } /* namespace OT */
    457 
    458 
    459 #endif /* HB_OT_LAYOUT_GDEF_TABLE_HH */
    460