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