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