| OLD | NEW | 
|     1 /* |     1 /* | 
|     2  * Copyright (C) 2007,2008,2009,2010  Red Hat, Inc. |     2  * Copyright © 2007,2008,2009,2010  Red Hat, Inc. | 
|     3  * Copyright (C) 2010  Google, Inc. |     3  * Copyright © 2010  Google, Inc. | 
|     4  * |     4  * | 
|     5  *  This is part of HarfBuzz, a text shaping library. |     5  *  This is part of HarfBuzz, a text shaping library. | 
|     6  * |     6  * | 
|     7  * Permission is hereby granted, without written agreement and without |     7  * Permission is hereby granted, without written agreement and without | 
|     8  * license or royalty fees, to use, copy, modify, and distribute this |     8  * license or royalty fees, to use, copy, modify, and distribute this | 
|     9  * software and its documentation for any purpose, provided that the |     9  * software and its documentation for any purpose, provided that the | 
|    10  * above copyright notice and the following two paragraphs appear in |    10  * above copyright notice and the following two paragraphs appear in | 
|    11  * all copies of this software. |    11  * all copies of this software. | 
|    12  * |    12  * | 
|    13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |    13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 
|    14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |    14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | 
|    15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |    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 |    16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | 
|    17  * DAMAGE. |    17  * DAMAGE. | 
|    18  * |    18  * | 
|    19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |    19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | 
|    20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |    20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | 
|    21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS |    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 |    22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO | 
|    23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |    23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 
|    24  * |    24  * | 
|    25  * Red Hat Author(s): Behdad Esfahbod |    25  * Red Hat Author(s): Behdad Esfahbod | 
|    26  * Google Author(s): Behdad Esfahbod |    26  * Google Author(s): Behdad Esfahbod | 
|    27  */ |    27  */ | 
|    28  |    28  | 
|    29 #ifndef HB_OT_LAYOUT_GPOS_PRIVATE_HH |    29 #ifndef HB_OT_LAYOUT_GPOS_TABLE_HH | 
|    30 #define HB_OT_LAYOUT_GPOS_PRIVATE_HH |    30 #define HB_OT_LAYOUT_GPOS_TABLE_HH | 
|    31  |    31  | 
|    32 #include "hb-ot-layout-gsubgpos-private.hh" |    32 #include "hb-ot-layout-gsubgpos-private.hh" | 
|    33  |    33  | 
|    34 HB_BEGIN_DECLS |  | 
|    35  |    34  | 
|    36  |    35  | 
|    37 /* buffer var allocations */ |    36 /* buffer **position** var allocations */ | 
|    38 #define attach_lookback() var.u16[0] /* number of glyphs to go back to attach th
      is glyph to its base */ |    37 #define attach_lookback() var.u16[0] /* number of glyphs to go back to attach th
      is glyph to its base */ | 
|    39 #define cursive_chain() var.i16[1] /* character to which this connects, may be p
      ositive or negative */ |    38 #define cursive_chain() var.i16[1] /* character to which this connects, may be p
      ositive or negative */ | 
|    40  |    39  | 
|    41  |    40  | 
|    42 /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */ |    41 /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */ | 
|    43  |    42  | 
|    44 typedef USHORT Value; |    43 typedef USHORT Value; | 
|    45  |    44  | 
|    46 typedef Value ValueRecord[VAR]; |    45 typedef Value ValueRecord[VAR]; | 
|    47  |    46  | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|    87   Offset        yAdvDevice;             /* Offset to Device table for vertical |    86   Offset        yAdvDevice;             /* Offset to Device table for vertical | 
|    88                                          * advance--measured from beginning of |    87                                          * advance--measured from beginning of | 
|    89                                          * PosTable (may be NULL) */ |    88                                          * PosTable (may be NULL) */ | 
|    90 #endif |    89 #endif | 
|    91  |    90  | 
|    92   inline unsigned int get_len (void) const |    91   inline unsigned int get_len (void) const | 
|    93   { return _hb_popcount32 ((unsigned int) *this); } |    92   { return _hb_popcount32 ((unsigned int) *this); } | 
|    94   inline unsigned int get_size (void) const |    93   inline unsigned int get_size (void) const | 
|    95   { return get_len () * Value::static_size; } |    94   { return get_len () * Value::static_size; } | 
|    96  |    95  | 
|    97   void apply_value (hb_ot_layout_context_t *layout, |    96   void apply_value (hb_font_t            *font, | 
|    98 »       »           const void             *base, |    97 »       »           hb_direction_t        direction, | 
|    99 »       »           const Value            *values, |    98 »       »           const void           *base, | 
|   100 »       »           hb_glyph_position_t    &glyph_pos) const |    99 »       »           const Value          *values, | 
 |   100 »       »           hb_glyph_position_t  &glyph_pos) const | 
|   101   { |   101   { | 
|   102     unsigned int x_ppem, y_ppem; |   102     unsigned int x_ppem, y_ppem; | 
|   103     unsigned int format = *this; |   103     unsigned int format = *this; | 
 |   104     hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (direction); | 
|   104  |   105  | 
|   105     if (!format) return; |   106     if (!format) return; | 
|   106  |   107  | 
|   107     /* design units -> fractional pixel */ |   108     if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short 
      (values++)); | 
|   108     if (format & xPlacement) glyph_pos.x_offset  += layout->scale_x (get_short (
      values++)); |   109     if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short 
      (values++)); | 
|   109     if (format & yPlacement) glyph_pos.y_offset  += layout->scale_y (get_short (
      values++)); |   110     if (format & xAdvance) { | 
|   110     if (format & xAdvance)   glyph_pos.x_advance += layout->scale_x (get_short (
      values++)); |   111       if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_shor
      t (values++)); else values++; | 
|   111     if (format & yAdvance)   glyph_pos.y_advance += layout->scale_y (get_short (
      values++)); |   112     } | 
 |   113     /* y_advance values grow downward but font-space grows upward, hence negatio
      n */ | 
 |   114     if (format & yAdvance) { | 
 |   115       if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_s
      hort (values++)); else values++; | 
 |   116     } | 
|   112  |   117  | 
|   113     if (!has_device ()) return; |   118     if (!has_device ()) return; | 
|   114  |   119  | 
|   115     x_ppem = layout->font->x_ppem; |   120     x_ppem = font->x_ppem; | 
|   116     y_ppem = layout->font->y_ppem; |   121     y_ppem = font->y_ppem; | 
|   117  |   122  | 
|   118     if (!x_ppem && !y_ppem) return; |   123     if (!x_ppem && !y_ppem) return; | 
|   119  |   124  | 
|   120     /* pixel -> fractional pixel */ |   125     /* pixel -> fractional pixel */ | 
|   121     if (format & xPlaDevice) { |   126     if (format & xPlaDevice) { | 
|   122       if (x_ppem) glyph_pos.x_offset  += (base + get_device (values++)).get_x_de
      lta (layout); else values++; |   127       if (x_ppem) glyph_pos.x_offset  += (base + get_device (values++)).get_x_de
      lta (font); else values++; | 
|   123     } |   128     } | 
|   124     if (format & yPlaDevice) { |   129     if (format & yPlaDevice) { | 
|   125       if (y_ppem) glyph_pos.y_offset  += (base + get_device (values++)).get_y_de
      lta (layout); else values++; |   130       if (y_ppem) glyph_pos.y_offset  += (base + get_device (values++)).get_y_de
      lta (font); else values++; | 
|   126     } |   131     } | 
|   127     if (format & xAdvDevice) { |   132     if (format & xAdvDevice) { | 
|   128       if (x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_x_de
      lta (layout); else values++; |   133       if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (value
      s++)).get_x_delta (font); else values++; | 
|   129     } |   134     } | 
|   130     if (format & yAdvDevice) { |   135     if (format & yAdvDevice) { | 
|   131       if (y_ppem) glyph_pos.y_advance += (base + get_device (values++)).get_y_de
      lta (layout); else values++; |   136       /* y_advance values grow downward but font-space grows upward, hence negat
      ion */ | 
 |   137       if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (valu
      es++)).get_y_delta (font); else values++; | 
|   132     } |   138     } | 
|   133   } |   139   } | 
|   134  |   140  | 
|   135   private: |   141   private: | 
|   136   inline bool sanitize_value_devices (hb_sanitize_context_t *c, void *base, Valu
      e *values) { |   142   inline bool sanitize_value_devices (hb_sanitize_context_t *c, void *base, Valu
      e *values) { | 
|   137     unsigned int format = *this; |   143     unsigned int format = *this; | 
|   138  |   144  | 
|   139     if (format & xPlacement) values++; |   145     if (format & xPlacement) values++; | 
|   140     if (format & yPlacement) values++; |   146     if (format & yPlacement) values++; | 
|   141     if (format & xAdvance)   values++; |   147     if (format & xAdvance)   values++; | 
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   202     return true; |   208     return true; | 
|   203   } |   209   } | 
|   204 }; |   210 }; | 
|   205  |   211  | 
|   206  |   212  | 
|   207 struct AnchorFormat1 |   213 struct AnchorFormat1 | 
|   208 { |   214 { | 
|   209   friend struct Anchor; |   215   friend struct Anchor; | 
|   210  |   216  | 
|   211   private: |   217   private: | 
|   212   inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_i
      d HB_UNUSED, |   218   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, | 
|   213                           hb_position_t *x, hb_position_t *y) const |   219                           hb_position_t *x, hb_position_t *y) const | 
|   214   { |   220   { | 
|   215       *x = layout->scale_x (xCoordinate); |   221       *x = font->em_scale_x (xCoordinate); | 
|   216       *y = layout->scale_y (yCoordinate); |   222       *y = font->em_scale_y (yCoordinate); | 
|   217   } |   223   } | 
|   218  |   224  | 
|   219   inline bool sanitize (hb_sanitize_context_t *c) { |   225   inline bool sanitize (hb_sanitize_context_t *c) { | 
|   220     TRACE_SANITIZE (); |   226     TRACE_SANITIZE (); | 
|   221     return c->check_struct (this); |   227     return c->check_struct (this); | 
|   222   } |   228   } | 
|   223  |   229  | 
|   224   private: |   230   private: | 
|   225   USHORT        format;                 /* Format identifier--format = 1 */ |   231   USHORT        format;                 /* Format identifier--format = 1 */ | 
|   226   SHORT         xCoordinate;            /* Horizontal value--in design units */ |   232   SHORT         xCoordinate;            /* Horizontal value--in design units */ | 
|   227   SHORT         yCoordinate;            /* Vertical value--in design units */ |   233   SHORT         yCoordinate;            /* Vertical value--in design units */ | 
|   228   public: |   234   public: | 
|   229   DEFINE_SIZE_STATIC (6); |   235   DEFINE_SIZE_STATIC (6); | 
|   230 }; |   236 }; | 
|   231  |   237  | 
|   232 struct AnchorFormat2 |   238 struct AnchorFormat2 | 
|   233 { |   239 { | 
|   234   friend struct Anchor; |   240   friend struct Anchor; | 
|   235  |   241  | 
|   236   private: |   242   private: | 
|   237   inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_i
      d, |   243   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, | 
|   238                           hb_position_t *x, hb_position_t *y) const |   244                           hb_position_t *x, hb_position_t *y) const | 
|   239   { |   245   { | 
|   240       unsigned int x_ppem = layout->font->x_ppem; |   246       unsigned int x_ppem = font->x_ppem; | 
|   241       unsigned int y_ppem = layout->font->y_ppem; |   247       unsigned int y_ppem = font->y_ppem; | 
|   242       hb_position_t cx, cy; |   248       hb_position_t cx, cy; | 
|   243       hb_bool_t ret = false; |   249       hb_bool_t ret = false; | 
|   244  |   250  | 
|   245       if (x_ppem || y_ppem) |   251       if (x_ppem || y_ppem) | 
|   246 »       ret = hb_font_get_contour_point (layout->font, layout->face, anchorPoint
      , glyph_id, &cx, &cy); |   252 »       ret = hb_font_get_glyph_contour_point_for_origin (font, glyph_id, anchor
      Point, HB_DIRECTION_LTR, &cx, &cy); | 
|   247       *x = x_ppem && ret ? cx : layout->scale_x (xCoordinate); |   253       *x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate); | 
|   248       *y = y_ppem && ret ? cy : layout->scale_y (yCoordinate); |   254       *y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate); | 
|   249   } |   255   } | 
|   250  |   256  | 
|   251   inline bool sanitize (hb_sanitize_context_t *c) { |   257   inline bool sanitize (hb_sanitize_context_t *c) { | 
|   252     TRACE_SANITIZE (); |   258     TRACE_SANITIZE (); | 
|   253     return c->check_struct (this); |   259     return c->check_struct (this); | 
|   254   } |   260   } | 
|   255  |   261  | 
|   256   private: |   262   private: | 
|   257   USHORT        format;                 /* Format identifier--format = 2 */ |   263   USHORT        format;                 /* Format identifier--format = 2 */ | 
|   258   SHORT         xCoordinate;            /* Horizontal value--in design units */ |   264   SHORT         xCoordinate;            /* Horizontal value--in design units */ | 
|   259   SHORT         yCoordinate;            /* Vertical value--in design units */ |   265   SHORT         yCoordinate;            /* Vertical value--in design units */ | 
|   260   USHORT        anchorPoint;            /* Index to glyph contour point */ |   266   USHORT        anchorPoint;            /* Index to glyph contour point */ | 
|   261   public: |   267   public: | 
|   262   DEFINE_SIZE_STATIC (8); |   268   DEFINE_SIZE_STATIC (8); | 
|   263 }; |   269 }; | 
|   264  |   270  | 
|   265 struct AnchorFormat3 |   271 struct AnchorFormat3 | 
|   266 { |   272 { | 
|   267   friend struct Anchor; |   273   friend struct Anchor; | 
|   268  |   274  | 
|   269   private: |   275   private: | 
|   270   inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_i
      d HB_UNUSED, |   276   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, | 
|   271                           hb_position_t *x, hb_position_t *y) const |   277                           hb_position_t *x, hb_position_t *y) const | 
|   272   { |   278   { | 
|   273       *x = layout->scale_x (xCoordinate); |   279       *x = font->em_scale_x (xCoordinate); | 
|   274       *y = layout->scale_y (yCoordinate); |   280       *y = font->em_scale_y (yCoordinate); | 
|   275  |   281  | 
|   276       /* pixel -> fractional pixel */ |   282       if (font->x_ppem) | 
|   277       if (layout->font->x_ppem) |   283 »       *x += (this+xDeviceTable).get_x_delta (font); | 
|   278 »       *x += (this+xDeviceTable).get_x_delta (layout); |   284       if (font->y_ppem) | 
|   279       if (layout->font->y_ppem) |   285 »       *y += (this+yDeviceTable).get_x_delta (font); | 
|   280 »       *y += (this+yDeviceTable).get_x_delta (layout); |  | 
|   281   } |   286   } | 
|   282  |   287  | 
|   283   inline bool sanitize (hb_sanitize_context_t *c) { |   288   inline bool sanitize (hb_sanitize_context_t *c) { | 
|   284     TRACE_SANITIZE (); |   289     TRACE_SANITIZE (); | 
|   285     return c->check_struct (this) |   290     return c->check_struct (this) | 
|   286         && xDeviceTable.sanitize (c, this) |   291         && xDeviceTable.sanitize (c, this) | 
|   287         && yDeviceTable.sanitize (c, this); |   292         && yDeviceTable.sanitize (c, this); | 
|   288   } |   293   } | 
|   289  |   294  | 
|   290   private: |   295   private: | 
|   291   USHORT        format;                 /* Format identifier--format = 3 */ |   296   USHORT        format;                 /* Format identifier--format = 3 */ | 
|   292   SHORT         xCoordinate;            /* Horizontal value--in design units */ |   297   SHORT         xCoordinate;            /* Horizontal value--in design units */ | 
|   293   SHORT         yCoordinate;            /* Vertical value--in design units */ |   298   SHORT         yCoordinate;            /* Vertical value--in design units */ | 
|   294   OffsetTo<Device> |   299   OffsetTo<Device> | 
|   295                 xDeviceTable;           /* Offset to Device table for X |   300                 xDeviceTable;           /* Offset to Device table for X | 
|   296                                          * coordinate-- from beginning of |   301                                          * coordinate-- from beginning of | 
|   297                                          * Anchor table (may be NULL) */ |   302                                          * Anchor table (may be NULL) */ | 
|   298   OffsetTo<Device> |   303   OffsetTo<Device> | 
|   299                 yDeviceTable;           /* Offset to Device table for Y |   304                 yDeviceTable;           /* Offset to Device table for Y | 
|   300                                          * coordinate-- from beginning of |   305                                          * coordinate-- from beginning of | 
|   301                                          * Anchor table (may be NULL) */ |   306                                          * Anchor table (may be NULL) */ | 
|   302   public: |   307   public: | 
|   303   DEFINE_SIZE_STATIC (10); |   308   DEFINE_SIZE_STATIC (10); | 
|   304 }; |   309 }; | 
|   305  |   310  | 
|   306 struct Anchor |   311 struct Anchor | 
|   307 { |   312 { | 
|   308   inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_i
      d, |   313   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, | 
|   309                           hb_position_t *x, hb_position_t *y) const |   314                           hb_position_t *x, hb_position_t *y) const | 
|   310   { |   315   { | 
|   311     *x = *y = 0; |   316     *x = *y = 0; | 
|   312     switch (u.format) { |   317     switch (u.format) { | 
|   313     case 1: u.format1.get_anchor (layout, glyph_id, x, y); return; |   318     case 1: u.format1.get_anchor (font, glyph_id, x, y); return; | 
|   314     case 2: u.format2.get_anchor (layout, glyph_id, x, y); return; |   319     case 2: u.format2.get_anchor (font, glyph_id, x, y); return; | 
|   315     case 3: u.format3.get_anchor (layout, glyph_id, x, y); return; |   320     case 3: u.format3.get_anchor (font, glyph_id, x, y); return; | 
|   316     default:»   »       »       »       »       »           return; |   321     default:»   »       »       »       »       »        return; | 
|   317     } |   322     } | 
|   318   } |   323   } | 
|   319  |   324  | 
|   320   inline bool sanitize (hb_sanitize_context_t *c) { |   325   inline bool sanitize (hb_sanitize_context_t *c) { | 
|   321     TRACE_SANITIZE (); |   326     TRACE_SANITIZE (); | 
|   322     if (!u.format.sanitize (c)) return false; |   327     if (!u.format.sanitize (c)) return false; | 
|   323     switch (u.format) { |   328     switch (u.format) { | 
|   324     case 1: return u.format1.sanitize (c); |   329     case 1: return u.format1.sanitize (c); | 
|   325     case 2: return u.format2.sanitize (c); |   330     case 2: return u.format2.sanitize (c); | 
|   326     case 3: return u.format3.sanitize (c); |   331     case 3: return u.format3.sanitize (c); | 
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   396   { |   401   { | 
|   397     TRACE_APPLY (); |   402     TRACE_APPLY (); | 
|   398     const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index); |   403     const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index); | 
|   399     unsigned int mark_class = record.klass; |   404     unsigned int mark_class = record.klass; | 
|   400  |   405  | 
|   401     const Anchor& mark_anchor = this + record.markAnchor; |   406     const Anchor& mark_anchor = this + record.markAnchor; | 
|   402     const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, cl
      ass_count); |   407     const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, cl
      ass_count); | 
|   403  |   408  | 
|   404     hb_position_t mark_x, mark_y, base_x, base_y; |   409     hb_position_t mark_x, mark_y, base_x, base_y; | 
|   405  |   410  | 
|   406     mark_anchor.get_anchor (c->layout, c->buffer->info[c->buffer->i].codepoint, 
      &mark_x, &mark_y); |   411     mark_anchor.get_anchor (c->font, c->buffer->info[c->buffer->idx].codepoint, 
      &mark_x, &mark_y); | 
|   407     glyph_anchor.get_anchor (c->layout, c->buffer->info[glyph_pos].codepoint, &b
      ase_x, &base_y); |   412     glyph_anchor.get_anchor (c->font, c->buffer->info[glyph_pos].codepoint, &bas
      e_x, &base_y); | 
|   408  |   413  | 
|   409     hb_glyph_position_t &o = c->buffer->pos[c->buffer->i]; |   414     hb_glyph_position_t &o = c->buffer->pos[c->buffer->idx]; | 
|   410     o.x_offset = base_x - mark_x; |   415     o.x_offset = base_x - mark_x; | 
|   411     o.y_offset = base_y - mark_y; |   416     o.y_offset = base_y - mark_y; | 
|   412     o.attach_lookback() = c->buffer->i - glyph_pos; |   417     o.attach_lookback() = c->buffer->idx - glyph_pos; | 
|   413  |   418  | 
|   414     c->buffer->i++; |   419     c->buffer->idx++; | 
|   415     return true; |   420     return true; | 
|   416   } |   421   } | 
|   417  |   422  | 
|   418   inline bool sanitize (hb_sanitize_context_t *c) { |   423   inline bool sanitize (hb_sanitize_context_t *c) { | 
|   419     TRACE_SANITIZE (); |   424     TRACE_SANITIZE (); | 
|   420     return ArrayOf<MarkRecord>::sanitize (c, this); |   425     return ArrayOf<MarkRecord>::sanitize (c, this); | 
|   421   } |   426   } | 
|   422 }; |   427 }; | 
|   423  |   428  | 
|   424  |   429  | 
|   425 /* Lookups */ |   430 /* Lookups */ | 
|   426  |   431  | 
|   427 struct SinglePosFormat1 |   432 struct SinglePosFormat1 | 
|   428 { |   433 { | 
|   429   friend struct SinglePos; |   434   friend struct SinglePos; | 
|   430  |   435  | 
|   431   private: |   436   private: | 
|   432   inline bool apply (hb_apply_context_t *c) const |   437   inline bool apply (hb_apply_context_t *c) const | 
|   433   { |   438   { | 
|   434     TRACE_APPLY (); |   439     TRACE_APPLY (); | 
|   435     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoin
      t); |   440     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepo
      int); | 
|   436     if (likely (index == NOT_COVERED)) |   441     if (likely (index == NOT_COVERED)) | 
|   437       return false; |   442       return false; | 
|   438  |   443  | 
|   439     valueFormat.apply_value (c->layout, this, values, c->buffer->pos[c->buffer->
      i]); |   444     valueFormat.apply_value (c->font, c->direction, this, | 
 |   445 »       »       »            values, c->buffer->pos[c->buffer->idx]); | 
|   440  |   446  | 
|   441     c->buffer->i++; |   447     c->buffer->idx++; | 
|   442     return true; |   448     return true; | 
|   443   } |   449   } | 
|   444  |   450  | 
|   445   inline bool sanitize (hb_sanitize_context_t *c) { |   451   inline bool sanitize (hb_sanitize_context_t *c) { | 
|   446     TRACE_SANITIZE (); |   452     TRACE_SANITIZE (); | 
|   447     return c->check_struct (this) |   453     return c->check_struct (this) | 
|   448         && coverage.sanitize (c, this) |   454         && coverage.sanitize (c, this) | 
|   449         && valueFormat.sanitize_value (c, this, values); |   455         && valueFormat.sanitize_value (c, this, values); | 
|   450   } |   456   } | 
|   451  |   457  | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|   464 }; |   470 }; | 
|   465  |   471  | 
|   466 struct SinglePosFormat2 |   472 struct SinglePosFormat2 | 
|   467 { |   473 { | 
|   468   friend struct SinglePos; |   474   friend struct SinglePos; | 
|   469  |   475  | 
|   470   private: |   476   private: | 
|   471   inline bool apply (hb_apply_context_t *c) const |   477   inline bool apply (hb_apply_context_t *c) const | 
|   472   { |   478   { | 
|   473     TRACE_APPLY (); |   479     TRACE_APPLY (); | 
|   474     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoin
      t); |   480     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepo
      int); | 
|   475     if (likely (index == NOT_COVERED)) |   481     if (likely (index == NOT_COVERED)) | 
|   476       return false; |   482       return false; | 
|   477  |   483  | 
|   478     if (likely (index >= valueCount)) |   484     if (likely (index >= valueCount)) | 
|   479       return false; |   485       return false; | 
|   480  |   486  | 
|   481     valueFormat.apply_value (c->layout, this, |   487     valueFormat.apply_value (c->font, c->direction, this, | 
|   482                              &values[index * valueFormat.get_len ()], |   488                              &values[index * valueFormat.get_len ()], | 
|   483 »       »       »            c->buffer->pos[c->buffer->i]); |   489 »       »       »            c->buffer->pos[c->buffer->idx]); | 
|   484  |   490  | 
|   485     c->buffer->i++; |   491     c->buffer->idx++; | 
|   486     return true; |   492     return true; | 
|   487   } |   493   } | 
|   488  |   494  | 
|   489   inline bool sanitize (hb_sanitize_context_t *c) { |   495   inline bool sanitize (hb_sanitize_context_t *c) { | 
|   490     TRACE_SANITIZE (); |   496     TRACE_SANITIZE (); | 
|   491     return c->check_struct (this) |   497     return c->check_struct (this) | 
|   492         && coverage.sanitize (c, this) |   498         && coverage.sanitize (c, this) | 
|   493         && valueFormat.sanitize_values (c, this, values, valueCount); |   499         && valueFormat.sanitize_values (c, this, values, valueCount); | 
|   494   } |   500   } | 
|   495  |   501  | 
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   567     unsigned int len1 = valueFormats[0].get_len (); |   573     unsigned int len1 = valueFormats[0].get_len (); | 
|   568     unsigned int len2 = valueFormats[1].get_len (); |   574     unsigned int len2 = valueFormats[1].get_len (); | 
|   569     unsigned int record_size = USHORT::static_size * (1 + len1 + len2); |   575     unsigned int record_size = USHORT::static_size * (1 + len1 + len2); | 
|   570  |   576  | 
|   571     unsigned int count = len; |   577     unsigned int count = len; | 
|   572     const PairValueRecord *record = CastP<PairValueRecord> (array); |   578     const PairValueRecord *record = CastP<PairValueRecord> (array); | 
|   573     for (unsigned int i = 0; i < count; i++) |   579     for (unsigned int i = 0; i < count; i++) | 
|   574     { |   580     { | 
|   575       if (c->buffer->info[pos].codepoint == record->secondGlyph) |   581       if (c->buffer->info[pos].codepoint == record->secondGlyph) | 
|   576       { |   582       { | 
|   577 »       valueFormats[0].apply_value (c->layout, this, &record->values[0], c->buf
      fer->pos[c->buffer->i]); |   583 »       valueFormats[0].apply_value (c->font, c->direction, this, | 
|   578 »       valueFormats[1].apply_value (c->layout, this, &record->values[len1], c->
      buffer->pos[pos]); |   584 »       »       »       »            &record->values[0], c->buffer->pos[c->buffe
      r->idx]); | 
 |   585 »       valueFormats[1].apply_value (c->font, c->direction, this, | 
 |   586 »       »       »       »            &record->values[len1], c->buffer->pos[pos])
      ; | 
|   579         if (len2) |   587         if (len2) | 
|   580           pos++; |   588           pos++; | 
|   581 »       c->buffer->i = pos; |   589 »       c->buffer->idx = pos; | 
|   582         return true; |   590         return true; | 
|   583       } |   591       } | 
|   584       record = &StructAtOffset<PairValueRecord> (record, record_size); |   592       record = &StructAtOffset<PairValueRecord> (record, record_size); | 
|   585     } |   593     } | 
|   586  |   594  | 
|   587     return false; |   595     return false; | 
|   588   } |   596   } | 
|   589  |   597  | 
|   590   struct sanitize_closure_t { |   598   struct sanitize_closure_t { | 
|   591     void *base; |   599     void *base; | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
|   614 }; |   622 }; | 
|   615  |   623  | 
|   616 struct PairPosFormat1 |   624 struct PairPosFormat1 | 
|   617 { |   625 { | 
|   618   friend struct PairPos; |   626   friend struct PairPos; | 
|   619  |   627  | 
|   620   private: |   628   private: | 
|   621   inline bool apply (hb_apply_context_t *c) const |   629   inline bool apply (hb_apply_context_t *c) const | 
|   622   { |   630   { | 
|   623     TRACE_APPLY (); |   631     TRACE_APPLY (); | 
|   624     unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length); |   632     hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff
      er->idx, 1); | 
|   625     if (unlikely (c->buffer->i + 2 > end)) |   633     if (skippy_iter.has_no_chance ()) | 
|   626       return false; |   634       return false; | 
|   627  |   635  | 
|   628     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoin
      t); |   636     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepo
      int); | 
|   629     if (likely (index == NOT_COVERED)) |   637     if (likely (index == NOT_COVERED)) | 
|   630       return false; |   638       return false; | 
|   631  |   639  | 
|   632     unsigned int j = c->buffer->i + 1; |   640     if (!skippy_iter.next ()) | 
|   633     while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->loo
      kup_props, NULL)) |   641       return false; | 
|   634     { |  | 
|   635       if (unlikely (j == end)) |  | 
|   636 »       return false; |  | 
|   637       j++; |  | 
|   638     } |  | 
|   639  |   642  | 
|   640     return (this+pairSet[index]).apply (c, &valueFormat1, j); |   643     return (this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx); | 
|   641   } |   644   } | 
|   642  |   645  | 
|   643   inline bool sanitize (hb_sanitize_context_t *c) { |   646   inline bool sanitize (hb_sanitize_context_t *c) { | 
|   644     TRACE_SANITIZE (); |   647     TRACE_SANITIZE (); | 
|   645  |   648  | 
|   646     unsigned int len1 = valueFormat1.get_len (); |   649     unsigned int len1 = valueFormat1.get_len (); | 
|   647     unsigned int len2 = valueFormat2.get_len (); |   650     unsigned int len2 = valueFormat2.get_len (); | 
|   648     PairSet::sanitize_closure_t closure = { |   651     PairSet::sanitize_closure_t closure = { | 
|   649       this, |   652       this, | 
|   650       &valueFormat1, |   653       &valueFormat1, | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
|   676 }; |   679 }; | 
|   677  |   680  | 
|   678 struct PairPosFormat2 |   681 struct PairPosFormat2 | 
|   679 { |   682 { | 
|   680   friend struct PairPos; |   683   friend struct PairPos; | 
|   681  |   684  | 
|   682   private: |   685   private: | 
|   683   inline bool apply (hb_apply_context_t *c) const |   686   inline bool apply (hb_apply_context_t *c) const | 
|   684   { |   687   { | 
|   685     TRACE_APPLY (); |   688     TRACE_APPLY (); | 
|   686     unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length); |   689     hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff
      er->idx, 1); | 
|   687     if (unlikely (c->buffer->i + 2 > end)) |   690     if (skippy_iter.has_no_chance ()) | 
|   688       return false; |   691       return false; | 
|   689  |   692  | 
|   690     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoin
      t); |   693     unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepo
      int); | 
|   691     if (likely (index == NOT_COVERED)) |   694     if (likely (index == NOT_COVERED)) | 
|   692       return false; |   695       return false; | 
|   693  |   696  | 
|   694     unsigned int j = c->buffer->i + 1; |   697     if (!skippy_iter.next ()) | 
|   695     while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->loo
      kup_props, NULL)) |   698       return false; | 
|   696     { |  | 
|   697       if (unlikely (j == end)) |  | 
|   698 »       return false; |  | 
|   699       j++; |  | 
|   700     } |  | 
|   701  |   699  | 
|   702     unsigned int len1 = valueFormat1.get_len (); |   700     unsigned int len1 = valueFormat1.get_len (); | 
|   703     unsigned int len2 = valueFormat2.get_len (); |   701     unsigned int len2 = valueFormat2.get_len (); | 
|   704     unsigned int record_len = len1 + len2; |   702     unsigned int record_len = len1 + len2; | 
|   705  |   703  | 
|   706     unsigned int klass1 = (this+classDef1) (c->buffer->info[c->buffer->i].codepo
      int); |   704     unsigned int klass1 = (this+classDef1) (c->buffer->info[c->buffer->idx].code
      point); | 
|   707     unsigned int klass2 = (this+classDef2) (c->buffer->info[j].codepoint); |   705     unsigned int klass2 = (this+classDef2) (c->buffer->info[skippy_iter.idx].cod
      epoint); | 
|   708     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) |   706     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) | 
|   709       return false; |   707       return false; | 
|   710  |   708  | 
|   711     const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; |   709     const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; | 
|   712     valueFormat1.apply_value (c->layout, this, v, c->buffer->pos[c->buffer->i]); |   710     valueFormat1.apply_value (c->font, c->direction, this, | 
|   713     valueFormat2.apply_value (c->layout, this, v + len1, c->buffer->pos[j]); |   711 »       »       »             v, c->buffer->pos[c->buffer->idx]); | 
 |   712     valueFormat2.apply_value (c->font, c->direction, this, | 
 |   713 »       »       »             v + len1, c->buffer->pos[skippy_iter.idx]); | 
|   714  |   714  | 
 |   715     c->buffer->idx = skippy_iter.idx; | 
|   715     if (len2) |   716     if (len2) | 
|   716       j++; |   717       c->buffer->idx++; | 
|   717     c->buffer->i = j; |  | 
|   718  |   718  | 
|   719     return true; |   719     return true; | 
|   720   } |   720   } | 
|   721  |   721  | 
|   722   inline bool sanitize (hb_sanitize_context_t *c) { |   722   inline bool sanitize (hb_sanitize_context_t *c) { | 
|   723     TRACE_SANITIZE (); |   723     TRACE_SANITIZE (); | 
|   724     if (!(c->check_struct (this) |   724     if (!(c->check_struct (this) | 
|   725        && coverage.sanitize (c, this) |   725        && coverage.sanitize (c, this) | 
|   726        && classDef1.sanitize (c, this) |   726        && classDef1.sanitize (c, this) | 
|   727        && classDef2.sanitize (c, this))) return false; |   727        && classDef2.sanitize (c, this))) return false; | 
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   829  |   829  | 
|   830   private: |   830   private: | 
|   831   inline bool apply (hb_apply_context_t *c) const |   831   inline bool apply (hb_apply_context_t *c) const | 
|   832   { |   832   { | 
|   833     TRACE_APPLY (); |   833     TRACE_APPLY (); | 
|   834  |   834  | 
|   835     /* We don't handle mark glyphs here. */ |   835     /* We don't handle mark glyphs here. */ | 
|   836     if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) |   836     if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) | 
|   837       return false; |   837       return false; | 
|   838  |   838  | 
|   839     unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length); |   839     hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff
      er->idx, 1); | 
|   840     if (unlikely (c->buffer->i + 2 > end)) |   840     if (skippy_iter.has_no_chance ()) | 
|   841       return false; |   841       return false; | 
|   842  |   842  | 
|   843     const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buf
      fer->info[c->buffer->i].codepoint)]; |   843     const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buf
      fer->info[c->buffer->idx].codepoint)]; | 
|   844     if (!this_record.exitAnchor) |   844     if (!this_record.exitAnchor) | 
|   845       return false; |   845       return false; | 
|   846  |   846  | 
|   847     unsigned int j = c->buffer->i + 1; |   847     if (!skippy_iter.next ()) | 
|   848     while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->loo
      kup_props, NULL)) |   848       return false; | 
|   849     { |  | 
|   850       if (unlikely (j == end)) |  | 
|   851 »       return false; |  | 
|   852       j++; |  | 
|   853     } |  | 
|   854  |   849  | 
|   855     const EntryExitRecord &next_record = entryExitRecord[(this+coverage) (c->buf
      fer->info[j].codepoint)]; |   850     const EntryExitRecord &next_record = entryExitRecord[(this+coverage) (c->buf
      fer->info[skippy_iter.idx].codepoint)]; | 
|   856     if (!next_record.entryAnchor) |   851     if (!next_record.entryAnchor) | 
|   857       return false; |   852       return false; | 
|   858  |   853  | 
|   859     unsigned int i = c->buffer->i; |   854     unsigned int i = c->buffer->idx; | 
 |   855     unsigned int j = skippy_iter.idx; | 
|   860  |   856  | 
|   861     hb_position_t entry_x, entry_y, exit_x, exit_y; |   857     hb_position_t entry_x, entry_y, exit_x, exit_y; | 
|   862     (this+this_record.exitAnchor).get_anchor (c->layout, c->buffer->info[i].code
      point, &exit_x, &exit_y); |   858     (this+this_record.exitAnchor).get_anchor (c->font, c->buffer->info[i].codepo
      int, &exit_x, &exit_y); | 
|   863     (this+next_record.entryAnchor).get_anchor (c->layout, c->buffer->info[j].cod
      epoint, &entry_x, &entry_y); |   859     (this+next_record.entryAnchor).get_anchor (c->font, c->buffer->info[j].codep
      oint, &entry_x, &entry_y); | 
|   864  |   860  | 
|   865     hb_direction_t direction = c->buffer->props.direction; |   861     hb_glyph_position_t *pos = c->buffer->pos; | 
|   866  |   862  | 
|   867     /* Align the exit anchor of the left/top glyph with the entry anchor of the 
      right/bottom glyph |   863     hb_position_t d; | 
|   868      * by adjusting advance of the left/top glyph. */ |   864     /* Main-direction adjustment */ | 
|   869     if (HB_DIRECTION_IS_BACKWARD (direction)) |   865     switch (c->direction) { | 
|   870     { |   866       case HB_DIRECTION_LTR: | 
|   871       if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) |   867 »       pos[i].x_advance  =  exit_x + pos[i].x_offset; | 
|   872 »       c->buffer->pos[j].x_advance = c->buffer->pos[j].x_offset + entry_x - exi
      t_x; |   868  | 
|   873       else |   869 »       d = entry_x + pos[j].x_offset; | 
|   874 »       c->buffer->pos[j].y_advance = c->buffer->pos[j].y_offset + entry_y - exi
      t_y; |   870 »       pos[j].x_advance -= d; | 
|   875     } |   871 »       pos[j].x_offset  -= d; | 
|   876     else |   872 »       break; | 
|   877     { |   873       case HB_DIRECTION_RTL: | 
|   878       if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) |   874 »       d = exit_x + pos[i].x_offset; | 
|   879 »       c->buffer->pos[i].x_advance = c->buffer->pos[i].x_offset + exit_x - entr
      y_x; |   875 »       pos[i].x_advance -= d; | 
|   880       else |   876 »       pos[i].x_offset  -= d; | 
|   881 »       c->buffer->pos[i].y_advance = c->buffer->pos[i].y_offset + exit_y - entr
      y_y; |   877  | 
 |   878 »       pos[j].x_advance  =  entry_x + pos[j].x_offset; | 
 |   879 »       break; | 
 |   880       case HB_DIRECTION_TTB: | 
 |   881 »       pos[i].y_advance  =  exit_y + pos[i].y_offset; | 
 |   882  | 
 |   883 »       d = entry_y + pos[j].y_offset; | 
 |   884 »       pos[j].y_advance -= d; | 
 |   885 »       pos[j].y_offset  -= d; | 
 |   886 »       break; | 
 |   887       case HB_DIRECTION_BTT: | 
 |   888 »       d = exit_y + pos[i].y_offset; | 
 |   889 »       pos[i].y_advance -= d; | 
 |   890 »       pos[i].y_offset  -= d; | 
 |   891  | 
 |   892 »       pos[j].y_advance  =  entry_y; | 
 |   893 »       break; | 
 |   894       case HB_DIRECTION_INVALID: | 
 |   895       default: | 
 |   896 »       break; | 
|   882     } |   897     } | 
|   883  |   898  | 
|   884     if  (c->lookup_props & LookupFlag::RightToLeft) |   899     /* Cross-direction adjustment */ | 
|   885     { |   900     if  (c->lookup_props & LookupFlag::RightToLeft) { | 
|   886       c->buffer->pos[i].cursive_chain() = j - i; |   901       pos[i].cursive_chain() = j - i; | 
|   887       if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) |   902       if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) | 
|   888 »       c->buffer->pos[i].y_offset = entry_y - exit_y; |   903 »       pos[i].y_offset = entry_y - exit_y; | 
|   889       else |   904       else | 
|   890 »       c->buffer->pos[i].x_offset = entry_x - exit_x; |   905 »       pos[i].x_offset = entry_x - exit_x; | 
|   891     } |   906     } else { | 
|   892     else |   907       pos[j].cursive_chain() = i - j; | 
|   893     { |   908       if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) | 
|   894       c->buffer->pos[j].cursive_chain() = i - j; |   909 »       pos[j].y_offset = exit_y - entry_y; | 
|   895       if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) |  | 
|   896 »       c->buffer->pos[j].y_offset = exit_y - entry_y; |  | 
|   897       else |   910       else | 
|   898 »       c->buffer->pos[j].x_offset = exit_x - entry_x; |   911 »       pos[j].x_offset = exit_x - entry_x; | 
|   899     } |   912     } | 
|   900  |   913  | 
|   901     c->buffer->i = j; |   914     c->buffer->idx = j; | 
|   902     return true; |   915     return true; | 
|   903   } |   916   } | 
|   904  |   917  | 
|   905   inline bool sanitize (hb_sanitize_context_t *c) { |   918   inline bool sanitize (hb_sanitize_context_t *c) { | 
|   906     TRACE_SANITIZE (); |   919     TRACE_SANITIZE (); | 
|   907     return coverage.sanitize (c, this) |   920     return coverage.sanitize (c, this) | 
|   908         && entryExitRecord.sanitize (c, this); |   921         && entryExitRecord.sanitize (c, this); | 
|   909   } |   922   } | 
|   910  |   923  | 
|   911   private: |   924   private: | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   957                                          * ordered by class--zero-based. */ |   970                                          * ordered by class--zero-based. */ | 
|   958  |   971  | 
|   959 struct MarkBasePosFormat1 |   972 struct MarkBasePosFormat1 | 
|   960 { |   973 { | 
|   961   friend struct MarkBasePos; |   974   friend struct MarkBasePos; | 
|   962  |   975  | 
|   963   private: |   976   private: | 
|   964   inline bool apply (hb_apply_context_t *c) const |   977   inline bool apply (hb_apply_context_t *c) const | 
|   965   { |   978   { | 
|   966     TRACE_APPLY (); |   979     TRACE_APPLY (); | 
|   967     unsigned int mark_index = (this+markCoverage) (c->buffer->info[c->buffer->i]
      .codepoint); |   980     unsigned int mark_index = (this+markCoverage) (c->buffer->info[c->buffer->id
      x].codepoint); | 
|   968     if (likely (mark_index == NOT_COVERED)) |   981     if (likely (mark_index == NOT_COVERED)) | 
|   969       return false; |   982       return false; | 
|   970  |   983  | 
|   971     /* now we search backwards for a non-mark glyph */ |   984     /* now we search backwards for a non-mark glyph */ | 
|   972     unsigned int property; |   985     unsigned int property; | 
|   973     unsigned int j = c->buffer->i; |   986     hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buf
      fer->idx, 1); | 
|   974     do |   987     if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) | 
|   975     { |   988       return false; | 
|   976       if (unlikely (!j)) |  | 
|   977 »       return false; |  | 
|   978       j--; |  | 
|   979     } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], Look
      upFlag::IgnoreMarks, &property)); |  | 
|   980  |   989  | 
|   981     /* The following assertion is too strong, so we've disabled it. */ |   990     /* The following assertion is too strong, so we've disabled it. */ | 
|   982     if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH)) |   991     if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH)) | 
|   983     {/*return false;*/} |   992     {/*return false;*/} | 
|   984  |   993  | 
|   985     unsigned int base_index = (this+baseCoverage) (c->buffer->info[j].codepoint)
      ; |   994     unsigned int base_index = (this+baseCoverage) (c->buffer->info[skippy_iter.i
      dx].codepoint); | 
|   986     if (base_index == NOT_COVERED) |   995     if (base_index == NOT_COVERED) | 
|   987       return false; |   996       return false; | 
|   988  |   997  | 
|   989     return (this+markArray).apply (c, mark_index, base_index, this+baseArray, cl
      assCount, j); |   998     return (this+markArray).apply (c, mark_index, base_index, this+baseArray, cl
      assCount, skippy_iter.idx); | 
|   990   } |   999   } | 
|   991  |  1000  | 
|   992   inline bool sanitize (hb_sanitize_context_t *c) { |  1001   inline bool sanitize (hb_sanitize_context_t *c) { | 
|   993     TRACE_SANITIZE (); |  1002     TRACE_SANITIZE (); | 
|   994     return c->check_struct (this) |  1003     return c->check_struct (this) | 
|   995         && markCoverage.sanitize (c, this) |  1004         && markCoverage.sanitize (c, this) | 
|   996         && baseCoverage.sanitize (c, this) |  1005         && baseCoverage.sanitize (c, this) | 
|   997         && markArray.sanitize (c, this) |  1006         && markArray.sanitize (c, this) | 
|   998         && baseArray.sanitize (c, this, (unsigned int) classCount); |  1007         && baseArray.sanitize (c, this, (unsigned int) classCount); | 
|   999   } |  1008   } | 
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1059                                          * LigatureCoverage Index */ |  1068                                          * LigatureCoverage Index */ | 
|  1060  |  1069  | 
|  1061 struct MarkLigPosFormat1 |  1070 struct MarkLigPosFormat1 | 
|  1062 { |  1071 { | 
|  1063   friend struct MarkLigPos; |  1072   friend struct MarkLigPos; | 
|  1064  |  1073  | 
|  1065   private: |  1074   private: | 
|  1066   inline bool apply (hb_apply_context_t *c) const |  1075   inline bool apply (hb_apply_context_t *c) const | 
|  1067   { |  1076   { | 
|  1068     TRACE_APPLY (); |  1077     TRACE_APPLY (); | 
|  1069     unsigned int mark_index = (this+markCoverage) (c->buffer->info[c->buffer->i]
      .codepoint); |  1078     unsigned int mark_index = (this+markCoverage) (c->buffer->info[c->buffer->id
      x].codepoint); | 
|  1070     if (likely (mark_index == NOT_COVERED)) |  1079     if (likely (mark_index == NOT_COVERED)) | 
|  1071       return false; |  1080       return false; | 
|  1072  |  1081  | 
|  1073     /* now we search backwards for a non-mark glyph */ |  1082     /* now we search backwards for a non-mark glyph */ | 
|  1074     unsigned int property; |  1083     unsigned int property; | 
|  1075     unsigned int j = c->buffer->i; |  1084     hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buf
      fer->idx, 1); | 
|  1076     do |  1085     if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) | 
|  1077     { |  1086       return false; | 
|  1078       if (unlikely (!j)) |  | 
|  1079 »       return false; |  | 
|  1080       j--; |  | 
|  1081     } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], Look
      upFlag::IgnoreMarks, &property)); |  | 
|  1082  |  1087  | 
|  1083     /* The following assertion is too strong, so we've disabled it. */ |  1088     /* The following assertion is too strong, so we've disabled it. */ | 
|  1084     if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE)) |  1089     if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE)) | 
|  1085     {/*return false;*/} |  1090     {/*return false;*/} | 
|  1086  |  1091  | 
 |  1092     unsigned int j = skippy_iter.idx; | 
|  1087     unsigned int lig_index = (this+ligatureCoverage) (c->buffer->info[j].codepoi
      nt); |  1093     unsigned int lig_index = (this+ligatureCoverage) (c->buffer->info[j].codepoi
      nt); | 
|  1088     if (lig_index == NOT_COVERED) |  1094     if (lig_index == NOT_COVERED) | 
|  1089       return false; |  1095       return false; | 
|  1090  |  1096  | 
|  1091     const LigatureArray& lig_array = this+ligatureArray; |  1097     const LigatureArray& lig_array = this+ligatureArray; | 
|  1092     const LigatureAttach& lig_attach = lig_array[lig_index]; |  1098     const LigatureAttach& lig_attach = lig_array[lig_index]; | 
|  1093  |  1099  | 
|  1094     /* Find component to attach to */ |  1100     /* Find component to attach to */ | 
|  1095     unsigned int comp_count = lig_attach.rows; |  1101     unsigned int comp_count = lig_attach.rows; | 
|  1096     if (unlikely (!comp_count)) |  1102     if (unlikely (!comp_count)) | 
|  1097       return false; |  1103       return false; | 
|  1098     unsigned int comp_index; |  1104     unsigned int comp_index; | 
|  1099     /* We must now check whether the ligature ID of the current mark glyph |  1105     /* We must now check whether the ligature ID of the current mark glyph | 
|  1100      * is identical to the ligature ID of the found ligature.  If yes, we |  1106      * is identical to the ligature ID of the found ligature.  If yes, we | 
|  1101      * can directly use the component index.  If not, we attach the mark |  1107      * can directly use the component index.  If not, we attach the mark | 
|  1102      * glyph to the last component of the ligature. */ |  1108      * glyph to the last component of the ligature. */ | 
|  1103     if (c->buffer->info[j].lig_id() && c->buffer->info[j].lig_id() == c->buffer-
      >info[c->buffer->i].lig_id() && c->buffer->info[c->buffer->i].lig_comp()) |  1109     if (c->buffer->info[j].lig_id() && c->buffer->info[j].lig_id() == c->buffer-
      >info[c->buffer->idx].lig_id() && c->buffer->info[c->buffer->idx].lig_comp()) | 
|  1104     { |  1110     { | 
|  1105       comp_index = c->buffer->info[c->buffer->i].lig_comp() - 1; |  1111       comp_index = c->buffer->info[c->buffer->idx].lig_comp() - 1; | 
|  1106       if (comp_index >= comp_count) |  1112       if (comp_index >= comp_count) | 
|  1107         comp_index = comp_count - 1; |  1113         comp_index = comp_count - 1; | 
|  1108     } |  1114     } | 
|  1109     else |  1115     else | 
|  1110       comp_index = comp_count - 1; |  1116       comp_index = comp_count - 1; | 
|  1111  |  1117  | 
|  1112     return (this+markArray).apply (c, mark_index, comp_index, lig_attach, classC
      ount, j); |  1118     return (this+markArray).apply (c, mark_index, comp_index, lig_attach, classC
      ount, j); | 
|  1113   } |  1119   } | 
|  1114  |  1120  | 
|  1115   inline bool sanitize (hb_sanitize_context_t *c) { |  1121   inline bool sanitize (hb_sanitize_context_t *c) { | 
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1178                                          * ordered by class--zero-based. */ |  1184                                          * ordered by class--zero-based. */ | 
|  1179  |  1185  | 
|  1180 struct MarkMarkPosFormat1 |  1186 struct MarkMarkPosFormat1 | 
|  1181 { |  1187 { | 
|  1182   friend struct MarkMarkPos; |  1188   friend struct MarkMarkPos; | 
|  1183  |  1189  | 
|  1184   private: |  1190   private: | 
|  1185   inline bool apply (hb_apply_context_t *c) const |  1191   inline bool apply (hb_apply_context_t *c) const | 
|  1186   { |  1192   { | 
|  1187     TRACE_APPLY (); |  1193     TRACE_APPLY (); | 
|  1188     unsigned int mark1_index = (this+mark1Coverage) (c->buffer->info[c->buffer->
      i].codepoint); |  1194     unsigned int mark1_index = (this+mark1Coverage) (c->buffer->info[c->buffer->
      idx].codepoint); | 
|  1189     if (likely (mark1_index == NOT_COVERED)) |  1195     if (likely (mark1_index == NOT_COVERED)) | 
|  1190       return false; |  1196       return false; | 
|  1191  |  1197  | 
|  1192     /* now we search backwards for a suitable mark glyph until a non-mark glyph 
      */ |  1198     /* now we search backwards for a suitable mark glyph until a non-mark glyph 
      */ | 
|  1193     unsigned int property; |  1199     unsigned int property; | 
|  1194     unsigned int j = c->buffer->i; |  1200     hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buf
      fer->idx, 1); | 
|  1195     do |  1201     if (!skippy_iter.prev (&property)) | 
|  1196     { |  1202       return false; | 
|  1197       if (unlikely (!j)) |  | 
|  1198 »       return false; |  | 
|  1199       j--; |  | 
|  1200     } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->l
      ookup_props, &property)); |  | 
|  1201  |  1203  | 
|  1202     if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)) |  1204     if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)) | 
|  1203       return false; |  1205       return false; | 
|  1204  |  1206  | 
 |  1207     unsigned int j = skippy_iter.idx; | 
 |  1208  | 
|  1205     /* Two marks match only if they belong to the same base, or same component |  1209     /* Two marks match only if they belong to the same base, or same component | 
|  1206      * of the same ligature.  That is, the component numbers must match, and |  1210      * of the same ligature.  That is, the component numbers must match, and | 
|  1207      * if those are non-zero, the ligid number should also match. */ |  1211      * if those are non-zero, the ligid number should also match. */ | 
|  1208     if ((c->buffer->info[j].lig_comp() != c->buffer->info[c->buffer->i].lig_comp
      ()) || |  1212     if ((c->buffer->info[j].lig_comp() != c->buffer->info[c->buffer->idx].lig_co
      mp()) || | 
|  1209 »       (c->buffer->info[j].lig_comp() && c->buffer->info[j].lig_id() != c->buff
      er->info[c->buffer->i].lig_id())) |  1213 »       (c->buffer->info[j].lig_comp() && c->buffer->info[j].lig_id() != c->buff
      er->info[c->buffer->idx].lig_id())) | 
|  1210       return false; |  1214       return false; | 
|  1211  |  1215  | 
|  1212     unsigned int mark2_index = (this+mark2Coverage) (c->buffer->info[j].codepoin
      t); |  1216     unsigned int mark2_index = (this+mark2Coverage) (c->buffer->info[j].codepoin
      t); | 
|  1213     if (mark2_index == NOT_COVERED) |  1217     if (mark2_index == NOT_COVERED) | 
|  1214       return false; |  1218       return false; | 
|  1215  |  1219  | 
|  1216     return (this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array
      , classCount, j); |  1220     return (this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array
      , classCount, j); | 
|  1217   } |  1221   } | 
|  1218  |  1222  | 
|  1219   inline bool sanitize (hb_sanitize_context_t *c) { |  1223   inline bool sanitize (hb_sanitize_context_t *c) { | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1270   } |  1274   } | 
|  1271  |  1275  | 
|  1272   private: |  1276   private: | 
|  1273   union { |  1277   union { | 
|  1274   USHORT                format;         /* Format identifier */ |  1278   USHORT                format;         /* Format identifier */ | 
|  1275   MarkMarkPosFormat1    format1; |  1279   MarkMarkPosFormat1    format1; | 
|  1276   } u; |  1280   } u; | 
|  1277 }; |  1281 }; | 
|  1278  |  1282  | 
|  1279  |  1283  | 
|  1280 HB_BEGIN_DECLS |  | 
|  1281 static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
      ndex); |  1284 static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
      ndex); | 
|  1282 HB_END_DECLS |  | 
|  1283  |  1285  | 
|  1284 struct ContextPos : Context |  1286 struct ContextPos : Context | 
|  1285 { |  1287 { | 
|  1286   friend struct PosLookupSubTable; |  1288   friend struct PosLookupSubTable; | 
|  1287  |  1289  | 
|  1288   private: |  1290   private: | 
|  1289   inline bool apply (hb_apply_context_t *c) const |  1291   inline bool apply (hb_apply_context_t *c) const | 
|  1290   { |  1292   { | 
|  1291     TRACE_APPLY (); |  1293     TRACE_APPLY (); | 
|  1292     return Context::apply (c, position_lookup); |  1294     return Context::apply (c, position_lookup); | 
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1395   public: |  1397   public: | 
|  1396   DEFINE_SIZE_UNION (2, sub_format); |  1398   DEFINE_SIZE_UNION (2, sub_format); | 
|  1397 }; |  1399 }; | 
|  1398  |  1400  | 
|  1399  |  1401  | 
|  1400 struct PosLookup : Lookup |  1402 struct PosLookup : Lookup | 
|  1401 { |  1403 { | 
|  1402   inline const PosLookupSubTable& get_subtable (unsigned int i) const |  1404   inline const PosLookupSubTable& get_subtable (unsigned int i) const | 
|  1403   { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; } |  1405   { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; } | 
|  1404  |  1406  | 
|  1405   inline bool apply_once (hb_ot_layout_context_t *layout, |  1407   inline bool apply_once (hb_font_t *font, | 
|  1406                           hb_buffer_t *buffer, |  1408                           hb_buffer_t *buffer, | 
|  1407                           hb_mask_t lookup_mask, |  1409                           hb_mask_t lookup_mask, | 
|  1408                           unsigned int context_length, |  1410                           unsigned int context_length, | 
|  1409                           unsigned int nesting_level_left) const |  1411                           unsigned int nesting_level_left) const | 
|  1410   { |  1412   { | 
|  1411     unsigned int lookup_type = get_type (); |  1413     unsigned int lookup_type = get_type (); | 
|  1412     hb_apply_context_t c[1] = {{0}}; |  1414     hb_apply_context_t c[1] = {{0}}; | 
|  1413  |  1415  | 
|  1414     c->layout = layout; |  1416     c->font = font; | 
 |  1417     c->face = font->face; | 
|  1415     c->buffer = buffer; |  1418     c->buffer = buffer; | 
 |  1419     c->direction = buffer->props.direction; | 
|  1416     c->lookup_mask = lookup_mask; |  1420     c->lookup_mask = lookup_mask; | 
|  1417     c->context_length = context_length; |  1421     c->context_length = context_length; | 
|  1418     c->nesting_level_left = nesting_level_left; |  1422     c->nesting_level_left = nesting_level_left; | 
|  1419     c->lookup_props = get_props (); |  1423     c->lookup_props = get_props (); | 
|  1420  |  1424  | 
|  1421     if (!_hb_ot_layout_check_glyph_property (c->layout->face, &c->buffer->info[c
      ->buffer->i], c->lookup_props, &c->property)) |  1425     if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->info[c->buffer
      ->idx], c->lookup_props, &c->property)) | 
|  1422       return false; |  1426       return false; | 
|  1423  |  1427  | 
|  1424     for (unsigned int i = 0; i < get_subtable_count (); i++) |  1428     for (unsigned int i = 0; i < get_subtable_count (); i++) | 
|  1425       if (get_subtable (i).apply (c, lookup_type)) |  1429       if (get_subtable (i).apply (c, lookup_type)) | 
|  1426         return true; |  1430         return true; | 
|  1427  |  1431  | 
|  1428     return false; |  1432     return false; | 
|  1429   } |  1433   } | 
|  1430  |  1434  | 
|  1431    inline bool apply_string (hb_ot_layout_context_t *layout, |  1435    inline bool apply_string (hb_font_t   *font, | 
|  1432                              hb_buffer_t *buffer, |  1436                              hb_buffer_t *buffer, | 
|  1433                              hb_mask_t    mask) const |  1437                              hb_mask_t    mask) const | 
|  1434   { |  1438   { | 
|  1435     bool ret = false; |  1439     bool ret = false; | 
|  1436  |  1440  | 
|  1437     if (unlikely (!buffer->len)) |  1441     if (unlikely (!buffer->len)) | 
|  1438       return false; |  1442       return false; | 
|  1439  |  1443  | 
|  1440     buffer->i = 0; |  1444     buffer->idx = 0; | 
|  1441     while (buffer->i < buffer->len) |  1445     while (buffer->idx < buffer->len) | 
|  1442     { |  1446     { | 
|  1443       if ((buffer->info[buffer->i].mask & mask) && |  1447       if ((buffer->info[buffer->idx].mask & mask) && | 
|  1444 »         apply_once (layout, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL)) |  1448 »         apply_once (font, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL)) | 
|  1445         ret = true; |  1449         ret = true; | 
|  1446       else |  1450       else | 
|  1447 »       buffer->i++; |  1451 »       buffer->idx++; | 
|  1448     } |  1452     } | 
|  1449  |  1453  | 
|  1450     return ret; |  1454     return ret; | 
|  1451   } |  1455   } | 
|  1452  |  1456  | 
|  1453   inline bool sanitize (hb_sanitize_context_t *c) { |  1457   inline bool sanitize (hb_sanitize_context_t *c) { | 
|  1454     TRACE_SANITIZE (); |  1458     TRACE_SANITIZE (); | 
|  1455     if (unlikely (!Lookup::sanitize (c))) return false; |  1459     if (unlikely (!Lookup::sanitize (c))) return false; | 
|  1456     OffsetArrayOf<PosLookupSubTable> &list = CastR<OffsetArrayOf<PosLookupSubTab
      le> > (subTable); |  1460     OffsetArrayOf<PosLookupSubTable> &list = CastR<OffsetArrayOf<PosLookupSubTab
      le> > (subTable); | 
|  1457     return list.sanitize (c, this, get_type ()); |  1461     return list.sanitize (c, this, get_type ()); | 
|  1458   } |  1462   } | 
|  1459 }; |  1463 }; | 
|  1460  |  1464  | 
|  1461 typedef OffsetListOf<PosLookup> PosLookupList; |  1465 typedef OffsetListOf<PosLookup> PosLookupList; | 
|  1462  |  1466  | 
|  1463 /* |  1467 /* | 
|  1464  * GPOS |  1468  * GPOS -- The Glyph Positioning Table | 
|  1465  */ |  1469  */ | 
|  1466  |  1470  | 
|  1467 struct GPOS : GSUBGPOS |  1471 struct GPOS : GSUBGPOS | 
|  1468 { |  1472 { | 
|  1469   static const hb_tag_t Tag     = HB_OT_TAG_GPOS; |  1473   static const hb_tag_t Tag     = HB_OT_TAG_GPOS; | 
|  1470  |  1474  | 
|  1471   inline const PosLookup& get_lookup (unsigned int i) const |  1475   inline const PosLookup& get_lookup (unsigned int i) const | 
|  1472   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); } |  1476   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); } | 
|  1473  |  1477  | 
|  1474   inline bool position_lookup (hb_ot_layout_context_t *layout, |  1478   inline bool position_lookup (hb_font_t    *font, | 
|  1475                                hb_buffer_t  *buffer, |  1479                                hb_buffer_t  *buffer, | 
|  1476                                unsigned int  lookup_index, |  1480                                unsigned int  lookup_index, | 
|  1477                                hb_mask_t     mask) const |  1481                                hb_mask_t     mask) const | 
|  1478   { return get_lookup (lookup_index).apply_string (layout, buffer, mask); } |  1482   { return get_lookup (lookup_index).apply_string (font, buffer, mask); } | 
|  1479  |  1483  | 
 |  1484   static inline void position_start (hb_buffer_t *buffer); | 
|  1480   static inline void position_finish (hb_buffer_t *buffer); |  1485   static inline void position_finish (hb_buffer_t *buffer); | 
|  1481  |  1486  | 
|  1482   inline bool sanitize (hb_sanitize_context_t *c) { |  1487   inline bool sanitize (hb_sanitize_context_t *c) { | 
|  1483     TRACE_SANITIZE (); |  1488     TRACE_SANITIZE (); | 
|  1484     if (unlikely (!GSUBGPOS::sanitize (c))) return false; |  1489     if (unlikely (!GSUBGPOS::sanitize (c))) return false; | 
|  1485     OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList)
      ; |  1490     OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList)
      ; | 
|  1486     return list.sanitize (c, this); |  1491     return list.sanitize (c, this); | 
|  1487   } |  1492   } | 
|  1488   public: |  1493   public: | 
|  1489   DEFINE_SIZE_STATIC (10); |  1494   DEFINE_SIZE_STATIC (10); | 
|  1490 }; |  1495 }; | 
|  1491  |  1496  | 
 |  1497  | 
 |  1498 static void | 
 |  1499 fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction
      _t direction) | 
 |  1500 { | 
 |  1501     unsigned int j = pos[i].cursive_chain(); | 
 |  1502     if (likely (!j)) | 
 |  1503       return; | 
 |  1504  | 
 |  1505     j += i; | 
 |  1506  | 
 |  1507     pos[i].cursive_chain() = 0; | 
 |  1508  | 
 |  1509     fix_cursive_minor_offset (pos, j, direction); | 
 |  1510  | 
 |  1511     if (HB_DIRECTION_IS_HORIZONTAL (direction)) | 
 |  1512       pos[i].y_offset += pos[j].y_offset; | 
 |  1513     else | 
 |  1514       pos[i].x_offset += pos[j].x_offset; | 
 |  1515 } | 
 |  1516  | 
 |  1517 static void | 
 |  1518 fix_mark_attachment (hb_glyph_position_t *pos, unsigned int i, hb_direction_t di
      rection) | 
 |  1519 { | 
 |  1520   if (likely (!(pos[i].attach_lookback()))) | 
 |  1521     return; | 
 |  1522  | 
 |  1523   unsigned int j = i - pos[i].attach_lookback(); | 
 |  1524  | 
 |  1525   pos[i].x_advance = 0; | 
 |  1526   pos[i].y_advance = 0; | 
 |  1527   pos[i].x_offset += pos[j].x_offset; | 
 |  1528   pos[i].y_offset += pos[j].y_offset; | 
 |  1529  | 
 |  1530   if (HB_DIRECTION_IS_FORWARD (direction)) | 
 |  1531     for (unsigned int k = j; k < i; k++) { | 
 |  1532       pos[i].x_offset -= pos[k].x_advance; | 
 |  1533       pos[i].y_offset -= pos[k].y_advance; | 
 |  1534     } | 
 |  1535   else | 
 |  1536     for (unsigned int k = j + 1; k < i + 1; k++) { | 
 |  1537       pos[i].x_offset += pos[k].x_advance; | 
 |  1538       pos[i].y_offset += pos[k].y_advance; | 
 |  1539     } | 
 |  1540 } | 
 |  1541  | 
 |  1542 void | 
 |  1543 GPOS::position_start (hb_buffer_t *buffer) | 
 |  1544 { | 
 |  1545   buffer->clear_positions (); | 
 |  1546  | 
 |  1547   unsigned int count = buffer->len; | 
 |  1548   for (unsigned int i = 0; i < count; i++) | 
 |  1549     buffer->pos[i].attach_lookback() = buffer->pos[i].cursive_chain() = 0; | 
 |  1550 } | 
 |  1551  | 
|  1492 void |  1552 void | 
|  1493 GPOS::position_finish (hb_buffer_t *buffer) |  1553 GPOS::position_finish (hb_buffer_t *buffer) | 
|  1494 { |  1554 { | 
|  1495   unsigned int i, j; |  1555   unsigned int len; | 
|  1496   unsigned int len = hb_buffer_get_length (buffer); |  1556   hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len); | 
|  1497   hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer); |  | 
|  1498   hb_direction_t direction = buffer->props.direction; |  1557   hb_direction_t direction = buffer->props.direction; | 
|  1499  |  1558  | 
|  1500   /* Handle cursive connections: |  1559   /* Handle cursive connections */ | 
|  1501    * First handle all chain-back connections, then handle all chain-forward conn
      ections. */ |  1560   for (unsigned int i = 0; i < len; i++) | 
|  1502   if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) |  1561     fix_cursive_minor_offset (pos, i, direction); | 
|  1503   { |  | 
|  1504     for (j = 0; j < len; j++) { |  | 
|  1505       if (pos[j].cursive_chain() < 0) |  | 
|  1506 »       pos[j].y_offset += pos[j + pos[j].cursive_chain()].y_offset; |  | 
|  1507     } |  | 
|  1508     for (i = len; i > 0; i--) { |  | 
|  1509       j = i - 1; |  | 
|  1510       if (pos[j].cursive_chain() > 0) |  | 
|  1511 »       pos[j].y_offset += pos[j + pos[j].cursive_chain()].y_offset; |  | 
|  1512     } |  | 
|  1513   } |  | 
|  1514   else |  | 
|  1515   { |  | 
|  1516     for (j = 0; j < len; j++) { |  | 
|  1517       if (pos[j].cursive_chain() < 0) |  | 
|  1518 »       pos[j].x_offset += pos[j + pos[j].cursive_chain()].x_offset; |  | 
|  1519     } |  | 
|  1520     for (i = len; i > 0; i--) { |  | 
|  1521       j = i - 1; |  | 
|  1522       if (pos[j].cursive_chain() > 0) |  | 
|  1523 »       pos[j].x_offset += pos[j + pos[j].cursive_chain()].x_offset; |  | 
|  1524     } |  | 
|  1525   } |  | 
|  1526  |  | 
|  1527  |  1562  | 
|  1528   /* Handle attachments */ |  1563   /* Handle attachments */ | 
|  1529   for (i = 0; i < len; i++) |  1564   for (unsigned int i = 0; i < len; i++) | 
|  1530     if (pos[i].attach_lookback()) |  1565     fix_mark_attachment (pos, i, direction); | 
|  1531     { |  | 
|  1532       unsigned int back = i - pos[i].attach_lookback(); |  | 
|  1533       pos[i].x_offset += pos[back].x_offset; |  | 
|  1534       pos[i].y_offset += pos[back].y_offset; |  | 
|  1535  |  1566  | 
|  1536       if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) |  1567   HB_BUFFER_DEALLOCATE_VAR (buffer, lig_comp); | 
|  1537 »       for (j = back + 1; j < i + 1; j++) { |  1568   HB_BUFFER_DEALLOCATE_VAR (buffer, lig_id); | 
|  1538 »         pos[i].x_offset += pos[j].x_advance; |  1569   HB_BUFFER_DEALLOCATE_VAR (buffer, props_cache); | 
|  1539 »         pos[i].y_offset += pos[j].y_advance; |  | 
|  1540 »       } |  | 
|  1541       else |  | 
|  1542 »       for (j = back; j < i; j++) { |  | 
|  1543 »         pos[i].x_offset -= pos[j].x_advance; |  | 
|  1544 »         pos[i].y_offset -= pos[j].y_advance; |  | 
|  1545 »       } |  | 
|  1546     } |  | 
|  1547 } |  1570 } | 
|  1548  |  1571  | 
|  1549  |  1572  | 
|  1550 /* Out-of-class implementation for methods recursing */ |  1573 /* Out-of-class implementation for methods recursing */ | 
|  1551  |  1574  | 
|  1552 inline bool ExtensionPos::apply (hb_apply_context_t *c) const |  1575 inline bool ExtensionPos::apply (hb_apply_context_t *c) const | 
|  1553 { |  1576 { | 
|  1554   TRACE_APPLY (); |  1577   TRACE_APPLY (); | 
|  1555   return get_subtable ().apply (c, get_type ()); |  1578   return get_subtable ().apply (c, get_type ()); | 
|  1556 } |  1579 } | 
|  1557  |  1580  | 
|  1558 inline bool ExtensionPos::sanitize (hb_sanitize_context_t *c) |  1581 inline bool ExtensionPos::sanitize (hb_sanitize_context_t *c) | 
|  1559 { |  1582 { | 
|  1560   TRACE_SANITIZE (); |  1583   TRACE_SANITIZE (); | 
|  1561   if (unlikely (!Extension::sanitize (c))) return false; |  1584   if (unlikely (!Extension::sanitize (c))) return false; | 
|  1562   unsigned int offset = get_offset (); |  1585   unsigned int offset = get_offset (); | 
|  1563   if (unlikely (!offset)) return true; |  1586   if (unlikely (!offset)) return true; | 
|  1564   return StructAtOffset<PosLookupSubTable> (this, offset).sanitize (c, get_type 
      ()); |  1587   return StructAtOffset<PosLookupSubTable> (this, offset).sanitize (c, get_type 
      ()); | 
|  1565 } |  1588 } | 
|  1566  |  1589  | 
|  1567 static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
      ndex) |  1590 static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
      ndex) | 
|  1568 { |  1591 { | 
|  1569   const GPOS &gpos = *(c->layout->face->ot_layout->gpos); |  1592   const GPOS &gpos = *(c->face->ot_layout->gpos); | 
|  1570   const PosLookup &l = gpos.get_lookup (lookup_index); |  1593   const PosLookup &l = gpos.get_lookup (lookup_index); | 
|  1571  |  1594  | 
|  1572   if (unlikely (c->nesting_level_left == 0)) |  1595   if (unlikely (c->nesting_level_left == 0)) | 
|  1573     return false; |  1596     return false; | 
|  1574  |  1597  | 
|  1575   if (unlikely (c->context_length < 1)) |  1598   if (unlikely (c->context_length < 1)) | 
|  1576     return false; |  1599     return false; | 
|  1577  |  1600  | 
|  1578   return l.apply_once (c->layout, c->buffer, c->lookup_mask, c->context_length, 
      c->nesting_level_left - 1); |  1601   return l.apply_once (c->font, c->buffer, c->lookup_mask, c->context_length, c-
      >nesting_level_left - 1); | 
|  1579 } |  1602 } | 
|  1580  |  1603  | 
|  1581  |  1604  | 
|  1582 #undef attach_lookback |  1605 #undef attach_lookback | 
|  1583 #undef cursive_chain |  1606 #undef cursive_chain | 
|  1584  |  1607  | 
|  1585  |  1608  | 
|  1586 HB_END_DECLS |  | 
|  1587  |  1609  | 
|  1588 #endif /* HB_OT_LAYOUT_GPOS_PRIVATE_HH */ |  1610 #endif /* HB_OT_LAYOUT_GPOS_TABLE_HH */ | 
| OLD | NEW |