hb-ot-layout-gsubgpos-private.hh 32.5 KB
Newer Older
1
/*
B
Behdad Esfahbod 已提交
2 3
 * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
 * Copyright © 2010  Google, Inc.
4
 *
B
Behdad Esfahbod 已提交
5
 *  This is part of HarfBuzz, a text shaping library.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * 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.
 *
 * Red Hat Author(s): Behdad Esfahbod
26
 * Google Author(s): Behdad Esfahbod
27 28
 */

29 30
#ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
#define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
31

32
#include "hb-buffer-private.hh"
33
#include "hb-ot-layout-gdef-table.hh"
34 35
#include "hb-ot-layout-closure.h"

36

B
Behdad Esfahbod 已提交
37

B
Behdad Esfahbod 已提交
38
/* buffer var allocations */
39 40
#define lig_id() var2.u8[2] /* unique ligature id */
#define lig_comp() var2.u8[3] /* component number in the ligature (0 = base) */
B
Behdad Esfahbod 已提交
41

42 43
static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) {
  uint8_t lig_id = buffer->next_serial ();
B
Minor  
Behdad Esfahbod 已提交
44 45 46 47 48
  if (unlikely (!lig_id)) lig_id = buffer->next_serial (); /* in case of overflow */
  return lig_id;
}


B
Behdad Esfahbod 已提交
49

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
#ifndef HB_DEBUG_CLOSURE
#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
#endif

#define TRACE_CLOSURE() \
	hb_auto_trace_t<HB_DEBUG_CLOSURE> trace (&c->debug_depth, "CLOSURE", this, NULL, HB_FUNC);



struct hb_closure_context_t
{
  hb_face_t *face;
  hb_glyph_map_t *glyphs;
  unsigned int nesting_level_left;
  unsigned int debug_depth;


  hb_closure_context_t (hb_face_t *face_,
			hb_glyph_map_t *glyphs_,
		        unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
			  face (face_), glyphs (glyphs_),
			  nesting_level_left (nesting_level_left_),
			  debug_depth (0) {}
};

typedef bool (*closure_lookup_func_t) (hb_closure_context_t *c, unsigned int lookup_index);



B
Behdad Esfahbod 已提交
79
#ifndef HB_DEBUG_APPLY
80
#define HB_DEBUG_APPLY (HB_DEBUG+0)
B
Behdad Esfahbod 已提交
81 82
#endif

B
Behdad Esfahbod 已提交
83
#define TRACE_APPLY() \
84
	hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", this, NULL, HB_FUNC);
85

B
Behdad Esfahbod 已提交
86

B
Behdad Esfahbod 已提交
87

88 89
struct hb_apply_context_t
{
90 91
  hb_font_t *font;
  hb_face_t *face;
B
Behdad Esfahbod 已提交
92
  hb_buffer_t *buffer;
93
  hb_direction_t direction;
B
Behdad Esfahbod 已提交
94
  hb_mask_t lookup_mask;
95
  unsigned int context_length;
96
  unsigned int nesting_level_left;
97
  unsigned int lookup_props;
98
  unsigned int property; /* propety of first glyph */
99
  unsigned int debug_depth;
100

101 102 103 104 105 106 107 108 109 110 111 112 113 114

  hb_apply_context_t (hb_font_t *font_,
		      hb_face_t *face_,
		      hb_buffer_t *buffer_,
		      hb_mask_t lookup_mask_,
		      const Lookup &l,
		      unsigned int context_length_ = NO_CONTEXT,
		      unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
			font (font_), face (face_), buffer (buffer_),
			direction (buffer_->props.direction),
			lookup_mask (lookup_mask_),
			context_length (context_length_),
			nesting_level_left (nesting_level_left_),
			lookup_props (l.get_props ()),
115
			property (0), debug_depth (0) {}
116 117 118 119 120 121 122

  hb_apply_context_t (const hb_apply_context_t &c, const Lookup &l) {
    *this = c;
    nesting_level_left--;
    lookup_props = l.get_props ();
  }

B
Behdad Esfahbod 已提交
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
  struct mark_skipping_forward_iterator_t
  {
    inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_,
					     unsigned int start_index_,
					     unsigned int num_items_)
    {
      c = c_;
      idx = start_index_;
      num_items = num_items_;
      end = MIN (c->buffer->len, c->buffer->idx + c->context_length);
    }
    inline bool has_no_chance (void) const
    {
      return unlikely (num_items && idx + num_items >= end);
    }
    inline bool next (unsigned int *property_out,
		      unsigned int lookup_props)
    {
141
      assert (num_items > 0);
B
Behdad Esfahbod 已提交
142 143 144 145
      do
      {
	if (has_no_chance ())
	  return false;
B
Behdad Esfahbod 已提交
146
	idx++;
B
Behdad Esfahbod 已提交
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
      } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[idx], lookup_props, property_out));
      num_items--;
      return true;
    }
    inline bool next (unsigned int *property_out = NULL)
    {
      return next (property_out, c->lookup_props);
    }

    unsigned int idx;
    private:
    hb_apply_context_t *c;
    unsigned int num_items;
    unsigned int end;
  };

  struct mark_skipping_backward_iterator_t
  {
    inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_,
					      unsigned int start_index_,
					      unsigned int num_items_)
    {
      c = c_;
      idx = start_index_;
      num_items = num_items_;
    }
    inline bool has_no_chance (void) const
    {
175
      return unlikely (idx < num_items);
B
Behdad Esfahbod 已提交
176 177 178 179
    }
    inline bool prev (unsigned int *property_out,
		      unsigned int lookup_props)
    {
180
      assert (num_items > 0);
B
Behdad Esfahbod 已提交
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
      do
      {
	if (has_no_chance ())
	  return false;
	idx--;
      } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->out_info[idx], lookup_props, property_out));
      num_items--;
      return true;
    }
    inline bool prev (unsigned int *property_out = NULL)
    {
      return prev (property_out, c->lookup_props);
    }

    unsigned int idx;
    private:
    hb_apply_context_t *c;
    unsigned int num_items;
  };

201 202 203 204
  inline bool should_mark_skip_current_glyph (void) const
  {
    return _hb_ot_layout_skip_mark (face, &buffer->info[buffer->idx], lookup_props, NULL);
  }
B
Behdad Esfahbod 已提交
205 206 207



208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
  inline void replace_glyph (hb_codepoint_t glyph_index) const
  {
    clear_property ();
    buffer->replace_glyph (glyph_index);
  }
  inline void replace_glyphs_be16 (unsigned int num_in,
				   unsigned int num_out,
				   const uint16_t *glyph_data_be) const
  {
    clear_property ();
    buffer->replace_glyphs_be16 (num_in, num_out, glyph_data_be);
  }

  inline void guess_glyph_class (unsigned int klass)
  {
B
Behdad Esfahbod 已提交
223
    /* XXX if ! has gdef */
224
    buffer->info[buffer->idx].props_cache() = klass;
225 226 227 228 229
  }

  private:
  inline void clear_property (void) const
  {
B
Behdad Esfahbod 已提交
230
    /* XXX if has gdef */
231
    buffer->info[buffer->idx].props_cache() = 0;
232
  }
233 234
};

235

B
Behdad Esfahbod 已提交
236

B
Behdad Esfahbod 已提交
237
typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
B
Behdad Esfahbod 已提交
238
typedef bool (*apply_lookup_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
239

B
Behdad Esfahbod 已提交
240 241
struct ContextFuncs
{
242 243
  match_func_t match;
  apply_lookup_func_t apply;
244 245
};

246

B
Behdad Esfahbod 已提交
247
static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
B
Behdad Esfahbod 已提交
248
{
249 250
  return glyph_id == value;
}
251

B
Behdad Esfahbod 已提交
252
static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
B
Behdad Esfahbod 已提交
253
{
B
Behdad Esfahbod 已提交
254
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
255 256 257
  return class_def.get_class (glyph_id) == value;
}

B
Behdad Esfahbod 已提交
258
static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
B
Behdad Esfahbod 已提交
259
{
260
  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
261 262 263
  return (data+coverage) (glyph_id) != NOT_COVERED;
}

264

B
Behdad Esfahbod 已提交
265
static inline bool match_input (hb_apply_context_t *c,
B
Behdad Esfahbod 已提交
266 267 268
				unsigned int count, /* Including the first glyph (not matched) */
				const USHORT input[], /* Array of input values--start with second glyph */
				match_func_t match_func,
B
Behdad Esfahbod 已提交
269
				const void *match_data,
B
Behdad Esfahbod 已提交
270 271
				unsigned int *context_length_out)
{
B
Behdad Esfahbod 已提交
272 273
  hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
  if (skippy_iter.has_no_chance ())
B
Behdad Esfahbod 已提交
274
    return false;
B
Behdad Esfahbod 已提交
275

B
Minor  
Behdad Esfahbod 已提交
276
  for (unsigned int i = 1; i < count; i++)
B
Behdad Esfahbod 已提交
277
  {
B
Behdad Esfahbod 已提交
278 279
    if (!skippy_iter.next ())
      return false;
B
Behdad Esfahbod 已提交
280

B
Behdad Esfahbod 已提交
281
    if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, input[i - 1], match_data)))
B
Behdad Esfahbod 已提交
282 283 284
      return false;
  }

B
Behdad Esfahbod 已提交
285
  *context_length_out = skippy_iter.idx - c->buffer->idx + 1;
B
Behdad Esfahbod 已提交
286 287 288 289

  return true;
}

B
Behdad Esfahbod 已提交
290
static inline bool match_backtrack (hb_apply_context_t *c,
291 292 293
				    unsigned int count,
				    const USHORT backtrack[],
				    match_func_t match_func,
B
Behdad Esfahbod 已提交
294
				    const void *match_data)
295
{
B
Behdad Esfahbod 已提交
296 297 298
  hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count);
  if (skippy_iter.has_no_chance ())
    return false;
299

300
  for (unsigned int i = 0; i < count; i++)
B
Behdad Esfahbod 已提交
301
  {
B
Behdad Esfahbod 已提交
302 303
    if (!skippy_iter.prev ())
      return false;
304

B
Behdad Esfahbod 已提交
305
    if (likely (!match_func (c->buffer->out_info[skippy_iter.idx].codepoint, backtrack[i], match_data)))
306 307 308 309 310 311
      return false;
  }

  return true;
}

B
Behdad Esfahbod 已提交
312
static inline bool match_lookahead (hb_apply_context_t *c,
B
Behdad Esfahbod 已提交
313 314 315
				    unsigned int count,
				    const USHORT lookahead[],
				    match_func_t match_func,
B
Behdad Esfahbod 已提交
316
				    const void *match_data,
B
Behdad Esfahbod 已提交
317
				    unsigned int offset)
318
{
B
Behdad Esfahbod 已提交
319 320 321
  hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count);
  if (skippy_iter.has_no_chance ())
    return false;
322

B
Minor  
Behdad Esfahbod 已提交
323
  for (unsigned int i = 0; i < count; i++)
B
Behdad Esfahbod 已提交
324
  {
B
Behdad Esfahbod 已提交
325 326
    if (!skippy_iter.next ())
      return false;
327

B
Behdad Esfahbod 已提交
328
    if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, lookahead[i], match_data)))
329 330 331
      return false;
  }

332 333 334
  return true;
}

B
Behdad Esfahbod 已提交
335

336

B
Behdad Esfahbod 已提交
337 338
struct LookupRecord
{
B
Behdad Esfahbod 已提交
339
  inline bool sanitize (hb_sanitize_context_t *c) {
340
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
341
    return c->check_struct (this);
B
Behdad Esfahbod 已提交
342 343
  }

344 345 346 347
  USHORT	sequenceIndex;		/* Index into current glyph
					 * sequence--first glyph = 0 */
  USHORT	lookupListIndex;	/* Lookup to apply to that
					 * position--zero--based */
B
Behdad Esfahbod 已提交
348 349
  public:
  DEFINE_SIZE_STATIC (4);
350 351
};

B
Behdad Esfahbod 已提交
352 353


B
Behdad Esfahbod 已提交
354
static inline bool apply_lookup (hb_apply_context_t *c,
355 356
				 unsigned int count, /* Including the first glyph */
				 unsigned int lookupCount,
357 358 359
				 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
				 apply_lookup_func_t apply_func)
{
360 361
  unsigned int end = MIN (c->buffer->len, c->buffer->idx + c->context_length);
  if (unlikely (count == 0 || c->buffer->idx + count > end))
362
    return false;
363

B
Behdad Esfahbod 已提交
364 365
  /* TODO We don't support lookupRecord arrays that are not increasing:
   *      Should be easy for in_place ones at least. */
B
Behdad Esfahbod 已提交
366

367
  /* Note: If sublookup is reverse, it will underflow after the first loop
B
Behdad Esfahbod 已提交
368 369 370
   * and we jump out of it.  Not entirely disastrous.  So we don't check
   * for reverse lookup here.
   */
B
Behdad Esfahbod 已提交
371
  for (unsigned int i = 0; i < count; /* NOP */)
B
Behdad Esfahbod 已提交
372
  {
373 374
    if (unlikely (c->buffer->idx == end))
      return true;
375
    while (c->should_mark_skip_current_glyph ())
B
Behdad Esfahbod 已提交
376
    {
377
      /* No lookup applied for this index */
B
Behdad Esfahbod 已提交
378
      c->buffer->next_glyph ();
379 380
      if (unlikely (c->buffer->idx == end))
	return true;
381 382
    }

B
Behdad Esfahbod 已提交
383
    if (lookupCount && i == lookupRecord->sequenceIndex)
384
    {
385
      unsigned int old_pos = c->buffer->idx;
386 387

      /* Apply a lookup */
B
Behdad Esfahbod 已提交
388
      bool done = apply_func (c, lookupRecord->lookupListIndex);
389

B
Behdad Esfahbod 已提交
390 391
      lookupRecord++;
      lookupCount--;
B
Behdad Esfahbod 已提交
392
      /* Err, this is wrong if the lookup jumped over some glyphs */
393 394
      i += c->buffer->idx - old_pos;
      if (unlikely (c->buffer->idx == end))
395
	return true;
396 397 398 399 400 401 402 403

      if (!done)
	goto not_applied;
    }
    else
    {
    not_applied:
      /* No lookup applied for this index */
B
Behdad Esfahbod 已提交
404
      c->buffer->next_glyph ();
405 406 407 408 409 410
      i++;
    }
  }

  return true;
}
411

B
Behdad Esfahbod 已提交
412

413 414 415

/* Contextual lookups */

B
Behdad Esfahbod 已提交
416 417
struct ContextLookupContext
{
418
  ContextFuncs funcs;
B
Behdad Esfahbod 已提交
419
  const void *match_data;
420 421
};

B
Behdad Esfahbod 已提交
422
static inline bool context_lookup (hb_apply_context_t *c,
423
				   unsigned int inputCount, /* Including the first glyph (not matched) */
424
				   const USHORT input[], /* Array of input values--start with second glyph */
425
				   unsigned int lookupCount,
426
				   const LookupRecord lookupRecord[],
B
Behdad Esfahbod 已提交
427
				   ContextLookupContext &lookup_context)
428
{
B
Behdad Esfahbod 已提交
429 430
  hb_apply_context_t new_context = *c;
  return match_input (c,
B
Behdad Esfahbod 已提交
431 432 433 434 435 436 437
		      inputCount, input,
		      lookup_context.funcs.match, lookup_context.match_data,
		      &new_context.context_length)
      && apply_lookup (&new_context,
		       inputCount,
		       lookupCount, lookupRecord,
		       lookup_context.funcs.apply);
438 439
}

B
Behdad Esfahbod 已提交
440 441
struct Rule
{
442 443 444
  friend struct RuleSet;

  private:
B
Behdad Esfahbod 已提交
445
  inline bool apply (hb_apply_context_t *c, ContextLookupContext &lookup_context) const
B
Behdad Esfahbod 已提交
446
  {
447
    TRACE_APPLY ();
B
Behdad Esfahbod 已提交
448
    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
B
Behdad Esfahbod 已提交
449
    return context_lookup (c,
450
			   inputCount, input,
B
Minor  
Behdad Esfahbod 已提交
451
			   lookupCount, lookupRecord,
B
Behdad Esfahbod 已提交
452
			   lookup_context);
453 454
  }

B
Behdad Esfahbod 已提交
455
  public:
B
Behdad Esfahbod 已提交
456
  inline bool sanitize (hb_sanitize_context_t *c) {
457
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
458 459 460
    return inputCount.sanitize (c)
	&& lookupCount.sanitize (c)
	&& c->check_range (input,
461 462
			   input[0].static_size * inputCount
			   + lookupRecordX[0].static_size * lookupCount);
B
Behdad Esfahbod 已提交
463 464
  }

465
  private:
466
  USHORT	inputCount;		/* Total number of glyphs in input
467 468
					 * glyph sequence--includes the  first
					 * glyph */
469
  USHORT	lookupCount;		/* Number of LookupRecords */
B
Behdad Esfahbod 已提交
470
  USHORT	input[VAR];		/* Array of match inputs--start with
471
					 * second glyph */
B
Behdad Esfahbod 已提交
472
  LookupRecord	lookupRecordX[VAR];	/* Array of LookupRecords--in
473
					 * design order */
B
Behdad Esfahbod 已提交
474
  public:
475
  DEFINE_SIZE_ARRAY2 (4, input, lookupRecordX);
476 477
};

B
Behdad Esfahbod 已提交
478 479
struct RuleSet
{
B
Behdad Esfahbod 已提交
480
  inline bool apply (hb_apply_context_t *c, ContextLookupContext &lookup_context) const
B
Behdad Esfahbod 已提交
481
  {
482
    TRACE_APPLY ();
483
    unsigned int num_rules = rule.len;
B
Behdad Esfahbod 已提交
484 485
    for (unsigned int i = 0; i < num_rules; i++)
    {
B
Behdad Esfahbod 已提交
486
      if ((this+rule[i]).apply (c, lookup_context))
487 488 489 490 491 492
        return true;
    }

    return false;
  }

B
Behdad Esfahbod 已提交
493
  inline bool sanitize (hb_sanitize_context_t *c) {
494
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
495
    return rule.sanitize (c, this);
B
Behdad Esfahbod 已提交
496 497
  }

498 499
  private:
  OffsetArrayOf<Rule>
500
		rule;			/* Array of Rule tables
501
					 * ordered by preference */
B
Behdad Esfahbod 已提交
502
  public:
503
  DEFINE_SIZE_ARRAY (2, rule);
504 505 506
};


B
Behdad Esfahbod 已提交
507 508
struct ContextFormat1
{
509 510 511
  friend struct Context;

  private:
512 513 514 515 516 517 518 519

  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
  {
    TRACE_CLOSURE ();
    /* TODO FILLME */
    return false;
  }

B
Behdad Esfahbod 已提交
520
  inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
B
Behdad Esfahbod 已提交
521
  {
522
    TRACE_APPLY ();
523
    unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
524
    if (likely (index == NOT_COVERED))
525 526
      return false;

527
    const RuleSet &rule_set = this+ruleSet[index];
B
Behdad Esfahbod 已提交
528
    struct ContextLookupContext lookup_context = {
529 530
      {match_glyph, apply_func},
      NULL
531
    };
B
Behdad Esfahbod 已提交
532
    return rule_set.apply (c, lookup_context);
533 534
  }

B
Behdad Esfahbod 已提交
535
  inline bool sanitize (hb_sanitize_context_t *c) {
536
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
537 538
    return coverage.sanitize (c, this)
	&& ruleSet.sanitize (c, this);
B
Behdad Esfahbod 已提交
539 540
  }

541 542 543 544 545 546 547 548
  private:
  USHORT	format;			/* Format identifier--format = 1 */
  OffsetTo<Coverage>
		coverage;		/* Offset to Coverage table--from
					 * beginning of table */
  OffsetArrayOf<RuleSet>
		ruleSet;		/* Array of RuleSet tables
					 * ordered by Coverage Index */
549
  public:
550
  DEFINE_SIZE_ARRAY (6, ruleSet);
551 552 553
};


B
Behdad Esfahbod 已提交
554 555
struct ContextFormat2
{
556 557 558
  friend struct Context;

  private:
559 560 561 562 563 564 565 566

  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
  {
    TRACE_CLOSURE ();
    /* TODO FILLME */
    return false;
  }

B
Behdad Esfahbod 已提交
567
  inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
B
Behdad Esfahbod 已提交
568
  {
569
    TRACE_APPLY ();
570
    unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
571
    if (likely (index == NOT_COVERED))
572 573 574
      return false;

    const ClassDef &class_def = this+classDef;
575
    index = class_def (c->buffer->info[c->buffer->idx].codepoint);
576
    const RuleSet &rule_set = this+ruleSet[index];
B
Behdad Esfahbod 已提交
577
    struct ContextLookupContext lookup_context = {
B
Behdad Esfahbod 已提交
578 579
      {match_class, apply_func},
      &class_def
580
    };
B
Behdad Esfahbod 已提交
581
    return rule_set.apply (c, lookup_context);
582 583
  }

B
Behdad Esfahbod 已提交
584
  inline bool sanitize (hb_sanitize_context_t *c) {
585
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
586 587 588
    return coverage.sanitize (c, this)
        && classDef.sanitize (c, this)
	&& ruleSet.sanitize (c, this);
B
Behdad Esfahbod 已提交
589 590
  }

591 592 593 594 595 596 597 598 599 600 601
  private:
  USHORT	format;			/* Format identifier--format = 2 */
  OffsetTo<Coverage>
		coverage;		/* Offset to Coverage table--from
					 * beginning of table */
  OffsetTo<ClassDef>
		classDef;		/* Offset to glyph ClassDef table--from
					 * beginning of table */
  OffsetArrayOf<RuleSet>
		ruleSet;		/* Array of RuleSet tables
					 * ordered by class */
602
  public:
603
  DEFINE_SIZE_ARRAY (8, ruleSet);
604 605 606
};


B
Behdad Esfahbod 已提交
607 608
struct ContextFormat3
{
609 610 611
  friend struct Context;

  private:
612 613 614 615 616 617 618 619

  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
  {
    TRACE_CLOSURE ();
    /* TODO FILLME */
    return false;
  }

B
Behdad Esfahbod 已提交
620
  inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
B
Behdad Esfahbod 已提交
621
  {
622
    TRACE_APPLY ();
623
    unsigned int index = (this+coverage[0]) (c->buffer->info[c->buffer->idx].codepoint);
624
    if (likely (index == NOT_COVERED))
625
      return false;
626

B
Behdad Esfahbod 已提交
627
    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
B
Behdad Esfahbod 已提交
628
    struct ContextLookupContext lookup_context = {
629
      {match_coverage, apply_func},
B
Behdad Esfahbod 已提交
630
      this
631
    };
B
Behdad Esfahbod 已提交
632
    return context_lookup (c,
633
			   glyphCount, (const USHORT *) (coverage + 1),
B
Minor  
Behdad Esfahbod 已提交
634
			   lookupCount, lookupRecord,
B
Behdad Esfahbod 已提交
635
			   lookup_context);
636 637
  }

B
Behdad Esfahbod 已提交
638
  inline bool sanitize (hb_sanitize_context_t *c) {
639
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
640
    if (!c->check_struct (this)) return false;
B
Behdad Esfahbod 已提交
641
    unsigned int count = glyphCount;
B
Behdad Esfahbod 已提交
642
    if (!c->check_array (coverage, coverage[0].static_size, count)) return false;
B
Behdad Esfahbod 已提交
643
    for (unsigned int i = 0; i < count; i++)
B
Behdad Esfahbod 已提交
644
      if (!coverage[i].sanitize (c, this)) return false;
B
Behdad Esfahbod 已提交
645
    LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * count);
B
Behdad Esfahbod 已提交
646
    return c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount);
B
Behdad Esfahbod 已提交
647 648
  }

649 650 651 652
  private:
  USHORT	format;			/* Format identifier--format = 3 */
  USHORT	glyphCount;		/* Number of glyphs in the input glyph
					 * sequence */
653
  USHORT	lookupCount;		/* Number of LookupRecords */
654
  OffsetTo<Coverage>
B
Behdad Esfahbod 已提交
655
		coverage[VAR];		/* Array of offsets to Coverage
656
					 * table in glyph sequence order */
B
Behdad Esfahbod 已提交
657
  LookupRecord	lookupRecordX[VAR];	/* Array of LookupRecords--in
658
					 * design order */
B
Behdad Esfahbod 已提交
659
  public:
660
  DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX);
661 662
};

B
Behdad Esfahbod 已提交
663 664
struct Context
{
665
  protected:
666 667 668 669 670 671 672 673 674 675 676 677

  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
  {
    TRACE_CLOSURE ();
    switch (u.format) {
    case 1: return u.format1.closure (c, closure_func);
    case 2: return u.format2.closure (c, closure_func);
    case 3: return u.format3.closure (c, closure_func);
    default:return false;
    }
  }

B
Behdad Esfahbod 已提交
678
  inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
B
Behdad Esfahbod 已提交
679
  {
680
    TRACE_APPLY ();
681
    switch (u.format) {
B
Behdad Esfahbod 已提交
682 683 684
    case 1: return u.format1.apply (c, apply_func);
    case 2: return u.format2.apply (c, apply_func);
    case 3: return u.format3.apply (c, apply_func);
685 686 687 688
    default:return false;
    }
  }

B
Behdad Esfahbod 已提交
689
  inline bool sanitize (hb_sanitize_context_t *c) {
690
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
691
    if (!u.format.sanitize (c)) return false;
B
Behdad Esfahbod 已提交
692
    switch (u.format) {
B
Behdad Esfahbod 已提交
693 694 695
    case 1: return u.format1.sanitize (c);
    case 2: return u.format2.sanitize (c);
    case 3: return u.format3.sanitize (c);
B
Behdad Esfahbod 已提交
696 697 698 699
    default:return true;
    }
  }

700 701
  private:
  union {
B
Behdad Esfahbod 已提交
702
  USHORT		format;		/* Format identifier */
B
Behdad Esfahbod 已提交
703 704 705
  ContextFormat1	format1;
  ContextFormat2	format2;
  ContextFormat3	format3;
706 707 708
  } u;
};

709 710 711

/* Chaining Contextual lookups */

B
Behdad Esfahbod 已提交
712 713
struct ChainContextLookupContext
{
714
  ContextFuncs funcs;
B
Behdad Esfahbod 已提交
715
  const void *match_data[3];
716 717
};

B
Behdad Esfahbod 已提交
718
static inline bool chain_context_lookup (hb_apply_context_t *c,
719
					 unsigned int backtrackCount,
720
					 const USHORT backtrack[],
721
					 unsigned int inputCount, /* Including the first glyph (not matched) */
722
					 const USHORT input[], /* Array of input values--start with second glyph */
723
					 unsigned int lookaheadCount,
724
					 const USHORT lookahead[],
725
					 unsigned int lookupCount,
726
					 const LookupRecord lookupRecord[],
B
Behdad Esfahbod 已提交
727
					 ChainContextLookupContext &lookup_context)
728
{
729
  /* First guess */
730
  if (unlikely (c->buffer->backtrack_len () < backtrackCount ||
731
		c->buffer->idx + inputCount + lookaheadCount > c->buffer->len ||
B
Behdad Esfahbod 已提交
732
		inputCount + lookaheadCount > c->context_length))
733 734
    return false;

B
Behdad Esfahbod 已提交
735 736
  hb_apply_context_t new_context = *c;
  return match_backtrack (c,
B
Behdad Esfahbod 已提交
737 738
			  backtrackCount, backtrack,
			  lookup_context.funcs.match, lookup_context.match_data[0])
B
Behdad Esfahbod 已提交
739
      && match_input (c,
B
Behdad Esfahbod 已提交
740 741 742
		      inputCount, input,
		      lookup_context.funcs.match, lookup_context.match_data[1],
		      &new_context.context_length)
B
Behdad Esfahbod 已提交
743
      && match_lookahead (c,
B
Behdad Esfahbod 已提交
744 745 746 747 748 749 750
			  lookaheadCount, lookahead,
			  lookup_context.funcs.match, lookup_context.match_data[2],
			  new_context.context_length)
      && apply_lookup (&new_context,
		       inputCount,
		       lookupCount, lookupRecord,
		       lookup_context.funcs.apply);
751
}
752

B
Behdad Esfahbod 已提交
753 754
struct ChainRule
{
755 756 757
  friend struct ChainRuleSet;

  private:
B
Behdad Esfahbod 已提交
758
  inline bool apply (hb_apply_context_t *c, ChainContextLookupContext &lookup_context) const
B
Behdad Esfahbod 已提交
759
  {
760
    TRACE_APPLY ();
761 762 763
    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
B
Behdad Esfahbod 已提交
764
    return chain_context_lookup (c,
B
Behdad Esfahbod 已提交
765 766 767 768
				 backtrack.len, backtrack.array,
				 input.len, input.array,
				 lookahead.len, lookahead.array,
				 lookup.len, lookup.array,
B
Behdad Esfahbod 已提交
769
				 lookup_context);
770 771
  }

B
Behdad Esfahbod 已提交
772
  public:
B
Behdad Esfahbod 已提交
773
  inline bool sanitize (hb_sanitize_context_t *c) {
774
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
775
    if (!backtrack.sanitize (c)) return false;
776
    HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
B
Behdad Esfahbod 已提交
777
    if (!input.sanitize (c)) return false;
778
    ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
B
Behdad Esfahbod 已提交
779
    if (!lookahead.sanitize (c)) return false;
780
    ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
B
Behdad Esfahbod 已提交
781
    return lookup.sanitize (c);
B
Behdad Esfahbod 已提交
782
  }
783 784

  private:
B
Behdad Esfahbod 已提交
785 786
  ArrayOf<USHORT>
		backtrack;		/* Array of backtracking values
787 788
					 * (to be matched before the input
					 * sequence) */
B
Behdad Esfahbod 已提交
789 790
  HeadlessArrayOf<USHORT>
		inputX;			/* Array of input values (start with
791
					 * second glyph) */
B
Behdad Esfahbod 已提交
792 793
  ArrayOf<USHORT>
		lookaheadX;		/* Array of lookahead values's (to be
794
					 * matched after the input sequence) */
B
Behdad Esfahbod 已提交
795
  ArrayOf<LookupRecord>
796
		lookupX;		/* Array of LookupRecords--in
797
					 * design order) */
798
  public:
B
Behdad Esfahbod 已提交
799
  DEFINE_SIZE_MIN (8);
800 801
};

B
Behdad Esfahbod 已提交
802 803
struct ChainRuleSet
{
B
Behdad Esfahbod 已提交
804
  inline bool apply (hb_apply_context_t *c, ChainContextLookupContext &lookup_context) const
B
Behdad Esfahbod 已提交
805
  {
806
    TRACE_APPLY ();
807
    unsigned int num_rules = rule.len;
B
Behdad Esfahbod 已提交
808 809
    for (unsigned int i = 0; i < num_rules; i++)
    {
B
Behdad Esfahbod 已提交
810
      if ((this+rule[i]).apply (c, lookup_context))
811 812 813 814 815
        return true;
    }

    return false;
  }
816

B
Behdad Esfahbod 已提交
817
  inline bool sanitize (hb_sanitize_context_t *c) {
818
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
819
    return rule.sanitize (c, this);
B
Behdad Esfahbod 已提交
820 821
  }

822
  private:
823 824 825
  OffsetArrayOf<ChainRule>
		rule;			/* Array of ChainRule tables
					 * ordered by preference */
826
  public:
827
  DEFINE_SIZE_ARRAY (2, rule);
828 829
};

B
Behdad Esfahbod 已提交
830 831
struct ChainContextFormat1
{
832 833 834
  friend struct ChainContext;

  private:
835 836 837 838 839 840 841 842

  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
  {
    TRACE_CLOSURE ();
    /* TODO FILLME */
    return false;
  }

B
Behdad Esfahbod 已提交
843
  inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
B
Behdad Esfahbod 已提交
844
  {
845
    TRACE_APPLY ();
846
    unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
847
    if (likely (index == NOT_COVERED))
848
      return false;
849

850
    const ChainRuleSet &rule_set = this+ruleSet[index];
B
Behdad Esfahbod 已提交
851
    struct ChainContextLookupContext lookup_context = {
852 853 854
      {match_glyph, apply_func},
      {NULL, NULL, NULL}
    };
B
Behdad Esfahbod 已提交
855
    return rule_set.apply (c, lookup_context);
856
  }
B
Behdad Esfahbod 已提交
857

B
Behdad Esfahbod 已提交
858
  inline bool sanitize (hb_sanitize_context_t *c) {
859
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
860 861
    return coverage.sanitize (c, this)
	&& ruleSet.sanitize (c, this);
B
Behdad Esfahbod 已提交
862 863
  }

864 865
  private:
  USHORT	format;			/* Format identifier--format = 1 */
866 867
  OffsetTo<Coverage>
		coverage;		/* Offset to Coverage table--from
868
					 * beginning of table */
869 870 871
  OffsetArrayOf<ChainRuleSet>
		ruleSet;		/* Array of ChainRuleSet tables
					 * ordered by Coverage Index */
872
  public:
873
  DEFINE_SIZE_ARRAY (6, ruleSet);
874 875
};

B
Behdad Esfahbod 已提交
876 877
struct ChainContextFormat2
{
878 879 880
  friend struct ChainContext;

  private:
881 882 883 884 885 886 887 888

  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
  {
    TRACE_CLOSURE ();
    /* TODO FILLME */
    return false;
  }

B
Behdad Esfahbod 已提交
889
  inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
B
Behdad Esfahbod 已提交
890
  {
891
    TRACE_APPLY ();
892
    unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
893
    if (likely (index == NOT_COVERED))
894 895 896 897 898 899
      return false;

    const ClassDef &backtrack_class_def = this+backtrackClassDef;
    const ClassDef &input_class_def = this+inputClassDef;
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;

900
    index = input_class_def (c->buffer->info[c->buffer->idx].codepoint);
901
    const ChainRuleSet &rule_set = this+ruleSet[index];
B
Behdad Esfahbod 已提交
902
    struct ChainContextLookupContext lookup_context = {
B
Behdad Esfahbod 已提交
903 904 905 906
      {match_class, apply_func},
      {&backtrack_class_def,
       &input_class_def,
       &lookahead_class_def}
907
    };
B
Behdad Esfahbod 已提交
908
    return rule_set.apply (c, lookup_context);
909 910
  }

B
Behdad Esfahbod 已提交
911
  inline bool sanitize (hb_sanitize_context_t *c) {
912
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
913 914 915 916 917
    return coverage.sanitize (c, this)
	&& backtrackClassDef.sanitize (c, this)
	&& inputClassDef.sanitize (c, this)
	&& lookaheadClassDef.sanitize (c, this)
	&& ruleSet.sanitize (c, this);
B
Behdad Esfahbod 已提交
918 919
  }

920 921
  private:
  USHORT	format;			/* Format identifier--format = 2 */
922 923
  OffsetTo<Coverage>
		coverage;		/* Offset to Coverage table--from
924
					 * beginning of table */
925 926
  OffsetTo<ClassDef>
		backtrackClassDef;	/* Offset to glyph ClassDef table
927 928
					 * containing backtrack sequence
					 * data--from beginning of table */
929 930
  OffsetTo<ClassDef>
		inputClassDef;		/* Offset to glyph ClassDef
931 932
					 * table containing input sequence
					 * data--from beginning of table */
933 934
  OffsetTo<ClassDef>
		lookaheadClassDef;	/* Offset to glyph ClassDef table
935 936
					 * containing lookahead sequence
					 * data--from beginning of table */
937 938 939
  OffsetArrayOf<ChainRuleSet>
		ruleSet;		/* Array of ChainRuleSet tables
					 * ordered by class */
940
  public:
941
  DEFINE_SIZE_ARRAY (12, ruleSet);
942 943
};

B
Behdad Esfahbod 已提交
944 945
struct ChainContextFormat3
{
946 947 948
  friend struct ChainContext;

  private:
949

950 951 952 953 954 955 956
  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
  {
    TRACE_CLOSURE ();
    /* TODO FILLME */
    return false;
  }

B
Behdad Esfahbod 已提交
957
  inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
B
Behdad Esfahbod 已提交
958
  {
959
    TRACE_APPLY ();
960
    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
961

962
    unsigned int index = (this+input[0]) (c->buffer->info[c->buffer->idx].codepoint);
963
    if (likely (index == NOT_COVERED))
964 965
      return false;

966 967
    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
B
Behdad Esfahbod 已提交
968
    struct ChainContextLookupContext lookup_context = {
969
      {match_coverage, apply_func},
B
Behdad Esfahbod 已提交
970
      {this, this, this}
971
    };
B
Behdad Esfahbod 已提交
972
    return chain_context_lookup (c,
B
Behdad Esfahbod 已提交
973 974 975 976
				 backtrack.len, (const USHORT *) backtrack.array,
				 input.len, (const USHORT *) input.array + 1,
				 lookahead.len, (const USHORT *) lookahead.array,
				 lookup.len, lookup.array,
B
Behdad Esfahbod 已提交
977
				 lookup_context);
978 979
  }

B
Behdad Esfahbod 已提交
980
  inline bool sanitize (hb_sanitize_context_t *c) {
981
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
982
    if (!backtrack.sanitize (c, this)) return false;
983
    OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
B
Behdad Esfahbod 已提交
984
    if (!input.sanitize (c, this)) return false;
985
    OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
B
Behdad Esfahbod 已提交
986
    if (!lookahead.sanitize (c, this)) return false;
987
    ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
B
Behdad Esfahbod 已提交
988
    return lookup.sanitize (c);
B
Behdad Esfahbod 已提交
989 990
  }

991 992
  private:
  USHORT	format;			/* Format identifier--format = 3 */
B
Behdad Esfahbod 已提交
993
  OffsetArrayOf<Coverage>
994
		backtrack;		/* Array of coverage tables
995 996
					 * in backtracking sequence, in  glyph
					 * sequence order */
B
Behdad Esfahbod 已提交
997
  OffsetArrayOf<Coverage>
998
		inputX		;	/* Array of coverage
999 1000
					 * tables in input sequence, in glyph
					 * sequence order */
B
Behdad Esfahbod 已提交
1001
  OffsetArrayOf<Coverage>
1002
		lookaheadX;		/* Array of coverage tables
1003 1004
					 * in lookahead sequence, in glyph
					 * sequence order */
B
Behdad Esfahbod 已提交
1005
  ArrayOf<LookupRecord>
1006
		lookupX;		/* Array of LookupRecords--in
B
Behdad Esfahbod 已提交
1007
					 * design order) */
1008
  public:
B
Behdad Esfahbod 已提交
1009
  DEFINE_SIZE_MIN (10);
1010 1011
};

B
Behdad Esfahbod 已提交
1012 1013
struct ChainContext
{
1014
  protected:
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026

  inline bool closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
  {
    TRACE_CLOSURE ();
    switch (u.format) {
    case 1: return u.format1.closure (c, closure_func);
    case 2: return u.format2.closure (c, closure_func);
    case 3: return u.format3.closure (c, closure_func);
    default:return false;
    }
  }

B
Behdad Esfahbod 已提交
1027
  inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
B
Behdad Esfahbod 已提交
1028
  {
1029
    TRACE_APPLY ();
1030
    switch (u.format) {
B
Behdad Esfahbod 已提交
1031 1032 1033
    case 1: return u.format1.apply (c, apply_func);
    case 2: return u.format2.apply (c, apply_func);
    case 3: return u.format3.apply (c, apply_func);
1034 1035 1036 1037
    default:return false;
    }
  }

B
Behdad Esfahbod 已提交
1038
  inline bool sanitize (hb_sanitize_context_t *c) {
1039
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
1040
    if (!u.format.sanitize (c)) return false;
B
Behdad Esfahbod 已提交
1041
    switch (u.format) {
B
Behdad Esfahbod 已提交
1042 1043 1044
    case 1: return u.format1.sanitize (c);
    case 2: return u.format2.sanitize (c);
    case 3: return u.format3.sanitize (c);
B
Behdad Esfahbod 已提交
1045 1046 1047 1048
    default:return true;
    }
  }

1049 1050 1051
  private:
  union {
  USHORT		format;	/* Format identifier */
B
Behdad Esfahbod 已提交
1052 1053 1054
  ChainContextFormat1	format1;
  ChainContextFormat2	format2;
  ChainContextFormat3	format3;
1055 1056 1057 1058
  } u;
};


1059 1060 1061 1062
struct ExtensionFormat1
{
  friend struct Extension;

B
Behdad Esfahbod 已提交
1063
  protected:
1064
  inline unsigned int get_type (void) const { return extensionLookupType; }
B
Behdad Esfahbod 已提交
1065
  inline unsigned int get_offset (void) const { return extensionOffset; }
1066

B
Behdad Esfahbod 已提交
1067
  inline bool sanitize (hb_sanitize_context_t *c) {
1068
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
1069
    return c->check_struct (this);
B
Behdad Esfahbod 已提交
1070 1071
  }

1072 1073 1074 1075 1076
  private:
  USHORT	format;			/* Format identifier. Set to 1. */
  USHORT	extensionLookupType;	/* Lookup type of subtable referenced
					 * by ExtensionOffset (i.e. the
					 * extension subtable). */
1077 1078
  ULONG		extensionOffset;	/* Offset to the extension subtable,
					 * of lookup type subtable. */
1079 1080
  public:
  DEFINE_SIZE_STATIC (8);
1081 1082 1083 1084 1085 1086 1087
};

struct Extension
{
  inline unsigned int get_type (void) const
  {
    switch (u.format) {
B
Behdad Esfahbod 已提交
1088
    case 1: return u.format1.get_type ();
1089 1090 1091
    default:return 0;
    }
  }
B
Behdad Esfahbod 已提交
1092
  inline unsigned int get_offset (void) const
1093 1094
  {
    switch (u.format) {
B
Behdad Esfahbod 已提交
1095
    case 1: return u.format1.get_offset ();
B
Behdad Esfahbod 已提交
1096
    default:return 0;
1097 1098 1099
    }
  }

B
Behdad Esfahbod 已提交
1100
  inline bool sanitize (hb_sanitize_context_t *c) {
1101
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
1102
    if (!u.format.sanitize (c)) return false;
B
Behdad Esfahbod 已提交
1103
    switch (u.format) {
B
Behdad Esfahbod 已提交
1104
    case 1: return u.format1.sanitize (c);
B
Behdad Esfahbod 已提交
1105 1106 1107 1108
    default:return true;
    }
  }

1109 1110 1111
  private:
  union {
  USHORT		format;		/* Format identifier */
B
Behdad Esfahbod 已提交
1112
  ExtensionFormat1	format1;
1113 1114 1115 1116
  } u;
};


B
Behdad Esfahbod 已提交
1117 1118 1119 1120
/*
 * GSUB/GPOS Common
 */

B
Behdad Esfahbod 已提交
1121 1122
struct GSUBGPOS
{
B
Behdad Esfahbod 已提交
1123 1124
  static const hb_tag_t GSUBTag	= HB_OT_TAG_GSUB;
  static const hb_tag_t GPOSTag	= HB_OT_TAG_GPOS;
B
Behdad Esfahbod 已提交
1125

1126 1127 1128 1129
  inline unsigned int get_script_count (void) const
  { return (this+scriptList).len; }
  inline const Tag& get_script_tag (unsigned int i) const
  { return (this+scriptList).get_tag (i); }
B
Behdad Esfahbod 已提交
1130 1131 1132 1133
  inline unsigned int get_script_tags (unsigned int start_offset,
				       unsigned int *script_count /* IN/OUT */,
				       hb_tag_t     *script_tags /* OUT */) const
  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
1134 1135 1136 1137 1138 1139 1140 1141 1142
  inline const Script& get_script (unsigned int i) const
  { return (this+scriptList)[i]; }
  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
  { return (this+scriptList).find_index (tag, index); }

  inline unsigned int get_feature_count (void) const
  { return (this+featureList).len; }
  inline const Tag& get_feature_tag (unsigned int i) const
  { return (this+featureList).get_tag (i); }
B
Behdad Esfahbod 已提交
1143 1144 1145 1146
  inline unsigned int get_feature_tags (unsigned int start_offset,
					unsigned int *feature_count /* IN/OUT */,
					hb_tag_t     *feature_tags /* OUT */) const
  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
1147 1148 1149 1150 1151 1152 1153 1154 1155
  inline const Feature& get_feature (unsigned int i) const
  { return (this+featureList)[i]; }
  inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
  { return (this+featureList).find_index (tag, index); }

  inline unsigned int get_lookup_count (void) const
  { return (this+lookupList).len; }
  inline const Lookup& get_lookup (unsigned int i) const
  { return (this+lookupList)[i]; }
B
Behdad Esfahbod 已提交
1156

B
Behdad Esfahbod 已提交
1157
  inline bool sanitize (hb_sanitize_context_t *c) {
1158
    TRACE_SANITIZE ();
B
Behdad Esfahbod 已提交
1159 1160 1161 1162
    return version.sanitize (c) && likely (version.major == 1)
	&& scriptList.sanitize (c, this)
	&& featureList.sanitize (c, this)
	&& lookupList.sanitize (c, this);
B
Behdad Esfahbod 已提交
1163 1164
  }

1165
  protected:
B
Behdad Esfahbod 已提交
1166
  FixedVersion	version;	/* Version of the GSUB/GPOS table--initially set
B
Behdad Esfahbod 已提交
1167 1168 1169 1170 1171 1172 1173
				 * to 0x00010000 */
  OffsetTo<ScriptList>
		scriptList;  	/* ScriptList table */
  OffsetTo<FeatureList>
		featureList; 	/* FeatureList table */
  OffsetTo<LookupList>
		lookupList; 	/* LookupList table */
1174 1175
  public:
  DEFINE_SIZE_STATIC (10);
B
Behdad Esfahbod 已提交
1176
};
1177

1178

B
Behdad Esfahbod 已提交
1179

1180
#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */