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