OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. | 2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. |
3 * Copyright © 2010,2012 Google, Inc. | 3 * Copyright © 2010,2012 Google, Inc. |
4 * | 4 * |
5 * This is part of HarfBuzz, a text shaping library. | 5 * This is part of HarfBuzz, a text shaping library. |
6 * | 6 * |
7 * Permission is hereby granted, without written agreement and without | 7 * Permission is hereby granted, without written agreement and without |
8 * license or royalty fees, to use, copy, modify, and distribute this | 8 * license or royalty fees, to use, copy, modify, and distribute this |
9 * software and its documentation for any purpose, provided that the | 9 * software and its documentation for any purpose, provided that the |
10 * above copyright notice and the following two paragraphs appear in | 10 * above copyright notice and the following two paragraphs appear in |
(...skipping 14 matching lines...) Expand all Loading... |
25 * Red Hat Author(s): Behdad Esfahbod | 25 * Red Hat Author(s): Behdad Esfahbod |
26 * Google Author(s): Behdad Esfahbod | 26 * Google Author(s): Behdad Esfahbod |
27 */ | 27 */ |
28 | 28 |
29 #ifndef HB_OT_LAYOUT_GPOS_TABLE_HH | 29 #ifndef HB_OT_LAYOUT_GPOS_TABLE_HH |
30 #define HB_OT_LAYOUT_GPOS_TABLE_HH | 30 #define HB_OT_LAYOUT_GPOS_TABLE_HH |
31 | 31 |
32 #include "hb-ot-layout-gsubgpos-private.hh" | 32 #include "hb-ot-layout-gsubgpos-private.hh" |
33 | 33 |
34 | 34 |
| 35 namespace OT { |
| 36 |
35 | 37 |
36 /* buffer **position** var allocations */ | 38 /* buffer **position** var allocations */ |
37 #define attach_lookback() var.u16[0] /* number of glyphs to go back to attach th
is glyph to its base */ | 39 #define attach_lookback() var.u16[0] /* number of glyphs to go back to attach th
is glyph to its base */ |
38 #define cursive_chain() var.i16[1] /* character to which this connects, may be p
ositive or negative */ | 40 #define cursive_chain() var.i16[1] /* character to which this connects, may be p
ositive or negative */ |
39 | 41 |
40 | 42 |
41 /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */ | 43 /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */ |
42 | 44 |
43 typedef USHORT Value; | 45 typedef USHORT Value; |
44 | 46 |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 { | 220 { |
219 *x = font->em_scale_x (xCoordinate); | 221 *x = font->em_scale_x (xCoordinate); |
220 *y = font->em_scale_y (yCoordinate); | 222 *y = font->em_scale_y (yCoordinate); |
221 } | 223 } |
222 | 224 |
223 inline bool sanitize (hb_sanitize_context_t *c) { | 225 inline bool sanitize (hb_sanitize_context_t *c) { |
224 TRACE_SANITIZE (); | 226 TRACE_SANITIZE (); |
225 return TRACE_RETURN (c->check_struct (this)); | 227 return TRACE_RETURN (c->check_struct (this)); |
226 } | 228 } |
227 | 229 |
228 private: | 230 protected: |
229 USHORT format; /* Format identifier--format = 1 */ | 231 USHORT format; /* Format identifier--format = 1 */ |
230 SHORT xCoordinate; /* Horizontal value--in design units */ | 232 SHORT xCoordinate; /* Horizontal value--in design units */ |
231 SHORT yCoordinate; /* Vertical value--in design units */ | 233 SHORT yCoordinate; /* Vertical value--in design units */ |
232 public: | 234 public: |
233 DEFINE_SIZE_STATIC (6); | 235 DEFINE_SIZE_STATIC (6); |
234 }; | 236 }; |
235 | 237 |
236 struct AnchorFormat2 | 238 struct AnchorFormat2 |
237 { | 239 { |
238 friend struct Anchor; | 240 friend struct Anchor; |
239 | 241 |
240 private: | 242 private: |
241 inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, | 243 inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, |
242 hb_position_t *x, hb_position_t *y) const | 244 hb_position_t *x, hb_position_t *y) const |
243 { | 245 { |
244 unsigned int x_ppem = font->x_ppem; | 246 unsigned int x_ppem = font->x_ppem; |
245 unsigned int y_ppem = font->y_ppem; | 247 unsigned int y_ppem = font->y_ppem; |
246 hb_position_t cx, cy; | 248 hb_position_t cx, cy; |
247 hb_bool_t ret = false; | 249 hb_bool_t ret = false; |
248 | 250 |
249 if (x_ppem || y_ppem) | 251 if (x_ppem || y_ppem) |
250 » ret = hb_font_get_glyph_contour_point_for_origin (font, glyph_id, anchor
Point, HB_DIRECTION_LTR, &cx, &cy); | 252 » ret = font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, H
B_DIRECTION_LTR, &cx, &cy); |
251 *x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate); | 253 *x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate); |
252 *y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate); | 254 *y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate); |
253 } | 255 } |
254 | 256 |
255 inline bool sanitize (hb_sanitize_context_t *c) { | 257 inline bool sanitize (hb_sanitize_context_t *c) { |
256 TRACE_SANITIZE (); | 258 TRACE_SANITIZE (); |
257 return TRACE_RETURN (c->check_struct (this)); | 259 return TRACE_RETURN (c->check_struct (this)); |
258 } | 260 } |
259 | 261 |
260 private: | 262 protected: |
261 USHORT format; /* Format identifier--format = 2 */ | 263 USHORT format; /* Format identifier--format = 2 */ |
262 SHORT xCoordinate; /* Horizontal value--in design units */ | 264 SHORT xCoordinate; /* Horizontal value--in design units */ |
263 SHORT yCoordinate; /* Vertical value--in design units */ | 265 SHORT yCoordinate; /* Vertical value--in design units */ |
264 USHORT anchorPoint; /* Index to glyph contour point */ | 266 USHORT anchorPoint; /* Index to glyph contour point */ |
265 public: | 267 public: |
266 DEFINE_SIZE_STATIC (8); | 268 DEFINE_SIZE_STATIC (8); |
267 }; | 269 }; |
268 | 270 |
269 struct AnchorFormat3 | 271 struct AnchorFormat3 |
270 { | 272 { |
(...skipping 10 matching lines...) Expand all Loading... |
281 *x += (this+xDeviceTable).get_x_delta (font); | 283 *x += (this+xDeviceTable).get_x_delta (font); |
282 if (font->y_ppem) | 284 if (font->y_ppem) |
283 *y += (this+yDeviceTable).get_x_delta (font); | 285 *y += (this+yDeviceTable).get_x_delta (font); |
284 } | 286 } |
285 | 287 |
286 inline bool sanitize (hb_sanitize_context_t *c) { | 288 inline bool sanitize (hb_sanitize_context_t *c) { |
287 TRACE_SANITIZE (); | 289 TRACE_SANITIZE (); |
288 return TRACE_RETURN (c->check_struct (this) && xDeviceTable.sanitize (c, thi
s) && yDeviceTable.sanitize (c, this)); | 290 return TRACE_RETURN (c->check_struct (this) && xDeviceTable.sanitize (c, thi
s) && yDeviceTable.sanitize (c, this)); |
289 } | 291 } |
290 | 292 |
291 private: | 293 protected: |
292 USHORT format; /* Format identifier--format = 3 */ | 294 USHORT format; /* Format identifier--format = 3 */ |
293 SHORT xCoordinate; /* Horizontal value--in design units */ | 295 SHORT xCoordinate; /* Horizontal value--in design units */ |
294 SHORT yCoordinate; /* Vertical value--in design units */ | 296 SHORT yCoordinate; /* Vertical value--in design units */ |
295 OffsetTo<Device> | 297 OffsetTo<Device> |
296 xDeviceTable; /* Offset to Device table for X | 298 xDeviceTable; /* Offset to Device table for X |
297 * coordinate-- from beginning of | 299 * coordinate-- from beginning of |
298 * Anchor table (may be NULL) */ | 300 * Anchor table (may be NULL) */ |
299 OffsetTo<Device> | 301 OffsetTo<Device> |
300 yDeviceTable; /* Offset to Device table for Y | 302 yDeviceTable; /* Offset to Device table for Y |
301 * coordinate-- from beginning of | 303 * coordinate-- from beginning of |
(...skipping 20 matching lines...) Expand all Loading... |
322 TRACE_SANITIZE (); | 324 TRACE_SANITIZE (); |
323 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 325 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
324 switch (u.format) { | 326 switch (u.format) { |
325 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 327 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
326 case 2: return TRACE_RETURN (u.format2.sanitize (c)); | 328 case 2: return TRACE_RETURN (u.format2.sanitize (c)); |
327 case 3: return TRACE_RETURN (u.format3.sanitize (c)); | 329 case 3: return TRACE_RETURN (u.format3.sanitize (c)); |
328 default:return TRACE_RETURN (true); | 330 default:return TRACE_RETURN (true); |
329 } | 331 } |
330 } | 332 } |
331 | 333 |
332 private: | 334 protected: |
333 union { | 335 union { |
334 USHORT format; /* Format identifier */ | 336 USHORT format; /* Format identifier */ |
335 AnchorFormat1 format1; | 337 AnchorFormat1 format1; |
336 AnchorFormat2 format2; | 338 AnchorFormat2 format2; |
337 AnchorFormat3 format3; | 339 AnchorFormat3 format3; |
338 } u; | 340 } u; |
339 public: | 341 public: |
340 DEFINE_SIZE_UNION (2, format); | 342 DEFINE_SIZE_UNION (2, format); |
341 }; | 343 }; |
342 | 344 |
(...skipping 10 matching lines...) Expand all Loading... |
353 if (!c->check_struct (this)) return TRACE_RETURN (false); | 355 if (!c->check_struct (this)) return TRACE_RETURN (false); |
354 if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_
RETURN (false); | 356 if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_
RETURN (false); |
355 unsigned int count = rows * cols; | 357 unsigned int count = rows * cols; |
356 if (!c->check_array (matrix, matrix[0].static_size, count)) return TRACE_RET
URN (false); | 358 if (!c->check_array (matrix, matrix[0].static_size, count)) return TRACE_RET
URN (false); |
357 for (unsigned int i = 0; i < count; i++) | 359 for (unsigned int i = 0; i < count; i++) |
358 if (!matrix[i].sanitize (c, this)) return TRACE_RETURN (false); | 360 if (!matrix[i].sanitize (c, this)) return TRACE_RETURN (false); |
359 return TRACE_RETURN (true); | 361 return TRACE_RETURN (true); |
360 } | 362 } |
361 | 363 |
362 USHORT rows; /* Number of rows */ | 364 USHORT rows; /* Number of rows */ |
363 private: | 365 protected: |
364 OffsetTo<Anchor> | 366 OffsetTo<Anchor> |
365 matrix[VAR]; /* Matrix of offsets to Anchor tables-- | 367 matrix[VAR]; /* Matrix of offsets to Anchor tables-- |
366 * from beginning of AnchorMatrix table
*/ | 368 * from beginning of AnchorMatrix table
*/ |
367 public: | 369 public: |
368 DEFINE_SIZE_ARRAY (2, matrix); | 370 DEFINE_SIZE_ARRAY (2, matrix); |
369 }; | 371 }; |
370 | 372 |
371 | 373 |
372 struct MarkRecord | 374 struct MarkRecord |
373 { | 375 { |
374 friend struct MarkArray; | 376 friend struct MarkArray; |
375 | 377 |
376 inline bool sanitize (hb_sanitize_context_t *c, void *base) { | 378 inline bool sanitize (hb_sanitize_context_t *c, void *base) { |
377 TRACE_SANITIZE (); | 379 TRACE_SANITIZE (); |
378 return TRACE_RETURN (c->check_struct (this) && markAnchor.sanitize (c, base)
); | 380 return TRACE_RETURN (c->check_struct (this) && markAnchor.sanitize (c, base)
); |
379 } | 381 } |
380 | 382 |
381 private: | 383 protected: |
382 USHORT klass; /* Class defined for this mark */ | 384 USHORT klass; /* Class defined for this mark */ |
383 OffsetTo<Anchor> | 385 OffsetTo<Anchor> |
384 markAnchor; /* Offset to Anchor table--from | 386 markAnchor; /* Offset to Anchor table--from |
385 * beginning of MarkArray table */ | 387 * beginning of MarkArray table */ |
386 public: | 388 public: |
387 DEFINE_SIZE_STATIC (4); | 389 DEFINE_SIZE_STATIC (4); |
388 }; | 390 }; |
389 | 391 |
390 struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage ord
er */ | 392 struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage ord
er */ |
391 { | 393 { |
(...skipping 30 matching lines...) Expand all Loading... |
422 }; | 424 }; |
423 | 425 |
424 | 426 |
425 /* Lookups */ | 427 /* Lookups */ |
426 | 428 |
427 struct SinglePosFormat1 | 429 struct SinglePosFormat1 |
428 { | 430 { |
429 friend struct SinglePos; | 431 friend struct SinglePos; |
430 | 432 |
431 private: | 433 private: |
| 434 |
| 435 inline const Coverage &get_coverage (void) const |
| 436 { |
| 437 return this+coverage; |
| 438 } |
| 439 |
432 inline bool apply (hb_apply_context_t *c) const | 440 inline bool apply (hb_apply_context_t *c) const |
433 { | 441 { |
434 TRACE_APPLY (); | 442 TRACE_APPLY (); |
435 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); | 443 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); |
436 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); | 444 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); |
437 | 445 |
438 valueFormat.apply_value (c->font, c->direction, this, | 446 valueFormat.apply_value (c->font, c->direction, this, |
439 values, c->buffer->cur_pos()); | 447 values, c->buffer->cur_pos()); |
440 | 448 |
441 c->buffer->idx++; | 449 c->buffer->idx++; |
442 return TRACE_RETURN (true); | 450 return TRACE_RETURN (true); |
443 } | 451 } |
444 | 452 |
445 inline bool sanitize (hb_sanitize_context_t *c) { | 453 inline bool sanitize (hb_sanitize_context_t *c) { |
446 TRACE_SANITIZE (); | 454 TRACE_SANITIZE (); |
447 return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) &
& valueFormat.sanitize_value (c, this, values)); | 455 return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) &
& valueFormat.sanitize_value (c, this, values)); |
448 } | 456 } |
449 | 457 |
450 private: | 458 protected: |
451 USHORT format; /* Format identifier--format = 1 */ | 459 USHORT format; /* Format identifier--format = 1 */ |
452 OffsetTo<Coverage> | 460 OffsetTo<Coverage> |
453 coverage; /* Offset to Coverage table--from | 461 coverage; /* Offset to Coverage table--from |
454 * beginning of subtable */ | 462 * beginning of subtable */ |
455 ValueFormat valueFormat; /* Defines the types of data in the | 463 ValueFormat valueFormat; /* Defines the types of data in the |
456 * ValueRecord */ | 464 * ValueRecord */ |
457 ValueRecord values; /* Defines positioning | 465 ValueRecord values; /* Defines positioning |
458 * value(s)--applied to all glyphs in | 466 * value(s)--applied to all glyphs in |
459 * the Coverage table */ | 467 * the Coverage table */ |
460 public: | 468 public: |
461 DEFINE_SIZE_ARRAY (6, values); | 469 DEFINE_SIZE_ARRAY (6, values); |
462 }; | 470 }; |
463 | 471 |
464 struct SinglePosFormat2 | 472 struct SinglePosFormat2 |
465 { | 473 { |
466 friend struct SinglePos; | 474 friend struct SinglePos; |
467 | 475 |
468 private: | 476 private: |
| 477 |
| 478 inline const Coverage &get_coverage (void) const |
| 479 { |
| 480 return this+coverage; |
| 481 } |
| 482 |
469 inline bool apply (hb_apply_context_t *c) const | 483 inline bool apply (hb_apply_context_t *c) const |
470 { | 484 { |
471 TRACE_APPLY (); | 485 TRACE_APPLY (); |
472 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); | 486 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); |
473 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); | 487 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); |
474 | 488 |
475 if (likely (index >= valueCount)) return TRACE_RETURN (false); | 489 if (likely (index >= valueCount)) return TRACE_RETURN (false); |
476 | 490 |
477 valueFormat.apply_value (c->font, c->direction, this, | 491 valueFormat.apply_value (c->font, c->direction, this, |
478 &values[index * valueFormat.get_len ()], | 492 &values[index * valueFormat.get_len ()], |
479 c->buffer->cur_pos()); | 493 c->buffer->cur_pos()); |
480 | 494 |
481 c->buffer->idx++; | 495 c->buffer->idx++; |
482 return TRACE_RETURN (true); | 496 return TRACE_RETURN (true); |
483 } | 497 } |
484 | 498 |
485 inline bool sanitize (hb_sanitize_context_t *c) { | 499 inline bool sanitize (hb_sanitize_context_t *c) { |
486 TRACE_SANITIZE (); | 500 TRACE_SANITIZE (); |
487 return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) &
& valueFormat.sanitize_values (c, this, values, valueCount)); | 501 return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) &
& valueFormat.sanitize_values (c, this, values, valueCount)); |
488 } | 502 } |
489 | 503 |
490 private: | 504 protected: |
491 USHORT format; /* Format identifier--format = 2 */ | 505 USHORT format; /* Format identifier--format = 2 */ |
492 OffsetTo<Coverage> | 506 OffsetTo<Coverage> |
493 coverage; /* Offset to Coverage table--from | 507 coverage; /* Offset to Coverage table--from |
494 * beginning of subtable */ | 508 * beginning of subtable */ |
495 ValueFormat valueFormat; /* Defines the types of data in the | 509 ValueFormat valueFormat; /* Defines the types of data in the |
496 * ValueRecord */ | 510 * ValueRecord */ |
497 USHORT valueCount; /* Number of ValueRecords */ | 511 USHORT valueCount; /* Number of ValueRecords */ |
498 ValueRecord values; /* Array of ValueRecords--positioning | 512 ValueRecord values; /* Array of ValueRecords--positioning |
499 * values applied to glyphs */ | 513 * values applied to glyphs */ |
500 public: | 514 public: |
501 DEFINE_SIZE_ARRAY (8, values); | 515 DEFINE_SIZE_ARRAY (8, values); |
502 }; | 516 }; |
503 | 517 |
504 struct SinglePos | 518 struct SinglePos |
505 { | 519 { |
506 friend struct PosLookupSubTable; | 520 friend struct PosLookupSubTable; |
507 | 521 |
508 private: | 522 private: |
| 523 |
| 524 inline const Coverage &get_coverage (void) const |
| 525 { |
| 526 switch (u.format) { |
| 527 case 1: return u.format1.get_coverage (); |
| 528 case 2: return u.format2.get_coverage (); |
| 529 default:return Null(Coverage); |
| 530 } |
| 531 } |
| 532 |
509 inline bool apply (hb_apply_context_t *c) const | 533 inline bool apply (hb_apply_context_t *c) const |
510 { | 534 { |
511 TRACE_APPLY (); | 535 TRACE_APPLY (); |
512 switch (u.format) { | 536 switch (u.format) { |
513 case 1: return TRACE_RETURN (u.format1.apply (c)); | 537 case 1: return TRACE_RETURN (u.format1.apply (c)); |
514 case 2: return TRACE_RETURN (u.format2.apply (c)); | 538 case 2: return TRACE_RETURN (u.format2.apply (c)); |
515 default:return TRACE_RETURN (false); | 539 default:return TRACE_RETURN (false); |
516 } | 540 } |
517 } | 541 } |
518 | 542 |
519 inline bool sanitize (hb_sanitize_context_t *c) { | 543 inline bool sanitize (hb_sanitize_context_t *c) { |
520 TRACE_SANITIZE (); | 544 TRACE_SANITIZE (); |
521 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 545 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
522 switch (u.format) { | 546 switch (u.format) { |
523 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 547 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
524 case 2: return TRACE_RETURN (u.format2.sanitize (c)); | 548 case 2: return TRACE_RETURN (u.format2.sanitize (c)); |
525 default:return TRACE_RETURN (true); | 549 default:return TRACE_RETURN (true); |
526 } | 550 } |
527 } | 551 } |
528 | 552 |
529 private: | 553 protected: |
530 union { | 554 union { |
531 USHORT format; /* Format identifier */ | 555 USHORT format; /* Format identifier */ |
532 SinglePosFormat1 format1; | 556 SinglePosFormat1 format1; |
533 SinglePosFormat2 format2; | 557 SinglePosFormat2 format2; |
534 } u; | 558 } u; |
535 }; | 559 }; |
536 | 560 |
537 | 561 |
538 struct PairValueRecord | 562 struct PairValueRecord |
539 { | 563 { |
540 friend struct PairSet; | 564 friend struct PairSet; |
541 | 565 |
542 private: | 566 protected: |
543 GlyphID secondGlyph; /* GlyphID of second glyph in the | 567 GlyphID secondGlyph; /* GlyphID of second glyph in the |
544 * pair--first glyph is listed in the | 568 * pair--first glyph is listed in the |
545 * Coverage table */ | 569 * Coverage table */ |
546 ValueRecord values; /* Positioning data for the first glyph | 570 ValueRecord values; /* Positioning data for the first glyph |
547 * followed by for second glyph */ | 571 * followed by for second glyph */ |
548 public: | 572 public: |
549 DEFINE_SIZE_ARRAY (2, values); | 573 DEFINE_SIZE_ARRAY (2, values); |
550 }; | 574 }; |
551 | 575 |
552 struct PairSet | 576 struct PairSet |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 TRACE_SANITIZE (); | 618 TRACE_SANITIZE (); |
595 if (!(c->check_struct (this) | 619 if (!(c->check_struct (this) |
596 && c->check_array (array, USHORT::static_size * closure->stride, len))) r
eturn TRACE_RETURN (false); | 620 && c->check_array (array, USHORT::static_size * closure->stride, len))) r
eturn TRACE_RETURN (false); |
597 | 621 |
598 unsigned int count = len; | 622 unsigned int count = len; |
599 PairValueRecord *record = CastP<PairValueRecord> (array); | 623 PairValueRecord *record = CastP<PairValueRecord> (array); |
600 return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe
(c, closure->base, &record->values[0], count, closure->stride) | 624 return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe
(c, closure->base, &record->values[0], count, closure->stride) |
601 && closure->valueFormats[1].sanitize_values_stride_unsafe
(c, closure->base, &record->values[closure->len1], count, closure->stride)); | 625 && closure->valueFormats[1].sanitize_values_stride_unsafe
(c, closure->base, &record->values[closure->len1], count, closure->stride)); |
602 } | 626 } |
603 | 627 |
604 private: | 628 protected: |
605 USHORT len; /* Number of PairValueRecords */ | 629 USHORT len; /* Number of PairValueRecords */ |
606 USHORT array[VAR]; /* Array of PairValueRecords--ordered | 630 USHORT array[VAR]; /* Array of PairValueRecords--ordered |
607 * by GlyphID of the second glyph */ | 631 * by GlyphID of the second glyph */ |
608 public: | 632 public: |
609 DEFINE_SIZE_ARRAY (2, array); | 633 DEFINE_SIZE_ARRAY (2, array); |
610 }; | 634 }; |
611 | 635 |
612 struct PairPosFormat1 | 636 struct PairPosFormat1 |
613 { | 637 { |
614 friend struct PairPos; | 638 friend struct PairPos; |
615 | 639 |
616 private: | 640 private: |
| 641 |
| 642 inline const Coverage &get_coverage (void) const |
| 643 { |
| 644 return this+coverage; |
| 645 } |
| 646 |
617 inline bool apply (hb_apply_context_t *c) const | 647 inline bool apply (hb_apply_context_t *c) const |
618 { | 648 { |
619 TRACE_APPLY (); | 649 TRACE_APPLY (); |
620 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff
er->idx, 1); | 650 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff
er->idx, 1); |
621 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); | 651 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); |
622 | 652 |
623 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); | 653 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); |
624 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); | 654 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); |
625 | 655 |
626 if (!skippy_iter.next ()) return TRACE_RETURN (false); | 656 if (!skippy_iter.next ()) return TRACE_RETURN (false); |
627 | 657 |
628 return TRACE_RETURN ((this+pairSet[index]).apply (c, &valueFormat1, skippy_i
ter.idx)); | 658 return TRACE_RETURN ((this+pairSet[index]).apply (c, &valueFormat1, skippy_i
ter.idx)); |
629 } | 659 } |
630 | 660 |
631 inline bool sanitize (hb_sanitize_context_t *c) { | 661 inline bool sanitize (hb_sanitize_context_t *c) { |
632 TRACE_SANITIZE (); | 662 TRACE_SANITIZE (); |
633 | 663 |
634 unsigned int len1 = valueFormat1.get_len (); | 664 unsigned int len1 = valueFormat1.get_len (); |
635 unsigned int len2 = valueFormat2.get_len (); | 665 unsigned int len2 = valueFormat2.get_len (); |
636 PairSet::sanitize_closure_t closure = { | 666 PairSet::sanitize_closure_t closure = { |
637 this, | 667 this, |
638 &valueFormat1, | 668 &valueFormat1, |
639 len1, | 669 len1, |
640 1 + len1 + len2 | 670 1 + len1 + len2 |
641 }; | 671 }; |
642 | 672 |
643 return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) &
& pairSet.sanitize (c, this, &closure)); | 673 return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) &
& pairSet.sanitize (c, this, &closure)); |
644 } | 674 } |
645 | 675 |
646 private: | 676 protected: |
647 USHORT format; /* Format identifier--format = 1 */ | 677 USHORT format; /* Format identifier--format = 1 */ |
648 OffsetTo<Coverage> | 678 OffsetTo<Coverage> |
649 coverage; /* Offset to Coverage table--from | 679 coverage; /* Offset to Coverage table--from |
650 * beginning of subtable */ | 680 * beginning of subtable */ |
651 ValueFormat valueFormat1; /* Defines the types of data in | 681 ValueFormat valueFormat1; /* Defines the types of data in |
652 * ValueRecord1--for the first glyph | 682 * ValueRecord1--for the first glyph |
653 * in the pair--may be zero (0) */ | 683 * in the pair--may be zero (0) */ |
654 ValueFormat valueFormat2; /* Defines the types of data in | 684 ValueFormat valueFormat2; /* Defines the types of data in |
655 * ValueRecord2--for the second glyph | 685 * ValueRecord2--for the second glyph |
656 * in the pair--may be zero (0) */ | 686 * in the pair--may be zero (0) */ |
657 OffsetArrayOf<PairSet> | 687 OffsetArrayOf<PairSet> |
658 pairSet; /* Array of PairSet tables | 688 pairSet; /* Array of PairSet tables |
659 * ordered by Coverage Index */ | 689 * ordered by Coverage Index */ |
660 public: | 690 public: |
661 DEFINE_SIZE_ARRAY (10, pairSet); | 691 DEFINE_SIZE_ARRAY (10, pairSet); |
662 }; | 692 }; |
663 | 693 |
664 struct PairPosFormat2 | 694 struct PairPosFormat2 |
665 { | 695 { |
666 friend struct PairPos; | 696 friend struct PairPos; |
667 | 697 |
668 private: | 698 private: |
| 699 |
| 700 inline const Coverage &get_coverage (void) const |
| 701 { |
| 702 return this+coverage; |
| 703 } |
| 704 |
669 inline bool apply (hb_apply_context_t *c) const | 705 inline bool apply (hb_apply_context_t *c) const |
670 { | 706 { |
671 TRACE_APPLY (); | 707 TRACE_APPLY (); |
672 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff
er->idx, 1); | 708 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff
er->idx, 1); |
673 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); | 709 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); |
674 | 710 |
675 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); | 711 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); |
676 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); | 712 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); |
677 | 713 |
678 if (!skippy_iter.next ()) return TRACE_RETURN (false); | 714 if (!skippy_iter.next ()) return TRACE_RETURN (false); |
(...skipping 29 matching lines...) Expand all Loading... |
708 unsigned int len1 = valueFormat1.get_len (); | 744 unsigned int len1 = valueFormat1.get_len (); |
709 unsigned int len2 = valueFormat2.get_len (); | 745 unsigned int len2 = valueFormat2.get_len (); |
710 unsigned int stride = len1 + len2; | 746 unsigned int stride = len1 + len2; |
711 unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size
(); | 747 unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size
(); |
712 unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count
; | 748 unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count
; |
713 return TRACE_RETURN (c->check_array (values, record_size, count) && | 749 return TRACE_RETURN (c->check_array (values, record_size, count) && |
714 valueFormat1.sanitize_values_stride_unsafe (c, this, &v
alues[0], count, stride) && | 750 valueFormat1.sanitize_values_stride_unsafe (c, this, &v
alues[0], count, stride) && |
715 valueFormat2.sanitize_values_stride_unsafe (c, this, &v
alues[len1], count, stride)); | 751 valueFormat2.sanitize_values_stride_unsafe (c, this, &v
alues[len1], count, stride)); |
716 } | 752 } |
717 | 753 |
718 private: | 754 protected: |
719 USHORT format; /* Format identifier--format = 2 */ | 755 USHORT format; /* Format identifier--format = 2 */ |
720 OffsetTo<Coverage> | 756 OffsetTo<Coverage> |
721 coverage; /* Offset to Coverage table--from | 757 coverage; /* Offset to Coverage table--from |
722 * beginning of subtable */ | 758 * beginning of subtable */ |
723 ValueFormat valueFormat1; /* ValueRecord definition--for the | 759 ValueFormat valueFormat1; /* ValueRecord definition--for the |
724 * first glyph of the pair--may be zero | 760 * first glyph of the pair--may be zero |
725 * (0) */ | 761 * (0) */ |
726 ValueFormat valueFormat2; /* ValueRecord definition--for the | 762 ValueFormat valueFormat2; /* ValueRecord definition--for the |
727 * second glyph of the pair--may be | 763 * second glyph of the pair--may be |
728 * zero (0) */ | 764 * zero (0) */ |
(...skipping 14 matching lines...) Expand all Loading... |
743 * Each entry has value1 and value2 */ | 779 * Each entry has value1 and value2 */ |
744 public: | 780 public: |
745 DEFINE_SIZE_ARRAY (16, values); | 781 DEFINE_SIZE_ARRAY (16, values); |
746 }; | 782 }; |
747 | 783 |
748 struct PairPos | 784 struct PairPos |
749 { | 785 { |
750 friend struct PosLookupSubTable; | 786 friend struct PosLookupSubTable; |
751 | 787 |
752 private: | 788 private: |
| 789 |
| 790 inline const Coverage &get_coverage (void) const |
| 791 { |
| 792 switch (u.format) { |
| 793 case 1: return u.format1.get_coverage (); |
| 794 case 2: return u.format2.get_coverage (); |
| 795 default:return Null(Coverage); |
| 796 } |
| 797 } |
| 798 |
753 inline bool apply (hb_apply_context_t *c) const | 799 inline bool apply (hb_apply_context_t *c) const |
754 { | 800 { |
755 TRACE_APPLY (); | 801 TRACE_APPLY (); |
756 switch (u.format) { | 802 switch (u.format) { |
757 case 1: return TRACE_RETURN (u.format1.apply (c)); | 803 case 1: return TRACE_RETURN (u.format1.apply (c)); |
758 case 2: return TRACE_RETURN (u.format2.apply (c)); | 804 case 2: return TRACE_RETURN (u.format2.apply (c)); |
759 default:return TRACE_RETURN (false); | 805 default:return TRACE_RETURN (false); |
760 } | 806 } |
761 } | 807 } |
762 | 808 |
763 inline bool sanitize (hb_sanitize_context_t *c) { | 809 inline bool sanitize (hb_sanitize_context_t *c) { |
764 TRACE_SANITIZE (); | 810 TRACE_SANITIZE (); |
765 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 811 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
766 switch (u.format) { | 812 switch (u.format) { |
767 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 813 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
768 case 2: return TRACE_RETURN (u.format2.sanitize (c)); | 814 case 2: return TRACE_RETURN (u.format2.sanitize (c)); |
769 default:return TRACE_RETURN (true); | 815 default:return TRACE_RETURN (true); |
770 } | 816 } |
771 } | 817 } |
772 | 818 |
773 private: | 819 protected: |
774 union { | 820 union { |
775 USHORT format; /* Format identifier */ | 821 USHORT format; /* Format identifier */ |
776 PairPosFormat1 format1; | 822 PairPosFormat1 format1; |
777 PairPosFormat2 format2; | 823 PairPosFormat2 format2; |
778 } u; | 824 } u; |
779 }; | 825 }; |
780 | 826 |
781 | 827 |
782 struct EntryExitRecord | 828 struct EntryExitRecord |
783 { | 829 { |
784 friend struct CursivePosFormat1; | 830 friend struct CursivePosFormat1; |
785 | 831 |
786 inline bool sanitize (hb_sanitize_context_t *c, void *base) { | 832 inline bool sanitize (hb_sanitize_context_t *c, void *base) { |
787 TRACE_SANITIZE (); | 833 TRACE_SANITIZE (); |
788 return TRACE_RETURN (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (
c, base)); | 834 return TRACE_RETURN (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (
c, base)); |
789 } | 835 } |
790 | 836 |
791 private: | 837 protected: |
792 OffsetTo<Anchor> | 838 OffsetTo<Anchor> |
793 entryAnchor; /* Offset to EntryAnchor table--from | 839 entryAnchor; /* Offset to EntryAnchor table--from |
794 * beginning of CursivePos | 840 * beginning of CursivePos |
795 * subtable--may be NULL */ | 841 * subtable--may be NULL */ |
796 OffsetTo<Anchor> | 842 OffsetTo<Anchor> |
797 exitAnchor; /* Offset to ExitAnchor table--from | 843 exitAnchor; /* Offset to ExitAnchor table--from |
798 * beginning of CursivePos | 844 * beginning of CursivePos |
799 * subtable--may be NULL */ | 845 * subtable--may be NULL */ |
800 public: | 846 public: |
801 DEFINE_SIZE_STATIC (4); | 847 DEFINE_SIZE_STATIC (4); |
802 }; | 848 }; |
803 | 849 |
804 struct CursivePosFormat1 | 850 struct CursivePosFormat1 |
805 { | 851 { |
806 friend struct CursivePos; | 852 friend struct CursivePos; |
807 | 853 |
808 private: | 854 private: |
| 855 |
| 856 inline const Coverage &get_coverage (void) const |
| 857 { |
| 858 return this+coverage; |
| 859 } |
| 860 |
809 inline bool apply (hb_apply_context_t *c) const | 861 inline bool apply (hb_apply_context_t *c) const |
810 { | 862 { |
811 TRACE_APPLY (); | 863 TRACE_APPLY (); |
812 | 864 |
813 /* We don't handle mark glyphs here. */ | 865 /* We don't handle mark glyphs here. */ |
814 if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) return TRACE_RETURN (false)
; | 866 if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) return TRACE_RETURN (false)
; |
815 | 867 |
816 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff
er->idx, 1); | 868 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff
er->idx, 1); |
817 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); | 869 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); |
818 | 870 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
886 | 938 |
887 c->buffer->idx = j; | 939 c->buffer->idx = j; |
888 return TRACE_RETURN (true); | 940 return TRACE_RETURN (true); |
889 } | 941 } |
890 | 942 |
891 inline bool sanitize (hb_sanitize_context_t *c) { | 943 inline bool sanitize (hb_sanitize_context_t *c) { |
892 TRACE_SANITIZE (); | 944 TRACE_SANITIZE (); |
893 return TRACE_RETURN (coverage.sanitize (c, this) && entryExitRecord.sanitize
(c, this)); | 945 return TRACE_RETURN (coverage.sanitize (c, this) && entryExitRecord.sanitize
(c, this)); |
894 } | 946 } |
895 | 947 |
896 private: | 948 protected: |
897 USHORT format; /* Format identifier--format = 1 */ | 949 USHORT format; /* Format identifier--format = 1 */ |
898 OffsetTo<Coverage> | 950 OffsetTo<Coverage> |
899 coverage; /* Offset to Coverage table--from | 951 coverage; /* Offset to Coverage table--from |
900 * beginning of subtable */ | 952 * beginning of subtable */ |
901 ArrayOf<EntryExitRecord> | 953 ArrayOf<EntryExitRecord> |
902 entryExitRecord; /* Array of EntryExit records--in | 954 entryExitRecord; /* Array of EntryExit records--in |
903 * Coverage Index order */ | 955 * Coverage Index order */ |
904 public: | 956 public: |
905 DEFINE_SIZE_ARRAY (6, entryExitRecord); | 957 DEFINE_SIZE_ARRAY (6, entryExitRecord); |
906 }; | 958 }; |
907 | 959 |
908 struct CursivePos | 960 struct CursivePos |
909 { | 961 { |
910 friend struct PosLookupSubTable; | 962 friend struct PosLookupSubTable; |
911 | 963 |
912 private: | 964 private: |
| 965 |
| 966 inline const Coverage &get_coverage (void) const |
| 967 { |
| 968 switch (u.format) { |
| 969 case 1: return u.format1.get_coverage (); |
| 970 default:return Null(Coverage); |
| 971 } |
| 972 } |
| 973 |
913 inline bool apply (hb_apply_context_t *c) const | 974 inline bool apply (hb_apply_context_t *c) const |
914 { | 975 { |
915 TRACE_APPLY (); | 976 TRACE_APPLY (); |
916 switch (u.format) { | 977 switch (u.format) { |
917 case 1: return TRACE_RETURN (u.format1.apply (c)); | 978 case 1: return TRACE_RETURN (u.format1.apply (c)); |
918 default:return TRACE_RETURN (false); | 979 default:return TRACE_RETURN (false); |
919 } | 980 } |
920 } | 981 } |
921 | 982 |
922 inline bool sanitize (hb_sanitize_context_t *c) { | 983 inline bool sanitize (hb_sanitize_context_t *c) { |
923 TRACE_SANITIZE (); | 984 TRACE_SANITIZE (); |
924 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 985 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
925 switch (u.format) { | 986 switch (u.format) { |
926 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 987 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
927 default:return TRACE_RETURN (true); | 988 default:return TRACE_RETURN (true); |
928 } | 989 } |
929 } | 990 } |
930 | 991 |
931 private: | 992 protected: |
932 union { | 993 union { |
933 USHORT format; /* Format identifier */ | 994 USHORT format; /* Format identifier */ |
934 CursivePosFormat1 format1; | 995 CursivePosFormat1 format1; |
935 } u; | 996 } u; |
936 }; | 997 }; |
937 | 998 |
938 | 999 |
939 typedef AnchorMatrix BaseArray; /* base-major-- | 1000 typedef AnchorMatrix BaseArray; /* base-major-- |
940 * in order of BaseCoverage Index--, | 1001 * in order of BaseCoverage Index--, |
941 * mark-minor-- | 1002 * mark-minor-- |
942 * ordered by class--zero-based. */ | 1003 * ordered by class--zero-based. */ |
943 | 1004 |
944 struct MarkBasePosFormat1 | 1005 struct MarkBasePosFormat1 |
945 { | 1006 { |
946 friend struct MarkBasePos; | 1007 friend struct MarkBasePos; |
947 | 1008 |
948 private: | 1009 private: |
| 1010 |
| 1011 inline const Coverage &get_coverage (void) const |
| 1012 { |
| 1013 return this+markCoverage; |
| 1014 } |
| 1015 |
949 inline bool apply (hb_apply_context_t *c) const | 1016 inline bool apply (hb_apply_context_t *c) const |
950 { | 1017 { |
951 TRACE_APPLY (); | 1018 TRACE_APPLY (); |
952 unsigned int mark_index = (this+markCoverage) (c->buffer->cur().codepoint); | 1019 unsigned int mark_index = (this+markCoverage) (c->buffer->cur().codepoint); |
953 if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); | 1020 if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); |
954 | 1021 |
955 /* now we search backwards for a non-mark glyph */ | 1022 /* now we search backwards for a non-mark glyph */ |
956 unsigned int property; | 1023 unsigned int property; |
957 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buf
fer->idx, 1); | 1024 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buf
fer->idx, 1); |
958 if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_RET
URN (false); | 1025 do { |
| 1026 if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_R
ETURN (false); |
| 1027 /* We only want to attach to the first of a MultipleSubst sequence. Rejec
t others. */ |
| 1028 if (0 == get_lig_comp (c->buffer->info[skippy_iter.idx])) break; |
| 1029 skippy_iter.reject (); |
| 1030 } while (1); |
959 | 1031 |
960 /* The following assertion is too strong, so we've disabled it. */ | 1032 /* The following assertion is too strong, so we've disabled it. */ |
961 if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH)) {/*return TRACE_RETUR
N (false);*/} | 1033 if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH)) {/*return TRACE_RETUR
N (false);*/} |
962 | 1034 |
963 unsigned int base_index = (this+baseCoverage) (c->buffer->info[skippy_iter.i
dx].codepoint); | 1035 unsigned int base_index = (this+baseCoverage) (c->buffer->info[skippy_iter.i
dx].codepoint); |
964 if (base_index == NOT_COVERED) return TRACE_RETURN (false); | 1036 if (base_index == NOT_COVERED) return TRACE_RETURN (false); |
965 | 1037 |
966 return TRACE_RETURN ((this+markArray).apply (c, mark_index, base_index, this
+baseArray, classCount, skippy_iter.idx)); | 1038 return TRACE_RETURN ((this+markArray).apply (c, mark_index, base_index, this
+baseArray, classCount, skippy_iter.idx)); |
967 } | 1039 } |
968 | 1040 |
969 inline bool sanitize (hb_sanitize_context_t *c) { | 1041 inline bool sanitize (hb_sanitize_context_t *c) { |
970 TRACE_SANITIZE (); | 1042 TRACE_SANITIZE (); |
971 return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, thi
s) && baseCoverage.sanitize (c, this) && | 1043 return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, thi
s) && baseCoverage.sanitize (c, this) && |
972 markArray.sanitize (c, this) && baseArray.sanitize (c,
this, (unsigned int) classCount)); | 1044 markArray.sanitize (c, this) && baseArray.sanitize (c,
this, (unsigned int) classCount)); |
973 } | 1045 } |
974 | 1046 |
975 private: | 1047 protected: |
976 USHORT format; /* Format identifier--format = 1 */ | 1048 USHORT format; /* Format identifier--format = 1 */ |
977 OffsetTo<Coverage> | 1049 OffsetTo<Coverage> |
978 markCoverage; /* Offset to MarkCoverage table--from | 1050 markCoverage; /* Offset to MarkCoverage table--from |
979 * beginning of MarkBasePos subtable */ | 1051 * beginning of MarkBasePos subtable */ |
980 OffsetTo<Coverage> | 1052 OffsetTo<Coverage> |
981 baseCoverage; /* Offset to BaseCoverage table--from | 1053 baseCoverage; /* Offset to BaseCoverage table--from |
982 * beginning of MarkBasePos subtable */ | 1054 * beginning of MarkBasePos subtable */ |
983 USHORT classCount; /* Number of classes defined for marks *
/ | 1055 USHORT classCount; /* Number of classes defined for marks *
/ |
984 OffsetTo<MarkArray> | 1056 OffsetTo<MarkArray> |
985 markArray; /* Offset to MarkArray table--from | 1057 markArray; /* Offset to MarkArray table--from |
986 * beginning of MarkBasePos subtable */ | 1058 * beginning of MarkBasePos subtable */ |
987 OffsetTo<BaseArray> | 1059 OffsetTo<BaseArray> |
988 baseArray; /* Offset to BaseArray table--from | 1060 baseArray; /* Offset to BaseArray table--from |
989 * beginning of MarkBasePos subtable */ | 1061 * beginning of MarkBasePos subtable */ |
990 public: | 1062 public: |
991 DEFINE_SIZE_STATIC (12); | 1063 DEFINE_SIZE_STATIC (12); |
992 }; | 1064 }; |
993 | 1065 |
994 struct MarkBasePos | 1066 struct MarkBasePos |
995 { | 1067 { |
996 friend struct PosLookupSubTable; | 1068 friend struct PosLookupSubTable; |
997 | 1069 |
998 private: | 1070 private: |
| 1071 |
| 1072 inline const Coverage &get_coverage (void) const |
| 1073 { |
| 1074 switch (u.format) { |
| 1075 case 1: return u.format1.get_coverage (); |
| 1076 default:return Null(Coverage); |
| 1077 } |
| 1078 } |
| 1079 |
999 inline bool apply (hb_apply_context_t *c) const | 1080 inline bool apply (hb_apply_context_t *c) const |
1000 { | 1081 { |
1001 TRACE_APPLY (); | 1082 TRACE_APPLY (); |
1002 switch (u.format) { | 1083 switch (u.format) { |
1003 case 1: return TRACE_RETURN (u.format1.apply (c)); | 1084 case 1: return TRACE_RETURN (u.format1.apply (c)); |
1004 default:return TRACE_RETURN (false); | 1085 default:return TRACE_RETURN (false); |
1005 } | 1086 } |
1006 } | 1087 } |
1007 | 1088 |
1008 inline bool sanitize (hb_sanitize_context_t *c) { | 1089 inline bool sanitize (hb_sanitize_context_t *c) { |
1009 TRACE_SANITIZE (); | 1090 TRACE_SANITIZE (); |
1010 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 1091 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
1011 switch (u.format) { | 1092 switch (u.format) { |
1012 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 1093 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
1013 default:return TRACE_RETURN (true); | 1094 default:return TRACE_RETURN (true); |
1014 } | 1095 } |
1015 } | 1096 } |
1016 | 1097 |
1017 private: | 1098 protected: |
1018 union { | 1099 union { |
1019 USHORT format; /* Format identifier */ | 1100 USHORT format; /* Format identifier */ |
1020 MarkBasePosFormat1 format1; | 1101 MarkBasePosFormat1 format1; |
1021 } u; | 1102 } u; |
1022 }; | 1103 }; |
1023 | 1104 |
1024 | 1105 |
1025 typedef AnchorMatrix LigatureAttach; /* component-major-- | 1106 typedef AnchorMatrix LigatureAttach; /* component-major-- |
1026 * in order of writing direction--, | 1107 * in order of writing direction--, |
1027 * mark-minor-- | 1108 * mark-minor-- |
1028 * ordered by class--zero-based. */ | 1109 * ordered by class--zero-based. */ |
1029 | 1110 |
1030 typedef OffsetListOf<LigatureAttach> LigatureArray; | 1111 typedef OffsetListOf<LigatureAttach> LigatureArray; |
1031 /* Array of LigatureAttach | 1112 /* Array of LigatureAttach |
1032 * tables ordered by | 1113 * tables ordered by |
1033 * LigatureCoverage Index */ | 1114 * LigatureCoverage Index */ |
1034 | 1115 |
1035 struct MarkLigPosFormat1 | 1116 struct MarkLigPosFormat1 |
1036 { | 1117 { |
1037 friend struct MarkLigPos; | 1118 friend struct MarkLigPos; |
1038 | 1119 |
1039 private: | 1120 private: |
| 1121 |
| 1122 inline const Coverage &get_coverage (void) const |
| 1123 { |
| 1124 return this+markCoverage; |
| 1125 } |
| 1126 |
1040 inline bool apply (hb_apply_context_t *c) const | 1127 inline bool apply (hb_apply_context_t *c) const |
1041 { | 1128 { |
1042 TRACE_APPLY (); | 1129 TRACE_APPLY (); |
1043 unsigned int mark_index = (this+markCoverage) (c->buffer->cur().codepoint); | 1130 unsigned int mark_index = (this+markCoverage) (c->buffer->cur().codepoint); |
1044 if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); | 1131 if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); |
1045 | 1132 |
1046 /* now we search backwards for a non-mark glyph */ | 1133 /* now we search backwards for a non-mark glyph */ |
1047 unsigned int property; | 1134 unsigned int property; |
1048 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buf
fer->idx, 1); | 1135 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buf
fer->idx, 1); |
1049 if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_RET
URN (false); | 1136 if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_RET
URN (false); |
1050 | 1137 |
1051 /* The following assertion is too strong, so we've disabled it. */ | 1138 /* The following assertion is too strong, so we've disabled it. */ |
1052 if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE)) {/*return TRACE_RETURN
(false);*/} | 1139 if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE)) {/*return TRACE_RETURN
(false);*/} |
1053 | 1140 |
1054 unsigned int j = skippy_iter.idx; | 1141 unsigned int j = skippy_iter.idx; |
1055 unsigned int lig_index = (this+ligatureCoverage) (c->buffer->info[j].codepoi
nt); | 1142 unsigned int lig_index = (this+ligatureCoverage) (c->buffer->info[j].codepoi
nt); |
1056 if (lig_index == NOT_COVERED) return TRACE_RETURN (false); | 1143 if (lig_index == NOT_COVERED) return TRACE_RETURN (false); |
1057 | 1144 |
1058 const LigatureArray& lig_array = this+ligatureArray; | 1145 const LigatureArray& lig_array = this+ligatureArray; |
1059 const LigatureAttach& lig_attach = lig_array[lig_index]; | 1146 const LigatureAttach& lig_attach = lig_array[lig_index]; |
1060 | 1147 |
1061 /* Find component to attach to */ | 1148 /* Find component to attach to */ |
1062 unsigned int comp_count = lig_attach.rows; | 1149 unsigned int comp_count = lig_attach.rows; |
1063 if (unlikely (!comp_count)) return TRACE_RETURN (false); | 1150 if (unlikely (!comp_count)) return TRACE_RETURN (false); |
1064 | 1151 |
1065 unsigned int comp_index; | |
1066 /* We must now check whether the ligature ID of the current mark glyph | 1152 /* We must now check whether the ligature ID of the current mark glyph |
1067 * is identical to the ligature ID of the found ligature. If yes, we | 1153 * is identical to the ligature ID of the found ligature. If yes, we |
1068 * can directly use the component index. If not, we attach the mark | 1154 * can directly use the component index. If not, we attach the mark |
1069 * glyph to the last component of the ligature. */ | 1155 * glyph to the last component of the ligature. */ |
1070 if (get_lig_id (c->buffer->info[j]) && | 1156 unsigned int comp_index; |
1071 » get_lig_id (c->buffer->cur()) && | 1157 unsigned int lig_id = get_lig_id (c->buffer->info[j]); |
1072 » get_lig_comp (c->buffer->cur()) > 0) | 1158 unsigned int mark_id = get_lig_id (c->buffer->cur()); |
1073 { | 1159 unsigned int mark_comp = get_lig_comp (c->buffer->cur()); |
1074 comp_index = get_lig_comp (c->buffer->cur()) - 1; | 1160 if (lig_id && lig_id == mark_id && mark_comp > 0) |
1075 if (comp_index >= comp_count) | 1161 comp_index = MIN (comp_count, get_lig_comp (c->buffer->cur())) - 1; |
1076 » comp_index = comp_count - 1; | |
1077 } | |
1078 else | 1162 else |
1079 comp_index = comp_count - 1; | 1163 comp_index = comp_count - 1; |
1080 | 1164 |
1081 return TRACE_RETURN ((this+markArray).apply (c, mark_index, comp_index, lig_
attach, classCount, j)); | 1165 return TRACE_RETURN ((this+markArray).apply (c, mark_index, comp_index, lig_
attach, classCount, j)); |
1082 } | 1166 } |
1083 | 1167 |
1084 inline bool sanitize (hb_sanitize_context_t *c) { | 1168 inline bool sanitize (hb_sanitize_context_t *c) { |
1085 TRACE_SANITIZE (); | 1169 TRACE_SANITIZE (); |
1086 return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, thi
s) && ligatureCoverage.sanitize (c, this) && | 1170 return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, thi
s) && ligatureCoverage.sanitize (c, this) && |
1087 markArray.sanitize (c, this) && ligatureArray.sanitize
(c, this, (unsigned int) classCount)); | 1171 markArray.sanitize (c, this) && ligatureArray.sanitize
(c, this, (unsigned int) classCount)); |
1088 } | 1172 } |
1089 | 1173 |
1090 private: | 1174 protected: |
1091 USHORT format; /* Format identifier--format = 1 */ | 1175 USHORT format; /* Format identifier--format = 1 */ |
1092 OffsetTo<Coverage> | 1176 OffsetTo<Coverage> |
1093 markCoverage; /* Offset to Mark Coverage table--from | 1177 markCoverage; /* Offset to Mark Coverage table--from |
1094 * beginning of MarkLigPos subtable */ | 1178 * beginning of MarkLigPos subtable */ |
1095 OffsetTo<Coverage> | 1179 OffsetTo<Coverage> |
1096 ligatureCoverage; /* Offset to Ligature Coverage | 1180 ligatureCoverage; /* Offset to Ligature Coverage |
1097 * table--from beginning of MarkLigPos | 1181 * table--from beginning of MarkLigPos |
1098 * subtable */ | 1182 * subtable */ |
1099 USHORT classCount; /* Number of defined mark classes */ | 1183 USHORT classCount; /* Number of defined mark classes */ |
1100 OffsetTo<MarkArray> | 1184 OffsetTo<MarkArray> |
1101 markArray; /* Offset to MarkArray table--from | 1185 markArray; /* Offset to MarkArray table--from |
1102 * beginning of MarkLigPos subtable */ | 1186 * beginning of MarkLigPos subtable */ |
1103 OffsetTo<LigatureArray> | 1187 OffsetTo<LigatureArray> |
1104 ligatureArray; /* Offset to LigatureArray table--from | 1188 ligatureArray; /* Offset to LigatureArray table--from |
1105 * beginning of MarkLigPos subtable */ | 1189 * beginning of MarkLigPos subtable */ |
1106 public: | 1190 public: |
1107 DEFINE_SIZE_STATIC (12); | 1191 DEFINE_SIZE_STATIC (12); |
1108 }; | 1192 }; |
1109 | 1193 |
1110 struct MarkLigPos | 1194 struct MarkLigPos |
1111 { | 1195 { |
1112 friend struct PosLookupSubTable; | 1196 friend struct PosLookupSubTable; |
1113 | 1197 |
1114 private: | 1198 private: |
| 1199 |
| 1200 inline const Coverage &get_coverage (void) const |
| 1201 { |
| 1202 switch (u.format) { |
| 1203 case 1: return u.format1.get_coverage (); |
| 1204 default:return Null(Coverage); |
| 1205 } |
| 1206 } |
| 1207 |
1115 inline bool apply (hb_apply_context_t *c) const | 1208 inline bool apply (hb_apply_context_t *c) const |
1116 { | 1209 { |
1117 TRACE_APPLY (); | 1210 TRACE_APPLY (); |
1118 switch (u.format) { | 1211 switch (u.format) { |
1119 case 1: return TRACE_RETURN (u.format1.apply (c)); | 1212 case 1: return TRACE_RETURN (u.format1.apply (c)); |
1120 default:return TRACE_RETURN (false); | 1213 default:return TRACE_RETURN (false); |
1121 } | 1214 } |
1122 } | 1215 } |
1123 | 1216 |
1124 inline bool sanitize (hb_sanitize_context_t *c) { | 1217 inline bool sanitize (hb_sanitize_context_t *c) { |
1125 TRACE_SANITIZE (); | 1218 TRACE_SANITIZE (); |
1126 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 1219 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
1127 switch (u.format) { | 1220 switch (u.format) { |
1128 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 1221 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
1129 default:return TRACE_RETURN (true); | 1222 default:return TRACE_RETURN (true); |
1130 } | 1223 } |
1131 } | 1224 } |
1132 | 1225 |
1133 private: | 1226 protected: |
1134 union { | 1227 union { |
1135 USHORT format; /* Format identifier */ | 1228 USHORT format; /* Format identifier */ |
1136 MarkLigPosFormat1 format1; | 1229 MarkLigPosFormat1 format1; |
1137 } u; | 1230 } u; |
1138 }; | 1231 }; |
1139 | 1232 |
1140 | 1233 |
1141 typedef AnchorMatrix Mark2Array; /* mark2-major-- | 1234 typedef AnchorMatrix Mark2Array; /* mark2-major-- |
1142 * in order of Mark2Coverage Index--, | 1235 * in order of Mark2Coverage Index--, |
1143 * mark1-minor-- | 1236 * mark1-minor-- |
1144 * ordered by class--zero-based. */ | 1237 * ordered by class--zero-based. */ |
1145 | 1238 |
1146 struct MarkMarkPosFormat1 | 1239 struct MarkMarkPosFormat1 |
1147 { | 1240 { |
1148 friend struct MarkMarkPos; | 1241 friend struct MarkMarkPos; |
1149 | 1242 |
1150 private: | 1243 private: |
| 1244 |
| 1245 inline const Coverage &get_coverage (void) const |
| 1246 { |
| 1247 return this+mark1Coverage; |
| 1248 } |
| 1249 |
1151 inline bool apply (hb_apply_context_t *c) const | 1250 inline bool apply (hb_apply_context_t *c) const |
1152 { | 1251 { |
1153 TRACE_APPLY (); | 1252 TRACE_APPLY (); |
1154 unsigned int mark1_index = (this+mark1Coverage) (c->buffer->cur().codepoint)
; | 1253 unsigned int mark1_index = (this+mark1Coverage) (c->buffer->cur().codepoint)
; |
1155 if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false); | 1254 if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false); |
1156 | 1255 |
1157 /* now we search backwards for a suitable mark glyph until a non-mark glyph
*/ | 1256 /* now we search backwards for a suitable mark glyph until a non-mark glyph
*/ |
1158 unsigned int property; | 1257 unsigned int property; |
1159 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buf
fer->idx, 1); | 1258 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buf
fer->idx, 1); |
1160 if (!skippy_iter.prev (&property)) return TRACE_RETURN (false); | 1259 if (!skippy_iter.prev (&property)) return TRACE_RETURN (false); |
1161 | 1260 |
1162 if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)) return TRACE_RETURN (false)
; | 1261 if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)) return TRACE_RETURN (false)
; |
1163 | 1262 |
1164 unsigned int j = skippy_iter.idx; | 1263 unsigned int j = skippy_iter.idx; |
1165 | 1264 |
1166 /* Two marks match only if they belong to the same base, or same component | 1265 unsigned int id1 = get_lig_id (c->buffer->cur()); |
1167 * of the same ligature. That is, the component numbers must match, and | 1266 unsigned int id2 = get_lig_id (c->buffer->info[j]); |
1168 * if those are non-zero, the ligid number should also match. */ | 1267 unsigned int comp1 = get_lig_comp (c->buffer->cur()); |
1169 if ((get_lig_comp (c->buffer->cur())) || | 1268 unsigned int comp2 = get_lig_comp (c->buffer->info[j]); |
1170 » (get_lig_comp (c->buffer->info[j]) > 0 && | |
1171 » get_lig_id (c->buffer->cur()))) | |
1172 return TRACE_RETURN (false); | |
1173 | 1269 |
| 1270 if (likely (id1 == id2)) { |
| 1271 if (id1 == 0) /* Marks belonging to the same base. */ |
| 1272 goto good; |
| 1273 else if (comp1 == comp2) /* Marks belonging to the same ligature component
. */ |
| 1274 goto good; |
| 1275 } else { |
| 1276 /* If ligature ids don't match, it may be the case that one of the marks |
| 1277 * itself is a ligature. In which case match. */ |
| 1278 if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2)) |
| 1279 goto good; |
| 1280 } |
| 1281 |
| 1282 /* Didn't match. */ |
| 1283 return TRACE_RETURN (false); |
| 1284 |
| 1285 good: |
1174 unsigned int mark2_index = (this+mark2Coverage) (c->buffer->info[j].codepoin
t); | 1286 unsigned int mark2_index = (this+mark2Coverage) (c->buffer->info[j].codepoin
t); |
1175 if (mark2_index == NOT_COVERED) return TRACE_RETURN (false); | 1287 if (mark2_index == NOT_COVERED) return TRACE_RETURN (false); |
1176 | 1288 |
1177 return TRACE_RETURN ((this+mark1Array).apply (c, mark1_index, mark2_index, t
his+mark2Array, classCount, j)); | 1289 return TRACE_RETURN ((this+mark1Array).apply (c, mark1_index, mark2_index, t
his+mark2Array, classCount, j)); |
1178 } | 1290 } |
1179 | 1291 |
1180 inline bool sanitize (hb_sanitize_context_t *c) { | 1292 inline bool sanitize (hb_sanitize_context_t *c) { |
1181 TRACE_SANITIZE (); | 1293 TRACE_SANITIZE (); |
1182 return TRACE_RETURN (c->check_struct (this) && mark1Coverage.sanitize (c, th
is) && | 1294 return TRACE_RETURN (c->check_struct (this) && mark1Coverage.sanitize (c, th
is) && |
1183 mark2Coverage.sanitize (c, this) && mark1Array.sanitize
(c, this) | 1295 mark2Coverage.sanitize (c, this) && mark1Array.sanitize
(c, this) |
1184 && mark2Array.sanitize (c, this, (unsigned int) classCo
unt)); | 1296 && mark2Array.sanitize (c, this, (unsigned int) classCo
unt)); |
1185 } | 1297 } |
1186 | 1298 |
1187 private: | 1299 protected: |
1188 USHORT format; /* Format identifier--format = 1 */ | 1300 USHORT format; /* Format identifier--format = 1 */ |
1189 OffsetTo<Coverage> | 1301 OffsetTo<Coverage> |
1190 mark1Coverage; /* Offset to Combining Mark1 Coverage | 1302 mark1Coverage; /* Offset to Combining Mark1 Coverage |
1191 * table--from beginning of MarkMarkPos | 1303 * table--from beginning of MarkMarkPos |
1192 * subtable */ | 1304 * subtable */ |
1193 OffsetTo<Coverage> | 1305 OffsetTo<Coverage> |
1194 mark2Coverage; /* Offset to Combining Mark2 Coverage | 1306 mark2Coverage; /* Offset to Combining Mark2 Coverage |
1195 * table--from beginning of MarkMarkPos | 1307 * table--from beginning of MarkMarkPos |
1196 * subtable */ | 1308 * subtable */ |
1197 USHORT classCount; /* Number of defined mark classes */ | 1309 USHORT classCount; /* Number of defined mark classes */ |
1198 OffsetTo<MarkArray> | 1310 OffsetTo<MarkArray> |
1199 mark1Array; /* Offset to Mark1Array table--from | 1311 mark1Array; /* Offset to Mark1Array table--from |
1200 * beginning of MarkMarkPos subtable */ | 1312 * beginning of MarkMarkPos subtable */ |
1201 OffsetTo<Mark2Array> | 1313 OffsetTo<Mark2Array> |
1202 mark2Array; /* Offset to Mark2Array table--from | 1314 mark2Array; /* Offset to Mark2Array table--from |
1203 * beginning of MarkMarkPos subtable */ | 1315 * beginning of MarkMarkPos subtable */ |
1204 public: | 1316 public: |
1205 DEFINE_SIZE_STATIC (12); | 1317 DEFINE_SIZE_STATIC (12); |
1206 }; | 1318 }; |
1207 | 1319 |
1208 struct MarkMarkPos | 1320 struct MarkMarkPos |
1209 { | 1321 { |
1210 friend struct PosLookupSubTable; | 1322 friend struct PosLookupSubTable; |
1211 | 1323 |
1212 private: | 1324 private: |
| 1325 |
| 1326 inline const Coverage &get_coverage (void) const |
| 1327 { |
| 1328 switch (u.format) { |
| 1329 case 1: return u.format1.get_coverage (); |
| 1330 default:return Null(Coverage); |
| 1331 } |
| 1332 } |
| 1333 |
1213 inline bool apply (hb_apply_context_t *c) const | 1334 inline bool apply (hb_apply_context_t *c) const |
1214 { | 1335 { |
1215 TRACE_APPLY (); | 1336 TRACE_APPLY (); |
1216 switch (u.format) { | 1337 switch (u.format) { |
1217 case 1: return TRACE_RETURN (u.format1.apply (c)); | 1338 case 1: return TRACE_RETURN (u.format1.apply (c)); |
1218 default:return TRACE_RETURN (false); | 1339 default:return TRACE_RETURN (false); |
1219 } | 1340 } |
1220 } | 1341 } |
1221 | 1342 |
1222 inline bool sanitize (hb_sanitize_context_t *c) { | 1343 inline bool sanitize (hb_sanitize_context_t *c) { |
1223 TRACE_SANITIZE (); | 1344 TRACE_SANITIZE (); |
1224 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 1345 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
1225 switch (u.format) { | 1346 switch (u.format) { |
1226 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 1347 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
1227 default:return TRACE_RETURN (true); | 1348 default:return TRACE_RETURN (true); |
1228 } | 1349 } |
1229 } | 1350 } |
1230 | 1351 |
1231 private: | 1352 protected: |
1232 union { | 1353 union { |
1233 USHORT format; /* Format identifier */ | 1354 USHORT format; /* Format identifier */ |
1234 MarkMarkPosFormat1 format1; | 1355 MarkMarkPosFormat1 format1; |
1235 } u; | 1356 } u; |
1236 }; | 1357 }; |
1237 | 1358 |
1238 | 1359 |
1239 static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
ndex); | 1360 static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
ndex); |
1240 | 1361 |
1241 struct ContextPos : Context | 1362 struct ContextPos : Context |
(...skipping 26 matching lines...) Expand all Loading... |
1268 friend struct PosLookupSubTable; | 1389 friend struct PosLookupSubTable; |
1269 | 1390 |
1270 private: | 1391 private: |
1271 inline const struct PosLookupSubTable& get_subtable (void) const | 1392 inline const struct PosLookupSubTable& get_subtable (void) const |
1272 { | 1393 { |
1273 unsigned int offset = get_offset (); | 1394 unsigned int offset = get_offset (); |
1274 if (unlikely (!offset)) return Null(PosLookupSubTable); | 1395 if (unlikely (!offset)) return Null(PosLookupSubTable); |
1275 return StructAtOffset<PosLookupSubTable> (this, offset); | 1396 return StructAtOffset<PosLookupSubTable> (this, offset); |
1276 } | 1397 } |
1277 | 1398 |
| 1399 inline const Coverage &get_coverage (void) const; |
| 1400 |
1278 inline bool apply (hb_apply_context_t *c) const; | 1401 inline bool apply (hb_apply_context_t *c) const; |
1279 | 1402 |
1280 inline bool sanitize (hb_sanitize_context_t *c); | 1403 inline bool sanitize (hb_sanitize_context_t *c); |
1281 }; | 1404 }; |
1282 | 1405 |
1283 | 1406 |
1284 | 1407 |
1285 /* | 1408 /* |
1286 * PosLookup | 1409 * PosLookup |
1287 */ | 1410 */ |
1288 | 1411 |
1289 | 1412 |
1290 struct PosLookupSubTable | 1413 struct PosLookupSubTable |
1291 { | 1414 { |
1292 friend struct PosLookup; | 1415 friend struct PosLookup; |
1293 | 1416 |
1294 enum Type { | 1417 enum Type { |
1295 Single = 1, | 1418 Single = 1, |
1296 Pair = 2, | 1419 Pair = 2, |
1297 Cursive = 3, | 1420 Cursive = 3, |
1298 MarkBase = 4, | 1421 MarkBase = 4, |
1299 MarkLig = 5, | 1422 MarkLig = 5, |
1300 MarkMark = 6, | 1423 MarkMark = 6, |
1301 Context = 7, | 1424 Context = 7, |
1302 ChainContext = 8, | 1425 ChainContext = 8, |
1303 Extension = 9 | 1426 Extension = 9 |
1304 }; | 1427 }; |
1305 | 1428 |
| 1429 inline const Coverage &get_coverage (unsigned int lookup_type) const |
| 1430 { |
| 1431 switch (lookup_type) { |
| 1432 case Single: return u.single.get_coverage (); |
| 1433 case Pair: return u.pair.get_coverage (); |
| 1434 case Cursive: return u.cursive.get_coverage (); |
| 1435 case MarkBase: return u.markBase.get_coverage (); |
| 1436 case MarkLig: return u.markLig.get_coverage (); |
| 1437 case MarkMark: return u.markMark.get_coverage (); |
| 1438 case Context: return u.context.get_coverage (); |
| 1439 case ChainContext: return u.chainContext.get_coverage (); |
| 1440 case Extension: return u.extension.get_coverage (); |
| 1441 default: return Null(Coverage); |
| 1442 } |
| 1443 } |
| 1444 |
1306 inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const | 1445 inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const |
1307 { | 1446 { |
1308 TRACE_APPLY (); | 1447 TRACE_APPLY (); |
1309 switch (lookup_type) { | 1448 switch (lookup_type) { |
1310 case Single: return TRACE_RETURN (u.single.apply (c)); | 1449 case Single: return TRACE_RETURN (u.single.apply (c)); |
1311 case Pair: return TRACE_RETURN (u.pair.apply (c)); | 1450 case Pair: return TRACE_RETURN (u.pair.apply (c)); |
1312 case Cursive: return TRACE_RETURN (u.cursive.apply (c)); | 1451 case Cursive: return TRACE_RETURN (u.cursive.apply (c)); |
1313 case MarkBase: return TRACE_RETURN (u.markBase.apply (c)); | 1452 case MarkBase: return TRACE_RETURN (u.markBase.apply (c)); |
1314 case MarkLig: return TRACE_RETURN (u.markLig.apply (c)); | 1453 case MarkLig: return TRACE_RETURN (u.markLig.apply (c)); |
1315 case MarkMark: return TRACE_RETURN (u.markMark.apply (c)); | 1454 case MarkMark: return TRACE_RETURN (u.markMark.apply (c)); |
1316 case Context:» » return TRACE_RETURN (u.c.apply (c)); | 1455 case Context:» » return TRACE_RETURN (u.context.apply (c)); |
1317 case ChainContext: return TRACE_RETURN (u.chainContext.apply (c)); | 1456 case ChainContext: return TRACE_RETURN (u.chainContext.apply (c)); |
1318 case Extension: return TRACE_RETURN (u.extension.apply (c)); | 1457 case Extension: return TRACE_RETURN (u.extension.apply (c)); |
1319 default: return TRACE_RETURN (false); | 1458 default: return TRACE_RETURN (false); |
1320 } | 1459 } |
1321 } | 1460 } |
1322 | 1461 |
1323 inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) { | 1462 inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) { |
1324 TRACE_SANITIZE (); | 1463 TRACE_SANITIZE (); |
| 1464 if (!u.header.sub_format.sanitize (c)) |
| 1465 return TRACE_RETURN (false); |
1325 switch (lookup_type) { | 1466 switch (lookup_type) { |
1326 case Single: return TRACE_RETURN (u.single.sanitize (c)); | 1467 case Single: return TRACE_RETURN (u.single.sanitize (c)); |
1327 case Pair: return TRACE_RETURN (u.pair.sanitize (c)); | 1468 case Pair: return TRACE_RETURN (u.pair.sanitize (c)); |
1328 case Cursive: return TRACE_RETURN (u.cursive.sanitize (c)); | 1469 case Cursive: return TRACE_RETURN (u.cursive.sanitize (c)); |
1329 case MarkBase: return TRACE_RETURN (u.markBase.sanitize (c)); | 1470 case MarkBase: return TRACE_RETURN (u.markBase.sanitize (c)); |
1330 case MarkLig: return TRACE_RETURN (u.markLig.sanitize (c)); | 1471 case MarkLig: return TRACE_RETURN (u.markLig.sanitize (c)); |
1331 case MarkMark: return TRACE_RETURN (u.markMark.sanitize (c)); | 1472 case MarkMark: return TRACE_RETURN (u.markMark.sanitize (c)); |
1332 case Context:» » return TRACE_RETURN (u.c.sanitize (c)); | 1473 case Context:» » return TRACE_RETURN (u.context.sanitize (c)); |
1333 case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c)
); | 1474 case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c)
); |
1334 case Extension: return TRACE_RETURN (u.extension.sanitize (c)); | 1475 case Extension: return TRACE_RETURN (u.extension.sanitize (c)); |
1335 default: return TRACE_RETURN (true); | 1476 default: return TRACE_RETURN (true); |
1336 } | 1477 } |
1337 } | 1478 } |
1338 | 1479 |
1339 private: | 1480 protected: |
1340 union { | 1481 union { |
1341 USHORT» » sub_format; | 1482 struct { |
| 1483 USHORT» » » sub_format; |
| 1484 } header; |
1342 SinglePos single; | 1485 SinglePos single; |
1343 PairPos pair; | 1486 PairPos pair; |
1344 CursivePos cursive; | 1487 CursivePos cursive; |
1345 MarkBasePos markBase; | 1488 MarkBasePos markBase; |
1346 MarkLigPos markLig; | 1489 MarkLigPos markLig; |
1347 MarkMarkPos markMark; | 1490 MarkMarkPos markMark; |
1348 ContextPos» » c; | 1491 ContextPos» » context; |
1349 ChainContextPos chainContext; | 1492 ChainContextPos chainContext; |
1350 ExtensionPos extension; | 1493 ExtensionPos extension; |
1351 } u; | 1494 } u; |
1352 public: | 1495 public: |
1353 DEFINE_SIZE_UNION (2, sub_format); | 1496 DEFINE_SIZE_UNION (2, header.sub_format); |
1354 }; | 1497 }; |
1355 | 1498 |
1356 | 1499 |
1357 struct PosLookup : Lookup | 1500 struct PosLookup : Lookup |
1358 { | 1501 { |
1359 inline const PosLookupSubTable& get_subtable (unsigned int i) const | 1502 inline const PosLookupSubTable& get_subtable (unsigned int i) const |
1360 { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; } | 1503 { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; } |
1361 | 1504 |
| 1505 template <typename set_t> |
| 1506 inline void add_coverage (set_t *glyphs) const |
| 1507 { |
| 1508 const Coverage *last = NULL; |
| 1509 unsigned int count = get_subtable_count (); |
| 1510 for (unsigned int i = 0; i < count; i++) { |
| 1511 const Coverage *c = &get_subtable (i).get_coverage (get_type ()); |
| 1512 if (c != last) { |
| 1513 c->add_coverage (glyphs); |
| 1514 last = c; |
| 1515 } |
| 1516 } |
| 1517 } |
| 1518 |
1362 inline bool apply_once (hb_apply_context_t *c) const | 1519 inline bool apply_once (hb_apply_context_t *c) const |
1363 { | 1520 { |
1364 unsigned int lookup_type = get_type (); | 1521 unsigned int lookup_type = get_type (); |
1365 | 1522 |
1366 if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->cur(), c->look
up_props, &c->property)) | 1523 if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props, &c->proper
ty)) |
1367 return false; | 1524 return false; |
1368 | 1525 |
1369 for (unsigned int i = 0; i < get_subtable_count (); i++) | 1526 unsigned int count = get_subtable_count (); |
| 1527 for (unsigned int i = 0; i < count; i++) |
1370 if (get_subtable (i).apply (c, lookup_type)) | 1528 if (get_subtable (i).apply (c, lookup_type)) |
1371 return true; | 1529 return true; |
1372 | 1530 |
1373 return false; | 1531 return false; |
1374 } | 1532 } |
1375 | 1533 |
1376 inline bool apply_string (hb_apply_context_t *c) const | 1534 inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest
) const |
1377 { | 1535 { |
1378 bool ret = false; | 1536 bool ret = false; |
1379 | 1537 |
1380 if (unlikely (!c->buffer->len)) | 1538 if (unlikely (!c->buffer->len || !c->lookup_mask)) |
1381 return false; | 1539 return false; |
1382 | 1540 |
1383 c->set_lookup (*this); | 1541 c->set_lookup (*this); |
1384 | 1542 |
1385 c->buffer->idx = 0; | 1543 c->buffer->idx = 0; |
| 1544 |
1386 while (c->buffer->idx < c->buffer->len) | 1545 while (c->buffer->idx < c->buffer->len) |
1387 { | 1546 { |
1388 if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c)) | 1547 if ((c->buffer->cur().mask & c->lookup_mask) && |
| 1548 » digest->may_have (c->buffer->cur().codepoint) && |
| 1549 » apply_once (c)) |
1389 ret = true; | 1550 ret = true; |
1390 else | 1551 else |
1391 c->buffer->idx++; | 1552 c->buffer->idx++; |
1392 } | 1553 } |
1393 | 1554 |
1394 return ret; | 1555 return ret; |
1395 } | 1556 } |
1396 | 1557 |
1397 inline bool sanitize (hb_sanitize_context_t *c) { | 1558 inline bool sanitize (hb_sanitize_context_t *c) { |
1398 TRACE_SANITIZE (); | 1559 TRACE_SANITIZE (); |
1399 if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); | 1560 if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); |
1400 OffsetArrayOf<PosLookupSubTable> &list = CastR<OffsetArrayOf<PosLookupSubTab
le> > (subTable); | 1561 OffsetArrayOf<PosLookupSubTable> &list = CastR<OffsetArrayOf<PosLookupSubTab
le> > (subTable); |
1401 return TRACE_RETURN (list.sanitize (c, this, get_type ())); | 1562 return TRACE_RETURN (list.sanitize (c, this, get_type ())); |
1402 } | 1563 } |
1403 }; | 1564 }; |
1404 | 1565 |
1405 typedef OffsetListOf<PosLookup> PosLookupList; | 1566 typedef OffsetListOf<PosLookup> PosLookupList; |
1406 | 1567 |
1407 /* | 1568 /* |
1408 * GPOS -- The Glyph Positioning Table | 1569 * GPOS -- The Glyph Positioning Table |
1409 */ | 1570 */ |
1410 | 1571 |
1411 struct GPOS : GSUBGPOS | 1572 struct GPOS : GSUBGPOS |
1412 { | 1573 { |
1413 static const hb_tag_t Tag = HB_OT_TAG_GPOS; | 1574 static const hb_tag_t Tag = HB_OT_TAG_GPOS; |
1414 | 1575 |
1415 inline const PosLookup& get_lookup (unsigned int i) const | 1576 inline const PosLookup& get_lookup (unsigned int i) const |
1416 { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); } | 1577 { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); } |
1417 | 1578 |
1418 inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index)
const | 1579 template <typename set_t> |
1419 { return get_lookup (lookup_index).apply_string (c); } | 1580 inline void add_coverage (set_t *glyphs, unsigned int lookup_index) const |
| 1581 { get_lookup (lookup_index).add_coverage (glyphs); } |
1420 | 1582 |
1421 static inline void position_start (hb_buffer_t *buffer); | 1583 static inline void position_start (hb_font_t *font, hb_buffer_t *buffer); |
1422 static inline void position_finish (hb_buffer_t *buffer); | 1584 static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer, hb_b
ool_t zero_width_attahced_marks); |
1423 | 1585 |
1424 inline bool sanitize (hb_sanitize_context_t *c) { | 1586 inline bool sanitize (hb_sanitize_context_t *c) { |
1425 TRACE_SANITIZE (); | 1587 TRACE_SANITIZE (); |
1426 if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false); | 1588 if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false); |
1427 OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList)
; | 1589 OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList)
; |
1428 return TRACE_RETURN (list.sanitize (c, this)); | 1590 return TRACE_RETURN (list.sanitize (c, this)); |
1429 } | 1591 } |
1430 public: | 1592 public: |
1431 DEFINE_SIZE_STATIC (10); | 1593 DEFINE_SIZE_STATIC (10); |
1432 }; | 1594 }; |
1433 | 1595 |
1434 | 1596 |
1435 static void | 1597 static void |
1436 fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction
_t direction) | 1598 fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction
_t direction) |
1437 { | 1599 { |
1438 unsigned int j = pos[i].cursive_chain(); | 1600 unsigned int j = pos[i].cursive_chain(); |
1439 if (likely (!j)) | 1601 if (likely (!j)) |
1440 return; | 1602 return; |
1441 | 1603 |
1442 j += i; | 1604 j += i; |
1443 | 1605 |
1444 pos[i].cursive_chain() = 0; | 1606 pos[i].cursive_chain() = 0; |
1445 | 1607 |
1446 fix_cursive_minor_offset (pos, j, direction); | 1608 fix_cursive_minor_offset (pos, j, direction); |
1447 | 1609 |
1448 if (HB_DIRECTION_IS_HORIZONTAL (direction)) | 1610 if (HB_DIRECTION_IS_HORIZONTAL (direction)) |
1449 pos[i].y_offset += pos[j].y_offset; | 1611 pos[i].y_offset += pos[j].y_offset; |
1450 else | 1612 else |
1451 pos[i].x_offset += pos[j].x_offset; | 1613 pos[i].x_offset += pos[j].x_offset; |
1452 } | 1614 } |
1453 | 1615 |
1454 static void | 1616 static void |
1455 fix_mark_attachment (hb_glyph_position_t *pos, unsigned int i, hb_direction_t di
rection) | 1617 fix_mark_attachment (hb_glyph_position_t *pos, unsigned int i, hb_direction_t di
rection, hb_bool_t zero_width_attached_marks) |
1456 { | 1618 { |
1457 if (likely (!(pos[i].attach_lookback()))) | 1619 if (likely (!(pos[i].attach_lookback()))) |
1458 return; | 1620 return; |
1459 | 1621 |
1460 unsigned int j = i - pos[i].attach_lookback(); | 1622 unsigned int j = i - pos[i].attach_lookback(); |
1461 | 1623 |
1462 pos[i].x_advance = 0; | 1624 if (zero_width_attached_marks) { |
1463 pos[i].y_advance = 0; | 1625 pos[i].x_advance = 0; |
| 1626 pos[i].y_advance = 0; |
| 1627 } |
1464 pos[i].x_offset += pos[j].x_offset; | 1628 pos[i].x_offset += pos[j].x_offset; |
1465 pos[i].y_offset += pos[j].y_offset; | 1629 pos[i].y_offset += pos[j].y_offset; |
1466 | 1630 |
1467 if (HB_DIRECTION_IS_FORWARD (direction)) | 1631 if (HB_DIRECTION_IS_FORWARD (direction)) |
1468 for (unsigned int k = j; k < i; k++) { | 1632 for (unsigned int k = j; k < i; k++) { |
1469 pos[i].x_offset -= pos[k].x_advance; | 1633 pos[i].x_offset -= pos[k].x_advance; |
1470 pos[i].y_offset -= pos[k].y_advance; | 1634 pos[i].y_offset -= pos[k].y_advance; |
1471 } | 1635 } |
1472 else | 1636 else |
1473 for (unsigned int k = j + 1; k < i + 1; k++) { | 1637 for (unsigned int k = j + 1; k < i + 1; k++) { |
1474 pos[i].x_offset += pos[k].x_advance; | 1638 pos[i].x_offset += pos[k].x_advance; |
1475 pos[i].y_offset += pos[k].y_advance; | 1639 pos[i].y_offset += pos[k].y_advance; |
1476 } | 1640 } |
1477 } | 1641 } |
1478 | 1642 |
1479 void | 1643 void |
1480 GPOS::position_start (hb_buffer_t *buffer) | 1644 GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) |
1481 { | 1645 { |
1482 buffer->clear_positions (); | 1646 buffer->clear_positions (); |
1483 | 1647 |
1484 unsigned int count = buffer->len; | 1648 unsigned int count = buffer->len; |
1485 for (unsigned int i = 0; i < count; i++) | 1649 for (unsigned int i = 0; i < count; i++) |
1486 buffer->pos[i].attach_lookback() = buffer->pos[i].cursive_chain() = 0; | 1650 buffer->pos[i].attach_lookback() = buffer->pos[i].cursive_chain() = 0; |
1487 } | 1651 } |
1488 | 1652 |
1489 void | 1653 void |
1490 GPOS::position_finish (hb_buffer_t *buffer) | 1654 GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer, hb_bool_t
zero_width_attached_marks) |
1491 { | 1655 { |
1492 unsigned int len; | 1656 unsigned int len; |
1493 hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len); | 1657 hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len); |
1494 hb_direction_t direction = buffer->props.direction; | 1658 hb_direction_t direction = buffer->props.direction; |
1495 | 1659 |
1496 /* Handle cursive connections */ | 1660 /* Handle cursive connections */ |
1497 for (unsigned int i = 0; i < len; i++) | 1661 for (unsigned int i = 0; i < len; i++) |
1498 fix_cursive_minor_offset (pos, i, direction); | 1662 fix_cursive_minor_offset (pos, i, direction); |
1499 | 1663 |
1500 /* Handle attachments */ | 1664 /* Handle attachments */ |
1501 for (unsigned int i = 0; i < len; i++) | 1665 for (unsigned int i = 0; i < len; i++) |
1502 fix_mark_attachment (pos, i, direction); | 1666 fix_mark_attachment (pos, i, direction, zero_width_attached_marks); |
1503 | 1667 |
1504 HB_BUFFER_DEALLOCATE_VAR (buffer, syllable); | 1668 HB_BUFFER_DEALLOCATE_VAR (buffer, syllable); |
1505 HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props); | 1669 HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props); |
1506 HB_BUFFER_DEALLOCATE_VAR (buffer, props_cache); | 1670 HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props); |
1507 } | 1671 } |
1508 | 1672 |
1509 | 1673 |
1510 /* Out-of-class implementation for methods recursing */ | 1674 /* Out-of-class implementation for methods recursing */ |
1511 | 1675 |
| 1676 inline const Coverage & ExtensionPos::get_coverage (void) const |
| 1677 { |
| 1678 return get_subtable ().get_coverage (get_type ()); |
| 1679 } |
| 1680 |
1512 inline bool ExtensionPos::apply (hb_apply_context_t *c) const | 1681 inline bool ExtensionPos::apply (hb_apply_context_t *c) const |
1513 { | 1682 { |
1514 TRACE_APPLY (); | 1683 TRACE_APPLY (); |
1515 return TRACE_RETURN (get_subtable ().apply (c, get_type ())); | 1684 return TRACE_RETURN (get_subtable ().apply (c, get_type ())); |
1516 } | 1685 } |
1517 | 1686 |
1518 inline bool ExtensionPos::sanitize (hb_sanitize_context_t *c) | 1687 inline bool ExtensionPos::sanitize (hb_sanitize_context_t *c) |
1519 { | 1688 { |
1520 TRACE_SANITIZE (); | 1689 TRACE_SANITIZE (); |
1521 if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false); | 1690 if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false); |
1522 unsigned int offset = get_offset (); | 1691 unsigned int offset = get_offset (); |
1523 if (unlikely (!offset)) return TRACE_RETURN (true); | 1692 if (unlikely (!offset)) return TRACE_RETURN (true); |
1524 return TRACE_RETURN (StructAtOffset<PosLookupSubTable> (this, offset).sanitize
(c, get_type ())); | 1693 return TRACE_RETURN (StructAtOffset<PosLookupSubTable> (this, offset).sanitize
(c, get_type ())); |
1525 } | 1694 } |
1526 | 1695 |
1527 static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
ndex) | 1696 static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
ndex) |
1528 { | 1697 { |
1529 const GPOS &gpos = *(c->face->ot_layout->gpos); | 1698 const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos); |
1530 const PosLookup &l = gpos.get_lookup (lookup_index); | 1699 const PosLookup &l = gpos.get_lookup (lookup_index); |
1531 | 1700 |
1532 if (unlikely (c->nesting_level_left == 0)) | 1701 if (unlikely (c->nesting_level_left == 0)) |
1533 return false; | 1702 return false; |
1534 | 1703 |
1535 hb_apply_context_t new_c (*c); | 1704 hb_apply_context_t new_c (*c); |
1536 new_c.nesting_level_left--; | 1705 new_c.nesting_level_left--; |
1537 new_c.set_lookup (l); | 1706 new_c.set_lookup (l); |
1538 return l.apply_once (&new_c); | 1707 return l.apply_once (&new_c); |
1539 } | 1708 } |
1540 | 1709 |
1541 | 1710 |
1542 #undef attach_lookback | 1711 #undef attach_lookback |
1543 #undef cursive_chain | 1712 #undef cursive_chain |
1544 | 1713 |
1545 | 1714 |
| 1715 } // namespace OT |
| 1716 |
1546 | 1717 |
1547 #endif /* HB_OT_LAYOUT_GPOS_TABLE_HH */ | 1718 #endif /* HB_OT_LAYOUT_GPOS_TABLE_HH */ |
OLD | NEW |