/src/harfbuzz/src/hb-ot-var-common.hh
Line | Count | Source (jump to first uncovered line) |
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: |
40 | | DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const |
41 | 0 | { |
42 | 0 | TRACE_SERIALIZE (this); |
43 | 0 | auto *out = c->start_embed (this); |
44 | 0 | if (unlikely (!out)) return_trace (nullptr); |
45 | 0 |
|
46 | 0 | unsigned total_size = min_size + mapCount * get_width (); |
47 | 0 | HBUINT8 *p = c->allocate_size<HBUINT8> (total_size); |
48 | 0 | if (unlikely (!p)) return_trace (nullptr); |
49 | 0 |
|
50 | 0 | hb_memcpy (p, this, HBUINT8::static_size * total_size); |
51 | 0 | return_trace (out); |
52 | 0 | } Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned short, 2u> >::copy(hb_serialize_context_t*) const Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned int, 4u> >::copy(hb_serialize_context_t*) const |
53 | | |
54 | | template <typename T> |
55 | | bool serialize (hb_serialize_context_t *c, const T &plan) |
56 | 0 | { |
57 | 0 | unsigned int width = plan.get_width (); |
58 | 0 | unsigned int inner_bit_count = plan.get_inner_bit_count (); |
59 | 0 | const hb_array_t<const uint32_t> output_map = plan.get_output_map (); |
60 | 0 |
|
61 | 0 | TRACE_SERIALIZE (this); |
62 | 0 | if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0)))) |
63 | 0 | return_trace (false); |
64 | 0 | if (unlikely (!c->extend_min (this))) return_trace (false); |
65 | 0 |
|
66 | 0 | entryFormat = ((width-1)<<4)|(inner_bit_count-1); |
67 | 0 | mapCount = output_map.length; |
68 | 0 | HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length); |
69 | 0 | if (unlikely (!p)) return_trace (false); |
70 | 0 | for (unsigned int i = 0; i < output_map.length; i++) |
71 | 0 | { |
72 | 0 | unsigned int v = output_map[i]; |
73 | 0 | unsigned int outer = v >> 16; |
74 | 0 | unsigned int inner = v & 0xFFFF; |
75 | 0 | unsigned int u = (outer << inner_bit_count) | inner; |
76 | 0 | for (unsigned int w = width; w > 0;) |
77 | 0 | { |
78 | 0 | p[--w] = u; |
79 | 0 | u >>= 8; |
80 | 0 | } |
81 | 0 | p += width; |
82 | 0 | } |
83 | 0 | return_trace (true); |
84 | 0 | } Unexecuted instantiation: bool OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned short, 2u> >::serialize<OT::index_map_subset_plan_t>(hb_serialize_context_t*, OT::index_map_subset_plan_t const&) Unexecuted instantiation: bool OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned int, 4u> >::serialize<OT::index_map_subset_plan_t>(hb_serialize_context_t*, OT::index_map_subset_plan_t const&) |
85 | | |
86 | | uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */ |
87 | 1.03M | { |
88 | | /* If count is zero, pass value unchanged. This takes |
89 | | * care of direct mapping for advance map. */ |
90 | 1.03M | if (!mapCount) |
91 | 925k | return v; |
92 | | |
93 | 106k | if (v >= mapCount) |
94 | 97.9k | v = mapCount - 1; |
95 | | |
96 | 106k | unsigned int u = 0; |
97 | 106k | { /* Fetch it. */ |
98 | 106k | unsigned int w = get_width (); |
99 | 106k | const HBUINT8 *p = mapDataZ.arrayZ + w * v; |
100 | 225k | for (; w; w--) |
101 | 118k | u = (u << 8) + *p++; |
102 | 106k | } |
103 | | |
104 | 106k | { /* Repack it. */ |
105 | 106k | unsigned int n = get_inner_bit_count (); |
106 | 106k | unsigned int outer = u >> n; |
107 | 106k | unsigned int inner = u & ((1 << n) - 1); |
108 | 106k | u = (outer<<16) | inner; |
109 | 106k | } |
110 | | |
111 | 106k | return u; |
112 | 1.03M | } OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned short, 2u> >::map(unsigned int) const Line | Count | Source | 87 | 1.02M | { | 88 | | /* If count is zero, pass value unchanged. This takes | 89 | | * care of direct mapping for advance map. */ | 90 | 1.02M | if (!mapCount) | 91 | 920k | return v; | 92 | | | 93 | 104k | if (v >= mapCount) | 94 | 96.2k | v = mapCount - 1; | 95 | | | 96 | 104k | unsigned int u = 0; | 97 | 104k | { /* Fetch it. */ | 98 | 104k | unsigned int w = get_width (); | 99 | 104k | const HBUINT8 *p = mapDataZ.arrayZ + w * v; | 100 | 218k | for (; w; w--) | 101 | 113k | u = (u << 8) + *p++; | 102 | 104k | } | 103 | | | 104 | 104k | { /* Repack it. */ | 105 | 104k | unsigned int n = get_inner_bit_count (); | 106 | 104k | unsigned int outer = u >> n; | 107 | 104k | unsigned int inner = u & ((1 << n) - 1); | 108 | 104k | u = (outer<<16) | inner; | 109 | 104k | } | 110 | | | 111 | 104k | return u; | 112 | 1.02M | } |
OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned int, 4u> >::map(unsigned int) const Line | Count | Source | 87 | 8.20k | { | 88 | | /* If count is zero, pass value unchanged. This takes | 89 | | * care of direct mapping for advance map. */ | 90 | 8.20k | if (!mapCount) | 91 | 5.71k | return v; | 92 | | | 93 | 2.49k | if (v >= mapCount) | 94 | 1.66k | v = mapCount - 1; | 95 | | | 96 | 2.49k | unsigned int u = 0; | 97 | 2.49k | { /* Fetch it. */ | 98 | 2.49k | unsigned int w = get_width (); | 99 | 2.49k | const HBUINT8 *p = mapDataZ.arrayZ + w * v; | 100 | 7.02k | for (; w; w--) | 101 | 4.53k | u = (u << 8) + *p++; | 102 | 2.49k | } | 103 | | | 104 | 2.49k | { /* Repack it. */ | 105 | 2.49k | unsigned int n = get_inner_bit_count (); | 106 | 2.49k | unsigned int outer = u >> n; | 107 | 2.49k | unsigned int inner = u & ((1 << n) - 1); | 108 | 2.49k | u = (outer<<16) | inner; | 109 | 2.49k | } | 110 | | | 111 | 2.49k | return u; | 112 | 8.20k | } |
|
113 | | |
114 | 0 | unsigned get_map_count () const { return mapCount; }Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned short, 2u> >::get_map_count() const Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned int, 4u> >::get_map_count() const |
115 | 129k | unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; }OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned short, 2u> >::get_width() const Line | Count | Source | 115 | 125k | unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; } |
OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned int, 4u> >::get_width() const Line | Count | Source | 115 | 4.56k | unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; } |
|
116 | 106k | unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned short, 2u> >::get_inner_bit_count() const Line | Count | Source | 116 | 104k | unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; } |
OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned int, 4u> >::get_inner_bit_count() const Line | Count | Source | 116 | 2.49k | unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; } |
|
117 | | |
118 | | |
119 | | bool sanitize (hb_sanitize_context_t *c) const |
120 | 22.9k | { |
121 | 22.9k | TRACE_SANITIZE (this); |
122 | 22.9k | return_trace (c->check_struct (this) && |
123 | 22.9k | c->check_range (mapDataZ.arrayZ, |
124 | 22.9k | mapCount, |
125 | 22.9k | get_width ())); |
126 | 22.9k | } OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 120 | 20.8k | { | 121 | 20.8k | TRACE_SANITIZE (this); | 122 | 20.8k | return_trace (c->check_struct (this) && | 123 | 20.8k | c->check_range (mapDataZ.arrayZ, | 124 | 20.8k | mapCount, | 125 | 20.8k | get_width ())); | 126 | 20.8k | } |
OT::DeltaSetIndexMapFormat01<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const Line | Count | Source | 120 | 2.11k | { | 121 | 2.11k | TRACE_SANITIZE (this); | 122 | 2.11k | return_trace (c->check_struct (this) && | 123 | 2.11k | c->check_range (mapDataZ.arrayZ, | 124 | 2.11k | mapCount, | 125 | 2.11k | get_width ())); | 126 | 2.11k | } |
|
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> |
143 | | bool serialize (hb_serialize_context_t *c, const T &plan) |
144 | 0 | { |
145 | 0 | TRACE_SERIALIZE (this); |
146 | 0 | unsigned length = plan.get_output_map ().length; |
147 | 0 | u.format = length <= 0xFFFF ? 0 : 1; |
148 | 0 | switch (u.format) { |
149 | 0 | case 0: return_trace (u.format0.serialize (c, plan)); |
150 | 0 | case 1: return_trace (u.format1.serialize (c, plan)); |
151 | 0 | default:return_trace (false); |
152 | 0 | } |
153 | 0 | } |
154 | | |
155 | | uint32_t map (unsigned v) const |
156 | 1.04M | { |
157 | 1.04M | switch (u.format) { |
158 | 1.02M | case 0: return (u.format0.map (v)); |
159 | 8.20k | case 1: return (u.format1.map (v)); |
160 | 9.10k | default:return v; |
161 | 1.04M | } |
162 | 1.04M | } |
163 | | |
164 | | unsigned get_map_count () const |
165 | 0 | { |
166 | 0 | switch (u.format) { |
167 | 0 | case 0: return u.format0.get_map_count (); |
168 | 0 | case 1: return u.format1.get_map_count (); |
169 | 0 | default:return 0; |
170 | 0 | } |
171 | 0 | } |
172 | | |
173 | | unsigned get_width () const |
174 | 0 | { |
175 | 0 | switch (u.format) { |
176 | 0 | case 0: return u.format0.get_width (); |
177 | 0 | case 1: return u.format1.get_width (); |
178 | 0 | default:return 0; |
179 | 0 | } |
180 | 0 | } |
181 | | |
182 | | unsigned get_inner_bit_count () const |
183 | 0 | { |
184 | 0 | switch (u.format) { |
185 | 0 | case 0: return u.format0.get_inner_bit_count (); |
186 | 0 | case 1: return u.format1.get_inner_bit_count (); |
187 | 0 | default:return 0; |
188 | 0 | } |
189 | 0 | } |
190 | | |
191 | | bool sanitize (hb_sanitize_context_t *c) const |
192 | 37.8k | { |
193 | 37.8k | TRACE_SANITIZE (this); |
194 | 37.8k | if (!u.format.sanitize (c)) return_trace (false); |
195 | 25.8k | switch (u.format) { |
196 | 20.8k | case 0: return_trace (u.format0.sanitize (c)); |
197 | 2.11k | case 1: return_trace (u.format1.sanitize (c)); |
198 | 2.90k | default:return_trace (true); |
199 | 25.8k | } |
200 | 25.8k | } |
201 | | |
202 | | DeltaSetIndexMap* copy (hb_serialize_context_t *c) const |
203 | 0 | { |
204 | 0 | TRACE_SERIALIZE (this); |
205 | 0 | switch (u.format) { |
206 | 0 | case 0: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c))); |
207 | 0 | case 1: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c))); |
208 | 0 | default:return_trace (nullptr); |
209 | 0 | } |
210 | 0 | } |
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 | | { |
225 | | VarStoreInstancer (const VariationStore &varStore, |
226 | | const DeltaSetIndexMap &varIdxMap, |
227 | | hb_array_t<int> coords) : |
228 | 118k | varStore (varStore), varIdxMap (varIdxMap), coords (coords) {} |
229 | | |
230 | 53 | operator bool () const { return bool (coords); } |
231 | | |
232 | | float operator() (uint32_t varIdx, unsigned short offset = 0) const |
233 | 1.03M | { 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 */ |