LCOV - code coverage report
Current view: directory - gfx/harfbuzz/src - hb-ot-layout-gsubgpos-private.hh (source / functions) Found Hit Coverage
Test: app.info Lines: 341 0 0.0 %
Date: 2012-06-02 Functions: 61 0 0.0 %

       1                 : /*
       2                 :  * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
       3                 :  * Copyright © 2010  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_GSUBGPOS_PRIVATE_HH
      30                 : #define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
      31                 : 
      32                 : #include "hb-buffer-private.hh"
      33                 : #include "hb-ot-layout-gdef-table.hh"
      34                 : 
      35                 : 
      36                 : /* buffer var allocations */
      37                 : #define lig_id() var2.u8[2] /* unique ligature id */
      38                 : #define lig_comp() var2.u8[3] /* component number in the ligature (0 = base) */
      39                 : 
      40               0 : static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) {
      41               0 :   uint8_t lig_id = buffer->next_serial ();
      42               0 :   if (unlikely (!lig_id)) lig_id = buffer->next_serial (); /* in case of overflow */
      43               0 :   return lig_id;
      44                 : }
      45                 : 
      46                 : 
      47                 : 
      48                 : #ifndef HB_DEBUG_APPLY
      49                 : #define HB_DEBUG_APPLY (HB_DEBUG+0)
      50                 : #endif
      51                 : 
      52                 : #define TRACE_APPLY() \
      53                 :         hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", this, NULL, HB_FUNC);
      54                 : 
      55                 : 
      56                 : 
      57                 : struct hb_apply_context_t
      58                 : {
      59                 :   unsigned int debug_depth;
      60                 :   hb_font_t *font;
      61                 :   hb_face_t *face;
      62                 :   hb_buffer_t *buffer;
      63                 :   hb_direction_t direction;
      64                 :   hb_mask_t lookup_mask;
      65                 :   unsigned int context_length;
      66                 :   unsigned int nesting_level_left;
      67                 :   unsigned int lookup_props;
      68                 :   unsigned int property; /* propety of first glyph */
      69                 : 
      70                 :   struct mark_skipping_forward_iterator_t
      71                 :   {
      72               0 :     inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_,
      73                 :                                              unsigned int start_index_,
      74                 :                                              unsigned int num_items_)
      75                 :     {
      76               0 :       c = c_;
      77               0 :       idx = start_index_;
      78               0 :       num_items = num_items_;
      79               0 :       end = MIN (c->buffer->len, c->buffer->idx + c->context_length);
      80               0 :     }
      81               0 :     inline bool has_no_chance (void) const
      82                 :     {
      83               0 :       return unlikely (num_items && idx + num_items >= end);
      84                 :     }
      85               0 :     inline bool next (unsigned int *property_out,
      86                 :                       unsigned int lookup_props)
      87                 :     {
      88               0 :       assert (num_items > 0);
      89               0 :       do
      90                 :       {
      91               0 :         if (has_no_chance ())
      92               0 :           return false;
      93               0 :         idx++;
      94               0 :       } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[idx], lookup_props, property_out));
      95               0 :       num_items--;
      96               0 :       return true;
      97                 :     }
      98               0 :     inline bool next (unsigned int *property_out = NULL)
      99                 :     {
     100               0 :       return next (property_out, c->lookup_props);
     101                 :     }
     102                 : 
     103                 :     unsigned int idx;
     104                 :     private:
     105                 :     hb_apply_context_t *c;
     106                 :     unsigned int num_items;
     107                 :     unsigned int end;
     108                 :   };
     109                 : 
     110                 :   struct mark_skipping_backward_iterator_t
     111                 :   {
     112               0 :     inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_,
     113                 :                                               unsigned int start_index_,
     114                 :                                               unsigned int num_items_)
     115                 :     {
     116               0 :       c = c_;
     117               0 :       idx = start_index_;
     118               0 :       num_items = num_items_;
     119               0 :     }
     120               0 :     inline bool has_no_chance (void) const
     121                 :     {
     122               0 :       return unlikely (idx < num_items);
     123                 :     }
     124               0 :     inline bool prev (unsigned int *property_out,
     125                 :                       unsigned int lookup_props)
     126                 :     {
     127               0 :       assert (num_items > 0);
     128               0 :       do
     129                 :       {
     130               0 :         if (has_no_chance ())
     131               0 :           return false;
     132               0 :         idx--;
     133               0 :       } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->out_info[idx], lookup_props, property_out));
     134               0 :       num_items--;
     135               0 :       return true;
     136                 :     }
     137               0 :     inline bool prev (unsigned int *property_out = NULL)
     138                 :     {
     139               0 :       return prev (property_out, c->lookup_props);
     140                 :     }
     141                 : 
     142                 :     unsigned int idx;
     143                 :     private:
     144                 :     hb_apply_context_t *c;
     145                 :     unsigned int num_items;
     146                 :   };
     147                 : 
     148               0 :   inline bool should_mark_skip_current_glyph (void) const
     149                 :   {
     150               0 :     return _hb_ot_layout_skip_mark (face, &buffer->info[buffer->idx], lookup_props, NULL);
     151                 :   }
     152                 : 
     153                 : 
     154                 : 
     155               0 :   inline void replace_glyph (hb_codepoint_t glyph_index) const
     156                 :   {
     157               0 :     clear_property ();
     158               0 :     buffer->replace_glyph (glyph_index);
     159               0 :   }
     160               0 :   inline void replace_glyphs_be16 (unsigned int num_in,
     161                 :                                    unsigned int num_out,
     162                 :                                    const uint16_t *glyph_data_be) const
     163                 :   {
     164               0 :     clear_property ();
     165               0 :     buffer->replace_glyphs_be16 (num_in, num_out, glyph_data_be);
     166               0 :   }
     167                 : 
     168               0 :   inline void guess_glyph_class (unsigned int klass)
     169                 :   {
     170                 :     /* XXX if ! has gdef */
     171               0 :     buffer->info[buffer->idx].props_cache() = klass;
     172               0 :   }
     173                 : 
     174                 :   private:
     175               0 :   inline void clear_property (void) const
     176                 :   {
     177                 :     /* XXX if has gdef */
     178               0 :     buffer->info[buffer->idx].props_cache() = 0;
     179               0 :   }
     180                 : };
     181                 : 
     182                 : 
     183                 : 
     184                 : typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
     185                 : typedef bool (*apply_lookup_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
     186                 : 
     187                 : struct ContextFuncs
     188                 : {
     189                 :   match_func_t match;
     190                 :   apply_lookup_func_t apply;
     191                 : };
     192                 : 
     193                 : 
     194               0 : static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
     195                 : {
     196               0 :   return glyph_id == value;
     197                 : }
     198                 : 
     199               0 : static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
     200                 : {
     201               0 :   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
     202               0 :   return class_def.get_class (glyph_id) == value;
     203                 : }
     204                 : 
     205               0 : static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
     206                 : {
     207               0 :   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
     208               0 :   return (data+coverage) (glyph_id) != NOT_COVERED;
     209                 : }
     210                 : 
     211                 : 
     212               0 : static inline bool match_input (hb_apply_context_t *c,
     213                 :                                 unsigned int count, /* Including the first glyph (not matched) */
     214                 :                                 const USHORT input[], /* Array of input values--start with second glyph */
     215                 :                                 match_func_t match_func,
     216                 :                                 const void *match_data,
     217                 :                                 unsigned int *context_length_out)
     218                 : {
     219               0 :   hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
     220               0 :   if (skippy_iter.has_no_chance ())
     221               0 :     return false;
     222                 : 
     223               0 :   for (unsigned int i = 1; i < count; i++)
     224                 :   {
     225               0 :     if (!skippy_iter.next ())
     226               0 :       return false;
     227                 : 
     228               0 :     if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, input[i - 1], match_data)))
     229               0 :       return false;
     230                 :   }
     231                 : 
     232               0 :   *context_length_out = skippy_iter.idx - c->buffer->idx + 1;
     233                 : 
     234               0 :   return true;
     235                 : }
     236                 : 
     237               0 : static inline bool match_backtrack (hb_apply_context_t *c,
     238                 :                                     unsigned int count,
     239                 :                                     const USHORT backtrack[],
     240                 :                                     match_func_t match_func,
     241                 :                                     const void *match_data)
     242                 : {
     243               0 :   hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count);
     244               0 :   if (skippy_iter.has_no_chance ())
     245               0 :     return false;
     246                 : 
     247               0 :   for (unsigned int i = 0; i < count; i++)
     248                 :   {
     249               0 :     if (!skippy_iter.prev ())
     250               0 :       return false;
     251                 : 
     252               0 :     if (likely (!match_func (c->buffer->out_info[skippy_iter.idx].codepoint, backtrack[i], match_data)))
     253               0 :       return false;
     254                 :   }
     255                 : 
     256               0 :   return true;
     257                 : }
     258                 : 
     259               0 : static inline bool match_lookahead (hb_apply_context_t *c,
     260                 :                                     unsigned int count,
     261                 :                                     const USHORT lookahead[],
     262                 :                                     match_func_t match_func,
     263                 :                                     const void *match_data,
     264                 :                                     unsigned int offset)
     265                 : {
     266               0 :   hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count);
     267               0 :   if (skippy_iter.has_no_chance ())
     268               0 :     return false;
     269                 : 
     270               0 :   for (unsigned int i = 0; i < count; i++)
     271                 :   {
     272               0 :     if (!skippy_iter.next ())
     273               0 :       return false;
     274                 : 
     275               0 :     if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, lookahead[i], match_data)))
     276               0 :       return false;
     277                 :   }
     278                 : 
     279               0 :   return true;
     280                 : }
     281                 : 
     282                 : 
     283                 : 
     284                 : struct LookupRecord
     285                 : {
     286                 :   inline bool sanitize (hb_sanitize_context_t *c) {
     287                 :     TRACE_SANITIZE ();
     288                 :     return c->check_struct (this);
     289                 :   }
     290                 : 
     291                 :   USHORT        sequenceIndex;          /* Index into current glyph
     292                 :                                          * sequence--first glyph = 0 */
     293                 :   USHORT        lookupListIndex;        /* Lookup to apply to that
     294                 :                                          * position--zero--based */
     295                 :   public:
     296                 :   DEFINE_SIZE_STATIC (4);
     297                 : };
     298                 : 
     299                 : 
     300                 : 
     301               0 : static inline bool apply_lookup (hb_apply_context_t *c,
     302                 :                                  unsigned int count, /* Including the first glyph */
     303                 :                                  unsigned int lookupCount,
     304                 :                                  const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
     305                 :                                  apply_lookup_func_t apply_func)
     306                 : {
     307               0 :   unsigned int end = MIN (c->buffer->len, c->buffer->idx + c->context_length);
     308               0 :   if (unlikely (count == 0 || c->buffer->idx + count > end))
     309               0 :     return false;
     310                 : 
     311                 :   /* TODO We don't support lookupRecord arrays that are not increasing:
     312                 :    *      Should be easy for in_place ones at least. */
     313                 : 
     314                 :   /* Note: If sublookup is reverse, it will underflow after the first loop
     315                 :    * and we jump out of it.  Not entirely disastrous.  So we don't check
     316                 :    * for reverse lookup here.
     317                 :    */
     318               0 :   for (unsigned int i = 0; i < count; /* NOP */)
     319                 :   {
     320               0 :     if (unlikely (c->buffer->idx == end))
     321               0 :       return true;
     322               0 :     while (c->should_mark_skip_current_glyph ())
     323                 :     {
     324                 :       /* No lookup applied for this index */
     325               0 :       c->buffer->next_glyph ();
     326               0 :       if (unlikely (c->buffer->idx == end))
     327               0 :         return true;
     328                 :     }
     329                 : 
     330               0 :     if (lookupCount && i == lookupRecord->sequenceIndex)
     331                 :     {
     332               0 :       unsigned int old_pos = c->buffer->idx;
     333                 : 
     334                 :       /* Apply a lookup */
     335               0 :       bool done = apply_func (c, lookupRecord->lookupListIndex);
     336                 : 
     337               0 :       lookupRecord++;
     338               0 :       lookupCount--;
     339                 :       /* Err, this is wrong if the lookup jumped over some glyphs */
     340               0 :       i += c->buffer->idx - old_pos;
     341               0 :       if (unlikely (c->buffer->idx == end))
     342               0 :         return true;
     343                 : 
     344               0 :       if (!done)
     345               0 :         goto not_applied;
     346                 :     }
     347                 :     else
     348                 :     {
     349                 :     not_applied:
     350                 :       /* No lookup applied for this index */
     351               0 :       c->buffer->next_glyph ();
     352               0 :       i++;
     353                 :     }
     354                 :   }
     355                 : 
     356               0 :   return true;
     357                 : }
     358                 : 
     359                 : 
     360                 : 
     361                 : /* Contextual lookups */
     362                 : 
     363                 : struct ContextLookupContext
     364                 : {
     365                 :   ContextFuncs funcs;
     366                 :   const void *match_data;
     367                 : };
     368                 : 
     369               0 : static inline bool context_lookup (hb_apply_context_t *c,
     370                 :                                    unsigned int inputCount, /* Including the first glyph (not matched) */
     371                 :                                    const USHORT input[], /* Array of input values--start with second glyph */
     372                 :                                    unsigned int lookupCount,
     373                 :                                    const LookupRecord lookupRecord[],
     374                 :                                    ContextLookupContext &lookup_context)
     375                 : {
     376               0 :   hb_apply_context_t new_context = *c;
     377                 :   return match_input (c,
     378                 :                       inputCount, input,
     379                 :                       lookup_context.funcs.match, lookup_context.match_data,
     380               0 :                       &new_context.context_length)
     381                 :       && apply_lookup (&new_context,
     382                 :                        inputCount,
     383                 :                        lookupCount, lookupRecord,
     384               0 :                        lookup_context.funcs.apply);
     385                 : }
     386                 : 
     387                 : struct Rule
     388                 : {
     389                 :   friend struct RuleSet;
     390                 : 
     391                 :   private:
     392               0 :   inline bool apply (hb_apply_context_t *c, ContextLookupContext &lookup_context) const
     393                 :   {
     394               0 :     TRACE_APPLY ();
     395               0 :     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
     396                 :     return context_lookup (c,
     397                 :                            inputCount, input,
     398                 :                            lookupCount, lookupRecord,
     399               0 :                            lookup_context);
     400                 :   }
     401                 : 
     402                 :   public:
     403               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     404               0 :     TRACE_SANITIZE ();
     405               0 :     return inputCount.sanitize (c)
     406               0 :         && lookupCount.sanitize (c)
     407                 :         && c->check_range (input,
     408               0 :                                  input[0].static_size * inputCount
     409               0 :                                  + lookupRecordX[0].static_size * lookupCount);
     410                 :   }
     411                 : 
     412                 :   private:
     413                 :   USHORT        inputCount;             /* Total number of glyphs in input
     414                 :                                          * glyph sequence--includes the  first
     415                 :                                          * glyph */
     416                 :   USHORT        lookupCount;            /* Number of LookupRecords */
     417                 :   USHORT        input[VAR];             /* Array of match inputs--start with
     418                 :                                          * second glyph */
     419                 :   LookupRecord  lookupRecordX[VAR];     /* Array of LookupRecords--in
     420                 :                                          * design order */
     421                 :   public:
     422                 :   DEFINE_SIZE_ARRAY2 (4, input, lookupRecordX);
     423                 : };
     424                 : 
     425                 : struct RuleSet
     426                 : {
     427               0 :   inline bool apply (hb_apply_context_t *c, ContextLookupContext &lookup_context) const
     428                 :   {
     429               0 :     TRACE_APPLY ();
     430               0 :     unsigned int num_rules = rule.len;
     431               0 :     for (unsigned int i = 0; i < num_rules; i++)
     432                 :     {
     433               0 :       if ((this+rule[i]).apply (c, lookup_context))
     434               0 :         return true;
     435                 :     }
     436                 : 
     437               0 :     return false;
     438                 :   }
     439                 : 
     440               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     441               0 :     TRACE_SANITIZE ();
     442               0 :     return rule.sanitize (c, this);
     443                 :   }
     444                 : 
     445                 :   private:
     446                 :   OffsetArrayOf<Rule>
     447                 :                 rule;                   /* Array of Rule tables
     448                 :                                          * ordered by preference */
     449                 :   public:
     450                 :   DEFINE_SIZE_ARRAY (2, rule);
     451                 : };
     452                 : 
     453                 : 
     454                 : struct ContextFormat1
     455                 : {
     456                 :   friend struct Context;
     457                 : 
     458                 :   private:
     459               0 :   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
     460                 :   {
     461               0 :     TRACE_APPLY ();
     462               0 :     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
     463               0 :     if (likely (index == NOT_COVERED))
     464               0 :       return false;
     465                 : 
     466               0 :     const RuleSet &rule_set = this+ruleSet[index];
     467                 :     struct ContextLookupContext lookup_context = {
     468                 :       {match_glyph, apply_func},
     469                 :       NULL
     470               0 :     };
     471               0 :     return rule_set.apply (c, lookup_context);
     472                 :   }
     473                 : 
     474               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     475               0 :     TRACE_SANITIZE ();
     476               0 :     return coverage.sanitize (c, this)
     477               0 :         && ruleSet.sanitize (c, this);
     478                 :   }
     479                 : 
     480                 :   private:
     481                 :   USHORT        format;                 /* Format identifier--format = 1 */
     482                 :   OffsetTo<Coverage>
     483                 :                 coverage;               /* Offset to Coverage table--from
     484                 :                                          * beginning of table */
     485                 :   OffsetArrayOf<RuleSet>
     486                 :                 ruleSet;                /* Array of RuleSet tables
     487                 :                                          * ordered by Coverage Index */
     488                 :   public:
     489                 :   DEFINE_SIZE_ARRAY (6, ruleSet);
     490                 : };
     491                 : 
     492                 : 
     493                 : struct ContextFormat2
     494                 : {
     495                 :   friend struct Context;
     496                 : 
     497                 :   private:
     498               0 :   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
     499                 :   {
     500               0 :     TRACE_APPLY ();
     501               0 :     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
     502               0 :     if (likely (index == NOT_COVERED))
     503               0 :       return false;
     504                 : 
     505               0 :     const ClassDef &class_def = this+classDef;
     506               0 :     index = class_def (c->buffer->info[c->buffer->idx].codepoint);
     507               0 :     const RuleSet &rule_set = this+ruleSet[index];
     508                 :     struct ContextLookupContext lookup_context = {
     509                 :       {match_class, apply_func},
     510                 :       &class_def
     511               0 :     };
     512               0 :     return rule_set.apply (c, lookup_context);
     513                 :   }
     514                 : 
     515               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     516               0 :     TRACE_SANITIZE ();
     517               0 :     return coverage.sanitize (c, this)
     518               0 :         && classDef.sanitize (c, this)
     519               0 :         && ruleSet.sanitize (c, this);
     520                 :   }
     521                 : 
     522                 :   private:
     523                 :   USHORT        format;                 /* Format identifier--format = 2 */
     524                 :   OffsetTo<Coverage>
     525                 :                 coverage;               /* Offset to Coverage table--from
     526                 :                                          * beginning of table */
     527                 :   OffsetTo<ClassDef>
     528                 :                 classDef;               /* Offset to glyph ClassDef table--from
     529                 :                                          * beginning of table */
     530                 :   OffsetArrayOf<RuleSet>
     531                 :                 ruleSet;                /* Array of RuleSet tables
     532                 :                                          * ordered by class */
     533                 :   public:
     534                 :   DEFINE_SIZE_ARRAY (8, ruleSet);
     535                 : };
     536                 : 
     537                 : 
     538                 : struct ContextFormat3
     539                 : {
     540                 :   friend struct Context;
     541                 : 
     542                 :   private:
     543               0 :   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
     544                 :   {
     545               0 :     TRACE_APPLY ();
     546               0 :     unsigned int index = (this+coverage[0]) (c->buffer->info[c->buffer->idx].codepoint);
     547               0 :     if (likely (index == NOT_COVERED))
     548               0 :       return false;
     549                 : 
     550               0 :     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
     551                 :     struct ContextLookupContext lookup_context = {
     552                 :       {match_coverage, apply_func},
     553                 :       this
     554               0 :     };
     555                 :     return context_lookup (c,
     556               0 :                            glyphCount, (const USHORT *) (coverage + 1),
     557                 :                            lookupCount, lookupRecord,
     558               0 :                            lookup_context);
     559                 :   }
     560                 : 
     561               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     562               0 :     TRACE_SANITIZE ();
     563               0 :     if (!c->check_struct (this)) return false;
     564               0 :     unsigned int count = glyphCount;
     565               0 :     if (!c->check_array (coverage, coverage[0].static_size, count)) return false;
     566               0 :     for (unsigned int i = 0; i < count; i++)
     567               0 :       if (!coverage[i].sanitize (c, this)) return false;
     568               0 :     LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * count);
     569               0 :     return c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount);
     570                 :   }
     571                 : 
     572                 :   private:
     573                 :   USHORT        format;                 /* Format identifier--format = 3 */
     574                 :   USHORT        glyphCount;             /* Number of glyphs in the input glyph
     575                 :                                          * sequence */
     576                 :   USHORT        lookupCount;            /* Number of LookupRecords */
     577                 :   OffsetTo<Coverage>
     578                 :                 coverage[VAR];          /* Array of offsets to Coverage
     579                 :                                          * table in glyph sequence order */
     580                 :   LookupRecord  lookupRecordX[VAR];     /* Array of LookupRecords--in
     581                 :                                          * design order */
     582                 :   public:
     583                 :   DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX);
     584                 : };
     585                 : 
     586                 : struct Context
     587                 : {
     588                 :   protected:
     589               0 :   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
     590                 :   {
     591               0 :     TRACE_APPLY ();
     592               0 :     switch (u.format) {
     593               0 :     case 1: return u.format1.apply (c, apply_func);
     594               0 :     case 2: return u.format2.apply (c, apply_func);
     595               0 :     case 3: return u.format3.apply (c, apply_func);
     596               0 :     default:return false;
     597                 :     }
     598                 :   }
     599                 : 
     600               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     601               0 :     TRACE_SANITIZE ();
     602               0 :     if (!u.format.sanitize (c)) return false;
     603               0 :     switch (u.format) {
     604               0 :     case 1: return u.format1.sanitize (c);
     605               0 :     case 2: return u.format2.sanitize (c);
     606               0 :     case 3: return u.format3.sanitize (c);
     607               0 :     default:return true;
     608                 :     }
     609                 :   }
     610                 : 
     611                 :   private:
     612                 :   union {
     613                 :   USHORT                format;         /* Format identifier */
     614                 :   ContextFormat1        format1;
     615                 :   ContextFormat2        format2;
     616                 :   ContextFormat3        format3;
     617                 :   } u;
     618                 : };
     619                 : 
     620                 : 
     621                 : /* Chaining Contextual lookups */
     622                 : 
     623                 : struct ChainContextLookupContext
     624                 : {
     625                 :   ContextFuncs funcs;
     626                 :   const void *match_data[3];
     627                 : };
     628                 : 
     629               0 : static inline bool chain_context_lookup (hb_apply_context_t *c,
     630                 :                                          unsigned int backtrackCount,
     631                 :                                          const USHORT backtrack[],
     632                 :                                          unsigned int inputCount, /* Including the first glyph (not matched) */
     633                 :                                          const USHORT input[], /* Array of input values--start with second glyph */
     634                 :                                          unsigned int lookaheadCount,
     635                 :                                          const USHORT lookahead[],
     636                 :                                          unsigned int lookupCount,
     637                 :                                          const LookupRecord lookupRecord[],
     638                 :                                          ChainContextLookupContext &lookup_context)
     639                 : {
     640                 :   /* First guess */
     641               0 :   if (unlikely (c->buffer->backtrack_len () < backtrackCount ||
     642                 :                 c->buffer->idx + inputCount + lookaheadCount > c->buffer->len ||
     643                 :                 inputCount + lookaheadCount > c->context_length))
     644               0 :     return false;
     645                 : 
     646               0 :   hb_apply_context_t new_context = *c;
     647                 :   return match_backtrack (c,
     648                 :                           backtrackCount, backtrack,
     649               0 :                           lookup_context.funcs.match, lookup_context.match_data[0])
     650                 :       && match_input (c,
     651                 :                       inputCount, input,
     652                 :                       lookup_context.funcs.match, lookup_context.match_data[1],
     653               0 :                       &new_context.context_length)
     654                 :       && match_lookahead (c,
     655                 :                           lookaheadCount, lookahead,
     656                 :                           lookup_context.funcs.match, lookup_context.match_data[2],
     657               0 :                           new_context.context_length)
     658                 :       && apply_lookup (&new_context,
     659                 :                        inputCount,
     660                 :                        lookupCount, lookupRecord,
     661               0 :                        lookup_context.funcs.apply);
     662                 : }
     663                 : 
     664                 : struct ChainRule
     665                 : {
     666                 :   friend struct ChainRuleSet;
     667                 : 
     668                 :   private:
     669               0 :   inline bool apply (hb_apply_context_t *c, ChainContextLookupContext &lookup_context) const
     670                 :   {
     671               0 :     TRACE_APPLY ();
     672               0 :     const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
     673               0 :     const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
     674               0 :     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     675                 :     return chain_context_lookup (c,
     676                 :                                  backtrack.len, backtrack.array,
     677                 :                                  input.len, input.array,
     678                 :                                  lookahead.len, lookahead.array,
     679                 :                                  lookup.len, lookup.array,
     680               0 :                                  lookup_context);
     681                 :   }
     682                 : 
     683                 :   public:
     684               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     685               0 :     TRACE_SANITIZE ();
     686               0 :     if (!backtrack.sanitize (c)) return false;
     687               0 :     HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
     688               0 :     if (!input.sanitize (c)) return false;
     689               0 :     ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
     690               0 :     if (!lookahead.sanitize (c)) return false;
     691               0 :     ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     692               0 :     return lookup.sanitize (c);
     693                 :   }
     694                 : 
     695                 :   private:
     696                 :   ArrayOf<USHORT>
     697                 :                 backtrack;              /* Array of backtracking values
     698                 :                                          * (to be matched before the input
     699                 :                                          * sequence) */
     700                 :   HeadlessArrayOf<USHORT>
     701                 :                 inputX;                 /* Array of input values (start with
     702                 :                                          * second glyph) */
     703                 :   ArrayOf<USHORT>
     704                 :                 lookaheadX;             /* Array of lookahead values's (to be
     705                 :                                          * matched after the input sequence) */
     706                 :   ArrayOf<LookupRecord>
     707                 :                 lookupX;                /* Array of LookupRecords--in
     708                 :                                          * design order) */
     709                 :   public:
     710                 :   DEFINE_SIZE_MIN (8);
     711                 : };
     712                 : 
     713                 : struct ChainRuleSet
     714                 : {
     715               0 :   inline bool apply (hb_apply_context_t *c, ChainContextLookupContext &lookup_context) const
     716                 :   {
     717               0 :     TRACE_APPLY ();
     718               0 :     unsigned int num_rules = rule.len;
     719               0 :     for (unsigned int i = 0; i < num_rules; i++)
     720                 :     {
     721               0 :       if ((this+rule[i]).apply (c, lookup_context))
     722               0 :         return true;
     723                 :     }
     724                 : 
     725               0 :     return false;
     726                 :   }
     727                 : 
     728               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     729               0 :     TRACE_SANITIZE ();
     730               0 :     return rule.sanitize (c, this);
     731                 :   }
     732                 : 
     733                 :   private:
     734                 :   OffsetArrayOf<ChainRule>
     735                 :                 rule;                   /* Array of ChainRule tables
     736                 :                                          * ordered by preference */
     737                 :   public:
     738                 :   DEFINE_SIZE_ARRAY (2, rule);
     739                 : };
     740                 : 
     741                 : struct ChainContextFormat1
     742                 : {
     743                 :   friend struct ChainContext;
     744                 : 
     745                 :   private:
     746               0 :   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
     747                 :   {
     748               0 :     TRACE_APPLY ();
     749               0 :     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
     750               0 :     if (likely (index == NOT_COVERED))
     751               0 :       return false;
     752                 : 
     753               0 :     const ChainRuleSet &rule_set = this+ruleSet[index];
     754                 :     struct ChainContextLookupContext lookup_context = {
     755                 :       {match_glyph, apply_func},
     756                 :       {NULL, NULL, NULL}
     757               0 :     };
     758               0 :     return rule_set.apply (c, lookup_context);
     759                 :   }
     760                 : 
     761               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     762               0 :     TRACE_SANITIZE ();
     763               0 :     return coverage.sanitize (c, this)
     764               0 :         && ruleSet.sanitize (c, this);
     765                 :   }
     766                 : 
     767                 :   private:
     768                 :   USHORT        format;                 /* Format identifier--format = 1 */
     769                 :   OffsetTo<Coverage>
     770                 :                 coverage;               /* Offset to Coverage table--from
     771                 :                                          * beginning of table */
     772                 :   OffsetArrayOf<ChainRuleSet>
     773                 :                 ruleSet;                /* Array of ChainRuleSet tables
     774                 :                                          * ordered by Coverage Index */
     775                 :   public:
     776                 :   DEFINE_SIZE_ARRAY (6, ruleSet);
     777                 : };
     778                 : 
     779                 : struct ChainContextFormat2
     780                 : {
     781                 :   friend struct ChainContext;
     782                 : 
     783                 :   private:
     784               0 :   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
     785                 :   {
     786               0 :     TRACE_APPLY ();
     787               0 :     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
     788               0 :     if (likely (index == NOT_COVERED))
     789               0 :       return false;
     790                 : 
     791               0 :     const ClassDef &backtrack_class_def = this+backtrackClassDef;
     792               0 :     const ClassDef &input_class_def = this+inputClassDef;
     793               0 :     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
     794                 : 
     795               0 :     index = input_class_def (c->buffer->info[c->buffer->idx].codepoint);
     796               0 :     const ChainRuleSet &rule_set = this+ruleSet[index];
     797                 :     struct ChainContextLookupContext lookup_context = {
     798                 :       {match_class, apply_func},
     799                 :       {&backtrack_class_def,
     800                 :        &input_class_def,
     801                 :        &lookahead_class_def}
     802               0 :     };
     803               0 :     return rule_set.apply (c, lookup_context);
     804                 :   }
     805                 : 
     806               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     807               0 :     TRACE_SANITIZE ();
     808               0 :     return coverage.sanitize (c, this)
     809               0 :         && backtrackClassDef.sanitize (c, this)
     810               0 :         && inputClassDef.sanitize (c, this)
     811               0 :         && lookaheadClassDef.sanitize (c, this)
     812               0 :         && ruleSet.sanitize (c, this);
     813                 :   }
     814                 : 
     815                 :   private:
     816                 :   USHORT        format;                 /* Format identifier--format = 2 */
     817                 :   OffsetTo<Coverage>
     818                 :                 coverage;               /* Offset to Coverage table--from
     819                 :                                          * beginning of table */
     820                 :   OffsetTo<ClassDef>
     821                 :                 backtrackClassDef;      /* Offset to glyph ClassDef table
     822                 :                                          * containing backtrack sequence
     823                 :                                          * data--from beginning of table */
     824                 :   OffsetTo<ClassDef>
     825                 :                 inputClassDef;          /* Offset to glyph ClassDef
     826                 :                                          * table containing input sequence
     827                 :                                          * data--from beginning of table */
     828                 :   OffsetTo<ClassDef>
     829                 :                 lookaheadClassDef;      /* Offset to glyph ClassDef table
     830                 :                                          * containing lookahead sequence
     831                 :                                          * data--from beginning of table */
     832                 :   OffsetArrayOf<ChainRuleSet>
     833                 :                 ruleSet;                /* Array of ChainRuleSet tables
     834                 :                                          * ordered by class */
     835                 :   public:
     836                 :   DEFINE_SIZE_ARRAY (12, ruleSet);
     837                 : };
     838                 : 
     839                 : struct ChainContextFormat3
     840                 : {
     841                 :   friend struct ChainContext;
     842                 : 
     843                 :   private:
     844                 : 
     845               0 :   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
     846                 :   {
     847               0 :     TRACE_APPLY ();
     848               0 :     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     849                 : 
     850               0 :     unsigned int index = (this+input[0]) (c->buffer->info[c->buffer->idx].codepoint);
     851               0 :     if (likely (index == NOT_COVERED))
     852               0 :       return false;
     853                 : 
     854               0 :     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
     855               0 :     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     856                 :     struct ChainContextLookupContext lookup_context = {
     857                 :       {match_coverage, apply_func},
     858                 :       {this, this, this}
     859               0 :     };
     860                 :     return chain_context_lookup (c,
     861                 :                                  backtrack.len, (const USHORT *) backtrack.array,
     862                 :                                  input.len, (const USHORT *) input.array + 1,
     863                 :                                  lookahead.len, (const USHORT *) lookahead.array,
     864                 :                                  lookup.len, lookup.array,
     865               0 :                                  lookup_context);
     866                 :   }
     867                 : 
     868               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     869               0 :     TRACE_SANITIZE ();
     870               0 :     if (!backtrack.sanitize (c, this)) return false;
     871               0 :     OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     872               0 :     if (!input.sanitize (c, this)) return false;
     873               0 :     OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
     874               0 :     if (!lookahead.sanitize (c, this)) return false;
     875               0 :     ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     876               0 :     return lookup.sanitize (c);
     877                 :   }
     878                 : 
     879                 :   private:
     880                 :   USHORT        format;                 /* Format identifier--format = 3 */
     881                 :   OffsetArrayOf<Coverage>
     882                 :                 backtrack;              /* Array of coverage tables
     883                 :                                          * in backtracking sequence, in  glyph
     884                 :                                          * sequence order */
     885                 :   OffsetArrayOf<Coverage>
     886                 :                 inputX          ;       /* Array of coverage
     887                 :                                          * tables in input sequence, in glyph
     888                 :                                          * sequence order */
     889                 :   OffsetArrayOf<Coverage>
     890                 :                 lookaheadX;             /* Array of coverage tables
     891                 :                                          * in lookahead sequence, in glyph
     892                 :                                          * sequence order */
     893                 :   ArrayOf<LookupRecord>
     894                 :                 lookupX;                /* Array of LookupRecords--in
     895                 :                                          * design order) */
     896                 :   public:
     897                 :   DEFINE_SIZE_MIN (10);
     898                 : };
     899                 : 
     900                 : struct ChainContext
     901                 : {
     902                 :   protected:
     903               0 :   inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
     904                 :   {
     905               0 :     TRACE_APPLY ();
     906               0 :     switch (u.format) {
     907               0 :     case 1: return u.format1.apply (c, apply_func);
     908               0 :     case 2: return u.format2.apply (c, apply_func);
     909               0 :     case 3: return u.format3.apply (c, apply_func);
     910               0 :     default:return false;
     911                 :     }
     912                 :   }
     913                 : 
     914               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     915               0 :     TRACE_SANITIZE ();
     916               0 :     if (!u.format.sanitize (c)) return false;
     917               0 :     switch (u.format) {
     918               0 :     case 1: return u.format1.sanitize (c);
     919               0 :     case 2: return u.format2.sanitize (c);
     920               0 :     case 3: return u.format3.sanitize (c);
     921               0 :     default:return true;
     922                 :     }
     923                 :   }
     924                 : 
     925                 :   private:
     926                 :   union {
     927                 :   USHORT                format; /* Format identifier */
     928                 :   ChainContextFormat1   format1;
     929                 :   ChainContextFormat2   format2;
     930                 :   ChainContextFormat3   format3;
     931                 :   } u;
     932                 : };
     933                 : 
     934                 : 
     935                 : struct ExtensionFormat1
     936                 : {
     937                 :   friend struct Extension;
     938                 : 
     939                 :   protected:
     940               0 :   inline unsigned int get_type (void) const { return extensionLookupType; }
     941               0 :   inline unsigned int get_offset (void) const { return extensionOffset; }
     942                 : 
     943               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     944               0 :     TRACE_SANITIZE ();
     945               0 :     return c->check_struct (this);
     946                 :   }
     947                 : 
     948                 :   private:
     949                 :   USHORT        format;                 /* Format identifier. Set to 1. */
     950                 :   USHORT        extensionLookupType;    /* Lookup type of subtable referenced
     951                 :                                          * by ExtensionOffset (i.e. the
     952                 :                                          * extension subtable). */
     953                 :   ULONG         extensionOffset;        /* Offset to the extension subtable,
     954                 :                                          * of lookup type subtable. */
     955                 :   public:
     956                 :   DEFINE_SIZE_STATIC (8);
     957                 : };
     958                 : 
     959                 : struct Extension
     960                 : {
     961               0 :   inline unsigned int get_type (void) const
     962                 :   {
     963               0 :     switch (u.format) {
     964               0 :     case 1: return u.format1.get_type ();
     965               0 :     default:return 0;
     966                 :     }
     967                 :   }
     968               0 :   inline unsigned int get_offset (void) const
     969                 :   {
     970               0 :     switch (u.format) {
     971               0 :     case 1: return u.format1.get_offset ();
     972               0 :     default:return 0;
     973                 :     }
     974                 :   }
     975                 : 
     976               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     977               0 :     TRACE_SANITIZE ();
     978               0 :     if (!u.format.sanitize (c)) return false;
     979               0 :     switch (u.format) {
     980               0 :     case 1: return u.format1.sanitize (c);
     981               0 :     default:return true;
     982                 :     }
     983                 :   }
     984                 : 
     985                 :   private:
     986                 :   union {
     987                 :   USHORT                format;         /* Format identifier */
     988                 :   ExtensionFormat1      format1;
     989                 :   } u;
     990                 : };
     991                 : 
     992                 : 
     993                 : /*
     994                 :  * GSUB/GPOS Common
     995                 :  */
     996                 : 
     997                 : struct GSUBGPOS
     998                 : {
     999                 :   static const hb_tag_t GSUBTag = HB_OT_TAG_GSUB;
    1000                 :   static const hb_tag_t GPOSTag = HB_OT_TAG_GPOS;
    1001                 : 
    1002                 :   inline unsigned int get_script_count (void) const
    1003                 :   { return (this+scriptList).len; }
    1004                 :   inline const Tag& get_script_tag (unsigned int i) const
    1005                 :   { return (this+scriptList).get_tag (i); }
    1006               0 :   inline unsigned int get_script_tags (unsigned int start_offset,
    1007                 :                                        unsigned int *script_count /* IN/OUT */,
    1008                 :                                        hb_tag_t     *script_tags /* OUT */) const
    1009               0 :   { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
    1010               0 :   inline const Script& get_script (unsigned int i) const
    1011               0 :   { return (this+scriptList)[i]; }
    1012               0 :   inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
    1013               0 :   { return (this+scriptList).find_index (tag, index); }
    1014                 : 
    1015                 :   inline unsigned int get_feature_count (void) const
    1016                 :   { return (this+featureList).len; }
    1017               0 :   inline const Tag& get_feature_tag (unsigned int i) const
    1018               0 :   { return (this+featureList).get_tag (i); }
    1019               0 :   inline unsigned int get_feature_tags (unsigned int start_offset,
    1020                 :                                         unsigned int *feature_count /* IN/OUT */,
    1021                 :                                         hb_tag_t     *feature_tags /* OUT */) const
    1022               0 :   { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
    1023               0 :   inline const Feature& get_feature (unsigned int i) const
    1024               0 :   { return (this+featureList)[i]; }
    1025                 :   inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
    1026                 :   { return (this+featureList).find_index (tag, index); }
    1027                 : 
    1028                 :   inline unsigned int get_lookup_count (void) const
    1029                 :   { return (this+lookupList).len; }
    1030               0 :   inline const Lookup& get_lookup (unsigned int i) const
    1031               0 :   { return (this+lookupList)[i]; }
    1032                 : 
    1033               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
    1034               0 :     TRACE_SANITIZE ();
    1035               0 :     return version.sanitize (c) && likely (version.major == 1)
    1036               0 :         && scriptList.sanitize (c, this)
    1037               0 :         && featureList.sanitize (c, this)
    1038               0 :         && lookupList.sanitize (c, this);
    1039                 :   }
    1040                 : 
    1041                 :   protected:
    1042                 :   FixedVersion  version;        /* Version of the GSUB/GPOS table--initially set
    1043                 :                                  * to 0x00010000 */
    1044                 :   OffsetTo<ScriptList>
    1045                 :                 scriptList;     /* ScriptList table */
    1046                 :   OffsetTo<FeatureList>
    1047                 :                 featureList;    /* FeatureList table */
    1048                 :   OffsetTo<LookupList>
    1049                 :                 lookupList;     /* LookupList table */
    1050                 :   public:
    1051                 :   DEFINE_SIZE_STATIC (10);
    1052                 : };
    1053                 : 
    1054                 : 
    1055                 : 
    1056                 : #endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */

Generated by: LCOV version 1.7