2 * Copyright © 2016 Elie Roux <elie.roux@telecom-bretagne.eu>
3 * Copyright © 2018 Google, Inc.
5 * This is part of HarfBuzz, a text shaping library.
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.
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
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.
25 * Google Author(s): Behdad Esfahbod
28 #ifndef HB_OT_LAYOUT_BASE_TABLE_HH
29 #define HB_OT_LAYOUT_BASE_TABLE_HH
31 #include "hb-open-type-private.hh"
32 #include "hb-ot-layout-common-private.hh"
36 #define NOT_INDEXED ((unsigned int) -1)
39 * BASE -- The BASE Table
42 struct BaseCoordFormat1
44 inline int get_coord (void) const { return coordinate; }
46 inline bool sanitize (hb_sanitize_context_t *c) const
48 TRACE_SANITIZE (this);
49 return_trace (c->check_struct (this));
53 HBUINT16 format; /* Format identifier--format = 1 */
54 HBINT16 coordinate; /* X or Y value, in design units */
56 DEFINE_SIZE_STATIC (4);
59 struct BaseCoordFormat2
61 inline int get_coord (void) const
67 inline bool sanitize (hb_sanitize_context_t *c) const
69 TRACE_SANITIZE (this);
70 return_trace (c->check_struct (this));
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
80 DEFINE_SIZE_STATIC (8);
83 struct BaseCoordFormat3
85 inline int get_coord (void) const
91 inline bool sanitize (hb_sanitize_context_t *c) const
93 TRACE_SANITIZE (this);
94 return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
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). */
104 DEFINE_SIZE_STATIC (6);
109 inline int get_coord (void) const
112 case 1: return u.format1.get_coord ();
113 case 2: return u.format2.get_coord ();
114 case 3: return u.format3.get_coord ();
119 inline bool sanitize (hb_sanitize_context_t *c) const
121 TRACE_SANITIZE (this);
122 if (!u.format.sanitize (c)) return_trace (false);
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);
134 BaseCoordFormat1 format1;
135 BaseCoordFormat2 format2;
136 BaseCoordFormat3 format3;
139 DEFINE_SIZE_UNION (2, format);
142 struct FeatMinMaxRecord
144 inline int get_min_value (void) const
145 { return (this+minCoord).get_coord(); }
147 inline int get_max_value (void) const
148 { return (this+maxCoord).get_coord(); }
150 inline const Tag &get_tag () const
153 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
155 TRACE_SANITIZE (this);
156 return_trace (c->check_struct (this) &&
157 minCoord.sanitize (c, base) &&
158 maxCoord.sanitize (c, base));
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) */
171 DEFINE_SIZE_STATIC (8);
177 inline unsigned int get_feature_tag_index (Tag featureTableTag) const
180 unsigned int count = featMinMaxRecords.len;
181 for (unsigned int i = 0; i < count; i++)
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;
191 inline int get_min_value (unsigned int featureTableTagIndex) const
193 if (featureTableTagIndex == NOT_INDEXED)
194 return (this+minCoord).get_coord();
195 return featMinMaxRecords[featureTableTagIndex].get_min_value();
198 inline int get_max_value (unsigned int featureTableTagIndex) const
200 if (featureTableTagIndex == NOT_INDEXED)
201 return (this+maxCoord).get_coord();
202 return featMinMaxRecords[featureTableTagIndex].get_max_value();
205 inline bool sanitize (hb_sanitize_context_t *c) const
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));
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 */
225 DEFINE_SIZE_ARRAY (6, featMinMaxRecords);
229 struct BaseLangSysRecord
231 inline const Tag& get_tag(void) const
232 { return baseLangSysTag; }
234 inline unsigned int get_feature_tag_index (Tag featureTableTag) const
235 { return (this+minMax).get_feature_tag_index(featureTableTag); }
237 inline int get_min_value (unsigned int featureTableTagIndex) const
238 { return (this+minMax).get_min_value(featureTableTagIndex); }
240 inline int get_max_value (unsigned int featureTableTagIndex) const
241 { return (this+minMax).get_max_value(featureTableTagIndex); }
243 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
245 TRACE_SANITIZE (this);
246 return_trace (c->check_struct (this) &&
247 minMax.sanitize (c, base));
252 OffsetTo<MinMax> minMax;
254 DEFINE_SIZE_STATIC (6);
260 inline unsigned int get_default_base_tag_index (void) const
261 { return defaultIndex; }
263 inline int get_base_coord (unsigned int baselineTagIndex) const
265 return (this+baseCoords[baselineTagIndex]).get_coord();
268 inline bool sanitize (hb_sanitize_context_t *c) const
270 TRACE_SANITIZE (this);
271 return_trace (c->check_struct (this) &&
272 defaultIndex <= baseCoordCount &&
273 baseCoords.sanitize (c, this));
278 HBUINT16 baseCoordCount;
279 OffsetArrayOf<BaseCoord> baseCoords;
281 DEFINE_SIZE_ARRAY (6, baseCoords);
287 inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
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;
301 inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
303 if (baseLangSysIndex == NOT_INDEXED) {
304 if (unlikely(defaultMinMax)) return NOT_INDEXED;
305 return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
307 if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
308 return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
311 inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
313 if (baseLangSysIndex == NOT_INDEXED)
314 return (this+defaultMinMax).get_min_value(featureTableTagIndex);
315 return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
318 inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
320 if (baseLangSysIndex == NOT_INDEXED)
321 return (this+defaultMinMax).get_min_value(featureTableTagIndex);
322 return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
325 inline unsigned int get_default_base_tag_index (void) const
326 { return (this+baseValues).get_default_base_tag_index(); }
328 inline int get_base_coord (unsigned int baselineTagIndex) const
329 { return (this+baseValues).get_base_coord(baselineTagIndex); }
331 inline bool sanitize (hb_sanitize_context_t *c) const
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));
341 OffsetTo<BaseValues> baseValues;
342 OffsetTo<MinMax> defaultMinMax;
343 HBUINT16 baseLangSysCount;
344 ArrayOf<BaseLangSysRecord> baseLangSysRecords;
347 DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
351 struct BaseScriptRecord {
353 inline const Tag& get_tag (void) const
354 { return baseScriptTag; }
356 inline unsigned int get_default_base_tag_index(void) const
357 { return (this+baseScript).get_default_base_tag_index(); }
359 inline int get_base_coord(unsigned int baselineTagIndex) const
360 { return (this+baseScript).get_base_coord(baselineTagIndex); }
362 inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
363 { return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
365 inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
366 { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
368 inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
369 { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
371 inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
372 { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
374 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
376 TRACE_SANITIZE (this);
377 return_trace (c->check_struct (this) &&
378 baseScript != Null(OffsetTo<BaseScript>) &&
379 baseScript.sanitize (c, base));
384 OffsetTo<BaseScript> baseScript;
387 DEFINE_SIZE_STATIC (6);
390 struct BaseScriptList {
392 inline unsigned int get_base_script_index (Tag baseScriptTag) const
394 for (unsigned int i = 0; i < baseScriptCount; i++)
395 if (baseScriptRecords[i].get_tag() == baseScriptTag)
400 inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
402 if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
403 return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
406 inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
408 return baseScriptRecords[baseScriptIndex].get_base_coord(baselineTagIndex);
411 inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
413 if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
414 return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
417 inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
419 if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
420 return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
423 inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
425 return baseScriptRecords[baseScriptIndex].get_max_value(baseLangSysIndex, featureTableTagIndex);
428 inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
430 return baseScriptRecords[baseScriptIndex].get_min_value(baseLangSysIndex, featureTableTagIndex);
433 inline bool sanitize (hb_sanitize_context_t *c) const
435 TRACE_SANITIZE (this);
436 return_trace (c->check_struct (this) &&
437 baseScriptRecords.sanitize (c, this));
441 HBUINT16 baseScriptCount;
442 ArrayOf<BaseScriptRecord> baseScriptRecords;
445 DEFINE_SIZE_ARRAY (4, baseScriptRecords);
452 inline unsigned int get_tag_index(Tag baselineTag) const
454 for (unsigned int i = 0; i < baseTagCount; i++)
455 if (baselineTags[i] == baselineTag)
460 inline bool sanitize (hb_sanitize_context_t *c) const
462 TRACE_SANITIZE (this);
463 return_trace (c->check_struct (this));
467 HBUINT16 baseTagCount;
468 SortedArrayOf<Tag> baselineTags;
471 DEFINE_SIZE_ARRAY (4, baselineTags);
477 inline unsigned int get_base_tag_index(Tag baselineTag) const
479 if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
480 return (this+baseTagList).get_tag_index(baselineTag);
483 inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
485 if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
486 return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
489 inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
491 return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
494 inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
496 if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
497 return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
500 inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
502 if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
503 return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
506 inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
508 return (this+baseScriptList).get_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
511 inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
513 return (this+baseScriptList).get_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
516 inline bool sanitize (hb_sanitize_context_t *c) const
518 TRACE_SANITIZE (this);
519 return_trace (c->check_struct (this) &&
520 baseTagList.sanitize (c, this) &&
521 baseScriptList.sanitize (c, this));
525 OffsetTo<BaseTagList> baseTagList;
526 OffsetTo<BaseScriptList> baseScriptList;
529 DEFINE_SIZE_STATIC (4);
534 static const hb_tag_t tableTag = HB_OT_TAG_BASE;
536 inline bool has_vert_axis(void)
537 { return vertAxis != Null(OffsetTo<Axis>); }
539 inline bool has_horiz_axis(void)
540 { return horizAxis != Null(OffsetTo<Axis>); }
542 // horizontal axis base coords:
544 inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
546 if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
547 return (this+horizAxis).get_base_tag_index(baselineTag);
550 inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
552 if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
553 return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
556 inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
558 return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
561 // vertical axis base coords:
563 inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
565 if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
566 return (this+vertAxis).get_base_tag_index(baselineTag);
569 inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
571 if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
572 return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
575 inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
577 return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
580 // horizontal axis min/max coords:
582 inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
584 if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
585 return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
588 inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
590 if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
591 return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
594 inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
596 return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
599 inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
601 return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
604 // vertical axis min/max coords:
606 inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
608 if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
609 return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
612 inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
614 if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
615 return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
618 inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
620 return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
623 inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
625 return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
628 inline bool sanitize (hb_sanitize_context_t *c) const
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)));
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. */
655 #endif /* HB_OT_LAYOUT_BASE_TABLE_HH */