< prev index next >

src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gpos-table.hh

Print this page




  86                                          * writing) */
  87   Offset        xPlaDevice;             /* Offset to Device table for
  88                                          * horizontal placement--measured from
  89                                          * beginning of PosTable (may be NULL) */
  90   Offset        yPlaDevice;             /* Offset to Device table for vertical
  91                                          * placement--measured from beginning
  92                                          * of PosTable (may be NULL) */
  93   Offset        xAdvDevice;             /* Offset to Device table for
  94                                          * horizontal advance--measured from
  95                                          * beginning of PosTable (may be NULL) */
  96   Offset        yAdvDevice;             /* Offset to Device table for vertical
  97                                          * advance--measured from beginning of
  98                                          * PosTable (may be NULL) */
  99 #endif
 100 
 101   inline unsigned int get_len (void) const
 102   { return _hb_popcount32 ((unsigned int) *this); }
 103   inline unsigned int get_size (void) const
 104   { return get_len () * Value::static_size; }
 105 
 106   void apply_value (hb_font_t            *font,
 107                     hb_direction_t        direction,
 108                     const void           *base,
 109                     const Value          *values,
 110                     hb_glyph_position_t  &glyph_pos) const
 111   {
 112     unsigned int x_ppem, y_ppem;
 113     unsigned int format = *this;
 114     hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (direction);
 115 
 116     if (!format) return;
 117 



 118     if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++));
 119     if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++));
 120     if (format & xAdvance) {
 121       if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values));
 122       values++;
 123     }
 124     /* y_advance values grow downward but font-space grows upward, hence negation */
 125     if (format & yAdvance) {
 126       if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values));
 127       values++;
 128     }
 129 
 130     if (!has_device ()) return;
 131 
 132     x_ppem = font->x_ppem;
 133     y_ppem = font->y_ppem;
 134 
 135     if (!x_ppem && !y_ppem) return;


 136 
 137     /* pixel -> fractional pixel */
 138     if (format & xPlaDevice) {
 139       if (x_ppem) glyph_pos.x_offset  += (base + get_device (values)).get_x_delta (font);
 140       values++;
 141     }
 142     if (format & yPlaDevice) {
 143       if (y_ppem) glyph_pos.y_offset  += (base + get_device (values)).get_y_delta (font);
 144       values++;
 145     }
 146     if (format & xAdvDevice) {
 147       if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font);
 148       values++;
 149     }
 150     if (format & yAdvDevice) {
 151       /* y_advance values grow downward but font-space grows upward, hence negation */
 152       if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font);
 153       values++;
 154     }
 155   }
 156 
 157   private:
 158   inline bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
 159   {
 160     unsigned int format = *this;
 161 
 162     if (format & xPlacement) values++;
 163     if (format & yPlacement) values++;
 164     if (format & xAdvance)   values++;
 165     if (format & yAdvance)   values++;
 166 
 167     if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
 168     if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
 169     if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
 170     if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
 171 
 172     return true;


 214   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
 215   inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
 216   {
 217     TRACE_SANITIZE (this);
 218 
 219     if (!has_device ()) return_trace (true);
 220 
 221     for (unsigned int i = 0; i < count; i++) {
 222       if (!sanitize_value_devices (c, base, values))
 223         return_trace (false);
 224       values += stride;
 225     }
 226 
 227     return_trace (true);
 228   }
 229 };
 230 
 231 
 232 struct AnchorFormat1
 233 {
 234   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
 235                           hb_position_t *x, hb_position_t *y) const
 236   {

 237       *x = font->em_scale_x (xCoordinate);
 238       *y = font->em_scale_y (yCoordinate);
 239   }
 240 
 241   inline bool sanitize (hb_sanitize_context_t *c) const
 242   {
 243     TRACE_SANITIZE (this);
 244     return_trace (c->check_struct (this));
 245   }
 246 
 247   protected:
 248   USHORT        format;                 /* Format identifier--format = 1 */
 249   SHORT         xCoordinate;            /* Horizontal value--in design units */
 250   SHORT         yCoordinate;            /* Vertical value--in design units */
 251   public:
 252   DEFINE_SIZE_STATIC (6);
 253 };
 254 
 255 struct AnchorFormat2
 256 {
 257   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
 258                           hb_position_t *x, hb_position_t *y) const
 259   {

 260       unsigned int x_ppem = font->x_ppem;
 261       unsigned int y_ppem = font->y_ppem;
 262       hb_position_t cx, cy;
 263       hb_bool_t ret;
 264 
 265       ret = (x_ppem || y_ppem) &&
 266              font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
 267       *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate);
 268       *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate);
 269   }
 270 
 271   inline bool sanitize (hb_sanitize_context_t *c) const
 272   {
 273     TRACE_SANITIZE (this);
 274     return_trace (c->check_struct (this));
 275   }
 276 
 277   protected:
 278   USHORT        format;                 /* Format identifier--format = 2 */
 279   SHORT         xCoordinate;            /* Horizontal value--in design units */
 280   SHORT         yCoordinate;            /* Vertical value--in design units */
 281   USHORT        anchorPoint;            /* Index to glyph contour point */
 282   public:
 283   DEFINE_SIZE_STATIC (8);
 284 };
 285 
 286 struct AnchorFormat3
 287 {
 288   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
 289                           hb_position_t *x, hb_position_t *y) const
 290   {

 291       *x = font->em_scale_x (xCoordinate);
 292       *y = font->em_scale_y (yCoordinate);
 293 
 294       if (font->x_ppem)
 295         *x += (this+xDeviceTable).get_x_delta (font);
 296       if (font->y_ppem)
 297         *y += (this+yDeviceTable).get_x_delta (font);
 298   }
 299 
 300   inline bool sanitize (hb_sanitize_context_t *c) const
 301   {
 302     TRACE_SANITIZE (this);
 303     return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
 304   }
 305 
 306   protected:
 307   USHORT        format;                 /* Format identifier--format = 3 */
 308   SHORT         xCoordinate;            /* Horizontal value--in design units */
 309   SHORT         yCoordinate;            /* Vertical value--in design units */
 310   OffsetTo<Device>
 311                 xDeviceTable;           /* Offset to Device table for X
 312                                          * coordinate-- from beginning of
 313                                          * Anchor table (may be NULL) */
 314   OffsetTo<Device>
 315                 yDeviceTable;           /* Offset to Device table for Y
 316                                          * coordinate-- from beginning of
 317                                          * Anchor table (may be NULL) */
 318   public:
 319   DEFINE_SIZE_STATIC (10);
 320 };
 321 
 322 struct Anchor
 323 {
 324   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
 325                           hb_position_t *x, hb_position_t *y) const
 326   {
 327     *x = *y = 0;
 328     switch (u.format) {
 329     case 1: u.format1.get_anchor (font, glyph_id, x, y); return;
 330     case 2: u.format2.get_anchor (font, glyph_id, x, y); return;
 331     case 3: u.format3.get_anchor (font, glyph_id, x, y); return;
 332     default:                                             return;
 333     }
 334   }
 335 
 336   inline bool sanitize (hb_sanitize_context_t *c) const
 337   {
 338     TRACE_SANITIZE (this);
 339     if (!u.format.sanitize (c)) return_trace (false);
 340     switch (u.format) {
 341     case 1: return_trace (u.format1.sanitize (c));
 342     case 2: return_trace (u.format2.sanitize (c));
 343     case 3: return_trace (u.format3.sanitize (c));
 344     default:return_trace (true);
 345     }
 346   }
 347 
 348   protected:
 349   union {
 350   USHORT                format;         /* Format identifier */
 351   AnchorFormat1         format1;


 353   AnchorFormat3         format3;
 354   } u;
 355   public:
 356   DEFINE_SIZE_UNION (2, format);
 357 };
 358 
 359 
 360 struct AnchorMatrix
 361 {
 362   inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const {
 363     *found = false;
 364     if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
 365     *found = !matrixZ[row * cols + col].is_null ();
 366     return this+matrixZ[row * cols + col];
 367   }
 368 
 369   inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
 370   {
 371     TRACE_SANITIZE (this);
 372     if (!c->check_struct (this)) return_trace (false);
 373     if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return_trace (false);
 374     unsigned int count = rows * cols;
 375     if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false);
 376     for (unsigned int i = 0; i < count; i++)
 377       if (!matrixZ[i].sanitize (c, this)) return_trace (false);
 378     return_trace (true);
 379   }
 380 
 381   USHORT        rows;                   /* Number of rows */
 382   protected:
 383   OffsetTo<Anchor>
 384                 matrixZ[VAR];           /* Matrix of offsets to Anchor tables--
 385                                          * from beginning of AnchorMatrix table */
 386   public:
 387   DEFINE_SIZE_ARRAY (2, matrixZ);
 388 };
 389 
 390 
 391 struct MarkRecord
 392 {
 393   friend struct MarkArray;


 411 {
 412   inline bool apply (hb_apply_context_t *c,
 413                      unsigned int mark_index, unsigned int glyph_index,
 414                      const AnchorMatrix &anchors, unsigned int class_count,
 415                      unsigned int glyph_pos) const
 416   {
 417     TRACE_APPLY (this);
 418     hb_buffer_t *buffer = c->buffer;
 419     const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index);
 420     unsigned int mark_class = record.klass;
 421 
 422     const Anchor& mark_anchor = this + record.markAnchor;
 423     bool found;
 424     const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
 425     /* If this subtable doesn't have an anchor for this base and this class,
 426      * return false such that the subsequent subtables have a chance at it. */
 427     if (unlikely (!found)) return_trace (false);
 428 
 429     hb_position_t mark_x, mark_y, base_x, base_y;
 430 
 431     mark_anchor.get_anchor (c->font, buffer->cur().codepoint, &mark_x, &mark_y);
 432     glyph_anchor.get_anchor (c->font, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
 433 
 434     hb_glyph_position_t &o = buffer->cur_pos();
 435     o.x_offset = base_x - mark_x;
 436     o.y_offset = base_y - mark_y;
 437     o.attach_type() = ATTACH_TYPE_MARK;
 438     o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
 439     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
 440 
 441     buffer->idx++;
 442     return_trace (true);
 443   }
 444 
 445   inline bool sanitize (hb_sanitize_context_t *c) const
 446   {
 447     TRACE_SANITIZE (this);
 448     return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
 449   }
 450 };
 451 
 452 


 455 struct SinglePosFormat1
 456 {
 457   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
 458   {
 459     TRACE_COLLECT_GLYPHS (this);
 460     (this+coverage).add_coverage (c->input);
 461   }
 462 
 463   inline const Coverage &get_coverage (void) const
 464   {
 465     return this+coverage;
 466   }
 467 
 468   inline bool apply (hb_apply_context_t *c) const
 469   {
 470     TRACE_APPLY (this);
 471     hb_buffer_t *buffer = c->buffer;
 472     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
 473     if (likely (index == NOT_COVERED)) return_trace (false);
 474 
 475     valueFormat.apply_value (c->font, c->direction, this,
 476                              values, buffer->cur_pos());
 477 
 478     buffer->idx++;
 479     return_trace (true);
 480   }
 481 
 482   inline bool sanitize (hb_sanitize_context_t *c) const
 483   {
 484     TRACE_SANITIZE (this);
 485     return_trace (c->check_struct (this) &&
 486                   coverage.sanitize (c, this) &&
 487                   valueFormat.sanitize_value (c, this, values));
 488   }
 489 
 490   protected:
 491   USHORT        format;                 /* Format identifier--format = 1 */
 492   OffsetTo<Coverage>
 493                 coverage;               /* Offset to Coverage table--from
 494                                          * beginning of subtable */
 495   ValueFormat   valueFormat;            /* Defines the types of data in the
 496                                          * ValueRecord */


 506   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
 507   {
 508     TRACE_COLLECT_GLYPHS (this);
 509     (this+coverage).add_coverage (c->input);
 510   }
 511 
 512   inline const Coverage &get_coverage (void) const
 513   {
 514     return this+coverage;
 515   }
 516 
 517   inline bool apply (hb_apply_context_t *c) const
 518   {
 519     TRACE_APPLY (this);
 520     hb_buffer_t *buffer = c->buffer;
 521     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
 522     if (likely (index == NOT_COVERED)) return_trace (false);
 523 
 524     if (likely (index >= valueCount)) return_trace (false);
 525 
 526     valueFormat.apply_value (c->font, c->direction, this,
 527                              &values[index * valueFormat.get_len ()],
 528                              buffer->cur_pos());
 529 
 530     buffer->idx++;
 531     return_trace (true);
 532   }
 533 
 534   inline bool sanitize (hb_sanitize_context_t *c) const
 535   {
 536     TRACE_SANITIZE (this);
 537     return_trace (c->check_struct (this) &&
 538                   coverage.sanitize (c, this) &&
 539                   valueFormat.sanitize_values (c, this, values, valueCount));
 540   }
 541 
 542   protected:
 543   USHORT        format;                 /* Format identifier--format = 2 */
 544   OffsetTo<Coverage>
 545                 coverage;               /* Offset to Coverage table--from
 546                                          * beginning of subtable */


 623 
 624     const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
 625     unsigned int count = len;
 626 
 627     /* Hand-coded bsearch. */
 628     if (unlikely (!count))
 629       return_trace (false);
 630     hb_codepoint_t x = buffer->info[pos].codepoint;
 631     int min = 0, max = (int) count - 1;
 632     while (min <= max)
 633     {
 634       int mid = (min + max) / 2;
 635       const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
 636       hb_codepoint_t mid_x = record->secondGlyph;
 637       if (x < mid_x)
 638         max = mid - 1;
 639       else if (x > mid_x)
 640         min = mid + 1;
 641       else
 642       {
 643         valueFormats[0].apply_value (c->font, c->direction, this,
 644                                      &record->values[0], buffer->cur_pos());
 645         valueFormats[1].apply_value (c->font, c->direction, this,
 646                                      &record->values[len1], buffer->pos[pos]);
 647         if (len2)
 648           pos++;
 649         buffer->idx = pos;
 650         return_trace (true);
 651       }
 652     }
 653 
 654     return_trace (false);
 655   }
 656 
 657   struct sanitize_closure_t {
 658     const void *base;
 659     const ValueFormat *valueFormats;
 660     unsigned int len1; /* valueFormats[0].get_len() */
 661     unsigned int stride; /* 1 + len1 + len2 */
 662   };
 663 
 664   inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
 665   {
 666     TRACE_SANITIZE (this);


 672     return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
 673                   closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
 674   }
 675 
 676   protected:
 677   USHORT        len;                    /* Number of PairValueRecords */
 678   USHORT        arrayZ[VAR];            /* Array of PairValueRecords--ordered
 679                                          * by GlyphID of the second glyph */
 680   public:
 681   DEFINE_SIZE_ARRAY (2, arrayZ);
 682 };
 683 
 684 struct PairPosFormat1
 685 {
 686   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
 687   {
 688     TRACE_COLLECT_GLYPHS (this);
 689     (this+coverage).add_coverage (c->input);
 690     unsigned int count = pairSet.len;
 691     for (unsigned int i = 0; i < count; i++)
 692       (this+pairSet[i]).collect_glyphs (c, &valueFormat1);
 693   }
 694 
 695   inline const Coverage &get_coverage (void) const
 696   {
 697     return this+coverage;
 698   }
 699 
 700   inline bool apply (hb_apply_context_t *c) const
 701   {
 702     TRACE_APPLY (this);
 703     hb_buffer_t *buffer = c->buffer;
 704     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
 705     if (likely (index == NOT_COVERED)) return_trace (false);
 706 
 707     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
 708     skippy_iter.reset (buffer->idx, 1);
 709     if (!skippy_iter.next ()) return_trace (false);
 710 
 711     return_trace ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx));
 712   }
 713 
 714   inline bool sanitize (hb_sanitize_context_t *c) const
 715   {
 716     TRACE_SANITIZE (this);
 717 
 718     if (!c->check_struct (this)) return_trace (false);
 719 
 720     unsigned int len1 = valueFormat1.get_len ();
 721     unsigned int len2 = valueFormat2.get_len ();
 722     PairSet::sanitize_closure_t closure = {
 723       this,
 724       &valueFormat1,
 725       len1,
 726       1 + len1 + len2
 727     };
 728 
 729     return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
 730   }
 731 
 732   protected:
 733   USHORT        format;                 /* Format identifier--format = 1 */
 734   OffsetTo<Coverage>
 735                 coverage;               /* Offset to Coverage table--from
 736                                          * beginning of subtable */
 737   ValueFormat   valueFormat1;           /* Defines the types of data in
 738                                          * ValueRecord1--for the first glyph
 739                                          * in the pair--may be zero (0) */
 740   ValueFormat   valueFormat2;           /* Defines the types of data in
 741                                          * ValueRecord2--for the second glyph
 742                                          * in the pair--may be zero (0) */
 743   OffsetArrayOf<PairSet>
 744                 pairSet;                /* Array of PairSet tables
 745                                          * ordered by Coverage Index */
 746   public:
 747   DEFINE_SIZE_ARRAY (10, pairSet);
 748 };
 749 
 750 struct PairPosFormat2
 751 {
 752   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
 753   {
 754     TRACE_COLLECT_GLYPHS (this);
 755     (this+coverage).add_coverage (c->input);
 756 
 757     unsigned int count1 = class1Count;
 758     const ClassDef &klass1 = this+classDef1;
 759     for (unsigned int i = 0; i < count1; i++)
 760       klass1.add_class (c->input, i);


 773   inline bool apply (hb_apply_context_t *c) const
 774   {
 775     TRACE_APPLY (this);
 776     hb_buffer_t *buffer = c->buffer;
 777     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
 778     if (likely (index == NOT_COVERED)) return_trace (false);
 779 
 780     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
 781     skippy_iter.reset (buffer->idx, 1);
 782     if (!skippy_iter.next ()) return_trace (false);
 783 
 784     unsigned int len1 = valueFormat1.get_len ();
 785     unsigned int len2 = valueFormat2.get_len ();
 786     unsigned int record_len = len1 + len2;
 787 
 788     unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
 789     unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
 790     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
 791 
 792     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
 793     valueFormat1.apply_value (c->font, c->direction, this,
 794                               v, buffer->cur_pos());
 795     valueFormat2.apply_value (c->font, c->direction, this,
 796                               v + len1, buffer->pos[skippy_iter.idx]);
 797 
 798     buffer->idx = skippy_iter.idx;
 799     if (len2)
 800       buffer->idx++;
 801 
 802     return_trace (true);
 803   }
 804 
 805   inline bool sanitize (hb_sanitize_context_t *c) const
 806   {
 807     TRACE_SANITIZE (this);
 808     if (!(c->check_struct (this)
 809        && coverage.sanitize (c, this)
 810        && classDef1.sanitize (c, this)
 811        && classDef2.sanitize (c, this))) return_trace (false);
 812 
 813     unsigned int len1 = valueFormat1.get_len ();
 814     unsigned int len2 = valueFormat2.get_len ();
 815     unsigned int stride = len1 + len2;
 816     unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();


 914 
 915   inline bool apply (hb_apply_context_t *c) const
 916   {
 917     TRACE_APPLY (this);
 918     hb_buffer_t *buffer = c->buffer;
 919 
 920     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
 921     if (!this_record.exitAnchor) return_trace (false);
 922 
 923     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
 924     skippy_iter.reset (buffer->idx, 1);
 925     if (!skippy_iter.next ()) return_trace (false);
 926 
 927     const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
 928     if (!next_record.entryAnchor) return_trace (false);
 929 
 930     unsigned int i = buffer->idx;
 931     unsigned int j = skippy_iter.idx;
 932 
 933     hb_position_t entry_x, entry_y, exit_x, exit_y;
 934     (this+this_record.exitAnchor).get_anchor (c->font, buffer->info[i].codepoint, &exit_x, &exit_y);
 935     (this+next_record.entryAnchor).get_anchor (c->font, buffer->info[j].codepoint, &entry_x, &entry_y);
 936 
 937     hb_glyph_position_t *pos = buffer->pos;
 938 
 939     hb_position_t d;
 940     /* Main-direction adjustment */
 941     switch (c->direction) {
 942       case HB_DIRECTION_LTR:
 943         pos[i].x_advance  =  exit_x + pos[i].x_offset;
 944 
 945         d = entry_x + pos[j].x_offset;
 946         pos[j].x_advance -= d;
 947         pos[j].x_offset  -= d;
 948         break;
 949       case HB_DIRECTION_RTL:
 950         d = exit_x + pos[i].x_offset;
 951         pos[i].x_advance -= d;
 952         pos[i].x_offset  -= d;
 953 
 954         pos[j].x_advance  =  entry_x + pos[j].x_offset;
 955         break;


1502  */
1503 
1504 struct GPOS : GSUBGPOS
1505 {
1506   static const hb_tag_t tableTag        = HB_OT_TAG_GPOS;
1507 
1508   inline const PosLookup& get_lookup (unsigned int i) const
1509   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
1510 
1511   static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
1512   static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
1513   static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
1514 
1515   inline bool sanitize (hb_sanitize_context_t *c) const
1516   {
1517     TRACE_SANITIZE (this);
1518     if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
1519     const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
1520     return_trace (list.sanitize (c, this));
1521   }
1522   public:
1523   DEFINE_SIZE_STATIC (10);
1524 };
1525 
1526 
1527 static void
1528 reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
1529 {
1530   int chain = pos[i].attach_chain(), type = pos[i].attach_type();
1531   if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
1532     return;
1533 
1534   pos[i].attach_chain() = 0;
1535 
1536   unsigned int j = (int) i + chain;
1537 
1538   /* Stop if we see new parent in the chain. */
1539   if (j == new_parent)
1540     return;
1541 
1542   reverse_cursive_minor_offset (pos, j, direction, new_parent);
1543 




  86                                          * writing) */
  87   Offset        xPlaDevice;             /* Offset to Device table for
  88                                          * horizontal placement--measured from
  89                                          * beginning of PosTable (may be NULL) */
  90   Offset        yPlaDevice;             /* Offset to Device table for vertical
  91                                          * placement--measured from beginning
  92                                          * of PosTable (may be NULL) */
  93   Offset        xAdvDevice;             /* Offset to Device table for
  94                                          * horizontal advance--measured from
  95                                          * beginning of PosTable (may be NULL) */
  96   Offset        yAdvDevice;             /* Offset to Device table for vertical
  97                                          * advance--measured from beginning of
  98                                          * PosTable (may be NULL) */
  99 #endif
 100 
 101   inline unsigned int get_len (void) const
 102   { return _hb_popcount32 ((unsigned int) *this); }
 103   inline unsigned int get_size (void) const
 104   { return get_len () * Value::static_size; }
 105 
 106   void apply_value (hb_apply_context_t   *c,

 107                     const void           *base,
 108                     const Value          *values,
 109                     hb_glyph_position_t  &glyph_pos) const
 110   {

 111     unsigned int format = *this;


 112     if (!format) return;
 113 
 114     hb_font_t *font = c->font;
 115     hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
 116 
 117     if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++));
 118     if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++));
 119     if (format & xAdvance) {
 120       if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values));
 121       values++;
 122     }
 123     /* y_advance values grow downward but font-space grows upward, hence negation */
 124     if (format & yAdvance) {
 125       if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values));
 126       values++;
 127     }
 128 
 129     if (!has_device ()) return;
 130 
 131     bool use_x_device = font->x_ppem || font->num_coords;
 132     bool use_y_device = font->y_ppem || font->num_coords;
 133 
 134     if (!use_x_device && !use_y_device) return;
 135 
 136     const VariationStore &store = c->var_store;
 137 
 138     /* pixel -> fractional pixel */
 139     if (format & xPlaDevice) {
 140       if (use_x_device) glyph_pos.x_offset  += (base + get_device (values)).get_x_delta (font, store);
 141       values++;
 142     }
 143     if (format & yPlaDevice) {
 144       if (use_y_device) glyph_pos.y_offset  += (base + get_device (values)).get_y_delta (font, store);
 145       values++;
 146     }
 147     if (format & xAdvDevice) {
 148       if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store);
 149       values++;
 150     }
 151     if (format & yAdvDevice) {
 152       /* y_advance values grow downward but font-space grows upward, hence negation */
 153       if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store);
 154       values++;
 155     }
 156   }
 157 
 158   private:
 159   inline bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
 160   {
 161     unsigned int format = *this;
 162 
 163     if (format & xPlacement) values++;
 164     if (format & yPlacement) values++;
 165     if (format & xAdvance)   values++;
 166     if (format & yAdvance)   values++;
 167 
 168     if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
 169     if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
 170     if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
 171     if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
 172 
 173     return true;


 215   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
 216   inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
 217   {
 218     TRACE_SANITIZE (this);
 219 
 220     if (!has_device ()) return_trace (true);
 221 
 222     for (unsigned int i = 0; i < count; i++) {
 223       if (!sanitize_value_devices (c, base, values))
 224         return_trace (false);
 225       values += stride;
 226     }
 227 
 228     return_trace (true);
 229   }
 230 };
 231 
 232 
 233 struct AnchorFormat1
 234 {
 235   inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
 236                           hb_position_t *x, hb_position_t *y) const
 237   {
 238     hb_font_t *font = c->font;
 239     *x = font->em_scale_x (xCoordinate);
 240     *y = font->em_scale_y (yCoordinate);
 241   }
 242 
 243   inline bool sanitize (hb_sanitize_context_t *c) const
 244   {
 245     TRACE_SANITIZE (this);
 246     return_trace (c->check_struct (this));
 247   }
 248 
 249   protected:
 250   USHORT        format;                 /* Format identifier--format = 1 */
 251   SHORT         xCoordinate;            /* Horizontal value--in design units */
 252   SHORT         yCoordinate;            /* Vertical value--in design units */
 253   public:
 254   DEFINE_SIZE_STATIC (6);
 255 };
 256 
 257 struct AnchorFormat2
 258 {
 259   inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
 260                           hb_position_t *x, hb_position_t *y) const
 261   {
 262     hb_font_t *font = c->font;
 263     unsigned int x_ppem = font->x_ppem;
 264     unsigned int y_ppem = font->y_ppem;
 265     hb_position_t cx, cy;
 266     hb_bool_t ret;
 267 
 268     ret = (x_ppem || y_ppem) &&
 269            font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
 270     *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate);
 271     *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate);
 272   }
 273 
 274   inline bool sanitize (hb_sanitize_context_t *c) const
 275   {
 276     TRACE_SANITIZE (this);
 277     return_trace (c->check_struct (this));
 278   }
 279 
 280   protected:
 281   USHORT        format;                 /* Format identifier--format = 2 */
 282   SHORT         xCoordinate;            /* Horizontal value--in design units */
 283   SHORT         yCoordinate;            /* Vertical value--in design units */
 284   USHORT        anchorPoint;            /* Index to glyph contour point */
 285   public:
 286   DEFINE_SIZE_STATIC (8);
 287 };
 288 
 289 struct AnchorFormat3
 290 {
 291   inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
 292                           hb_position_t *x, hb_position_t *y) const
 293   {
 294     hb_font_t *font = c->font;
 295     *x = font->em_scale_x (xCoordinate);
 296     *y = font->em_scale_y (yCoordinate);
 297 
 298     if (font->x_ppem || font->num_coords)
 299       *x += (this+xDeviceTable).get_x_delta (font, c->var_store);
 300     if (font->y_ppem || font->num_coords)
 301       *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
 302   }
 303 
 304   inline bool sanitize (hb_sanitize_context_t *c) const
 305   {
 306     TRACE_SANITIZE (this);
 307     return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
 308   }
 309 
 310   protected:
 311   USHORT        format;                 /* Format identifier--format = 3 */
 312   SHORT         xCoordinate;            /* Horizontal value--in design units */
 313   SHORT         yCoordinate;            /* Vertical value--in design units */
 314   OffsetTo<Device>
 315                 xDeviceTable;           /* Offset to Device table for X
 316                                          * coordinate-- from beginning of
 317                                          * Anchor table (may be NULL) */
 318   OffsetTo<Device>
 319                 yDeviceTable;           /* Offset to Device table for Y
 320                                          * coordinate-- from beginning of
 321                                          * Anchor table (may be NULL) */
 322   public:
 323   DEFINE_SIZE_STATIC (10);
 324 };
 325 
 326 struct Anchor
 327 {
 328   inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
 329                           hb_position_t *x, hb_position_t *y) const
 330   {
 331     *x = *y = 0;
 332     switch (u.format) {
 333     case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
 334     case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
 335     case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
 336     default:                                             return;
 337     }
 338   }
 339 
 340   inline bool sanitize (hb_sanitize_context_t *c) const
 341   {
 342     TRACE_SANITIZE (this);
 343     if (!u.format.sanitize (c)) return_trace (false);
 344     switch (u.format) {
 345     case 1: return_trace (u.format1.sanitize (c));
 346     case 2: return_trace (u.format2.sanitize (c));
 347     case 3: return_trace (u.format3.sanitize (c));
 348     default:return_trace (true);
 349     }
 350   }
 351 
 352   protected:
 353   union {
 354   USHORT                format;         /* Format identifier */
 355   AnchorFormat1         format1;


 357   AnchorFormat3         format3;
 358   } u;
 359   public:
 360   DEFINE_SIZE_UNION (2, format);
 361 };
 362 
 363 
 364 struct AnchorMatrix
 365 {
 366   inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const {
 367     *found = false;
 368     if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
 369     *found = !matrixZ[row * cols + col].is_null ();
 370     return this+matrixZ[row * cols + col];
 371   }
 372 
 373   inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
 374   {
 375     TRACE_SANITIZE (this);
 376     if (!c->check_struct (this)) return_trace (false);
 377     if (unlikely (_hb_unsigned_int_mul_overflows (rows, cols))) return_trace (false);
 378     unsigned int count = rows * cols;
 379     if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false);
 380     for (unsigned int i = 0; i < count; i++)
 381       if (!matrixZ[i].sanitize (c, this)) return_trace (false);
 382     return_trace (true);
 383   }
 384 
 385   USHORT        rows;                   /* Number of rows */
 386   protected:
 387   OffsetTo<Anchor>
 388                 matrixZ[VAR];           /* Matrix of offsets to Anchor tables--
 389                                          * from beginning of AnchorMatrix table */
 390   public:
 391   DEFINE_SIZE_ARRAY (2, matrixZ);
 392 };
 393 
 394 
 395 struct MarkRecord
 396 {
 397   friend struct MarkArray;


 415 {
 416   inline bool apply (hb_apply_context_t *c,
 417                      unsigned int mark_index, unsigned int glyph_index,
 418                      const AnchorMatrix &anchors, unsigned int class_count,
 419                      unsigned int glyph_pos) const
 420   {
 421     TRACE_APPLY (this);
 422     hb_buffer_t *buffer = c->buffer;
 423     const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index);
 424     unsigned int mark_class = record.klass;
 425 
 426     const Anchor& mark_anchor = this + record.markAnchor;
 427     bool found;
 428     const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
 429     /* If this subtable doesn't have an anchor for this base and this class,
 430      * return false such that the subsequent subtables have a chance at it. */
 431     if (unlikely (!found)) return_trace (false);
 432 
 433     hb_position_t mark_x, mark_y, base_x, base_y;
 434 
 435     mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
 436     glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
 437 
 438     hb_glyph_position_t &o = buffer->cur_pos();
 439     o.x_offset = base_x - mark_x;
 440     o.y_offset = base_y - mark_y;
 441     o.attach_type() = ATTACH_TYPE_MARK;
 442     o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
 443     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
 444 
 445     buffer->idx++;
 446     return_trace (true);
 447   }
 448 
 449   inline bool sanitize (hb_sanitize_context_t *c) const
 450   {
 451     TRACE_SANITIZE (this);
 452     return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
 453   }
 454 };
 455 
 456 


 459 struct SinglePosFormat1
 460 {
 461   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
 462   {
 463     TRACE_COLLECT_GLYPHS (this);
 464     (this+coverage).add_coverage (c->input);
 465   }
 466 
 467   inline const Coverage &get_coverage (void) const
 468   {
 469     return this+coverage;
 470   }
 471 
 472   inline bool apply (hb_apply_context_t *c) const
 473   {
 474     TRACE_APPLY (this);
 475     hb_buffer_t *buffer = c->buffer;
 476     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
 477     if (likely (index == NOT_COVERED)) return_trace (false);
 478 
 479     valueFormat.apply_value (c, this, values, buffer->cur_pos());

 480 
 481     buffer->idx++;
 482     return_trace (true);
 483   }
 484 
 485   inline bool sanitize (hb_sanitize_context_t *c) const
 486   {
 487     TRACE_SANITIZE (this);
 488     return_trace (c->check_struct (this) &&
 489                   coverage.sanitize (c, this) &&
 490                   valueFormat.sanitize_value (c, this, values));
 491   }
 492 
 493   protected:
 494   USHORT        format;                 /* Format identifier--format = 1 */
 495   OffsetTo<Coverage>
 496                 coverage;               /* Offset to Coverage table--from
 497                                          * beginning of subtable */
 498   ValueFormat   valueFormat;            /* Defines the types of data in the
 499                                          * ValueRecord */


 509   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
 510   {
 511     TRACE_COLLECT_GLYPHS (this);
 512     (this+coverage).add_coverage (c->input);
 513   }
 514 
 515   inline const Coverage &get_coverage (void) const
 516   {
 517     return this+coverage;
 518   }
 519 
 520   inline bool apply (hb_apply_context_t *c) const
 521   {
 522     TRACE_APPLY (this);
 523     hb_buffer_t *buffer = c->buffer;
 524     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
 525     if (likely (index == NOT_COVERED)) return_trace (false);
 526 
 527     if (likely (index >= valueCount)) return_trace (false);
 528 
 529     valueFormat.apply_value (c, this,
 530                              &values[index * valueFormat.get_len ()],
 531                              buffer->cur_pos());
 532 
 533     buffer->idx++;
 534     return_trace (true);
 535   }
 536 
 537   inline bool sanitize (hb_sanitize_context_t *c) const
 538   {
 539     TRACE_SANITIZE (this);
 540     return_trace (c->check_struct (this) &&
 541                   coverage.sanitize (c, this) &&
 542                   valueFormat.sanitize_values (c, this, values, valueCount));
 543   }
 544 
 545   protected:
 546   USHORT        format;                 /* Format identifier--format = 2 */
 547   OffsetTo<Coverage>
 548                 coverage;               /* Offset to Coverage table--from
 549                                          * beginning of subtable */


 626 
 627     const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
 628     unsigned int count = len;
 629 
 630     /* Hand-coded bsearch. */
 631     if (unlikely (!count))
 632       return_trace (false);
 633     hb_codepoint_t x = buffer->info[pos].codepoint;
 634     int min = 0, max = (int) count - 1;
 635     while (min <= max)
 636     {
 637       int mid = (min + max) / 2;
 638       const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
 639       hb_codepoint_t mid_x = record->secondGlyph;
 640       if (x < mid_x)
 641         max = mid - 1;
 642       else if (x > mid_x)
 643         min = mid + 1;
 644       else
 645       {
 646         valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
 647         valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);


 648         if (len2)
 649           pos++;
 650         buffer->idx = pos;
 651         return_trace (true);
 652       }
 653     }
 654 
 655     return_trace (false);
 656   }
 657 
 658   struct sanitize_closure_t {
 659     const void *base;
 660     const ValueFormat *valueFormats;
 661     unsigned int len1; /* valueFormats[0].get_len() */
 662     unsigned int stride; /* 1 + len1 + len2 */
 663   };
 664 
 665   inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
 666   {
 667     TRACE_SANITIZE (this);


 673     return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
 674                   closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
 675   }
 676 
 677   protected:
 678   USHORT        len;                    /* Number of PairValueRecords */
 679   USHORT        arrayZ[VAR];            /* Array of PairValueRecords--ordered
 680                                          * by GlyphID of the second glyph */
 681   public:
 682   DEFINE_SIZE_ARRAY (2, arrayZ);
 683 };
 684 
 685 struct PairPosFormat1
 686 {
 687   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
 688   {
 689     TRACE_COLLECT_GLYPHS (this);
 690     (this+coverage).add_coverage (c->input);
 691     unsigned int count = pairSet.len;
 692     for (unsigned int i = 0; i < count; i++)
 693       (this+pairSet[i]).collect_glyphs (c, valueFormat);
 694   }
 695 
 696   inline const Coverage &get_coverage (void) const
 697   {
 698     return this+coverage;
 699   }
 700 
 701   inline bool apply (hb_apply_context_t *c) const
 702   {
 703     TRACE_APPLY (this);
 704     hb_buffer_t *buffer = c->buffer;
 705     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
 706     if (likely (index == NOT_COVERED)) return_trace (false);
 707 
 708     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
 709     skippy_iter.reset (buffer->idx, 1);
 710     if (!skippy_iter.next ()) return_trace (false);
 711 
 712     return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
 713   }
 714 
 715   inline bool sanitize (hb_sanitize_context_t *c) const
 716   {
 717     TRACE_SANITIZE (this);
 718 
 719     if (!c->check_struct (this)) return_trace (false);
 720 
 721     unsigned int len1 = valueFormat[0].get_len ();
 722     unsigned int len2 = valueFormat[1].get_len ();
 723     PairSet::sanitize_closure_t closure = {
 724       this,
 725       valueFormat,
 726       len1,
 727       1 + len1 + len2
 728     };
 729 
 730     return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
 731   }
 732 
 733   protected:
 734   USHORT        format;                 /* Format identifier--format = 1 */
 735   OffsetTo<Coverage>
 736                 coverage;               /* Offset to Coverage table--from
 737                                          * beginning of subtable */
 738   ValueFormat   valueFormat[2];         /* [0] Defines the types of data in
 739                                          * ValueRecord1--for the first glyph
 740                                          * in the pair--may be zero (0) */
 741                                         /* [1] Defines the types of data in
 742                                          * ValueRecord2--for the second glyph
 743                                          * in the pair--may be zero (0) */
 744   OffsetArrayOf<PairSet>
 745                 pairSet;                /* Array of PairSet tables
 746                                          * ordered by Coverage Index */
 747   public:
 748   DEFINE_SIZE_ARRAY (10, pairSet);
 749 };
 750 
 751 struct PairPosFormat2
 752 {
 753   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
 754   {
 755     TRACE_COLLECT_GLYPHS (this);
 756     (this+coverage).add_coverage (c->input);
 757 
 758     unsigned int count1 = class1Count;
 759     const ClassDef &klass1 = this+classDef1;
 760     for (unsigned int i = 0; i < count1; i++)
 761       klass1.add_class (c->input, i);


 774   inline bool apply (hb_apply_context_t *c) const
 775   {
 776     TRACE_APPLY (this);
 777     hb_buffer_t *buffer = c->buffer;
 778     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
 779     if (likely (index == NOT_COVERED)) return_trace (false);
 780 
 781     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
 782     skippy_iter.reset (buffer->idx, 1);
 783     if (!skippy_iter.next ()) return_trace (false);
 784 
 785     unsigned int len1 = valueFormat1.get_len ();
 786     unsigned int len2 = valueFormat2.get_len ();
 787     unsigned int record_len = len1 + len2;
 788 
 789     unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
 790     unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
 791     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
 792 
 793     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
 794     valueFormat1.apply_value (c, this, v, buffer->cur_pos());
 795     valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);


 796 
 797     buffer->idx = skippy_iter.idx;
 798     if (len2)
 799       buffer->idx++;
 800 
 801     return_trace (true);
 802   }
 803 
 804   inline bool sanitize (hb_sanitize_context_t *c) const
 805   {
 806     TRACE_SANITIZE (this);
 807     if (!(c->check_struct (this)
 808        && coverage.sanitize (c, this)
 809        && classDef1.sanitize (c, this)
 810        && classDef2.sanitize (c, this))) return_trace (false);
 811 
 812     unsigned int len1 = valueFormat1.get_len ();
 813     unsigned int len2 = valueFormat2.get_len ();
 814     unsigned int stride = len1 + len2;
 815     unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();


 913 
 914   inline bool apply (hb_apply_context_t *c) const
 915   {
 916     TRACE_APPLY (this);
 917     hb_buffer_t *buffer = c->buffer;
 918 
 919     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
 920     if (!this_record.exitAnchor) return_trace (false);
 921 
 922     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
 923     skippy_iter.reset (buffer->idx, 1);
 924     if (!skippy_iter.next ()) return_trace (false);
 925 
 926     const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
 927     if (!next_record.entryAnchor) return_trace (false);
 928 
 929     unsigned int i = buffer->idx;
 930     unsigned int j = skippy_iter.idx;
 931 
 932     hb_position_t entry_x, entry_y, exit_x, exit_y;
 933     (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
 934     (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
 935 
 936     hb_glyph_position_t *pos = buffer->pos;
 937 
 938     hb_position_t d;
 939     /* Main-direction adjustment */
 940     switch (c->direction) {
 941       case HB_DIRECTION_LTR:
 942         pos[i].x_advance  =  exit_x + pos[i].x_offset;
 943 
 944         d = entry_x + pos[j].x_offset;
 945         pos[j].x_advance -= d;
 946         pos[j].x_offset  -= d;
 947         break;
 948       case HB_DIRECTION_RTL:
 949         d = exit_x + pos[i].x_offset;
 950         pos[i].x_advance -= d;
 951         pos[i].x_offset  -= d;
 952 
 953         pos[j].x_advance  =  entry_x + pos[j].x_offset;
 954         break;


1501  */
1502 
1503 struct GPOS : GSUBGPOS
1504 {
1505   static const hb_tag_t tableTag        = HB_OT_TAG_GPOS;
1506 
1507   inline const PosLookup& get_lookup (unsigned int i) const
1508   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
1509 
1510   static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
1511   static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
1512   static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
1513 
1514   inline bool sanitize (hb_sanitize_context_t *c) const
1515   {
1516     TRACE_SANITIZE (this);
1517     if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
1518     const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
1519     return_trace (list.sanitize (c, this));
1520   }


1521 };
1522 
1523 
1524 static void
1525 reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
1526 {
1527   int chain = pos[i].attach_chain(), type = pos[i].attach_type();
1528   if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
1529     return;
1530 
1531   pos[i].attach_chain() = 0;
1532 
1533   unsigned int j = (int) i + chain;
1534 
1535   /* Stop if we see new parent in the chain. */
1536   if (j == new_parent)
1537     return;
1538 
1539   reverse_cursive_minor_offset (pos, j, direction, new_parent);
1540 


< prev index next >