1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright © 2017  Google, Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci *  This is part of HarfBuzz, a text shaping library.
5cb93a386Sopenharmony_ci *
6cb93a386Sopenharmony_ci * Permission is hereby granted, without written agreement and without
7cb93a386Sopenharmony_ci * license or royalty fees, to use, copy, modify, and distribute this
8cb93a386Sopenharmony_ci * software and its documentation for any purpose, provided that the
9cb93a386Sopenharmony_ci * above copyright notice and the following two paragraphs appear in
10cb93a386Sopenharmony_ci * all copies of this software.
11cb93a386Sopenharmony_ci *
12cb93a386Sopenharmony_ci * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13cb93a386Sopenharmony_ci * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14cb93a386Sopenharmony_ci * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15cb93a386Sopenharmony_ci * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16cb93a386Sopenharmony_ci * DAMAGE.
17cb93a386Sopenharmony_ci *
18cb93a386Sopenharmony_ci * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19cb93a386Sopenharmony_ci * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20cb93a386Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21cb93a386Sopenharmony_ci * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22cb93a386Sopenharmony_ci * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23cb93a386Sopenharmony_ci *
24cb93a386Sopenharmony_ci * Google Author(s): Behdad Esfahbod
25cb93a386Sopenharmony_ci */
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ci#ifndef HB_OT_VAR_AVAR_TABLE_HH
28cb93a386Sopenharmony_ci#define HB_OT_VAR_AVAR_TABLE_HH
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ci#include "hb-open-type.hh"
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci/*
33cb93a386Sopenharmony_ci * avar -- Axis Variations
34cb93a386Sopenharmony_ci * https://docs.microsoft.com/en-us/typography/opentype/spec/avar
35cb93a386Sopenharmony_ci */
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ci#define HB_OT_TAG_avar HB_TAG('a','v','a','r')
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_cinamespace OT {
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_cistruct AxisValueMap
44cb93a386Sopenharmony_ci{
45cb93a386Sopenharmony_ci  bool sanitize (hb_sanitize_context_t *c) const
46cb93a386Sopenharmony_ci  {
47cb93a386Sopenharmony_ci    TRACE_SANITIZE (this);
48cb93a386Sopenharmony_ci    return_trace (c->check_struct (this));
49cb93a386Sopenharmony_ci  }
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ci  public:
52cb93a386Sopenharmony_ci  F2DOT14	coords[2];
53cb93a386Sopenharmony_ci//   F2DOT14	fromCoord;	/* A normalized coordinate value obtained using
54cb93a386Sopenharmony_ci//				 * default normalization. */
55cb93a386Sopenharmony_ci//   F2DOT14	toCoord;	/* The modified, normalized coordinate value. */
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci  public:
58cb93a386Sopenharmony_ci  DEFINE_SIZE_STATIC (4);
59cb93a386Sopenharmony_ci};
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_cistruct SegmentMaps : Array16Of<AxisValueMap>
62cb93a386Sopenharmony_ci{
63cb93a386Sopenharmony_ci  int map (int value, unsigned int from_offset = 0, unsigned int to_offset = 1) const
64cb93a386Sopenharmony_ci  {
65cb93a386Sopenharmony_ci#define fromCoord coords[from_offset]
66cb93a386Sopenharmony_ci#define toCoord coords[to_offset]
67cb93a386Sopenharmony_ci    /* The following special-cases are not part of OpenType, which requires
68cb93a386Sopenharmony_ci     * that at least -1, 0, and +1 must be mapped. But we include these as
69cb93a386Sopenharmony_ci     * part of a better error recovery scheme. */
70cb93a386Sopenharmony_ci    if (len < 2)
71cb93a386Sopenharmony_ci    {
72cb93a386Sopenharmony_ci      if (!len)
73cb93a386Sopenharmony_ci	return value;
74cb93a386Sopenharmony_ci      else /* len == 1*/
75cb93a386Sopenharmony_ci	return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
76cb93a386Sopenharmony_ci    }
77cb93a386Sopenharmony_ci
78cb93a386Sopenharmony_ci    if (value <= arrayZ[0].fromCoord)
79cb93a386Sopenharmony_ci      return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci    unsigned int i;
82cb93a386Sopenharmony_ci    unsigned int count = len - 1;
83cb93a386Sopenharmony_ci    for (i = 1; i < count && value > arrayZ[i].fromCoord; i++)
84cb93a386Sopenharmony_ci      ;
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci    if (value >= arrayZ[i].fromCoord)
87cb93a386Sopenharmony_ci      return value - arrayZ[i].fromCoord + arrayZ[i].toCoord;
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci    if (unlikely (arrayZ[i-1].fromCoord == arrayZ[i].fromCoord))
90cb93a386Sopenharmony_ci      return arrayZ[i-1].toCoord;
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ci    int denom = arrayZ[i].fromCoord - arrayZ[i-1].fromCoord;
93cb93a386Sopenharmony_ci    return roundf (arrayZ[i-1].toCoord + ((float) (arrayZ[i].toCoord - arrayZ[i-1].toCoord) *
94cb93a386Sopenharmony_ci					  (value - arrayZ[i-1].fromCoord)) / denom);
95cb93a386Sopenharmony_ci#undef toCoord
96cb93a386Sopenharmony_ci#undef fromCoord
97cb93a386Sopenharmony_ci  }
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_ci  int unmap (int value) const { return map (value, 1, 0); }
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci  public:
102cb93a386Sopenharmony_ci  DEFINE_SIZE_ARRAY (2, *this);
103cb93a386Sopenharmony_ci};
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_cistruct avar
106cb93a386Sopenharmony_ci{
107cb93a386Sopenharmony_ci  static constexpr hb_tag_t tableTag = HB_OT_TAG_avar;
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci  bool sanitize (hb_sanitize_context_t *c) const
110cb93a386Sopenharmony_ci  {
111cb93a386Sopenharmony_ci    TRACE_SANITIZE (this);
112cb93a386Sopenharmony_ci    if (unlikely (!(version.sanitize (c) &&
113cb93a386Sopenharmony_ci		    version.major == 1 &&
114cb93a386Sopenharmony_ci		    c->check_struct (this))))
115cb93a386Sopenharmony_ci      return_trace (false);
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    const SegmentMaps *map = &firstAxisSegmentMaps;
118cb93a386Sopenharmony_ci    unsigned int count = axisCount;
119cb93a386Sopenharmony_ci    for (unsigned int i = 0; i < count; i++)
120cb93a386Sopenharmony_ci    {
121cb93a386Sopenharmony_ci      if (unlikely (!map->sanitize (c)))
122cb93a386Sopenharmony_ci	return_trace (false);
123cb93a386Sopenharmony_ci      map = &StructAfter<SegmentMaps> (*map);
124cb93a386Sopenharmony_ci    }
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci    return_trace (true);
127cb93a386Sopenharmony_ci  }
128cb93a386Sopenharmony_ci
129cb93a386Sopenharmony_ci  void map_coords (int *coords, unsigned int coords_length) const
130cb93a386Sopenharmony_ci  {
131cb93a386Sopenharmony_ci    unsigned int count = hb_min (coords_length, axisCount);
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci    const SegmentMaps *map = &firstAxisSegmentMaps;
134cb93a386Sopenharmony_ci    for (unsigned int i = 0; i < count; i++)
135cb93a386Sopenharmony_ci    {
136cb93a386Sopenharmony_ci      coords[i] = map->map (coords[i]);
137cb93a386Sopenharmony_ci      map = &StructAfter<SegmentMaps> (*map);
138cb93a386Sopenharmony_ci    }
139cb93a386Sopenharmony_ci  }
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_ci  void unmap_coords (int *coords, unsigned int coords_length) const
142cb93a386Sopenharmony_ci  {
143cb93a386Sopenharmony_ci    unsigned int count = hb_min (coords_length, axisCount);
144cb93a386Sopenharmony_ci
145cb93a386Sopenharmony_ci    const SegmentMaps *map = &firstAxisSegmentMaps;
146cb93a386Sopenharmony_ci    for (unsigned int i = 0; i < count; i++)
147cb93a386Sopenharmony_ci    {
148cb93a386Sopenharmony_ci      coords[i] = map->unmap (coords[i]);
149cb93a386Sopenharmony_ci      map = &StructAfter<SegmentMaps> (*map);
150cb93a386Sopenharmony_ci    }
151cb93a386Sopenharmony_ci  }
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_ci  protected:
154cb93a386Sopenharmony_ci  FixedVersion<>version;	/* Version of the avar table
155cb93a386Sopenharmony_ci				 * initially set to 0x00010000u */
156cb93a386Sopenharmony_ci  HBUINT16	reserved;	/* This field is permanently reserved. Set to 0. */
157cb93a386Sopenharmony_ci  HBUINT16	axisCount;	/* The number of variation axes in the font. This
158cb93a386Sopenharmony_ci				 * must be the same number as axisCount in the
159cb93a386Sopenharmony_ci				 * 'fvar' table. */
160cb93a386Sopenharmony_ci  SegmentMaps	firstAxisSegmentMaps;
161cb93a386Sopenharmony_ci
162cb93a386Sopenharmony_ci  public:
163cb93a386Sopenharmony_ci  DEFINE_SIZE_MIN (8);
164cb93a386Sopenharmony_ci};
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ci} /* namespace OT */
167cb93a386Sopenharmony_ci
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci#endif /* HB_OT_VAR_AVAR_TABLE_HH */
170