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 {
  62   bool sanitize (hb_sanitize_context_t *c) const
  63   {
  64     TRACE_SANITIZE (this);
  65     return_trace (likely (c->check_struct (this)));
  66   }
  67 
  68   protected:
  69   HBUINT16      format;         /* Format identifier — set to 1. */
  70   HBUINT16      axisIndex;      /* Zero-base index into the axis record array
  71                                  * identifying the axis of design variation
  72                                  * to which the axis value record applies.
  73                                  * Must be less than designAxisCount. */
  74   HBUINT16      flags;          /* Flags — see below for details. */
  75   NameID        valueNameID;    /* The name ID for entries in the 'name' table
  76                                  * that provide a display string for this
  77                                  * attribute value. */
  78   Fixed         value;          /* A numeric value for this attribute value. */
  79   public:
  80   DEFINE_SIZE_STATIC (12);
  81 };
  82 
  83 struct AxisValueFormat2
  84 {
  85   bool sanitize (hb_sanitize_context_t *c) const
  86   {
  87     TRACE_SANITIZE (this);
  88     return_trace (likely (c->check_struct (this)));
  89   }
  90 
  91   protected:
  92   HBUINT16      format;         /* Format identifier — set to 2. */
  93   HBUINT16      axisIndex;      /* Zero-base index into the axis record array
  94                                  * identifying the axis of design variation
  95                                  * to which the axis value record applies.
  96                                  * Must be less than designAxisCount. */
  97   HBUINT16      flags;          /* Flags — see below for details. */
  98   NameID        valueNameID;    /* The name ID for entries in the 'name' table
  99                                  * that provide a display string for this
 100                                  * attribute value. */
 101   Fixed         nominalValue;   /* A numeric value for this attribute value. */
 102   Fixed         rangeMinValue;  /* The minimum value for a range associated
 103                                  * with the specified name ID. */
 104   Fixed         rangeMaxValue;  /* The maximum value for a range associated
 105                                  * with the specified name ID. */
 106   public:
 107   DEFINE_SIZE_STATIC (20);
 108 };
 109 
 110 struct AxisValueFormat3
 111 {
 112   bool sanitize (hb_sanitize_context_t *c) const
 113   {
 114     TRACE_SANITIZE (this);
 115     return_trace (likely (c->check_struct (this)));
 116   }
 117 
 118   protected:
 119   HBUINT16      format;         /* Format identifier — set to 3. */
 120   HBUINT16      axisIndex;      /* Zero-base index into the axis record array
 121                                  * identifying the axis of design variation
 122                                  * to which the axis value record applies.
 123                                  * Must be less than designAxisCount. */
 124   HBUINT16      flags;          /* Flags — see below for details. */
 125   NameID        valueNameID;    /* The name ID for entries in the 'name' table
 126                                  * that provide a display string for this
 127                                  * attribute value. */
 128   Fixed         value;          /* A numeric value for this attribute value. */
 129   Fixed         linkedValue;    /* The numeric value for a style-linked mapping
 130                                  * from this value. */
 131   public:
 132   DEFINE_SIZE_STATIC (16);
 133 };
 134 
 135 struct AxisValueRecord
 136 {
 137   bool sanitize (hb_sanitize_context_t *c) const
 138   {
 139     TRACE_SANITIZE (this);
 140     return_trace (likely (c->check_struct (this)));
 141   }
 142 
 143   protected:
 144   HBUINT16      axisIndex;      /* Zero-base index into the axis record array
 145                                  * identifying the axis to which this value
 146                                  * applies. Must be less than designAxisCount. */
 147   Fixed         value;          /* A numeric value for this attribute value. */
 148   public:
 149   DEFINE_SIZE_STATIC (6);
 150 };
 151 
 152 struct AxisValueFormat4
 153 {
 154   bool sanitize (hb_sanitize_context_t *c) const
 155   {
 156     TRACE_SANITIZE (this);
 157     return_trace (likely (c->check_struct (this)));
 158   }
 159 
 160   protected:
 161   HBUINT16      format;         /* Format identifier — set to 4. */
 162   HBUINT16      axisCount;      /* The total number of axes contributing to
 163                                  * this axis-values combination. */
 164   HBUINT16      flags;          /* Flags — see below for details. */
 165   NameID        valueNameID;    /* The name ID for entries in the 'name' table
 166                                  * that provide a display string for this
 167                                  * attribute value. */
 168   UnsizedArrayOf<AxisValueRecord>
 169                 axisValues;     /* Array of AxisValue records that provide the
 170                                  * combination of axis values, one for each
 171                                  * contributing axis. */
 172   public:
 173   DEFINE_SIZE_ARRAY (8, axisValues);
 174 };
 175 
 176 struct AxisValue
 177 {
 178   bool sanitize (hb_sanitize_context_t *c) const
 179   {
 180     TRACE_SANITIZE (this);
 181     if (unlikely (c->check_struct (this)))
 182       return_trace (false);
 183 
 184     switch (u.format)
 185     {
 186     case 1:  return_trace (likely (u.format1.sanitize (c)));
 187     case 2:  return_trace (likely (u.format2.sanitize (c)));
 188     case 3:  return_trace (likely (u.format3.sanitize (c)));
 189     case 4:  return_trace (likely (u.format4.sanitize (c)));
 190     default: return_trace (true);
 191     }
 192   }
 193 
 194   protected:
 195   union
 196   {
 197   HBUINT16              format;
 198   AxisValueFormat1      format1;
 199   AxisValueFormat2      format2;
 200   AxisValueFormat3      format3;
 201   AxisValueFormat4      format4;
 202   } u;
 203   public:
 204   DEFINE_SIZE_UNION (2, format);
 205 };
 206 
 207 struct StatAxisRecord
 208 {
 209   bool sanitize (hb_sanitize_context_t *c) const
 210   {
 211     TRACE_SANITIZE (this);
 212     return_trace (likely (c->check_struct (this)));
 213   }
 214 
 215   protected:
 216   Tag           tag;            /* A tag identifying the axis of design variation. */
 217   NameID        nameID;         /* The name ID for entries in the 'name' table that
 218                                  * provide a display string for this axis. */
 219   HBUINT16      ordering;       /* A value that applications can use to determine
 220                                  * primary sorting of face names, or for ordering
 221                                  * of descriptors when composing family or face names. */
 222   public:
 223   DEFINE_SIZE_STATIC (8);
 224 };
 225 
 226 struct STAT
 227 {
 228   static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT;
 229 
 230   bool sanitize (hb_sanitize_context_t *c) const
 231   {
 232     TRACE_SANITIZE (this);
 233     return_trace (likely (c->check_struct (this) &&
 234                           majorVersion == 1 &&
 235                           minorVersion > 0 &&
 236                           designAxesOffset.sanitize (c, this, designAxisCount) &&
 237                           offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
 238   }
 239 
 240   protected:
 241   HBUINT16      majorVersion;   /* Major version number of the style attributes
 242                                  * table — set to 1. */
 243   HBUINT16      minorVersion;   /* Minor version number of the style attributes
 244                                  * table — set to 2. */
 245   HBUINT16      designAxisSize; /* The size in bytes of each axis record. */
 246   HBUINT16      designAxisCount;/* The number of design axis records. In a
 247                                  * font with an 'fvar' table, this value must be
 248                                  * greater than or equal to the axisCount value
 249                                  * in the 'fvar' table. In all fonts, must
 250                                  * be greater than zero if axisValueCount
 251                                  * is greater than zero. */
 252   LNNOffsetTo<UnsizedArrayOf<StatAxisRecord> >
 253                 designAxesOffset;
 254                                 /* Offset in bytes from the beginning of
 255                                  * the STAT table to the start of the design
 256                                  * axes array. If designAxisCount is zero,
 257                                  * set to zero; if designAxisCount is greater
 258                                  * than zero, must be greater than zero. */
 259   HBUINT16      axisValueCount; /* The number of axis value tables. */
 260   LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue> > >
 261                 offsetToAxisValueOffsets;
 262                                 /* Offset in bytes from the beginning of
 263                                  * the STAT table to the start of the design
 264                                  * axes value offsets array. If axisValueCount
 265                                  * is zero, set to zero; if axisValueCount is
 266                                  * greater than zero, must be greater than zero. */
 267   NameID        elidedFallbackNameID;
 268                                 /* Name ID used as fallback when projection of
 269                                  * names into a particular font model produces
 270                                  * a subfamily name containing only elidable
 271                                  * elements. */
 272   public:
 273   DEFINE_SIZE_STATIC (20);
 274 };
 275 
 276 
 277 } /* namespace OT */
 278 
 279 
 280 #endif /* HB_OT_STAT_TABLE_HH */