Imported Upstream version 1.8.1
[platform/upstream/harfbuzz.git] / src / hb-ot-layout-base-table.hh
1 /*
2  * Copyright © 2016 Elie Roux <elie.roux@telecom-bretagne.eu>
3  * Copyright © 2018  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  * Google Author(s): Behdad Esfahbod
26  */
27
28 #ifndef HB_OT_LAYOUT_BASE_TABLE_HH
29 #define HB_OT_LAYOUT_BASE_TABLE_HH
30
31 #include "hb-open-type-private.hh"
32 #include "hb-ot-layout-common-private.hh"
33
34 namespace OT {
35
36 #define NOT_INDEXED   ((unsigned int) -1)
37
38 /*
39  * BASE -- Baseline
40  * https://docs.microsoft.com/en-us/typography/opentype/spec/base
41  */
42
43 struct BaseCoordFormat1
44 {
45   inline int get_coord (void) const { return coordinate; }
46
47   inline bool sanitize (hb_sanitize_context_t *c) const
48   {
49     TRACE_SANITIZE (this);
50     return_trace (c->check_struct (this));
51   }
52
53   protected:
54   HBUINT16      format;         /* Format identifier--format = 1 */
55   HBINT16       coordinate;     /* X or Y value, in design units */
56   public:
57   DEFINE_SIZE_STATIC (4);
58 };
59
60 struct BaseCoordFormat2
61 {
62   inline int get_coord (void) const
63   {
64     /* TODO */
65     return coordinate;
66   }
67
68   inline bool sanitize (hb_sanitize_context_t *c) const
69   {
70     TRACE_SANITIZE (this);
71     return_trace (c->check_struct (this));
72   }
73
74   protected:
75   HBUINT16      format;         /* Format identifier--format = 2 */
76   HBINT16       coordinate;     /* X or Y value, in design units */
77   GlyphID       referenceGlyph; /* Glyph ID of control glyph */
78   HBUINT16      coordPoint;     /* Index of contour point on the
79                                  * reference glyph */
80   public:
81   DEFINE_SIZE_STATIC (8);
82 };
83
84 struct BaseCoordFormat3
85 {
86   inline int get_coord (void) const
87   {
88     /* TODO */
89     return coordinate;
90   }
91
92   inline bool sanitize (hb_sanitize_context_t *c) const
93   {
94     TRACE_SANITIZE (this);
95     return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
96   }
97
98   protected:
99   HBUINT16              format;         /* Format identifier--format = 3 */
100   HBINT16               coordinate;     /* X or Y value, in design units */
101   OffsetTo<Device>      deviceTable;    /* Offset to Device table for X or
102                                          * Y value, from beginning of
103                                          * BaseCoord table (may be NULL). */
104   public:
105   DEFINE_SIZE_STATIC (6);
106 };
107
108 struct BaseCoord
109 {
110   inline int get_coord (void) const
111   {
112     switch (u.format) {
113     case 1: return u.format1.get_coord ();
114     case 2: return u.format2.get_coord ();
115     case 3: return u.format3.get_coord ();
116     default:return 0;
117     }
118   }
119
120   inline bool sanitize (hb_sanitize_context_t *c) const
121   {
122     TRACE_SANITIZE (this);
123     if (!u.format.sanitize (c)) return_trace (false);
124     switch (u.format) {
125     case 1: return_trace (u.format1.sanitize (c));
126     case 2: return_trace (u.format2.sanitize (c));
127     case 3: return_trace (u.format3.sanitize (c));
128     default:return_trace (false);
129     }
130   }
131
132   protected:
133   union {
134     HBUINT16            format;
135     BaseCoordFormat1    format1;
136     BaseCoordFormat2    format2;
137     BaseCoordFormat3    format3;
138   } u;
139   public:
140   DEFINE_SIZE_UNION (2, format);
141 };
142
143 struct FeatMinMaxRecord
144 {
145   inline int get_min_value (void) const
146   { return (this+minCoord).get_coord(); }
147
148   inline int get_max_value (void) const
149   { return (this+maxCoord).get_coord(); }
150
151   inline const Tag &get_tag () const
152   { return tag; }
153
154   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
155   {
156     TRACE_SANITIZE (this);
157     return_trace (c->check_struct (this) &&
158                   minCoord.sanitize (c, base) &&
159                   maxCoord.sanitize (c, base));
160   }
161
162   protected:
163   Tag                   tag;            /* 4-byte feature identification tag--must
164                                          * match feature tag in FeatureList */
165   OffsetTo<BaseCoord>   minCoord;       /* Offset to BaseCoord table that defines
166                                          * the minimum extent value, from beginning
167                                          * of MinMax table (may be NULL) */
168   OffsetTo<BaseCoord>   maxCoord;       /* Offset to BaseCoord table that defines
169                                          * the maximum extent value, from beginning
170                                          * of MinMax table (may be NULL) */
171   public:
172   DEFINE_SIZE_STATIC (8);
173
174 };
175
176 struct MinMax
177 {
178   inline unsigned int get_feature_tag_index (Tag featureTableTag) const
179   {
180     /* TODO bsearch */
181     unsigned int count = featMinMaxRecords.len;
182     for (unsigned int i = 0; i < count; i++)
183     {
184       Tag tag = featMinMaxRecords[i].get_tag();
185       int cmp = tag.cmp(featureTableTag);
186       if (cmp == 0) return i;
187       if (cmp > 0)  return NOT_INDEXED;
188     }
189     return NOT_INDEXED;
190   }
191
192   inline int get_min_value (unsigned int featureTableTagIndex) const
193   {
194     if (featureTableTagIndex == NOT_INDEXED)
195       return (this+minCoord).get_coord();
196     return featMinMaxRecords[featureTableTagIndex].get_min_value();
197   }
198
199   inline int get_max_value (unsigned int featureTableTagIndex) const
200   {
201     if (featureTableTagIndex == NOT_INDEXED)
202       return (this+maxCoord).get_coord();
203     return featMinMaxRecords[featureTableTagIndex].get_max_value();
204   }
205
206   inline bool sanitize (hb_sanitize_context_t *c) const
207   {
208     TRACE_SANITIZE (this);
209     return_trace (c->check_struct (this) &&
210                   minCoord.sanitize (c, this) &&
211                   maxCoord.sanitize (c, this) &&
212                   featMinMaxRecords.sanitize (c, this));
213   }
214
215   protected:
216   OffsetTo<BaseCoord>   minCoord;       /* Offset to BaseCoord table that defines
217                                          * minimum extent value, from the beginning
218                                          * of MinMax table (may be NULL) */
219   OffsetTo<BaseCoord>   maxCoord;       /* Offset to BaseCoord table that defines
220                                          * maximum extent value, from the beginning
221                                          * of MinMax table (may be NULL) */
222   ArrayOf<FeatMinMaxRecord>
223                 featMinMaxRecords;      /* Array of FeatMinMaxRecords, in alphabetical
224                                          * order by featureTableTag */
225   public:
226   DEFINE_SIZE_ARRAY (6, featMinMaxRecords);
227 };
228
229 /* TODO... */
230 struct BaseLangSysRecord
231 {
232   inline const Tag& get_tag(void) const
233   { return baseLangSysTag; }
234
235   inline unsigned int get_feature_tag_index (Tag featureTableTag) const
236   { return (this+minMax).get_feature_tag_index(featureTableTag); }
237
238   inline int get_min_value (unsigned int featureTableTagIndex) const
239   { return (this+minMax).get_min_value(featureTableTagIndex); }
240
241   inline int get_max_value (unsigned int featureTableTagIndex) const
242   { return (this+minMax).get_max_value(featureTableTagIndex); }
243
244   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
245   {
246     TRACE_SANITIZE (this);
247     return_trace (c->check_struct (this) &&
248                   minMax.sanitize (c, base));
249   }
250
251   protected:
252   Tag                   baseLangSysTag;
253   OffsetTo<MinMax>      minMax;
254   public:
255   DEFINE_SIZE_STATIC (6);
256
257 };
258
259 struct BaseValues
260 {
261   inline unsigned int get_default_base_tag_index (void) const
262   { return defaultIndex; }
263
264   inline int get_base_coord (unsigned int baselineTagIndex) const
265   {
266     return (this+baseCoords[baselineTagIndex]).get_coord();
267   }
268
269   inline bool sanitize (hb_sanitize_context_t *c) const
270   {
271     TRACE_SANITIZE (this);
272     return_trace (c->check_struct (this) &&
273       defaultIndex <= baseCoordCount &&
274       baseCoords.sanitize (c, this));
275   }
276
277   protected:
278   Index                         defaultIndex;
279   HBUINT16                      baseCoordCount;
280   OffsetArrayOf<BaseCoord>      baseCoords;
281   public:
282   DEFINE_SIZE_ARRAY (6, baseCoords);
283
284 };
285
286 struct BaseScript {
287
288   inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
289   {
290     Tag tag;
291     int cmp;
292     for (unsigned int i = 0; i < baseLangSysCount; i++) {
293       tag = baseLangSysRecords[i].get_tag();
294       // taking advantage of alphabetical order
295       cmp = tag.cmp(baseLangSysTag);
296       if (cmp == 0) return i;
297       if (cmp > 0)  return NOT_INDEXED;
298     }
299     return NOT_INDEXED;
300   }
301
302   inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
303   {
304     if (baseLangSysIndex == NOT_INDEXED) {
305       if (unlikely(defaultMinMax)) return NOT_INDEXED;
306       return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
307     }
308     if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
309     return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
310   }
311
312   inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
313   {
314     if (baseLangSysIndex == NOT_INDEXED)
315       return (this+defaultMinMax).get_min_value(featureTableTagIndex);
316     return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
317   }
318
319   inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
320   {
321     if (baseLangSysIndex == NOT_INDEXED)
322       return (this+defaultMinMax).get_min_value(featureTableTagIndex);
323     return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
324   }
325
326   inline unsigned int get_default_base_tag_index (void) const
327   { return (this+baseValues).get_default_base_tag_index(); }
328
329   inline int get_base_coord (unsigned int baselineTagIndex) const
330   { return (this+baseValues).get_base_coord(baselineTagIndex); }
331
332   inline bool sanitize (hb_sanitize_context_t *c) const
333   {
334     TRACE_SANITIZE (this);
335     return_trace (c->check_struct (this) &&
336       baseValues.sanitize (c, this) &&
337       defaultMinMax.sanitize (c, this) &&
338       baseLangSysRecords.sanitize (c, this));
339   }
340
341   protected:
342   OffsetTo<BaseValues>        baseValues;
343   OffsetTo<MinMax>            defaultMinMax;
344   HBUINT16                      baseLangSysCount;
345   ArrayOf<BaseLangSysRecord>  baseLangSysRecords;
346
347   public:
348     DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
349 };
350
351
352 struct BaseScriptRecord {
353
354   inline const Tag& get_tag (void) const
355   { return baseScriptTag; }
356
357   inline unsigned int get_default_base_tag_index(void) const
358   { return (this+baseScript).get_default_base_tag_index(); }
359
360   inline int get_base_coord(unsigned int baselineTagIndex) const
361   { return (this+baseScript).get_base_coord(baselineTagIndex); }
362
363   inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
364   { return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
365
366   inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
367   { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
368
369   inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
370   { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
371
372   inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
373   { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
374
375   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
376   {
377     TRACE_SANITIZE (this);
378     return_trace (c->check_struct (this) &&
379       baseScript != Null(OffsetTo<BaseScript>) &&
380       baseScript.sanitize (c, base));
381   }
382
383   protected:
384   Tag                   baseScriptTag;
385   OffsetTo<BaseScript>  baseScript;
386
387   public:
388     DEFINE_SIZE_STATIC (6);
389 };
390
391 struct BaseScriptList {
392
393   inline unsigned int get_base_script_index (Tag baseScriptTag) const
394   {
395     for (unsigned int i = 0; i < baseScriptCount; i++)
396       if (baseScriptRecords[i].get_tag() == baseScriptTag)
397         return i;
398     return NOT_INDEXED;
399   }
400
401   inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
402   {
403     if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
404     return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
405   }
406
407   inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
408   {
409     return baseScriptRecords[baseScriptIndex].get_base_coord(baselineTagIndex);
410   }
411
412   inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
413   {
414     if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
415     return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
416   }
417
418   inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
419   {
420     if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
421     return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
422   }
423
424   inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
425   {
426     return baseScriptRecords[baseScriptIndex].get_max_value(baseLangSysIndex, featureTableTagIndex);
427   }
428
429   inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
430   {
431     return baseScriptRecords[baseScriptIndex].get_min_value(baseLangSysIndex, featureTableTagIndex);
432   }
433
434   inline bool sanitize (hb_sanitize_context_t *c) const
435   {
436     TRACE_SANITIZE (this);
437     return_trace (c->check_struct (this) &&
438       baseScriptRecords.sanitize (c, this));
439   }
440
441   protected:
442   HBUINT16                    baseScriptCount;
443   ArrayOf<BaseScriptRecord> baseScriptRecords;
444
445   public:
446   DEFINE_SIZE_ARRAY (4, baseScriptRecords);
447
448 };
449
450 struct BaseTagList
451 {
452
453   inline unsigned int get_tag_index(Tag baselineTag) const
454   {
455     for (unsigned int i = 0; i < baseTagCount; i++)
456       if (baselineTags[i] == baselineTag)
457         return i;
458     return NOT_INDEXED;
459   }
460
461   inline bool sanitize (hb_sanitize_context_t *c) const
462   {
463     TRACE_SANITIZE (this);
464     return_trace (c->check_struct (this));
465   }
466
467   protected:
468   HBUINT16        baseTagCount;
469   SortedArrayOf<Tag>  baselineTags;
470
471   public:
472   DEFINE_SIZE_ARRAY (4, baselineTags);
473 };
474
475 struct Axis
476 {
477
478   inline unsigned int get_base_tag_index(Tag baselineTag) const
479   {
480     if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
481     return (this+baseTagList).get_tag_index(baselineTag);
482   }
483
484   inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
485   {
486     if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
487     return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
488   }
489
490   inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
491   {
492     return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
493   }
494
495   inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
496   {
497     if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
498     return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
499   }
500
501   inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
502   {
503     if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
504     return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
505   }
506
507   inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
508   {
509     return (this+baseScriptList).get_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
510   }
511
512   inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
513   {
514     return (this+baseScriptList).get_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
515   }
516
517   inline bool sanitize (hb_sanitize_context_t *c) const
518   {
519     TRACE_SANITIZE (this);
520     return_trace (c->check_struct (this) &&
521       baseTagList.sanitize (c, this) &&
522       baseScriptList.sanitize (c, this));
523   }
524
525   protected:
526   OffsetTo<BaseTagList>     baseTagList;
527   OffsetTo<BaseScriptList>  baseScriptList;
528
529   public:
530   DEFINE_SIZE_STATIC (4);
531 };
532
533 struct BASE
534 {
535   static const hb_tag_t tableTag = HB_OT_TAG_BASE;
536
537   inline bool has_vert_axis(void)
538   { return vertAxis != Null(OffsetTo<Axis>); }
539
540   inline bool has_horiz_axis(void)
541   { return horizAxis != Null(OffsetTo<Axis>); }
542
543   // horizontal axis base coords:
544
545   inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
546   {
547     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
548     return (this+horizAxis).get_base_tag_index(baselineTag);
549   }
550
551   inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
552   {
553     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
554     return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
555   }
556
557   inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
558   {
559     return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
560   }
561
562   // vertical axis base coords:
563
564   inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
565   {
566     if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
567     return (this+vertAxis).get_base_tag_index(baselineTag);
568   }
569
570   inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
571   {
572     if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
573     return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
574   }
575
576   inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
577   {
578     return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
579   }
580
581   // horizontal axis min/max coords:
582
583   inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
584   {
585     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
586     return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
587   }
588
589   inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
590   {
591     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
592     return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
593   }
594
595   inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
596   {
597     return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
598   }
599
600   inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
601   {
602     return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
603   }
604
605     // vertical axis min/max coords:
606
607   inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
608   {
609     if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
610     return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
611   }
612
613   inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
614   {
615     if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
616     return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
617   }
618
619   inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
620   {
621     return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
622   }
623
624   inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
625   {
626     return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
627   }
628
629   inline bool sanitize (hb_sanitize_context_t *c) const
630   {
631     TRACE_SANITIZE (this);
632     return_trace (c->check_struct (this) &&
633                   likely (version.major == 1) &&
634                   horizAxis.sanitize (c, this) &&
635                   vertAxis.sanitize (c, this) &&
636                   (version.to_int () < 0x00010001u || varStore.sanitize (c, this)));
637   }
638
639   protected:
640   FixedVersion<>  version;
641   OffsetTo<Axis>  horizAxis;
642   OffsetTo<Axis>  vertAxis;
643   LOffsetTo<VariationStore>
644                 varStore;               /* Offset to the table of Item Variation
645                                          * Store--from beginning of BASE
646                                          * header (may be NULL).  Introduced
647                                          * in version 0x00010001. */
648   public:
649   DEFINE_SIZE_MIN (8);
650 };
651
652
653 } /* namespace OT */
654
655
656 #endif /* HB_OT_LAYOUT_BASE_TABLE_HH */