Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  2017  Google, Inc.
      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  * Google Author(s): Behdad Esfahbod
     25  */
     26 
     27 #ifndef HB_OT_VAR_AVAR_TABLE_HH
     28 #define HB_OT_VAR_AVAR_TABLE_HH
     29 
     30 #include "hb-open-type.hh"
     31 
     32 /*
     33  * avar -- Axis Variations
     34  * https://docs.microsoft.com/en-us/typography/opentype/spec/avar
     35  */
     36 
     37 #define HB_OT_TAG_avar HB_TAG('a','v','a','r')
     38 
     39 
     40 namespace OT {
     41 
     42 
     43 struct AxisValueMap
     44 {
     45   bool sanitize (hb_sanitize_context_t *c) const
     46   {
     47     TRACE_SANITIZE (this);
     48     return_trace (c->check_struct (this));
     49   }
     50 
     51   public:
     52   F2DOT14	fromCoord;	/* A normalized coordinate value obtained using
     53 				 * default normalization. */
     54   F2DOT14	toCoord;	/* The modified, normalized coordinate value. */
     55 
     56   public:
     57   DEFINE_SIZE_STATIC (4);
     58 };
     59 
     60 struct SegmentMaps : ArrayOf<AxisValueMap>
     61 {
     62   int map (int value) const
     63   {
     64     /* The following special-cases are not part of OpenType, which requires
     65      * that at least -1, 0, and +1 must be mapped. But we include these as
     66      * part of a better error recovery scheme. */
     67 
     68     if (len < 2)
     69     {
     70       if (!len)
     71 	return value;
     72       else /* len == 1*/
     73 	return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
     74     }
     75 
     76     if (value <= arrayZ[0].fromCoord)
     77       return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
     78 
     79     unsigned int i;
     80     unsigned int count = len;
     81     for (i = 1; i < count && value > arrayZ[i].fromCoord; i++)
     82       ;
     83 
     84     if (value >= arrayZ[i].fromCoord)
     85       return value - arrayZ[i].fromCoord + arrayZ[i].toCoord;
     86 
     87     if (unlikely (arrayZ[i-1].fromCoord == arrayZ[i].fromCoord))
     88       return arrayZ[i-1].toCoord;
     89 
     90     int denom = arrayZ[i].fromCoord - arrayZ[i-1].fromCoord;
     91     return arrayZ[i-1].toCoord +
     92 	   ((arrayZ[i].toCoord - arrayZ[i-1].toCoord) *
     93 	    (value - arrayZ[i-1].fromCoord) + denom/2) / denom;
     94   }
     95 
     96   public:
     97   DEFINE_SIZE_ARRAY (2, *this);
     98 };
     99 
    100 struct avar
    101 {
    102   enum { tableTag = HB_OT_TAG_avar };
    103 
    104   bool sanitize (hb_sanitize_context_t *c) const
    105   {
    106     TRACE_SANITIZE (this);
    107     if (unlikely (!(version.sanitize (c) &&
    108 		    version.major == 1 &&
    109 		    c->check_struct (this))))
    110       return_trace (false);
    111 
    112     const SegmentMaps *map = &firstAxisSegmentMaps;
    113     unsigned int count = axisCount;
    114     for (unsigned int i = 0; i < count; i++)
    115     {
    116       if (unlikely (!map->sanitize (c)))
    117         return_trace (false);
    118       map = &StructAfter<SegmentMaps> (*map);
    119     }
    120 
    121     return_trace (true);
    122   }
    123 
    124   void map_coords (int *coords, unsigned int coords_length) const
    125   {
    126     unsigned int count = MIN<unsigned int> (coords_length, axisCount);
    127 
    128     const SegmentMaps *map = &firstAxisSegmentMaps;
    129     for (unsigned int i = 0; i < count; i++)
    130     {
    131       coords[i] = map->map (coords[i]);
    132       map = &StructAfter<SegmentMaps> (*map);
    133     }
    134   }
    135 
    136   protected:
    137   FixedVersion<>version;	/* Version of the avar table
    138 				 * initially set to 0x00010000u */
    139   HBUINT16	reserved;	/* This field is permanently reserved. Set to 0. */
    140   HBUINT16	axisCount;	/* The number of variation axes in the font. This
    141 				 * must be the same number as axisCount in the
    142 				 * 'fvar' table. */
    143   SegmentMaps   firstAxisSegmentMaps;
    144 
    145   public:
    146   DEFINE_SIZE_MIN (8);
    147 };
    148 
    149 } /* namespace OT */
    150 
    151 
    152 #endif /* HB_OT_VAR_AVAR_TABLE_HH */
    153