• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2021  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  */
25 
26 #ifndef HB_OT_VAR_COMMON_HH
27 #define HB_OT_VAR_COMMON_HH
28 
29 #include "hb-ot-layout-common.hh"
30 
31 
32 namespace OT {
33 
34 template <typename MapCountT>
35 struct DeltaSetIndexMapFormat01
36 {
37   friend struct DeltaSetIndexMap;
38 
39   private:
copyOT::DeltaSetIndexMapFormat0140   DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
41   {
42     TRACE_SERIALIZE (this);
43     auto *out = c->start_embed (this);
44     if (unlikely (!out)) return_trace (nullptr);
45 
46     unsigned total_size = min_size + mapCount * get_width ();
47     HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
48     if (unlikely (!p)) return_trace (nullptr);
49 
50     hb_memcpy (p, this, HBUINT8::static_size * total_size);
51     return_trace (out);
52   }
53 
54   template <typename T>
serializeOT::DeltaSetIndexMapFormat0155   bool serialize (hb_serialize_context_t *c, const T &plan)
56   {
57     unsigned int width = plan.get_width ();
58     unsigned int inner_bit_count = plan.get_inner_bit_count ();
59     const hb_array_t<const uint32_t> output_map = plan.get_output_map ();
60 
61     TRACE_SERIALIZE (this);
62     if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
63       return_trace (false);
64     if (unlikely (!c->extend_min (this))) return_trace (false);
65 
66     entryFormat = ((width-1)<<4)|(inner_bit_count-1);
67     mapCount = output_map.length;
68     HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
69     if (unlikely (!p)) return_trace (false);
70     for (unsigned int i = 0; i < output_map.length; i++)
71     {
72       unsigned int v = output_map[i];
73       unsigned int outer = v >> 16;
74       unsigned int inner = v & 0xFFFF;
75       unsigned int u = (outer << inner_bit_count) | inner;
76       for (unsigned int w = width; w > 0;)
77       {
78         p[--w] = u;
79         u >>= 8;
80       }
81       p += width;
82     }
83     return_trace (true);
84   }
85 
mapOT::DeltaSetIndexMapFormat0186   uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
87   {
88     /* If count is zero, pass value unchanged.  This takes
89      * care of direct mapping for advance map. */
90     if (!mapCount)
91       return v;
92 
93     if (v >= mapCount)
94       v = mapCount - 1;
95 
96     unsigned int u = 0;
97     { /* Fetch it. */
98       unsigned int w = get_width ();
99       const HBUINT8 *p = mapDataZ.arrayZ + w * v;
100       for (; w; w--)
101         u = (u << 8) + *p++;
102     }
103 
104     { /* Repack it. */
105       unsigned int n = get_inner_bit_count ();
106       unsigned int outer = u >> n;
107       unsigned int inner = u & ((1 << n) - 1);
108       u = (outer<<16) | inner;
109     }
110 
111     return u;
112   }
113 
get_map_countOT::DeltaSetIndexMapFormat01114   unsigned get_map_count () const       { return mapCount; }
get_widthOT::DeltaSetIndexMapFormat01115   unsigned get_width () const           { return ((entryFormat >> 4) & 3) + 1; }
get_inner_bit_countOT::DeltaSetIndexMapFormat01116   unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
117 
118 
sanitizeOT::DeltaSetIndexMapFormat01119   bool sanitize (hb_sanitize_context_t *c) const
120   {
121     TRACE_SANITIZE (this);
122     return_trace (c->check_struct (this) &&
123                   c->check_range (mapDataZ.arrayZ,
124                                   mapCount,
125                                   get_width ()));
126   }
127 
128   protected:
129   HBUINT8       format;         /* Format identifier--format = 0 */
130   HBUINT8       entryFormat;    /* A packed field that describes the compressed
131                                  * representation of delta-set indices. */
132   MapCountT     mapCount;       /* The number of mapping entries. */
133   UnsizedArrayOf<HBUINT8>
134                 mapDataZ;       /* The delta-set index mapping data. */
135 
136   public:
137   DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ);
138 };
139 
140 struct DeltaSetIndexMap
141 {
142   template <typename T>
serializeOT::DeltaSetIndexMap143   bool serialize (hb_serialize_context_t *c, const T &plan)
144   {
145     TRACE_SERIALIZE (this);
146     unsigned length = plan.get_output_map ().length;
147     u.format = length <= 0xFFFF ? 0 : 1;
148     switch (u.format) {
149     case 0: return_trace (u.format0.serialize (c, plan));
150     case 1: return_trace (u.format1.serialize (c, plan));
151     default:return_trace (false);
152     }
153   }
154 
mapOT::DeltaSetIndexMap155   uint32_t map (unsigned v) const
156   {
157     switch (u.format) {
158     case 0: return (u.format0.map (v));
159     case 1: return (u.format1.map (v));
160     default:return v;
161     }
162   }
163 
get_map_countOT::DeltaSetIndexMap164   unsigned get_map_count () const
165   {
166     switch (u.format) {
167     case 0: return u.format0.get_map_count ();
168     case 1: return u.format1.get_map_count ();
169     default:return 0;
170     }
171   }
172 
get_widthOT::DeltaSetIndexMap173   unsigned get_width () const
174   {
175     switch (u.format) {
176     case 0: return u.format0.get_width ();
177     case 1: return u.format1.get_width ();
178     default:return 0;
179     }
180   }
181 
get_inner_bit_countOT::DeltaSetIndexMap182   unsigned get_inner_bit_count () const
183   {
184     switch (u.format) {
185     case 0: return u.format0.get_inner_bit_count ();
186     case 1: return u.format1.get_inner_bit_count ();
187     default:return 0;
188     }
189   }
190 
sanitizeOT::DeltaSetIndexMap191   bool sanitize (hb_sanitize_context_t *c) const
192   {
193     TRACE_SANITIZE (this);
194     if (!u.format.sanitize (c)) return_trace (false);
195     switch (u.format) {
196     case 0: return_trace (u.format0.sanitize (c));
197     case 1: return_trace (u.format1.sanitize (c));
198     default:return_trace (true);
199     }
200   }
201 
copyOT::DeltaSetIndexMap202   DeltaSetIndexMap* copy (hb_serialize_context_t *c) const
203   {
204     TRACE_SERIALIZE (this);
205     switch (u.format) {
206     case 0: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c)));
207     case 1: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c)));
208     default:return_trace (nullptr);
209     }
210   }
211 
212   protected:
213   union {
214   HBUINT8                            format;         /* Format identifier */
215   DeltaSetIndexMapFormat01<HBUINT16> format0;
216   DeltaSetIndexMapFormat01<HBUINT32> format1;
217   } u;
218   public:
219   DEFINE_SIZE_UNION (1, format);
220 };
221 
222 
223 struct VarStoreInstancer
224 {
VarStoreInstancerOT::VarStoreInstancer225   VarStoreInstancer (const VariationStore &varStore,
226 		     const DeltaSetIndexMap &varIdxMap,
227 		     hb_array_t<int> coords) :
228     varStore (varStore), varIdxMap (varIdxMap), coords (coords) {}
229 
operator boolOT::VarStoreInstancer230   operator bool () const { return bool (coords); }
231 
operator ()OT::VarStoreInstancer232   float operator() (uint32_t varIdx, unsigned short offset = 0) const
233   { return varStore.get_delta (varIdxMap.map (VarIdx::add (varIdx, offset)), coords); }
234 
235   const VariationStore &varStore;
236   const DeltaSetIndexMap &varIdxMap;
237   hb_array_t<int> coords;
238 };
239 
240 
241 } /* namespace OT */
242 
243 
244 #endif /* HB_OT_VAR_COMMON_HH */
245