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<USHORT> 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 USHORT *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, hb_codepoint_t glyph_id HB_UNUSED) 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   USHORT	caretValueFormat;	/* Format identifier--format = 1 */
    113   SHORT		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   USHORT	caretValueFormat;	/* Format identifier--format = 2 */
    140   USHORT	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, hb_codepoint_t glyph_id HB_UNUSED) const
    150   {
    151     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
    152            font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) :
    153            font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font);
    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   USHORT	caretValueFormat;	/* Format identifier--format = 3 */
    164   SHORT		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, hb_direction_t direction, hb_codepoint_t glyph_id) const
    176   {
    177     switch (u.format) {
    178     case 1: return u.format1.get_caret_value (font, direction, glyph_id);
    179     case 2: return u.format2.get_caret_value (font, direction, glyph_id);
    180     case 3: return u.format3.get_caret_value (font, direction, glyph_id);
    181     default:return 0;
    182     }
    183   }
    184 
    185   inline bool sanitize (hb_sanitize_context_t *c) const
    186   {
    187     TRACE_SANITIZE (this);
    188     if (!u.format.sanitize (c)) return_trace (false);
    189     switch (u.format) {
    190     case 1: return_trace (u.format1.sanitize (c));
    191     case 2: return_trace (u.format2.sanitize (c));
    192     case 3: return_trace (u.format3.sanitize (c));
    193     default:return_trace (true);
    194     }
    195   }
    196 
    197   protected:
    198   union {
    199   USHORT		format;		/* Format identifier */
    200   CaretValueFormat1	format1;
    201   CaretValueFormat2	format2;
    202   CaretValueFormat3	format3;
    203   } u;
    204   public:
    205   DEFINE_SIZE_UNION (2, format);
    206 };
    207 
    208 struct LigGlyph
    209 {
    210   inline unsigned int get_lig_carets (hb_font_t *font,
    211 				      hb_direction_t direction,
    212 				      hb_codepoint_t glyph_id,
    213 				      unsigned int start_offset,
    214 				      unsigned int *caret_count /* IN/OUT */,
    215 				      hb_position_t *caret_array /* OUT */) const
    216   {
    217     if (caret_count) {
    218       const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
    219       unsigned int count = *caret_count;
    220       for (unsigned int i = 0; i < count; i++)
    221 	caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id);
    222     }
    223 
    224     return carets.len;
    225   }
    226 
    227   inline bool sanitize (hb_sanitize_context_t *c) const
    228   {
    229     TRACE_SANITIZE (this);
    230     return_trace (carets.sanitize (c, this));
    231   }
    232 
    233   protected:
    234   OffsetArrayOf<CaretValue>
    235 		carets;			/* Offset array of CaretValue tables
    236 					 * --from beginning of LigGlyph table
    237 					 * --in increasing coordinate order */
    238   public:
    239   DEFINE_SIZE_ARRAY (2, carets);
    240 };
    241 
    242 struct LigCaretList
    243 {
    244   inline unsigned int get_lig_carets (hb_font_t *font,
    245 				      hb_direction_t direction,
    246 				      hb_codepoint_t glyph_id,
    247 				      unsigned int start_offset,
    248 				      unsigned int *caret_count /* IN/OUT */,
    249 				      hb_position_t *caret_array /* OUT */) const
    250   {
    251     unsigned int index = (this+coverage).get_coverage (glyph_id);
    252     if (index == NOT_COVERED)
    253     {
    254       if (caret_count)
    255 	*caret_count = 0;
    256       return 0;
    257     }
    258     const LigGlyph &lig_glyph = this+ligGlyph[index];
    259     return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array);
    260   }
    261 
    262   inline bool sanitize (hb_sanitize_context_t *c) const
    263   {
    264     TRACE_SANITIZE (this);
    265     return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
    266   }
    267 
    268   protected:
    269   OffsetTo<Coverage>
    270 		coverage;		/* Offset to Coverage table--from
    271 					 * beginning of LigCaretList table */
    272   OffsetArrayOf<LigGlyph>
    273 		ligGlyph;		/* Array of LigGlyph tables
    274 					 * in Coverage Index order */
    275   public:
    276   DEFINE_SIZE_ARRAY (4, ligGlyph);
    277 };
    278 
    279 
    280 struct MarkGlyphSetsFormat1
    281 {
    282   inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
    283   { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
    284 
    285   inline bool sanitize (hb_sanitize_context_t *c) const
    286   {
    287     TRACE_SANITIZE (this);
    288     return_trace (coverage.sanitize (c, this));
    289   }
    290 
    291   protected:
    292   USHORT	format;			/* Format identifier--format = 1 */
    293   ArrayOf<OffsetTo<Coverage, ULONG> >
    294 		coverage;		/* Array of long offsets to mark set
    295 					 * coverage tables */
    296   public:
    297   DEFINE_SIZE_ARRAY (4, coverage);
    298 };
    299 
    300 struct MarkGlyphSets
    301 {
    302   inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
    303   {
    304     switch (u.format) {
    305     case 1: return u.format1.covers (set_index, glyph_id);
    306     default:return false;
    307     }
    308   }
    309 
    310   inline bool sanitize (hb_sanitize_context_t *c) const
    311   {
    312     TRACE_SANITIZE (this);
    313     if (!u.format.sanitize (c)) return_trace (false);
    314     switch (u.format) {
    315     case 1: return_trace (u.format1.sanitize (c));
    316     default:return_trace (true);
    317     }
    318   }
    319 
    320   protected:
    321   union {
    322   USHORT		format;		/* Format identifier */
    323   MarkGlyphSetsFormat1	format1;
    324   } u;
    325   public:
    326   DEFINE_SIZE_UNION (2, format);
    327 };
    328 
    329 
    330 /*
    331  * GDEF -- The Glyph Definition Table
    332  */
    333 
    334 struct GDEF
    335 {
    336   static const hb_tag_t tableTag	= HB_OT_TAG_GDEF;
    337 
    338   enum GlyphClasses {
    339     UnclassifiedGlyph	= 0,
    340     BaseGlyph		= 1,
    341     LigatureGlyph	= 2,
    342     MarkGlyph		= 3,
    343     ComponentGlyph	= 4
    344   };
    345 
    346   inline bool has_glyph_classes (void) const { return glyphClassDef != 0; }
    347   inline unsigned int get_glyph_class (hb_codepoint_t glyph) const
    348   { return (this+glyphClassDef).get_class (glyph); }
    349   inline void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
    350   { (this+glyphClassDef).add_class (glyphs, klass); }
    351 
    352   inline bool has_mark_attachment_types (void) const { return markAttachClassDef != 0; }
    353   inline unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
    354   { return (this+markAttachClassDef).get_class (glyph); }
    355 
    356   inline bool has_attach_points (void) const { return attachList != 0; }
    357   inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
    358 					 unsigned int start_offset,
    359 					 unsigned int *point_count /* IN/OUT */,
    360 					 unsigned int *point_array /* OUT */) const
    361   { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
    362 
    363   inline bool has_lig_carets (void) const { return ligCaretList != 0; }
    364   inline unsigned int get_lig_carets (hb_font_t *font,
    365 				      hb_direction_t direction,
    366 				      hb_codepoint_t glyph_id,
    367 				      unsigned int start_offset,
    368 				      unsigned int *caret_count /* IN/OUT */,
    369 				      hb_position_t *caret_array /* OUT */) const
    370   { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); }
    371 
    372   inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef[0] != 0; }
    373   inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
    374   { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
    375 
    376   inline bool sanitize (hb_sanitize_context_t *c) const
    377   {
    378     TRACE_SANITIZE (this);
    379     return_trace (version.sanitize (c) &&
    380 		  likely (version.major == 1) &&
    381 		  glyphClassDef.sanitize (c, this) &&
    382 		  attachList.sanitize (c, this) &&
    383 		  ligCaretList.sanitize (c, this) &&
    384 		  markAttachClassDef.sanitize (c, this) &&
    385 		  (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this)));
    386   }
    387 
    388 
    389   /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
    390    * glyph class and other bits, and high 8-bit gthe mark attachment type (if any).
    391    * Not to be confused with lookup_props which is very similar. */
    392   inline unsigned int get_glyph_props (hb_codepoint_t glyph) const
    393   {
    394     unsigned int klass = get_glyph_class (glyph);
    395 
    396     ASSERT_STATIC ((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs);
    397     ASSERT_STATIC ((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures);
    398     ASSERT_STATIC ((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks);
    399 
    400     switch (klass) {
    401     default:			return 0;
    402     case BaseGlyph:		return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
    403     case LigatureGlyph:		return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
    404     case MarkGlyph:
    405 	  klass = get_mark_attachment_type (glyph);
    406 	  return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8);
    407     }
    408   }
    409 
    410 
    411   protected:
    412   FixedVersion<>version;		/* Version of the GDEF table--currently
    413 					 * 0x00010002u */
    414   OffsetTo<ClassDef>
    415 		glyphClassDef;		/* Offset to class definition table
    416 					 * for glyph type--from beginning of
    417 					 * GDEF header (may be Null) */
    418   OffsetTo<AttachList>
    419 		attachList;		/* Offset to list of glyphs with
    420 					 * attachment points--from beginning
    421 					 * of GDEF header (may be Null) */
    422   OffsetTo<LigCaretList>
    423 		ligCaretList;		/* Offset to list of positioning points
    424 					 * for ligature carets--from beginning
    425 					 * of GDEF header (may be Null) */
    426   OffsetTo<ClassDef>
    427 		markAttachClassDef;	/* Offset to class definition table for
    428 					 * mark attachment type--from beginning
    429 					 * of GDEF header (may be Null) */
    430   OffsetTo<MarkGlyphSets>
    431 		markGlyphSetsDef[VAR];	/* Offset to the table of mark set
    432 					 * definitions--from beginning of GDEF
    433 					 * header (may be NULL).  Introduced
    434 					 * in version 00010002. */
    435   public:
    436   DEFINE_SIZE_ARRAY (12, markGlyphSetsDef);
    437 };
    438 
    439 
    440 } /* namespace OT */
    441 
    442 
    443 #endif /* HB_OT_LAYOUT_GDEF_TABLE_HH */
    444