Coverage Report

Created: 2026-10-14 08:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/src/OT/Layout/GDEF/GDEF.hh
Line
Count
Source
1
/*
2
 * Copyright © 2007,2008,2009  Red Hat, Inc.
3
 * Copyright © 2010,2011,2012  Google, Inc.
4
 *
5
 *  This is part of HarfBuzz, a text shaping library.
6
 *
7
 * Permission is hereby granted, without written agreement and without
8
 * license or royalty fees, to use, copy, modify, and distribute this
9
 * software and its documentation for any purpose, provided that the
10
 * above copyright notice and the following two paragraphs appear in
11
 * all copies of this software.
12
 *
13
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17
 * DAMAGE.
18
 *
19
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24
 *
25
 * Red Hat Author(s): Behdad Esfahbod
26
 * Google Author(s): Behdad Esfahbod
27
 */
28
29
#ifndef OT_LAYOUT_GDEF_GDEF_HH
30
#define OT_LAYOUT_GDEF_GDEF_HH
31
32
#include "../../../hb-ot-var-common.hh"
33
34
#include "../../../hb-font.hh"
35
#include "../../../hb-cache.hh"
36
37
38
namespace OT {
39
40
41
/*
42
 * Attachment List Table
43
 */
44
45
/* Array of contour point indices--in increasing numerical order */
46
struct AttachPoint : Array16Of<HBUINT16>
47
{
48
  bool subset (hb_subset_context_t *c) const
49
0
  {
50
0
    TRACE_SUBSET (this);
51
0
    auto *out = c->serializer->start_embed (*this);
52
0
    return_trace (out->serialize (c->serializer, + iter ()));
53
0
  }
54
};
55
56
/* AttachList is referenced by both GDEF attachListOffset and
57
 * attachListOffset2. The v1.4 top-level offset widens, but the
58
 * AttachList table itself keeps Offset16 internals. */
59
struct AttachList
60
{
61
  unsigned int get_attach_points (hb_codepoint_t glyph_id,
62
          unsigned int start_offset,
63
          unsigned int *point_count /* IN/OUT */,
64
          unsigned int *point_array /* OUT */) const
65
0
  {
66
0
    unsigned int index = (this+coverage).get_coverage (glyph_id);
67
0
    if (index == NOT_COVERED)
68
0
    {
69
0
      if (point_count)
70
0
  *point_count = 0;
71
0
      return 0;
72
0
    }
73
74
0
    const AttachPoint &points = this+attachPoint[index];
75
76
0
    if (point_count && point_array)
77
0
    {
78
0
      + points.as_array ().sub_array (start_offset, point_count)
79
0
      | hb_sink (hb_array (point_array, *point_count))
80
0
      ;
81
0
    }
82
83
0
    return points.len;
84
0
  }
85
86
  bool subset (hb_subset_context_t *c) const
87
0
  {
88
0
    TRACE_SUBSET (this);
89
0
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
90
0
    const hb_map_t &glyph_map = *c->plan->glyph_map;
91
92
0
    auto *out = c->serializer->start_embed (*this);
93
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
94
95
0
    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
96
0
    + hb_zip (this+coverage, attachPoint)
97
0
    | hb_filter (glyphset, hb_first)
98
0
    | hb_filter (subset_offset_array (c, out->attachPoint, this), hb_second)
99
0
    | hb_map (hb_first)
100
0
    | hb_map (glyph_map)
101
0
    | hb_sink (new_coverage)
102
0
    ;
103
0
    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
104
0
    return_trace (bool (new_coverage));
105
0
  }
106
107
  bool sanitize (hb_sanitize_context_t *c) const
108
0
  {
109
0
    TRACE_SANITIZE (this);
110
0
    return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
111
0
  }
112
113
  protected:
114
  Offset16To<Coverage>
115
    coverage;   /* Offset to Coverage table -- from
116
           * beginning of AttachList table */
117
  Array16OfOffset16To<AttachPoint>
118
    attachPoint;    /* Array of AttachPoint tables
119
           * in Coverage Index order */
120
  public:
121
  DEFINE_SIZE_ARRAY (4, attachPoint);
122
};
123
124
/*
125
 * Ligature Caret Table
126
 */
127
128
struct CaretValueFormat1
129
{
130
  friend struct CaretValue;
131
  bool subset (hb_subset_context_t *c) const
132
0
  {
133
0
    TRACE_SUBSET (this);
134
0
    auto *out = c->serializer->embed (this);
135
0
    if (unlikely (!out)) return_trace (false);
136
0
    return_trace (true);
137
0
  }
138
139
  private:
140
  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
141
0
  {
142
0
    return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
143
0
  }
144
145
  bool sanitize (hb_sanitize_context_t *c) const
146
0
  {
147
0
    TRACE_SANITIZE (this);
148
0
    return_trace (c->check_struct (this));
149
0
  }
150
151
  protected:
152
  HBUINT16  caretValueFormat; /* Format identifier--format = 1 */
153
  FWORD   coordinate;   /* X or Y value, in design units */
154
  public:
155
  DEFINE_SIZE_STATIC (4);
156
};
157
158
struct CaretValueFormat2
159
{
160
  friend struct CaretValue;
161
  bool subset (hb_subset_context_t *c) const
162
0
  {
163
0
    TRACE_SUBSET (this);
164
0
    auto *out = c->serializer->embed (this);
165
0
    if (unlikely (!out)) return_trace (false);
166
0
    return_trace (true);
167
0
  }
168
169
  private:
170
  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
171
0
  {
172
0
    hb_position_t x, y;
173
0
    font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y);
174
0
    return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
175
0
  }
176
177
  bool sanitize (hb_sanitize_context_t *c) const
178
0
  {
179
0
    TRACE_SANITIZE (this);
180
0
    return_trace (c->check_struct (this));
181
0
  }
182
183
  protected:
184
  HBUINT16  caretValueFormat; /* Format identifier--format = 2 */
185
  HBUINT16  caretValuePoint;  /* Contour point index on glyph */
186
  public:
187
  DEFINE_SIZE_STATIC (4);
188
};
189
190
struct CaretValueFormat3
191
{
192
  friend struct CaretValue;
193
194
  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction,
195
         const ItemVariationStore &var_store) const
196
0
  {
197
0
    return HB_DIRECTION_IS_HORIZONTAL (direction) ?
198
0
     hb_saturate_add (font->em_scale_x (coordinate), (this+deviceTable).get_x_delta (font, var_store)) :
199
0
     hb_saturate_add (font->em_scale_y (coordinate), (this+deviceTable).get_y_delta (font, var_store));
200
0
  }
201
202
  bool subset (hb_subset_context_t *c) const
203
0
  {
204
0
    TRACE_SUBSET (this);
205
0
    auto *out = c->serializer->start_embed (*this);
206
0
    if (!c->serializer->embed (caretValueFormat)) return_trace (false);
207
0
    if (!c->serializer->embed (coordinate)) return_trace (false);
208
209
0
    unsigned varidx = (this+deviceTable).get_variation_index ();
210
0
    hb_pair_t<unsigned, int> *new_varidx_delta;
211
0
    if (c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta)) {
212
0
      uint32_t new_varidx = hb_first (*new_varidx_delta);
213
0
      int delta = hb_second (*new_varidx_delta);
214
0
      if (delta != 0)
215
0
      {
216
0
        if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))
217
0
          return_trace (false);
218
0
      }
219
220
0
      if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
221
0
        return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
222
0
    }
223
224
0
    if (!c->serializer->embed (deviceTable))
225
0
      return_trace (false);
226
227
0
    return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this, c->serializer->to_bias (out),
228
0
               hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map));
229
0
  }
230
231
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
232
0
  { (this+deviceTable).collect_variation_indices (c); }
233
234
  bool sanitize (hb_sanitize_context_t *c) const
235
0
  {
236
0
    TRACE_SANITIZE (this);
237
0
    return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
238
0
  }
239
240
  protected:
241
  HBUINT16  caretValueFormat; /* Format identifier--format = 3 */
242
  FWORD   coordinate;   /* X or Y value, in design units */
243
  Offset16To<Device>
244
    deviceTable;    /* Offset to Device table for X or Y
245
           * value--from beginning of CaretValue
246
           * table */
247
  public:
248
  DEFINE_SIZE_STATIC (6);
249
};
250
251
struct CaretValue
252
{
253
  hb_position_t get_caret_value (hb_font_t *font,
254
         hb_direction_t direction,
255
         hb_codepoint_t glyph_id,
256
         const ItemVariationStore &var_store) const
257
0
  {
258
0
    switch (u.format.v) {
259
0
    case 1: hb_barrier (); return u.format1.get_caret_value (font, direction);
260
0
    case 2: hb_barrier (); return u.format2.get_caret_value (font, direction, glyph_id);
261
0
    case 3: hb_barrier (); return u.format3.get_caret_value (font, direction, var_store);
262
0
    default:return 0;
263
0
    }
264
0
  }
265
266
  template <typename context_t, typename ...Ts>
267
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
268
0
  {
269
0
    if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
270
0
    TRACE_DISPATCH (this, u.format.v);
271
0
    switch (u.format.v) {
272
0
    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
273
0
    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
274
0
    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
275
0
    default:return_trace (c->default_return_value ());
276
0
    }
277
0
  }
278
279
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
280
0
  {
281
0
    switch (u.format.v) {
282
0
    case 1:
283
0
    case 2:
284
0
      return;
285
0
    case 3:
286
0
      hb_barrier ();
287
0
      u.format3.collect_variation_indices (c);
288
0
      return;
289
0
    default: return;
290
0
    }
291
0
  }
292
293
  bool sanitize (hb_sanitize_context_t *c) const
294
0
  {
295
0
    TRACE_SANITIZE (this);
296
0
    if (!u.format.v.sanitize (c)) return_trace (false);
297
0
    hb_barrier ();
298
0
    switch (u.format.v) {
299
0
    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
300
0
    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
301
0
    case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
302
0
    default:return_trace (true);
303
0
    }
304
0
  }
305
306
  protected:
307
  union {
308
  struct { HBUINT16 v; }  format;   /* Format identifier */
309
  CaretValueFormat1 format1;
310
  CaretValueFormat2 format2;
311
  CaretValueFormat3 format3;
312
  } u;
313
  public:
314
  DEFINE_SIZE_UNION (2, format.v);
315
};
316
317
struct LigGlyph
318
{
319
  unsigned get_lig_carets (hb_font_t            *font,
320
         hb_direction_t        direction,
321
         hb_codepoint_t        glyph_id,
322
         const ItemVariationStore &var_store,
323
         unsigned              start_offset,
324
         unsigned             *caret_count /* IN/OUT */,
325
         hb_position_t        *caret_array /* OUT */) const
326
0
  {
327
0
    if (caret_count && caret_array)
328
0
    {
329
0
      + carets.as_array ().sub_array (start_offset, caret_count)
330
0
      | hb_map (hb_add (this))
331
0
      | hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); })
332
0
      | hb_sink (hb_array (caret_array, *caret_count))
333
0
      ;
334
0
    }
335
336
0
    return carets.len;
337
0
  }
338
339
  bool subset (hb_subset_context_t *c) const
340
0
  {
341
0
    TRACE_SUBSET (this);
342
0
    auto *out = c->serializer->start_embed (*this);
343
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
344
345
0
    + hb_iter (carets)
346
0
    | hb_apply (subset_offset_array (c, out->carets, this))
347
0
    ;
348
349
0
    return_trace (bool (out->carets));
350
0
  }
351
352
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
353
0
  {
354
0
    for (const Offset16To<CaretValue>& offset : carets.iter ())
355
0
      (this+offset).collect_variation_indices (c);
356
0
  }
357
358
  bool sanitize (hb_sanitize_context_t *c) const
359
0
  {
360
0
    TRACE_SANITIZE (this);
361
0
    return_trace (carets.sanitize (c, this));
362
0
  }
363
364
  protected:
365
  Array16OfOffset16To<CaretValue>
366
    carets;     /* Offset array of CaretValue tables
367
           * --from beginning of LigGlyph table
368
           * --in increasing coordinate order */
369
  public:
370
  DEFINE_SIZE_ARRAY (2, carets);
371
};
372
373
/* LigCaretList2 widens the LigCaretList coverage, count, and LigGlyph
374
 * offsets. The LigGlyph table itself keeps Offset16 caretValueOffsets. */
375
template <typename Types>
376
struct LigCaretList
377
{
378
  unsigned int get_lig_carets (hb_font_t *font,
379
             hb_direction_t direction,
380
             hb_codepoint_t glyph_id,
381
             const ItemVariationStore &var_store,
382
             unsigned int start_offset,
383
             unsigned int *caret_count /* IN/OUT */,
384
             hb_position_t *caret_array /* OUT */) const
385
0
  {
386
0
    unsigned int index = (this+coverage).get_coverage (glyph_id);
387
0
    if (index == NOT_COVERED)
388
0
    {
389
0
      if (caret_count)
390
0
  *caret_count = 0;
391
0
      return 0;
392
0
    }
393
0
    const LigGlyph &lig_glyph = this+ligGlyph[index];
394
0
    return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
395
0
  }
396
397
  bool subset (hb_subset_context_t *c) const
398
0
  {
399
0
    TRACE_SUBSET (this);
400
0
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
401
0
    const hb_map_t &glyph_map = *c->plan->glyph_map;
402
403
0
    auto *out = c->serializer->start_embed (*this);
404
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
405
406
0
    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
407
0
    + hb_zip (this+coverage, ligGlyph)
408
0
    | hb_filter (glyphset, hb_first)
409
0
    | hb_filter (subset_offset_array (c, out->ligGlyph, this), hb_second)
410
0
    | hb_map (hb_first)
411
0
    | hb_map (glyph_map)
412
0
    | hb_sink (new_coverage)
413
0
    ;
414
0
    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
415
0
    return_trace (bool (new_coverage));
416
0
  }
417
418
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
419
0
  {
420
0
    + hb_zip (this+coverage, ligGlyph)
421
0
    | hb_filter (c->glyph_set, hb_first)
422
0
    | hb_map (hb_second)
423
0
    | hb_map (hb_add (this))
424
0
    | hb_apply ([c] (const LigGlyph& _) { _.collect_variation_indices (c); })
425
0
    ;
426
0
  }
427
428
  bool sanitize (hb_sanitize_context_t *c) const
429
0
  {
430
0
    TRACE_SANITIZE (this);
431
0
    return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
432
0
  }
433
434
  protected:
435
  typename Types::template LOffsetTo<Coverage>
436
    coverage;   /* Offset to Coverage table--from
437
           * beginning of LigCaretList table */
438
  typename Types::template ArrayOf<typename Types::template OffsetTo<LigGlyph>>
439
    ligGlyph;   /* Array of LigGlyph tables
440
           * in Coverage Index order */
441
  public:
442
  DEFINE_SIZE_ARRAY (Types::LOffset::static_size + Types::HBUINT::static_size, ligGlyph);
443
};
444
445
#ifndef HB_NO_BEYOND_64K
446
static_assert (LigCaretList<MediumTypes>::min_size ==
447
         Offset32::static_size + HBUINT24::static_size, "");
448
#endif
449
450
451
struct MarkGlyphSetsFormat1
452
{
453
  bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
454
0
  { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
455
456
  void collect_used_mark_sets (const hb_set_t& glyph_set,
457
                               hb_set_t& used_mark_sets /* OUT */) const
458
0
  {
459
0
    unsigned i = 0;
460
0
    for (const auto &offset : coverage)
461
0
     {
462
0
       const auto &cov = this+offset;
463
0
       if (cov.intersects (&glyph_set))
464
0
         used_mark_sets.add (i);
465
466
0
       i++;
467
0
     }
468
0
  }
469
470
  template <typename set_t>
471
  void collect_coverage (hb_vector_t<set_t> &sets) const
472
0
  {
473
0
     for (const auto &offset : coverage)
474
0
     {
475
0
       const auto &cov = this+offset;
476
0
       cov.collect_coverage (sets.push ());
477
0
     }
478
0
  }
479
480
  bool subset (hb_subset_context_t *c) const
481
0
  {
482
0
    TRACE_SUBSET (this);
483
0
    auto *out = c->serializer->start_embed (*this);
484
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
485
0
    out->format = format;
486
487
0
    bool ret = true;
488
0
    for (const Offset32To<Coverage>& offset : coverage.iter ())
489
0
    {
490
0
      auto snap = c->serializer->snapshot ();
491
0
      auto *o = out->coverage.serialize_append (c->serializer);
492
0
      if (unlikely (!o))
493
0
      {
494
0
  ret = false;
495
0
  break;
496
0
      }
497
498
      //skip empty coverage
499
0
      c->serializer->push ();
500
0
      bool res = false;
501
0
      if (offset) res = c->dispatch (this+offset);
502
0
      if (!res)
503
0
      {
504
0
        c->serializer->pop_discard ();
505
0
        c->serializer->revert (snap);
506
0
        (out->coverage.len)--;
507
0
        continue;
508
0
      }
509
0
      c->serializer->add_link (*o, c->serializer->pop_pack ());
510
0
    }
511
512
0
    return_trace (ret && out->coverage.len);
513
0
  }
514
515
  bool sanitize (hb_sanitize_context_t *c) const
516
0
  {
517
0
    TRACE_SANITIZE (this);
518
0
    return_trace (coverage.sanitize (c, this));
519
0
  }
520
521
  protected:
522
  HBUINT16  format;     /* Format identifier--format = 1 */
523
  Array16Of<Offset32To<Coverage>>
524
    coverage;   /* Array of long offsets to mark set
525
           * coverage tables */
526
  public:
527
  DEFINE_SIZE_ARRAY (4, coverage);
528
};
529
530
struct MarkGlyphSets
531
{
532
  bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
533
0
  {
534
0
    switch (u.format.v) {
535
0
    case 1: hb_barrier (); return u.format1.covers (set_index, glyph_id);
536
0
    default:return false;
537
0
    }
538
0
  }
539
540
  template <typename set_t>
541
  void collect_coverage (hb_vector_t<set_t> &sets) const
542
0
  {
543
0
    switch (u.format.v) {
544
0
    case 1: hb_barrier (); u.format1.collect_coverage (sets); return;
545
0
    default:return;
546
0
    }
547
0
  }
548
549
  void collect_used_mark_sets (const hb_set_t& glyph_set,
550
                               hb_set_t& used_mark_sets /* OUT */) const
551
0
  {
552
0
    switch (u.format.v) {
553
0
    case 1: hb_barrier (); u.format1.collect_used_mark_sets (glyph_set, used_mark_sets); return;
554
0
    default:return;
555
0
    }
556
0
  }
557
558
  bool subset (hb_subset_context_t *c) const
559
0
  {
560
0
    TRACE_SUBSET (this);
561
0
    switch (u.format.v) {
562
0
    case 1: hb_barrier (); return_trace (u.format1.subset (c));
563
0
    default:return_trace (false);
564
0
    }
565
0
  }
566
567
  bool sanitize (hb_sanitize_context_t *c) const
568
0
  {
569
0
    TRACE_SANITIZE (this);
570
0
    if (!u.format.v.sanitize (c)) return_trace (false);
571
0
    hb_barrier ();
572
0
    switch (u.format.v) {
573
0
    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
574
0
    default:return_trace (true);
575
0
    }
576
0
  }
577
578
  protected:
579
  union {
580
  struct { HBUINT16 v; }  format;   /* Format identifier */
581
  MarkGlyphSetsFormat1  format1;
582
  } u;
583
  public:
584
  DEFINE_SIZE_UNION (2, format.v);
585
};
586
587
588
/*
589
 * GDEF -- Glyph Definition
590
 * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef
591
 */
592
593
594
struct GDEF
595
{
596
  static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF;
597
598
  enum GlyphClasses {
599
    UnclassifiedGlyph = 0,
600
    BaseGlyph   = 1,
601
    LigatureGlyph = 2,
602
    MarkGlyph   = 3,
603
    ComponentGlyph  = 4
604
  };
605
606
  size_t get_size () const
607
0
  {
608
0
    if (version.major != 1) return version.static_size;
609
610
0
    return min_size +
611
0
     (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
612
0
     (version.to_int () >= 0x00010003u ? varStore.static_size : 0) +
613
#ifndef HB_NO_BEYOND_64K
614
     (version.to_int () >= 0x00010004u ? 5 * Offset32::static_size : 0)
615
#else
616
0
     0
617
0
#endif
618
0
     ;
619
0
  }
620
621
  bool sanitize (hb_sanitize_context_t *c) const
622
0
  {
623
0
    TRACE_SANITIZE (this);
624
0
    if (unlikely (!version.sanitize (c) ||
625
0
      version.major != 1 ||
626
0
      !c->check_range (this, get_size ())))
627
0
      return_trace (false);
628
0
    hb_barrier ();
629
630
0
    bool glyph_class_def_ok = glyphClassDef.sanitize (c, this);
631
0
    bool attach_list_ok = attachList.sanitize (c, this);
632
0
    bool lig_caret_list_ok = ligCaretList.sanitize (c, this);
633
0
    bool mark_attach_class_def_ok = markAttachClassDef.sanitize (c, this);
634
0
    bool mark_glyph_sets_def_ok = version.to_int () < 0x00010002u ||
635
0
          markGlyphSetsDef.sanitize (c, this);
636
637
#ifndef HB_NO_BEYOND_64K
638
    if (version.to_int () >= 0x00010004u)
639
    {
640
      if (glyphClassDef2) glyph_class_def_ok = glyphClassDef2.sanitize (c, this);
641
      if (attachList2) attach_list_ok = attachList2.sanitize (c, this);
642
      if (ligCaretList2) lig_caret_list_ok = ligCaretList2.sanitize (c, this);
643
      if (markAttachClassDef2) mark_attach_class_def_ok = markAttachClassDef2.sanitize (c, this);
644
      if (markGlyphSetsDef2) mark_glyph_sets_def_ok = markGlyphSetsDef2.sanitize (c, this);
645
    }
646
#endif
647
648
0
    return_trace (glyph_class_def_ok &&
649
0
      attach_list_ok &&
650
0
      lig_caret_list_ok &&
651
0
      mark_attach_class_def_ok &&
652
0
      mark_glyph_sets_def_ok &&
653
0
      (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
654
0
  }
655
656
  bool subset (hb_subset_context_t *c) const
657
0
  {
658
0
    TRACE_SUBSET (this);
659
0
    if (version.major != 1) return_trace (false);
660
661
0
    auto *out = c->serializer->start_embed (*this);
662
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
663
664
    // Push var store first (if it's needed) so that it's last in the
665
    // serialization order. Some font consumers assume that varstore runs to
666
    // the end of the GDEF table.
667
    // See: https://github.com/harfbuzz/harfbuzz/issues/4636
668
0
    auto snapshot_version0 = c->serializer->snapshot ();
669
0
    if (unlikely (version.to_int () >= 0x00010002u && hb_barrier () &&
670
0
      !c->serializer->embed (markGlyphSetsDef)))
671
0
      return_trace (false);
672
673
0
    auto snapshot_version2 = c->serializer->snapshot ();
674
0
    if (unlikely (version.to_int () >= 0x00010003u && hb_barrier () &&
675
0
      !c->serializer->embed (varStore)))
676
0
      return_trace (false);
677
678
0
    bool use_v14 = false;
679
#ifndef HB_NO_BEYOND_64K
680
    use_v14 = version.to_int () >= 0x00010004u &&
681
        (glyphClassDef2 || attachList2 || ligCaretList2 ||
682
         markAttachClassDef2 || markGlyphSetsDef2);
683
    if (unlikely (version.to_int () >= 0x00010004u && hb_barrier () &&
684
      !c->serializer->extend_size (out, get_size ())))
685
      return_trace (false);
686
#endif
687
688
0
    bool subset_varstore = false;
689
0
    unsigned varstore_index = (unsigned) -1;
690
0
    if (version.to_int () >= 0x00010003u && hb_barrier ())
691
0
    {
692
0
      if (c->plan->all_axes_pinned)
693
0
  out->varStore = 0;
694
0
      else if (c->plan->normalized_coords)
695
0
      {
696
0
  if (varStore)
697
0
  {
698
0
    item_variations_t item_vars;
699
0
    if (unlikely (!c->serializer->check_success (
700
0
                  item_vars.instantiate (this+varStore, c->plan, true, true,
701
0
                                          c->plan->gdef_varstore_inner_maps.as_array (), true))))
702
0
            return_trace (false);
703
0
    subset_varstore = out->varStore.serialize_serialize (c->serializer,
704
0
                   item_vars.has_long_word (),
705
0
                   c->plan->axis_tags,
706
0
                   item_vars.get_region_list (),
707
0
                   item_vars.get_vardata_encodings ());
708
0
    varstore_index = c->serializer->last_added_child_index();
709
0
    remap_varidx_after_instantiation (item_vars.get_varidx_map (),
710
0
              c->plan->layout_variation_idx_delta_map);
711
0
          remap_varidx_after_instantiation (item_vars.get_varidx_map (),
712
0
                                            c->plan->layout_condition_idx_value_map);
713
0
  }
714
0
      }
715
0
      else
716
0
      {
717
0
  subset_varstore = out->varStore.serialize_subset (c, varStore, this,
718
0
                c->plan->gdef_varstore_inner_maps.as_array ());
719
0
  varstore_index = c->serializer->last_added_child_index();
720
0
      }
721
0
    }
722
723
0
    out->version.major = version.major;
724
0
    out->version.minor = version.minor;
725
726
0
    if (!subset_varstore && version.to_int () >= 0x00010002u && !use_v14) {
727
0
      c->serializer->revert (snapshot_version2);
728
0
    }
729
0
    if (!subset_varstore)
730
0
      out->varStore = 0;
731
0
    else
732
0
      c->plan->has_gdef_varstore = true;
733
734
0
    bool subset_markglyphsetsdef = false;
735
0
    if (version.to_int () >= 0x00010002u && hb_barrier ())
736
0
    {
737
#ifndef HB_NO_BEYOND_64K
738
      if (use_v14 && markGlyphSetsDef2)
739
      {
740
  out->markGlyphSetsDef = 0;
741
  subset_markglyphsetsdef = serialize_subset_offset (c, out->markGlyphSetsDef2,
742
                 markGlyphSetsDef2, this);
743
      }
744
      else
745
#endif
746
0
      {
747
#ifndef HB_NO_BEYOND_64K
748
  if (use_v14) out->markGlyphSetsDef2 = 0;
749
#endif
750
0
  subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
751
0
      }
752
0
    }
753
754
0
    if (use_v14)
755
0
    {
756
0
      out->version.minor = 4;
757
0
    } else if (subset_varstore) {
758
0
      out->version.minor = 3;
759
0
    } else if (subset_markglyphsetsdef) {
760
0
      out->version.minor = 2;
761
0
    } else  {
762
0
      out->version.minor = 0;
763
0
      c->serializer->revert (snapshot_version0);
764
0
    }
765
766
0
    bool subset_glyphclassdef = false;
767
0
    bool subset_attachlist = false;
768
0
    bool subset_markattachclassdef = false;
769
0
    bool subset_ligcaretlist = false;
770
771
#ifndef HB_NO_BEYOND_64K
772
    if (use_v14 && glyphClassDef2)
773
    {
774
      out->glyphClassDef = 0;
775
      subset_glyphclassdef = serialize_subset_offset (c, out->glyphClassDef2,
776
                  glyphClassDef2, this, nullptr, false, true);
777
    }
778
    else
779
#endif
780
0
    {
781
#ifndef HB_NO_BEYOND_64K
782
      if (use_v14) out->glyphClassDef2 = 0;
783
#endif
784
0
      subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
785
0
    }
786
787
#ifndef HB_NO_BEYOND_64K
788
    if (use_v14 && attachList2)
789
    {
790
      out->attachList = 0;
791
      subset_attachlist = serialize_subset_offset (c, out->attachList2, attachList2, this);
792
    }
793
    else
794
#endif
795
0
    {
796
#ifndef HB_NO_BEYOND_64K
797
      if (use_v14) out->attachList2 = 0;
798
#endif
799
0
      subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
800
0
    }
801
802
#ifndef HB_NO_BEYOND_64K
803
    if (use_v14 && markAttachClassDef2)
804
    {
805
      out->markAttachClassDef = 0;
806
      subset_markattachclassdef = serialize_subset_offset (c, out->markAttachClassDef2,
807
                 markAttachClassDef2, this, nullptr, false, true);
808
    }
809
    else
810
#endif
811
0
    {
812
#ifndef HB_NO_BEYOND_64K
813
      if (use_v14) out->markAttachClassDef2 = 0;
814
#endif
815
0
      subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef,
816
0
                     this, nullptr, false, true);
817
0
    }
818
819
#ifndef HB_NO_BEYOND_64K
820
    if (use_v14 && ligCaretList2)
821
    {
822
      out->ligCaretList = 0;
823
      subset_ligcaretlist = serialize_subset_offset (c, out->ligCaretList2, ligCaretList2, this);
824
    }
825
    else
826
#endif
827
0
    {
828
#ifndef HB_NO_BEYOND_64K
829
      if (use_v14) out->ligCaretList2 = 0;
830
#endif
831
0
      subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
832
0
    }
833
834
0
    if (subset_varstore && varstore_index != (unsigned) -1) {
835
0
      c->serializer->repack_last(varstore_index);
836
0
    }
837
838
0
    return_trace (subset_glyphclassdef || subset_attachlist ||
839
0
      subset_ligcaretlist || subset_markattachclassdef ||
840
0
      (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) ||
841
0
      (out->version.to_int () >= 0x00010003u && subset_varstore));
842
0
  }
843
844
  bool has_glyph_classes () const
845
0
  {
846
#ifndef HB_NO_BEYOND_64K
847
    if (version.to_int () >= 0x00010004u && glyphClassDef2) return true;
848
#endif
849
0
    return glyphClassDef != 0;
850
0
  }
851
  const ClassDef &get_glyph_class_def () const
852
0
  {
853
#ifndef HB_NO_BEYOND_64K
854
    if (version.to_int () >= 0x00010004u && glyphClassDef2) return this+glyphClassDef2;
855
#endif
856
0
    return this+glyphClassDef;
857
0
  }
858
  bool has_attach_list () const
859
0
  {
860
0
#ifndef HB_NO_BEYOND_64K
861
0
    if (version.to_int () >= 0x00010004u && attachList2) return true;
862
0
#endif
863
0
    return attachList != 0;
864
0
  }
865
  const AttachList &get_attach_list () const
866
0
  {
867
#ifndef HB_NO_BEYOND_64K
868
    if (version.to_int () >= 0x00010004u && attachList2) return this+attachList2;
869
#endif
870
0
    return this+attachList;
871
0
  }
872
  bool has_lig_carets () const
873
0
  {
874
0
#ifndef HB_NO_BEYOND_64K
875
0
    if (version.to_int () >= 0x00010004u && ligCaretList2) return true;
876
0
#endif
877
0
    return ligCaretList != 0;
878
0
  }
879
  bool has_mark_attachment_types () const
880
0
  {
881
0
#ifndef HB_NO_BEYOND_64K
882
0
    if (version.to_int () >= 0x00010004u && markAttachClassDef2) return true;
883
0
#endif
884
0
    return markAttachClassDef != 0;
885
0
  }
886
  const ClassDef &get_mark_attach_class_def () const
887
0
  {
888
#ifndef HB_NO_BEYOND_64K
889
    if (version.to_int () >= 0x00010004u && markAttachClassDef2) return this+markAttachClassDef2;
890
#endif
891
0
    return this+markAttachClassDef;
892
0
  }
893
  bool has_mark_glyph_sets () const
894
0
  {
895
0
    if (version.to_int () < 0x00010002u) return false;
896
#ifndef HB_NO_BEYOND_64K
897
    if (version.to_int () >= 0x00010004u && markGlyphSetsDef2) return true;
898
#endif
899
0
    return markGlyphSetsDef != 0;
900
0
  }
901
  const MarkGlyphSets &get_mark_glyph_sets () const
902
0
  {
903
0
    if (version.to_int () < 0x00010002u) return Null(MarkGlyphSets);
904
#ifndef HB_NO_BEYOND_64K
905
    if (version.to_int () >= 0x00010004u && markGlyphSetsDef2) return this+markGlyphSetsDef2;
906
#endif
907
0
    return this+markGlyphSetsDef;
908
0
  }
909
  bool has_var_store () const
910
0
  {
911
0
    return version.to_int () >= 0x00010003u && hb_barrier () && varStore != 0;
912
0
  }
913
  const ItemVariationStore &get_var_store () const
914
0
  {
915
0
    return version.to_int () >= 0x00010003u && hb_barrier () ? this+varStore : Null(ItemVariationStore);
916
0
  }
917
918
919
0
  bool has_data () const { return version.to_int (); }
920
  unsigned int get_glyph_class (hb_codepoint_t glyph) const
921
0
  { return get_glyph_class_def ().get_class (glyph); }
922
  void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
923
0
  { get_glyph_class_def ().collect_class (glyphs, klass); }
924
925
  unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
926
0
  { return get_mark_attach_class_def ().get_class (glyph); }
927
928
  unsigned int get_attach_points (hb_codepoint_t glyph_id,
929
          unsigned int start_offset,
930
          unsigned int *point_count /* IN/OUT */,
931
          unsigned int *point_array /* OUT */) const
932
0
  { return get_attach_list ().get_attach_points (glyph_id, start_offset, point_count, point_array); }
933
934
  unsigned int get_lig_carets (hb_font_t *font,
935
             hb_direction_t direction,
936
             hb_codepoint_t glyph_id,
937
             unsigned int start_offset,
938
             unsigned int *caret_count /* IN/OUT */,
939
             hb_position_t *caret_array /* OUT */) const
940
0
  {
941
#ifndef HB_NO_BEYOND_64K
942
    if (version.to_int () >= 0x00010004u && ligCaretList2)
943
      return (this+ligCaretList2).get_lig_carets (font, direction, glyph_id, get_var_store (),
944
              start_offset, caret_count, caret_array);
945
#endif
946
0
    return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, get_var_store (),
947
0
                 start_offset, caret_count, caret_array);
948
0
  }
949
950
  bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
951
0
  { return get_mark_glyph_sets ().covers (set_index, glyph_id); }
952
953
  /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
954
   * glyph class and other bits, and high 8-bit the mark attachment type (if any).
955
   * Not to be confused with lookup_props which is very similar. */
956
  unsigned int get_glyph_props (hb_codepoint_t glyph) const
957
0
  {
958
0
    unsigned int klass = get_glyph_class (glyph);
959
960
0
    static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), "");
961
0
    static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), "");
962
0
    static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), "");
963
964
0
    switch (klass) {
965
0
    default:      return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
966
0
    case BaseGlyph:   return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
967
0
    case LigatureGlyph:   return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
968
0
    case MarkGlyph:
969
0
    klass = get_mark_attachment_type (glyph);
970
0
    return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8);
971
0
    }
972
0
  }
973
974
  HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
975
           hb_face_t *face) const;
976
977
  struct accelerator_t
978
  {
979
    accelerator_t (hb_face_t *face)
980
0
    {
981
0
      table = hb_sanitize_context_t ().reference_table<GDEF> (face);
982
0
      if (unlikely (table->is_blocklisted (table.get_blob (), face)))
983
0
      {
984
0
  hb_blob_destroy (table.get_blob ());
985
0
  table = hb_blob_get_empty ();
986
0
      }
987
988
0
#ifndef HB_NO_GDEF_CACHE
989
      /* Flatten each mark set whose glyphs span fewer than PAGE_BITS
990
       * gids into a single bit-page biased at its first glyph, for
991
       * O(1) exact answers.  Wider sets, or on allocation failure,
992
       * fall back to the table. */
993
0
      {
994
0
  hb_vector_t<hb_set_t> sets;
995
0
  table->get_mark_glyph_sets ().collect_coverage (sets);
996
0
  if (!sets.in_error () &&
997
0
      mark_glyph_set_bitmaps.resize (sets.length))
998
0
    for (unsigned i = 0; i < sets.length; i++)
999
0
    {
1000
0
      auto &bitmap = mark_glyph_set_bitmaps.arrayZ[i];
1001
0
      bitmap.bias = HB_SET_VALUE_INVALID;
1002
0
      const auto &set = sets.arrayZ[i];
1003
0
      if (unlikely (set.in_error ())) continue;
1004
0
      hb_codepoint_t min_gid = HB_SET_VALUE_INVALID;
1005
0
      hb_codepoint_t max_gid = HB_SET_VALUE_INVALID;
1006
0
      hb_set_next (&set, &min_gid);
1007
0
      hb_set_previous (&set, &max_gid);
1008
0
      if (max_gid == HB_SET_VALUE_INVALID)
1009
0
        continue;
1010
0
      if (max_gid - min_gid >= hb_bit_page_t::PAGE_BITS)
1011
0
      {
1012
        /* Too wide for one page; a digest pre-filter instead. */
1013
0
        for (hb_codepoint_t gid : set)
1014
0
    bitmap.u.digest.add (gid);
1015
0
        continue;
1016
0
      }
1017
0
      bitmap.bias = min_gid;
1018
0
      for (hb_codepoint_t gid : set)
1019
0
        bitmap.u.page.add (gid - min_gid);
1020
0
    }
1021
0
      }
1022
0
#endif
1023
0
    }
1024
0
    ~accelerator_t () { table.destroy (); }
1025
1026
    unsigned int get_glyph_props (hb_codepoint_t glyph) const
1027
0
    {
1028
0
      unsigned v;
1029
1030
0
#ifndef HB_NO_GDEF_CACHE
1031
0
      if (glyph_props_cache.get (glyph, &v))
1032
0
        return v;
1033
0
#endif
1034
1035
0
      v = table->get_glyph_props (glyph);
1036
1037
0
#ifndef HB_NO_GDEF_CACHE
1038
0
      if (likely (table.get_blob ())) // Don't try setting if we are the null instance!
1039
0
  glyph_props_cache.set (glyph, v);
1040
0
#endif
1041
1042
0
      return v;
1043
1044
0
    }
1045
1046
    HB_ALWAYS_INLINE
1047
    bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
1048
0
    {
1049
0
#ifndef HB_NO_GDEF_CACHE
1050
      // We can access arrayZ directly because of sanitize_lookup_props() guarantee.
1051
0
      const auto &bitmap = mark_glyph_set_bitmaps.arrayZ[set_index];
1052
0
      if (likely (bitmap.bias != HB_SET_VALUE_INVALID))
1053
0
      {
1054
0
  hb_codepoint_t biased = glyph_id - bitmap.bias;
1055
0
  return biased < hb_bit_page_t::PAGE_BITS &&
1056
0
         bitmap.u.page.get (biased);
1057
0
      }
1058
0
      return mark_set_covers_slow (set_index, glyph_id);
1059
#else
1060
      return table->mark_set_covers (set_index, glyph_id);
1061
#endif
1062
0
    }
1063
1064
#ifndef HB_NO_GDEF_CACHE
1065
    HB_NEVER_INLINE
1066
    bool mark_set_covers_slow (unsigned int set_index, hb_codepoint_t glyph_id) const
1067
0
    {
1068
0
      const auto &bitmap = mark_glyph_set_bitmaps.arrayZ[set_index];
1069
0
      if (!bitmap.u.digest.may_have (glyph_id))
1070
0
  return false;
1071
0
      return table->mark_set_covers (set_index, glyph_id);
1072
0
    }
1073
#endif
1074
1075
    unsigned sanitize_lookup_props (unsigned lookup_props) const
1076
0
    {
1077
0
#ifndef HB_NO_GDEF_CACHE
1078
0
      if (lookup_props & LookupFlag::UseMarkFilteringSet &&
1079
0
    (lookup_props >> 16) >= mark_glyph_set_bitmaps.length)
1080
0
      {
1081
        // Invalid mark filtering set index; unset the flag.
1082
0
  lookup_props &= ~LookupFlag::UseMarkFilteringSet;
1083
0
      }
1084
0
#endif
1085
0
      return lookup_props;
1086
0
    }
1087
1088
    hb_blob_ptr_t<GDEF> table;
1089
#ifndef HB_NO_GDEF_CACHE
1090
    struct mark_glyph_set_bitmap_t
1091
    {
1092
      /* Gid of the first bit (not page-aligned) for an exact one-page
1093
       * set, or HB_SET_VALUE_INVALID; then digest is a pre-filter for
1094
       * the table.  The all-zeros state is valid for both members. */
1095
      hb_codepoint_t bias = HB_SET_VALUE_INVALID;
1096
      union u_t {
1097
0
  u_t () : page () {}
1098
  hb_bit_page_t page;
1099
  hb_set_digest_t digest;
1100
      } u;
1101
    };
1102
1103
    hb_vector_t<mark_glyph_set_bitmap_t> mark_glyph_set_bitmaps;
1104
    mutable hb_cache_t<21, 3> glyph_props_cache;
1105
    static_assert (sizeof (glyph_props_cache) == 512, "");
1106
#endif
1107
  };
1108
1109
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
1110
0
  {
1111
#ifndef HB_NO_BEYOND_64K
1112
    if (version.to_int () >= 0x00010004u && ligCaretList2)
1113
    {
1114
      (this+ligCaretList2).collect_variation_indices (c);
1115
      return;
1116
    }
1117
#endif
1118
0
    (this+ligCaretList).collect_variation_indices (c);
1119
0
  }
1120
1121
  protected:
1122
  template <typename Key>
1123
  static void remap_varidx_after_instantiation (const hb_map_t& varidx_map,
1124
                                                hb_hashmap_t<Key, hb_pair_t<unsigned, int>>& layout_variation_idx_delta_map /* IN/OUT */)
1125
0
  {
1126
    /* varidx_map is empty which means varstore is empty after instantiation,
1127
     * no variations, map all varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX.
1128
     * varidx_map doesn't have original varidx, indicating delta row is all
1129
     * zeros, map varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX */
1130
0
    for (auto _ : layout_variation_idx_delta_map.iter_ref ())
1131
0
    {
1132
      /* old_varidx->(varidx, delta) mapping generated for subsetting, then this
1133
       * varidx is used as key of varidx_map during instantiation */
1134
0
      uint32_t varidx = _.second.first;
1135
0
      uint32_t *new_varidx;
1136
0
      if (varidx_map.has (varidx, &new_varidx))
1137
0
  _.second.first = *new_varidx;
1138
0
      else
1139
0
  _.second.first = HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
1140
0
    }
1141
0
  }
Unexecuted instantiation: void OT::GDEF::remap_varidx_after_instantiation<unsigned int>(hb_map_t const&, hb_hashmap_t<unsigned int, hb_pair_t<unsigned int, int>, false>&)
Unexecuted instantiation: void OT::GDEF::remap_varidx_after_instantiation<unsigned long>(hb_map_t const&, hb_hashmap_t<unsigned long, hb_pair_t<unsigned int, int>, false>&)
1142
1143
  template <typename OffsetOut, typename OffsetIn, typename Base, typename ...Ts>
1144
  static bool serialize_subset_offset (hb_subset_context_t *c,
1145
               OffsetOut& out,
1146
               const OffsetIn& in,
1147
               const Base *base,
1148
               Ts&&... ds)
1149
  {
1150
    out = 0;
1151
    if (in.is_null ()) return false;
1152
1153
    auto *s = c->serializer;
1154
    s->push ();
1155
    bool ret = c->dispatch (base+in, std::forward<Ts> (ds)...);
1156
    if (ret) s->add_link (out, s->pop_pack ());
1157
    else s->pop_discard ();
1158
    return ret;
1159
  }
1160
1161
  FixedVersion<>version;    /* Version of the GDEF table--currently
1162
           * 0x00010004u */
1163
  Offset16To<ClassDef>
1164
    glyphClassDef;    /* Offset to class definition table
1165
           * for glyph type--from beginning of
1166
           * GDEF header (may be Null) */
1167
  Offset16To<AttachList>
1168
    attachList;   /* Offset to list of glyphs with
1169
           * attachment points--from beginning
1170
           * of GDEF header (may be Null) */
1171
  Offset16To<LigCaretList<SmallTypes>>
1172
    ligCaretList;   /* Offset to list of positioning points
1173
           * for ligature carets--from beginning
1174
           * of GDEF header (may be Null) */
1175
  Offset16To<ClassDef>
1176
    markAttachClassDef; /* Offset to class definition table for
1177
           * mark attachment type--from beginning
1178
           * of GDEF header (may be Null) */
1179
  Offset16To<MarkGlyphSets>
1180
    markGlyphSetsDef; /* Offset to the table of mark set
1181
           * definitions--from beginning of GDEF
1182
           * header (may be NULL).  Introduced
1183
           * in version 0x00010002. */
1184
  Offset32To<ItemVariationStore>
1185
    varStore;   /* Offset to the table of Item Variation
1186
           * Store--from beginning of GDEF
1187
           * header (may be NULL).  Introduced
1188
           * in version 0x00010003. */
1189
#ifndef HB_NO_BEYOND_64K
1190
  Offset32To<ClassDef>
1191
    glyphClassDef2;   /* 32-bit offset to class definition
1192
           * table for glyph type.  Introduced
1193
           * in version 0x00010004. */
1194
  Offset32To<AttachList>
1195
    attachList2;    /* 32-bit offset to list of glyphs
1196
           * with attachment points.  Introduced
1197
           * in version 0x00010004. */
1198
  Offset32To<LigCaretList<MediumTypes>>
1199
    ligCaretList2;    /* 32-bit offset to LigCaretList2.
1200
           * Introduced in version 0x00010004. */
1201
  Offset32To<ClassDef>
1202
    markAttachClassDef2;  /* 32-bit offset to class definition
1203
           * table for mark attachment type.
1204
           * Introduced in version 0x00010004. */
1205
  Offset32To<MarkGlyphSets>
1206
    markGlyphSetsDef2;  /* 32-bit offset to the table of mark
1207
           * set definitions.  Introduced in
1208
           * version 0x00010004. */
1209
#endif
1210
  public:
1211
  DEFINE_SIZE_MIN (12);
1212
};
1213
1214
struct GDEF_accelerator_t : GDEF::accelerator_t {
1215
0
  GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {}
1216
};
1217
1218
} /* namespace OT */
1219
1220
1221
#endif /* OT_LAYOUT_GDEF_GDEF_HH */