• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2018  Ebrahim Byagowi
3  *
4  *  This is part of HarfBuzz, a text shaping library.
5  *
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.
11  *
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
16  * DAMAGE.
17  *
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.
23  */
24 
25 #ifndef HB_OT_STAT_TABLE_HH
26 #define HB_OT_STAT_TABLE_HH
27 
28 #include "hb-open-type.hh"
29 #include "hb-ot-layout-common.hh"
30 
31 /*
32  * STAT -- Style Attributes
33  * https://docs.microsoft.com/en-us/typography/opentype/spec/stat
34  */
35 #define HB_OT_TAG_STAT HB_TAG('S','T','A','T')
36 
37 
38 namespace OT {
39 
40 enum
41 {
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. */
58 };
59 
60 struct AxisValueFormat1
61 {
get_value_name_idOT::AxisValueFormat162   hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
63 
sanitizeOT::AxisValueFormat164   bool sanitize (hb_sanitize_context_t *c) const
65   {
66     TRACE_SANITIZE (this);
67     return_trace (likely (c->check_struct (this)));
68   }
69 
70   protected:
71   HBUINT16	format;		/* Format identifier — set to 1. */
72   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
73 				 * identifying the axis of design variation
74 				 * to which the axis value record applies.
75 				 * Must be less than designAxisCount. */
76   HBUINT16	flags;		/* Flags — see below for details. */
77   NameID	valueNameID;	/* The name ID for entries in the 'name' table
78 				 * that provide a display string for this
79 				 * attribute value. */
80   HBFixed		value;		/* A numeric value for this attribute value. */
81   public:
82   DEFINE_SIZE_STATIC (12);
83 };
84 
85 struct AxisValueFormat2
86 {
get_value_name_idOT::AxisValueFormat287   hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
88 
sanitizeOT::AxisValueFormat289   bool sanitize (hb_sanitize_context_t *c) const
90   {
91     TRACE_SANITIZE (this);
92     return_trace (likely (c->check_struct (this)));
93   }
94 
95   protected:
96   HBUINT16	format;		/* Format identifier — set to 2. */
97   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
98 				 * identifying the axis of design variation
99 				 * to which the axis value record applies.
100 				 * Must be less than designAxisCount. */
101   HBUINT16	flags;		/* Flags — see below for details. */
102   NameID	valueNameID;	/* The name ID for entries in the 'name' table
103 				 * that provide a display string for this
104 				 * attribute value. */
105   HBFixed		nominalValue;	/* A numeric value for this attribute value. */
106   HBFixed		rangeMinValue;	/* The minimum value for a range associated
107 				 * with the specified name ID. */
108   HBFixed		rangeMaxValue;	/* The maximum value for a range associated
109 				 * with the specified name ID. */
110   public:
111   DEFINE_SIZE_STATIC (20);
112 };
113 
114 struct AxisValueFormat3
115 {
get_value_name_idOT::AxisValueFormat3116   hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
117 
sanitizeOT::AxisValueFormat3118   bool sanitize (hb_sanitize_context_t *c) const
119   {
120     TRACE_SANITIZE (this);
121     return_trace (likely (c->check_struct (this)));
122   }
123 
124   protected:
125   HBUINT16	format;		/* Format identifier — set to 3. */
126   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
127 				 * identifying the axis of design variation
128 				 * to which the axis value record applies.
129 				 * Must be less than designAxisCount. */
130   HBUINT16	flags;		/* Flags — see below for details. */
131   NameID	valueNameID;	/* The name ID for entries in the 'name' table
132 				 * that provide a display string for this
133 				 * attribute value. */
134   HBFixed		value;		/* A numeric value for this attribute value. */
135   HBFixed		linkedValue;	/* The numeric value for a style-linked mapping
136 				 * from this value. */
137   public:
138   DEFINE_SIZE_STATIC (16);
139 };
140 
141 struct AxisValueRecord
142 {
sanitizeOT::AxisValueRecord143   bool sanitize (hb_sanitize_context_t *c) const
144   {
145     TRACE_SANITIZE (this);
146     return_trace (likely (c->check_struct (this)));
147   }
148 
149   protected:
150   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
151 				 * identifying the axis to which this value
152 				 * applies. Must be less than designAxisCount. */
153   HBFixed		value;		/* A numeric value for this attribute value. */
154   public:
155   DEFINE_SIZE_STATIC (6);
156 };
157 
158 struct AxisValueFormat4
159 {
get_value_name_idOT::AxisValueFormat4160   hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
161 
sanitizeOT::AxisValueFormat4162   bool sanitize (hb_sanitize_context_t *c) const
163   {
164     TRACE_SANITIZE (this);
165     return_trace (likely (c->check_struct (this)));
166   }
167 
168   protected:
169   HBUINT16	format;		/* Format identifier — set to 4. */
170   HBUINT16	axisCount;	/* The total number of axes contributing to
171 				 * this axis-values combination. */
172   HBUINT16	flags;		/* Flags — see below for details. */
173   NameID	valueNameID;	/* The name ID for entries in the 'name' table
174 				 * that provide a display string for this
175 				 * attribute value. */
176   UnsizedArrayOf<AxisValueRecord>
177 		axisValues;	/* Array of AxisValue records that provide the
178 				 * combination of axis values, one for each
179 				 * contributing axis. */
180   public:
181   DEFINE_SIZE_ARRAY (8, axisValues);
182 };
183 
184 struct AxisValue
185 {
get_value_name_idOT::AxisValue186   hb_ot_name_id_t get_value_name_id () const
187   {
188     switch (u.format)
189     {
190     case 1: return u.format1.get_value_name_id ();
191     case 2: return u.format2.get_value_name_id ();
192     case 3: return u.format3.get_value_name_id ();
193     case 4: return u.format4.get_value_name_id ();
194     default:return HB_OT_NAME_ID_INVALID;
195     }
196   }
197 
sanitizeOT::AxisValue198   bool sanitize (hb_sanitize_context_t *c) const
199   {
200     TRACE_SANITIZE (this);
201     if (unlikely (!c->check_struct (this)))
202       return_trace (false);
203 
204     switch (u.format)
205     {
206     case 1: return_trace (u.format1.sanitize (c));
207     case 2: return_trace (u.format2.sanitize (c));
208     case 3: return_trace (u.format3.sanitize (c));
209     case 4: return_trace (u.format4.sanitize (c));
210     default:return_trace (true);
211     }
212   }
213 
214   protected:
215   union
216   {
217   HBUINT16		format;
218   AxisValueFormat1	format1;
219   AxisValueFormat2	format2;
220   AxisValueFormat3	format3;
221   AxisValueFormat4	format4;
222   } u;
223   public:
224   DEFINE_SIZE_UNION (2, format);
225 };
226 
227 struct StatAxisRecord
228 {
get_name_idOT::StatAxisRecord229   hb_ot_name_id_t get_name_id () const { return nameID; }
230 
sanitizeOT::StatAxisRecord231   bool sanitize (hb_sanitize_context_t *c) const
232   {
233     TRACE_SANITIZE (this);
234     return_trace (likely (c->check_struct (this)));
235   }
236 
237   protected:
238   Tag		tag;		/* A tag identifying the axis of design variation. */
239   NameID	nameID;		/* The name ID for entries in the 'name' table that
240 				 * provide a display string for this axis. */
241   HBUINT16	ordering;	/* A value that applications can use to determine
242 				 * primary sorting of face names, or for ordering
243 				 * of descriptors when composing family or face names. */
244   public:
245   DEFINE_SIZE_STATIC (8);
246 };
247 
248 struct STAT
249 {
250   static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT;
251 
has_dataOT::STAT252   bool has_data () const { return version.to_int (); }
253 
get_design_axis_countOT::STAT254   unsigned get_design_axis_count () const { return designAxisCount; }
255 
get_axis_record_name_idOT::STAT256   hb_ot_name_id_t get_axis_record_name_id (unsigned axis_record_index) const
257   {
258     if (unlikely (axis_record_index >= designAxisCount)) return HB_OT_NAME_ID_INVALID;
259     const StatAxisRecord &axis_record = get_design_axes ()[axis_record_index];
260     return axis_record.get_name_id ();
261   }
262 
get_axis_value_countOT::STAT263   unsigned get_axis_value_count () const { return axisValueCount; }
264 
get_axis_value_name_idOT::STAT265   hb_ot_name_id_t get_axis_value_name_id (unsigned axis_value_index) const
266   {
267     if (unlikely (axis_value_index >= axisValueCount)) return HB_OT_NAME_ID_INVALID;
268     const AxisValue &axis_value = (this + get_axis_value_offsets ()[axis_value_index]);
269     return axis_value.get_value_name_id ();
270   }
271 
collect_name_idsOT::STAT272   void collect_name_ids (hb_set_t *nameids_to_retain) const
273   {
274     if (!has_data ()) return;
275 
276     + get_design_axes ()
277     | hb_map (&StatAxisRecord::get_name_id)
278     | hb_sink (nameids_to_retain)
279     ;
280 
281     + get_axis_value_offsets ()
282     | hb_map (hb_add (&(this + offsetToAxisValueOffsets)))
283     | hb_map (&AxisValue::get_value_name_id)
284     | hb_sink (nameids_to_retain)
285     ;
286   }
287 
sanitizeOT::STAT288   bool sanitize (hb_sanitize_context_t *c) const
289   {
290     TRACE_SANITIZE (this);
291     return_trace (likely (c->check_struct (this) &&
292 			  version.major == 1 &&
293 			  version.minor > 0 &&
294 			  designAxesOffset.sanitize (c, this, designAxisCount) &&
295 			  offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
296   }
297 
298   protected:
get_design_axesOT::STAT299   hb_array_t<const StatAxisRecord> const get_design_axes () const
300   { return (this+designAxesOffset).as_array (designAxisCount); }
301 
get_axis_value_offsetsOT::STAT302   hb_array_t<const OffsetTo<AxisValue>> const get_axis_value_offsets () const
303   { return (this+offsetToAxisValueOffsets).as_array (axisValueCount); }
304 
305 
306   protected:
307   FixedVersion<>version;	/* Version of the stat table
308 				 * initially set to 0x00010002u */
309   HBUINT16	designAxisSize;	/* The size in bytes of each axis record. */
310   HBUINT16	designAxisCount;/* The number of design axis records. In a
311 				 * font with an 'fvar' table, this value must be
312 				 * greater than or equal to the axisCount value
313 				 * in the 'fvar' table. In all fonts, must
314 				 * be greater than zero if axisValueCount
315 				 * is greater than zero. */
316   LNNOffsetTo<UnsizedArrayOf<StatAxisRecord>>
317 		designAxesOffset;
318 				/* Offset in bytes from the beginning of
319 				 * the STAT table to the start of the design
320 				 * axes array. If designAxisCount is zero,
321 				 * set to zero; if designAxisCount is greater
322 				 * than zero, must be greater than zero. */
323   HBUINT16	axisValueCount;	/* The number of axis value tables. */
324   LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue>>>
325 		offsetToAxisValueOffsets;
326 				/* Offset in bytes from the beginning of
327 				 * the STAT table to the start of the design
328 				 * axes value offsets array. If axisValueCount
329 				 * is zero, set to zero; if axisValueCount is
330 				 * greater than zero, must be greater than zero. */
331   NameID	elidedFallbackNameID;
332 				/* Name ID used as fallback when projection of
333 				 * names into a particular font model produces
334 				 * a subfamily name containing only elidable
335 				 * elements. */
336   public:
337   DEFINE_SIZE_STATIC (20);
338 };
339 
340 
341 } /* namespace OT */
342 
343 
344 #endif /* HB_OT_STAT_TABLE_HH */
345