2 * Copyright © 2018 Ebrahim Byagowi
4 * This is part of HarfBuzz, a text shaping library.
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25 #ifndef HB_OT_STAT_TABLE_HH
26 #define HB_OT_STAT_TABLE_HH
28 #include "hb-open-type.hh"
29 #include "hb-ot-layout-common.hh"
32 * STAT -- Style Attributes
33 * https://docs.microsoft.com/en-us/typography/opentype/spec/stat
35 #define HB_OT_TAG_STAT HB_TAG('S','T','A','T')
42 OLDER_SIBLING_FONT_ATTRIBUTE
= 0x0001, /* If set, this axis value table
43 * provides axis value information
44 * that is applicable to other fonts
45 * within the same font family. This
46 * is used if the other fonts were
47 * released earlier and did not include
48 * information about values for some axis.
49 * If newer versions of the other
50 * fonts include the information
51 * themselves and are present,
52 * then this record is ignored. */
53 ELIDABLE_AXIS_VALUE_NAME
= 0x0002 /* If set, it indicates that the axis
54 * value represents the “normal” value
55 * for the axis and may be omitted when
56 * composing name strings. */
57 // Reserved = 0xFFFC /* Reserved for future use — set to zero. */
60 struct AxisValueFormat1
62 unsigned int get_axis_index () const { return axisIndex
; }
63 float get_value () const { return value
.to_float (); }
65 hb_ot_name_id_t
get_value_name_id () const { return valueNameID
; }
67 bool sanitize (hb_sanitize_context_t
*c
) const
69 TRACE_SANITIZE (this);
70 return_trace (likely (c
->check_struct (this)));
74 HBUINT16 format
; /* Format identifier — set to 1. */
75 HBUINT16 axisIndex
; /* Zero-base index into the axis record array
76 * identifying the axis of design variation
77 * to which the axis value record applies.
78 * Must be less than designAxisCount. */
79 HBUINT16 flags
; /* Flags — see below for details. */
80 NameID valueNameID
; /* The name ID for entries in the 'name' table
81 * that provide a display string for this
83 HBFixed value
; /* A numeric value for this attribute value. */
85 DEFINE_SIZE_STATIC (12);
88 struct AxisValueFormat2
90 unsigned int get_axis_index () const { return axisIndex
; }
91 float get_value () const { return nominalValue
.to_float (); }
93 hb_ot_name_id_t
get_value_name_id () const { return valueNameID
; }
95 bool sanitize (hb_sanitize_context_t
*c
) const
97 TRACE_SANITIZE (this);
98 return_trace (likely (c
->check_struct (this)));
102 HBUINT16 format
; /* Format identifier — set to 2. */
103 HBUINT16 axisIndex
; /* Zero-base index into the axis record array
104 * identifying the axis of design variation
105 * to which the axis value record applies.
106 * Must be less than designAxisCount. */
107 HBUINT16 flags
; /* Flags — see below for details. */
108 NameID valueNameID
; /* The name ID for entries in the 'name' table
109 * that provide a display string for this
110 * attribute value. */
111 HBFixed nominalValue
; /* A numeric value for this attribute value. */
112 HBFixed rangeMinValue
; /* The minimum value for a range associated
113 * with the specified name ID. */
114 HBFixed rangeMaxValue
; /* The maximum value for a range associated
115 * with the specified name ID. */
117 DEFINE_SIZE_STATIC (20);
120 struct AxisValueFormat3
122 unsigned int get_axis_index () const { return axisIndex
; }
123 float get_value () const { return value
.to_float (); }
125 hb_ot_name_id_t
get_value_name_id () const { return valueNameID
; }
127 bool sanitize (hb_sanitize_context_t
*c
) const
129 TRACE_SANITIZE (this);
130 return_trace (likely (c
->check_struct (this)));
134 HBUINT16 format
; /* Format identifier — set to 3. */
135 HBUINT16 axisIndex
; /* Zero-base index into the axis record array
136 * identifying the axis of design variation
137 * to which the axis value record applies.
138 * Must be less than designAxisCount. */
139 HBUINT16 flags
; /* Flags — see below for details. */
140 NameID valueNameID
; /* The name ID for entries in the 'name' table
141 * that provide a display string for this
142 * attribute value. */
143 HBFixed value
; /* A numeric value for this attribute value. */
144 HBFixed linkedValue
; /* The numeric value for a style-linked mapping
145 * from this value. */
147 DEFINE_SIZE_STATIC (16);
150 struct AxisValueRecord
152 unsigned int get_axis_index () const { return axisIndex
; }
153 float get_value () const { return value
.to_float (); }
155 bool sanitize (hb_sanitize_context_t
*c
) const
157 TRACE_SANITIZE (this);
158 return_trace (likely (c
->check_struct (this)));
162 HBUINT16 axisIndex
; /* Zero-base index into the axis record array
163 * identifying the axis to which this value
164 * applies. Must be less than designAxisCount. */
165 HBFixed value
; /* A numeric value for this attribute value. */
167 DEFINE_SIZE_STATIC (6);
170 struct AxisValueFormat4
172 const AxisValueRecord
&get_axis_record (unsigned int axis_index
) const
173 { return axisValues
.as_array (axisCount
)[axis_index
]; }
175 hb_ot_name_id_t
get_value_name_id () const { return valueNameID
; }
177 bool sanitize (hb_sanitize_context_t
*c
) const
179 TRACE_SANITIZE (this);
180 return_trace (likely (c
->check_struct (this)));
184 HBUINT16 format
; /* Format identifier — set to 4. */
185 HBUINT16 axisCount
; /* The total number of axes contributing to
186 * this axis-values combination. */
187 HBUINT16 flags
; /* Flags — see below for details. */
188 NameID valueNameID
; /* The name ID for entries in the 'name' table
189 * that provide a display string for this
190 * attribute value. */
191 UnsizedArrayOf
<AxisValueRecord
>
192 axisValues
; /* Array of AxisValue records that provide the
193 * combination of axis values, one for each
194 * contributing axis. */
196 DEFINE_SIZE_ARRAY (8, axisValues
);
201 bool get_value (unsigned int axis_index
) const
205 case 1: return u
.format1
.get_value ();
206 case 2: return u
.format2
.get_value ();
207 case 3: return u
.format3
.get_value ();
208 case 4: return u
.format4
.get_axis_record (axis_index
).get_value ();
213 unsigned int get_axis_index () const
217 case 1: return u
.format1
.get_axis_index ();
218 case 2: return u
.format2
.get_axis_index ();
219 case 3: return u
.format3
.get_axis_index ();
220 /* case 4: Makes more sense for variable fonts which are handled by fvar in hb-style */
225 hb_ot_name_id_t
get_value_name_id () const
229 case 1: return u
.format1
.get_value_name_id ();
230 case 2: return u
.format2
.get_value_name_id ();
231 case 3: return u
.format3
.get_value_name_id ();
232 case 4: return u
.format4
.get_value_name_id ();
233 default:return HB_OT_NAME_ID_INVALID
;
237 bool sanitize (hb_sanitize_context_t
*c
) const
239 TRACE_SANITIZE (this);
240 if (unlikely (!c
->check_struct (this)))
241 return_trace (false);
245 case 1: return_trace (u
.format1
.sanitize (c
));
246 case 2: return_trace (u
.format2
.sanitize (c
));
247 case 3: return_trace (u
.format3
.sanitize (c
));
248 case 4: return_trace (u
.format4
.sanitize (c
));
249 default:return_trace (true);
257 AxisValueFormat1 format1
;
258 AxisValueFormat2 format2
;
259 AxisValueFormat3 format3
;
260 AxisValueFormat4 format4
;
263 DEFINE_SIZE_UNION (2, format
);
266 struct StatAxisRecord
268 int cmp (hb_tag_t key
) const { return tag
.cmp (key
); }
270 hb_ot_name_id_t
get_name_id () const { return nameID
; }
272 bool sanitize (hb_sanitize_context_t
*c
) const
274 TRACE_SANITIZE (this);
275 return_trace (likely (c
->check_struct (this)));
279 Tag tag
; /* A tag identifying the axis of design variation. */
280 NameID nameID
; /* The name ID for entries in the 'name' table that
281 * provide a display string for this axis. */
282 HBUINT16 ordering
; /* A value that applications can use to determine
283 * primary sorting of face names, or for ordering
284 * of descriptors when composing family or face names. */
286 DEFINE_SIZE_STATIC (8);
291 static constexpr hb_tag_t tableTag
= HB_OT_TAG_STAT
;
293 bool has_data () const { return version
.to_int (); }
295 bool get_value (hb_tag_t tag
, float *value
) const
297 unsigned int axis_index
;
298 if (!get_design_axes ().lfind (tag
, &axis_index
)) return false;
300 hb_array_t
<const Offset16To
<AxisValue
>> axis_values
= get_axis_value_offsets ();
301 for (unsigned int i
= 0; i
< axis_values
.length
; i
++)
303 const AxisValue
& axis_value
= this+axis_values
[i
];
304 if (axis_value
.get_axis_index () == axis_index
)
307 *value
= axis_value
.get_value (axis_index
);
314 unsigned get_design_axis_count () const { return designAxisCount
; }
316 hb_ot_name_id_t
get_axis_record_name_id (unsigned axis_record_index
) const
318 if (unlikely (axis_record_index
>= designAxisCount
)) return HB_OT_NAME_ID_INVALID
;
319 const StatAxisRecord
&axis_record
= get_design_axes ()[axis_record_index
];
320 return axis_record
.get_name_id ();
323 unsigned get_axis_value_count () const { return axisValueCount
; }
325 hb_ot_name_id_t
get_axis_value_name_id (unsigned axis_value_index
) const
327 if (unlikely (axis_value_index
>= axisValueCount
)) return HB_OT_NAME_ID_INVALID
;
328 const AxisValue
&axis_value
= (this + get_axis_value_offsets ()[axis_value_index
]);
329 return axis_value
.get_value_name_id ();
332 void collect_name_ids (hb_set_t
*nameids_to_retain
) const
334 if (!has_data ()) return;
337 | hb_map (&StatAxisRecord::get_name_id
)
338 | hb_sink (nameids_to_retain
)
341 + get_axis_value_offsets ()
342 | hb_map (hb_add (&(this + offsetToAxisValueOffsets
)))
343 | hb_map (&AxisValue::get_value_name_id
)
344 | hb_sink (nameids_to_retain
)
348 bool sanitize (hb_sanitize_context_t
*c
) const
350 TRACE_SANITIZE (this);
351 return_trace (likely (c
->check_struct (this) &&
352 version
.major
== 1 &&
354 designAxesOffset
.sanitize (c
, this, designAxisCount
) &&
355 offsetToAxisValueOffsets
.sanitize (c
, this, axisValueCount
, &(this+offsetToAxisValueOffsets
))));
359 hb_array_t
<const StatAxisRecord
> const get_design_axes () const
360 { return (this+designAxesOffset
).as_array (designAxisCount
); }
362 hb_array_t
<const Offset16To
<AxisValue
>> const get_axis_value_offsets () const
363 { return (this+offsetToAxisValueOffsets
).as_array (axisValueCount
); }
367 FixedVersion
<>version
; /* Version of the stat table
368 * initially set to 0x00010002u */
369 HBUINT16 designAxisSize
; /* The size in bytes of each axis record. */
370 HBUINT16 designAxisCount
;/* The number of design axis records. In a
371 * font with an 'fvar' table, this value must be
372 * greater than or equal to the axisCount value
373 * in the 'fvar' table. In all fonts, must
374 * be greater than zero if axisValueCount
375 * is greater than zero. */
376 NNOffset32To
<UnsizedArrayOf
<StatAxisRecord
>>
378 /* Offset in bytes from the beginning of
379 * the STAT table to the start of the design
380 * axes array. If designAxisCount is zero,
381 * set to zero; if designAxisCount is greater
382 * than zero, must be greater than zero. */
383 HBUINT16 axisValueCount
; /* The number of axis value tables. */
384 NNOffset32To
<UnsizedArrayOf
<Offset16To
<AxisValue
>>>
385 offsetToAxisValueOffsets
;
386 /* Offset in bytes from the beginning of
387 * the STAT table to the start of the design
388 * axes value offsets array. If axisValueCount
389 * is zero, set to zero; if axisValueCount is
390 * greater than zero, must be greater than zero. */
391 NameID elidedFallbackNameID
;
392 /* Name ID used as fallback when projection of
393 * names into a particular font model produces
394 * a subfamily name containing only elidable
397 DEFINE_SIZE_STATIC (20);
404 #endif /* HB_OT_STAT_TABLE_HH */