hb-aat-layout-common.hh 17.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * Copyright © 2017  Google, Inc.
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Google Author(s): Behdad Esfahbod
 */

27 28
#ifndef HB_AAT_LAYOUT_COMMON_HH
#define HB_AAT_LAYOUT_COMMON_HH
29

30
#include "hb-aat-layout.hh"
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50


namespace AAT {

using namespace OT;


/*
 * Binary Searching Tables
 */

struct BinSearchHeader
{

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this));
  }

B
Behdad Esfahbod 已提交
51 52 53
  HBUINT16	unitSize;	/* Size of a lookup unit for this search in bytes. */
  HBUINT16	nUnits;		/* Number of units of the preceding size to be searched. */
  HBUINT16	searchRange;	/* The value of unitSize times the largest power of 2
54
				 * that is less than or equal to the value of nUnits. */
B
Behdad Esfahbod 已提交
55
  HBUINT16	entrySelector;	/* The log base 2 of the largest power of 2 less than
56
				 * or equal to the value of nUnits. */
B
Behdad Esfahbod 已提交
57
  HBUINT16	rangeShift;	/* The value of unitSize times the difference of the
58 59 60 61 62 63 64 65 66 67 68 69
				 * value of nUnits minus the largest power of 2 less
				 * than or equal to the value of nUnits. */
  public:
  DEFINE_SIZE_STATIC (10);
};

template <typename Type>
struct BinSearchArrayOf
{
  inline const Type& operator [] (unsigned int i) const
  {
    if (unlikely (i >= header.nUnits)) return Null(Type);
70
    return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
71 72 73
  }
  inline Type& operator [] (unsigned int i)
  {
74
    return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
  }
  inline unsigned int get_size (void) const
  { return header.static_size + header.nUnits * header.unitSize; }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!sanitize_shallow (c))) return_trace (false);

    /* Note: for structs that do not reference other structs,
     * we do not need to call their sanitize() as we already did
     * a bound check on the aggregate array size.  We just include
     * a small unreachable expression to make sure the structs
     * pointed to do have a simple sanitize(), ie. they do not
     * reference other structs via offsets.
     */
91
    (void) (false && StructAtOffset<Type> (&bytesZ, 0).sanitize (c));
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

    return_trace (true);
  }
  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!sanitize_shallow (c))) return_trace (false);
    unsigned int count = header.nUnits;
    for (unsigned int i = 0; i < count; i++)
      if (unlikely (!(*this)[i].sanitize (c, base)))
        return_trace (false);
    return_trace (true);
  }

  template <typename T>
B
Behdad Esfahbod 已提交
107
  inline const Type *bsearch (const T &key) const
108
  {
B
Behdad Esfahbod 已提交
109 110 111 112 113
    unsigned int size = header.unitSize;
    int min = 0, max = (int) header.nUnits - 1;
    while (min <= max)
    {
      int mid = (min + max) / 2;
114
      const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size));
B
Behdad Esfahbod 已提交
115 116 117 118 119 120 121 122
      int c = p->cmp (key);
      if (c < 0)
	max = mid - 1;
      else if (c > 0)
	min = mid + 1;
      else
	return p;
    }
B
Bruce Mitchener 已提交
123
    return nullptr;
124 125 126 127 128 129 130 131
  }

  private:
  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (header.sanitize (c) &&
		  Type::static_size >= header.unitSize &&
132
		  c->check_array (bytesZ.arrayZ, header.nUnits, header.unitSize));
133 134 135
  }

  protected:
136 137
  BinSearchHeader		header;
  UnsizedArrayOf<HBUINT8>	bytesZ;
138
  public:
139
  DEFINE_SIZE_ARRAY (10, bytesZ);
140 141 142
};


B
Behdad Esfahbod 已提交
143 144 145 146 147 148 149 150 151 152 153 154
/*
 * Lookup Table
 */

template <typename T> struct Lookup;

template <typename T>
struct LookupFormat0
{
  friend struct Lookup<T>;

  private:
155
  inline const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
B
Behdad Esfahbod 已提交
156
  {
157 158
    if (unlikely (glyph_id >= num_glyphs)) return nullptr;
    return &arrayZ[glyph_id];
B
Behdad Esfahbod 已提交
159 160 161 162 163
  }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
164
    return_trace (arrayZ.sanitize (c, c->get_num_glyphs ()));
B
Behdad Esfahbod 已提交
165 166 167
  }

  protected:
B
Behdad Esfahbod 已提交
168
  HBUINT16	format;		/* Format identifier--format = 0 */
B
Behdad Esfahbod 已提交
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
  UnsizedArrayOf<T>
		arrayZ;		/* Array of lookup values, indexed by glyph index. */
  public:
  DEFINE_SIZE_ARRAY (2, arrayZ);
};


template <typename T>
struct LookupSegmentSingle
{
  inline int cmp (hb_codepoint_t g) const {
    return g < first ? -1 : g <= last ? 0 : +1 ;
  }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) && value.sanitize (c));
  }

  GlyphID	last;		/* Last GlyphID in this segment */
  GlyphID	first;		/* First GlyphID in this segment */
  T		value;		/* The lookup value (only one) */
  public:
193
  DEFINE_SIZE_STATIC (4 + T::static_size);
B
Behdad Esfahbod 已提交
194 195 196 197 198 199 200 201
};

template <typename T>
struct LookupFormat2
{
  friend struct Lookup<T>;

  private:
202
  inline const T* get_value (hb_codepoint_t glyph_id) const
B
Behdad Esfahbod 已提交
203 204
  {
    const LookupSegmentSingle<T> *v = segments.bsearch (glyph_id);
205
    return v ? &v->value : nullptr;
B
Behdad Esfahbod 已提交
206 207 208 209 210 211 212 213 214
  }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (segments.sanitize (c));
  }

  protected:
B
Behdad Esfahbod 已提交
215
  HBUINT16	format;		/* Format identifier--format = 2 */
B
Behdad Esfahbod 已提交
216 217 218 219 220 221 222 223 224 225 226
  BinSearchArrayOf<LookupSegmentSingle<T> >
		segments;	/* The actual segments. These must already be sorted,
				 * according to the first word in each one (the last
				 * glyph in each segment). */
  public:
  DEFINE_SIZE_ARRAY (8, segments);
};

template <typename T>
struct LookupSegmentArray
{
227
  inline const T* get_value (hb_codepoint_t glyph_id, const void *base) const
B
Behdad Esfahbod 已提交
228
  {
229
    return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
B
Behdad Esfahbod 已提交
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
  }

  inline int cmp (hb_codepoint_t g) const {
    return g < first ? -1 : g <= last ? 0 : +1 ;
  }

  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) &&
		  first <= last &&
		  valuesZ.sanitize (c, base, last - first + 1));
  }

  GlyphID	last;		/* Last GlyphID in this segment */
  GlyphID	first;		/* First GlyphID in this segment */
246
  OffsetTo<UnsizedArrayOf<T>, HBUINT16, false>
B
Behdad Esfahbod 已提交
247 248 249 250 251 252 253 254 255 256 257 258
		valuesZ;	/* A 16-bit offset from the start of
				 * the table to the data. */
  public:
  DEFINE_SIZE_STATIC (6);
};

template <typename T>
struct LookupFormat4
{
  friend struct Lookup<T>;

  private:
259
  inline const T* get_value (hb_codepoint_t glyph_id) const
B
Behdad Esfahbod 已提交
260 261
  {
    const LookupSegmentArray<T> *v = segments.bsearch (glyph_id);
262
    return v ? v->get_value (glyph_id, this) : nullptr;
B
Behdad Esfahbod 已提交
263 264 265 266 267 268 269 270 271
  }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (segments.sanitize (c, this));
  }

  protected:
B
Behdad Esfahbod 已提交
272
  HBUINT16	format;		/* Format identifier--format = 2 */
B
Behdad Esfahbod 已提交
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
  BinSearchArrayOf<LookupSegmentArray<T> >
		segments;	/* The actual segments. These must already be sorted,
				 * according to the first word in each one (the last
				 * glyph in each segment). */
  public:
  DEFINE_SIZE_ARRAY (8, segments);
};

template <typename T>
struct LookupSingle
{
  inline int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) && value.sanitize (c));
  }

  GlyphID	glyph;		/* Last GlyphID */
  T		value;		/* The lookup value (only one) */
  public:
295
  DEFINE_SIZE_STATIC (4 + T::static_size);
B
Behdad Esfahbod 已提交
296 297 298 299 300 301 302 303
};

template <typename T>
struct LookupFormat6
{
  friend struct Lookup<T>;

  private:
304
  inline const T* get_value (hb_codepoint_t glyph_id) const
B
Behdad Esfahbod 已提交
305 306
  {
    const LookupSingle<T> *v = entries.bsearch (glyph_id);
307
    return v ? &v->value : nullptr;
B
Behdad Esfahbod 已提交
308 309 310 311 312 313 314 315 316
  }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (entries.sanitize (c));
  }

  protected:
B
Behdad Esfahbod 已提交
317
  HBUINT16	format;		/* Format identifier--format = 6 */
B
Behdad Esfahbod 已提交
318 319 320 321 322 323 324 325 326 327 328 329
  BinSearchArrayOf<LookupSingle<T> >
		entries;	/* The actual entries, sorted by glyph index. */
  public:
  DEFINE_SIZE_ARRAY (8, entries);
};

template <typename T>
struct LookupFormat8
{
  friend struct Lookup<T>;

  private:
330
  inline const T* get_value (hb_codepoint_t glyph_id) const
B
Behdad Esfahbod 已提交
331
  {
332
    return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ? &valueArrayZ[glyph_id - firstGlyph] : nullptr;
B
Behdad Esfahbod 已提交
333 334 335 336 337 338 339 340 341
  }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
  }

  protected:
B
Behdad Esfahbod 已提交
342
  HBUINT16	format;		/* Format identifier--format = 6 */
B
Behdad Esfahbod 已提交
343
  GlyphID	firstGlyph;	/* First glyph index included in the trimmed array. */
B
Behdad Esfahbod 已提交
344
  HBUINT16	glyphCount;	/* Total number of glyphs (equivalent to the last
B
Behdad Esfahbod 已提交
345 346 347 348 349 350 351 352 353 354 355
				 * glyph minus the value of firstGlyph plus 1). */
  UnsizedArrayOf<T>
		valueArrayZ;	/* The lookup values (indexed by the glyph index
				 * minus the value of firstGlyph). */
  public:
  DEFINE_SIZE_ARRAY (6, valueArrayZ);
};

template <typename T>
struct Lookup
{
356
  inline const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
B
Behdad Esfahbod 已提交
357 358 359 360 361 362 363
  {
    switch (u.format) {
    case 0: return u.format0.get_value (glyph_id, num_glyphs);
    case 2: return u.format2.get_value (glyph_id);
    case 4: return u.format4.get_value (glyph_id);
    case 6: return u.format6.get_value (glyph_id);
    case 8: return u.format8.get_value (glyph_id);
364
    default:return nullptr;
B
Behdad Esfahbod 已提交
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
    }
  }

  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (!u.format.sanitize (c)) return_trace (false);
    switch (u.format) {
    case 0: return_trace (u.format0.sanitize (c));
    case 2: return_trace (u.format2.sanitize (c));
    case 4: return_trace (u.format4.sanitize (c));
    case 6: return_trace (u.format6.sanitize (c));
    case 8: return_trace (u.format8.sanitize (c));
    default:return_trace (true);
    }
  }

  protected:
  union {
B
Behdad Esfahbod 已提交
384
  HBUINT16		format;		/* Format identifier */
B
Behdad Esfahbod 已提交
385 386 387 388 389 390 391 392 393 394 395
  LookupFormat0<T>	format0;
  LookupFormat2<T>	format2;
  LookupFormat4<T>	format4;
  LookupFormat6<T>	format6;
  LookupFormat8<T>	format8;
  } u;
  public:
  DEFINE_SIZE_UNION (2, format);
};


396
/*
B
Behdad Esfahbod 已提交
397
 * Extended State Table
398 399 400 401 402 403 404 405
 */

template <typename T>
struct Entry
{
  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
  {
    TRACE_SANITIZE (this);
406 407 408 409 410
    /* Note, we don't recurse-sanitize data because we don't access it.
     * That said, in our DEFINE_SIZE_STATIC we access T::static_size,
     * which ensures that data has a simple sanitize(). To be determined
     * if I need to remove that as well. */
    return_trace (c->check_struct (this));
411 412 413
  }

  public:
414 415 416
  HBUINT16	newState;	/* Byte offset from beginning of state table
				 * to the new state. Really?!?! Or just state
				 * number?  The latter in morx for sure. */
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
  HBUINT16	flags;		/* Table specific. */
  T		data;		/* Optional offsets to per-glyph tables. */
  public:
  DEFINE_SIZE_STATIC (4 + T::static_size);
};

template <>
struct Entry<void>
{
  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this));
  }

  public:
  HBUINT16	newState;	/* Byte offset from beginning of state table to the new state. */
  HBUINT16	flags;		/* Table specific. */
  public:
  DEFINE_SIZE_STATIC (4);
};

B
Behdad Esfahbod 已提交
439
template <typename Extra>
440 441
struct StateTable
{
442 443 444 445 446 447 448 449 450 451 452 453 454
  enum State
  {
    STATE_START_OF_TEXT = 0,
    STATE_START_OF_LINE = 1,
  };
  enum Class
  {
    CLASS_END_OF_TEXT = 0,
    CLASS_OUT_OF_BOUNDS = 1,
    CLASS_DELETED_GLYPH = 2,
    CLASS_END_OF_LINE = 3,
  };

455
  inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
B
Behdad Esfahbod 已提交
456 457
  {
    const HBUINT16 *v = (this+classTable).get_value (glyph_id, num_glyphs);
B
Behdad Esfahbod 已提交
458
    return v ? (unsigned) *v : (unsigned) CLASS_OUT_OF_BOUNDS;
B
Behdad Esfahbod 已提交
459
  }
460

461 462 463 464 465 466
  inline const Entry<Extra> *get_entries () const
  {
    return (this+entryTable).arrayZ;
  }

  inline const Entry<Extra> *get_entryZ (unsigned int state, unsigned int klass) const
467
  {
B
Behdad Esfahbod 已提交
468 469
    if (unlikely (klass >= nClasses)) return nullptr;

B
Behdad Esfahbod 已提交
470
    const HBUINT16 *states = (this+stateArrayTable).arrayZ;
471 472
    const Entry<Extra> *entries = (this+entryTable).arrayZ;

B
Behdad Esfahbod 已提交
473
    unsigned int entry = states[state * nClasses + klass];
474

B
Behdad Esfahbod 已提交
475
    return &entries[entry];
476 477
  }

478 479
  inline bool sanitize (hb_sanitize_context_t *c,
			unsigned int *num_entries_out = nullptr) const
480 481
  {
    TRACE_SANITIZE (this);
482 483
    if (unlikely (!(c->check_struct (this) &&
		    classTable.sanitize (c, this)))) return_trace (false);
B
Behdad Esfahbod 已提交
484

B
Behdad Esfahbod 已提交
485
    const HBUINT16 *states = (this+stateArrayTable).arrayZ;
B
Behdad Esfahbod 已提交
486 487 488 489 490 491 492 493 494
    const Entry<Extra> *entries = (this+entryTable).arrayZ;

    unsigned int num_states = 1;
    unsigned int num_entries = 0;

    unsigned int state = 0;
    unsigned int entry = 0;
    while (state < num_states)
    {
B
Behdad Esfahbod 已提交
495
      if (unlikely (!c->check_array (states,
496 497
				     num_states,
				     states[0].static_size * nClasses)))
B
Behdad Esfahbod 已提交
498 499
	return_trace (false);
      { /* Sweep new states. */
B
Behdad Esfahbod 已提交
500 501
	const HBUINT16 *stop = &states[num_states * nClasses];
	for (const HBUINT16 *p = &states[state * nClasses]; p < stop; p++)
B
Behdad Esfahbod 已提交
502 503 504 505
	  num_entries = MAX<unsigned int> (num_entries, *p + 1);
	state = num_states;
      }

506
      if (unlikely (!c->check_array (entries, num_entries)))
B
Behdad Esfahbod 已提交
507 508 509 510 511 512 513 514 515
	return_trace (false);
      { /* Sweep new entries. */
	const Entry<Extra> *stop = &entries[num_entries];
	for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
	  num_states = MAX<unsigned int> (num_states, p->newState + 1);
	entry = num_entries;
      }
    }

516 517 518
    if (num_entries_out)
      *num_entries_out = num_entries;

B
Behdad Esfahbod 已提交
519
    return_trace (true);
520 521 522
  }

  protected:
B
Behdad Esfahbod 已提交
523
  HBUINT32	nClasses;	/* Number of classes, which is the number of indices
524
				 * in a single line in the state array. */
525
  LOffsetTo<Lookup<HBUINT16>, false>
526
		classTable;	/* Offset to the class table. */
527
  LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
528
		stateArrayTable;/* Offset to the state array. */
529
  LOffsetTo<UnsizedArrayOf<Entry<Extra> >, false>
530 531 532
		entryTable;	/* Offset to the entry array. */

  public:
B
Behdad Esfahbod 已提交
533
  DEFINE_SIZE_STATIC (16);
534 535
};

536 537 538 539 540 541 542 543
template <typename EntryData>
struct StateTableDriver
{
  inline StateTableDriver (const StateTable<EntryData> &machine_,
			   hb_buffer_t *buffer_,
			   hb_face_t *face_) :
	      machine (machine_),
	      buffer (buffer_),
B
Behdad Esfahbod 已提交
544
	      num_glyphs (face_->get_num_glyphs ()) {}
545 546 547 548 549

  template <typename context_t>
  inline void drive (context_t *c)
  {
    hb_glyph_info_t *info = buffer->info;
550 551 552 553

    if (!c->in_place)
      buffer->clear_output ();

554
    unsigned int state = StateTable<EntryData>::STATE_START_OF_TEXT;
555
    bool last_was_dont_advance = false;
556
    for (buffer->idx = 0;;)
557
    {
558
      unsigned int klass = buffer->idx < buffer->len ?
559
			   machine.get_class (info[buffer->idx].codepoint, num_glyphs) :
560
			   (unsigned) StateTable<EntryData>::CLASS_END_OF_TEXT;
561 562 563 564
      const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
      if (unlikely (!entry))
	break;

B
Behdad Esfahbod 已提交
565 566 567 568
      /* Unsafe-to-break before this if not in state 0, as things might
       * go differently if we start from state 0 here. */
      if (state && buffer->idx)
      {
569 570 571
	/* If there's no action and we're just epsilon-transitioning to state 0,
	 * safe to break. */
	if (c->is_actionable (this, entry) ||
B
Behdad Esfahbod 已提交
572 573
	    !(entry->newState == StateTable<EntryData>::STATE_START_OF_TEXT &&
	      entry->flags == context_t::DontAdvance))
B
Behdad Esfahbod 已提交
574 575 576 577 578 579 580 581 582 583 584
	  buffer->unsafe_to_break (buffer->idx - 1, buffer->idx + 1);
      }

      /* Unsafe-to-break if end-of-text would kick in here. */
      if (buffer->idx + 2 <= buffer->len)
      {
	const Entry<EntryData> *end_entry = machine.get_entryZ (state, 0);
	if (c->is_actionable (this, end_entry))
	  buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
      }

585 586
      if (unlikely (!c->transition (this, entry)))
        break;
587

B
Behdad Esfahbod 已提交
588
      last_was_dont_advance = (entry->flags & context_t::DontAdvance) && buffer->max_ops-- > 0;
589

590 591 592 593 594
      state = entry->newState;

      if (buffer->idx == buffer->len)
        break;

595 596
      if (!last_was_dont_advance)
        buffer->next_glyph ();
597 598
    }

599 600
    if (!c->in_place)
    {
601
      for (; buffer->idx < buffer->len;)
602
        buffer->next_glyph ();
603
      buffer->swap_buffers ();
604
    }
605 606 607 608 609 610 611 612
  }

  public:
  const StateTable<EntryData> &machine;
  hb_buffer_t *buffer;
  unsigned int num_glyphs;
};

613

614 615 616 617 618 619 620 621 622 623 624 625 626

struct hb_aat_apply_context_t :
       hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
{
  inline const char *get_name (void) { return "APPLY"; }
  template <typename T>
  inline return_t dispatch (const T &obj) { return obj.apply (this); }
  static return_t default_return_value (void) { return false; }
  bool stop_sublookup_iteration (return_t r) const { return r; }

  hb_font_t *font;
  hb_face_t *face;
  hb_buffer_t *buffer;
627
  hb_sanitize_context_t sanitizer;
628

B
Behdad Esfahbod 已提交
629 630 631 632
  /* Unused. For debug tracing only. */
  unsigned int lookup_index;
  unsigned int debug_depth;

633 634 635 636
  inline hb_aat_apply_context_t (hb_font_t *font_,
				 hb_buffer_t *buffer_,
				 hb_blob_t *table) :
		font (font_), face (font->face), buffer (buffer_),
B
Behdad Esfahbod 已提交
637
		sanitizer (), lookup_index (0), debug_depth (0)
638 639
  {
    sanitizer.init (table);
640
    sanitizer.set_num_glyphs (face->get_num_glyphs ());
641 642 643
    sanitizer.start_processing ();
  }

B
Behdad Esfahbod 已提交
644 645
  inline void set_lookup_index (unsigned int i) { lookup_index = i; }

646 647 648 649
  inline ~hb_aat_apply_context_t (void)
  {
    sanitizer.end_processing ();
  }
650 651 652
};


653 654 655
} /* namespace AAT */


656
#endif /* HB_AAT_LAYOUT_COMMON_HH */