hb-ot-cff-common.hh (11038B)
1 /* 2 * Copyright © 2018 Adobe 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 * Adobe Author(s): Michiharu Ariza 25 */ 26 #ifndef HB_OT_CFF_COMMON_HH 27 #define HB_OT_CFF_COMMON_HH 28 29 #include "hb-open-type.hh" 30 #include "hb-bimap.hh" 31 #include "hb-ot-layout-common.hh" 32 #include "hb-cff-interp-dict-common.hh" 33 #include "hb-subset-plan.hh" 34 35 namespace CFF { 36 37 using namespace OT; 38 39 #define CFF_UNDEF_CODE 0xFFFFFFFF 40 41 using objidx_t = hb_serialize_context_t::objidx_t; 42 using whence_t = hb_serialize_context_t::whence_t; 43 44 /* CFF offsets can technically be negative */ 45 template<typename Type, typename ...Ts> 46 static inline const Type& StructAtOffsetOrNull (const void *P, int offset, hb_sanitize_context_t &sc, Ts&&... ds) 47 { 48 if (!offset) return Null (Type); 49 50 const char *p = (const char *) P + offset; 51 if (!sc.check_point (p)) return Null (Type); 52 53 const Type &obj = *reinterpret_cast<const Type *> (p); 54 if (!obj.sanitize (&sc, std::forward<Ts> (ds)...)) return Null (Type); 55 56 return obj; 57 } 58 59 60 struct code_pair_t 61 { 62 unsigned code; 63 hb_codepoint_t glyph; 64 }; 65 66 67 using str_buff_t = hb_vector_t<unsigned char>; 68 using str_buff_vec_t = hb_vector_t<str_buff_t>; 69 using glyph_to_sid_map_t = hb_vector_t<code_pair_t>; 70 71 /* Top Dict, Font Dict, Private Dict */ 72 struct Dict : UnsizedByteStr 73 { 74 template <typename DICTVAL, typename OP_SERIALIZER, typename ...Ts> 75 bool serialize (hb_serialize_context_t *c, 76 const DICTVAL &dictval, 77 OP_SERIALIZER& opszr, 78 Ts&&... ds) 79 { 80 TRACE_SERIALIZE (this); 81 for (unsigned int i = 0; i < dictval.get_count (); i++) 82 if (unlikely (!opszr.serialize (c, dictval[i], ds...))) 83 return_trace (false); 84 85 return_trace (true); 86 } 87 88 template <typename T, typename V> 89 static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, V value, op_code_t intOp) 90 { 91 if (unlikely ((!serialize_int<T, V> (c, intOp, value)))) 92 return false; 93 94 TRACE_SERIALIZE (this); 95 /* serialize the opcode */ 96 HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op), false); 97 if (unlikely (!p)) return_trace (false); 98 if (Is_OpCode_ESC (op)) 99 { 100 *p = OpCode_escape; 101 op = Unmake_OpCode_ESC (op); 102 p++; 103 } 104 *p = op; 105 return_trace (true); 106 } 107 108 template <typename V> 109 static bool serialize_int4_op (hb_serialize_context_t *c, op_code_t op, V value) 110 { return serialize_int_op<HBINT32> (c, op, value, OpCode_longintdict); } 111 112 template <typename V> 113 static bool serialize_int2_op (hb_serialize_context_t *c, op_code_t op, V value) 114 { return serialize_int_op<HBINT16> (c, op, value, OpCode_shortint); } 115 116 template <typename T, int int_op> 117 static bool serialize_link_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence) 118 { 119 T &ofs = *(T *) (c->head + OpCode_Size (int_op)); 120 if (unlikely (!serialize_int_op<T> (c, op, 0, int_op))) return false; 121 c->add_link (ofs, link, whence); 122 return true; 123 } 124 125 static bool serialize_link4_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence = whence_t::Head) 126 { return serialize_link_op<HBINT32, OpCode_longintdict> (c, op, link, whence); } 127 128 static bool serialize_link2_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence = whence_t::Head) 129 { return serialize_link_op<HBINT16, OpCode_shortint> (c, op, link, whence); } 130 }; 131 132 struct TopDict : Dict {}; 133 struct FontDict : Dict {}; 134 struct PrivateDict : Dict {}; 135 136 struct table_info_t 137 { 138 void init () { offset = size = 0; link = 0; } 139 140 unsigned int offset; 141 unsigned int size; 142 objidx_t link; 143 }; 144 145 template <typename COUNT> 146 struct FDArray : CFFIndex<COUNT> 147 { 148 template <typename DICTVAL, typename INFO, typename Iterator, typename OP_SERIALIZER> 149 bool serialize (hb_serialize_context_t *c, 150 Iterator it, 151 OP_SERIALIZER& opszr) 152 { 153 TRACE_SERIALIZE (this); 154 155 /* serialize INDEX data */ 156 hb_vector_t<unsigned> sizes; 157 if (it.is_random_access_iterator) 158 sizes.alloc (hb_len (it)); 159 160 c->push (); 161 char *data_base = c->head; 162 + it 163 | hb_map ([&] (const hb_pair_t<const DICTVAL&, const INFO&> &_) 164 { 165 FontDict *dict = c->start_embed<FontDict> (); 166 dict->serialize (c, _.first, opszr, _.second); 167 return c->head - (const char*)dict; 168 }) 169 | hb_sink (sizes) 170 ; 171 unsigned data_size = c->head - data_base; 172 c->pop_pack (false); 173 174 if (unlikely (sizes.in_error ())) return_trace (false); 175 176 /* It just happens that the above is packed right after the header below. 177 * Such a hack. */ 178 179 /* serialize INDEX header */ 180 return_trace (CFFIndex<COUNT>::serialize_header (c, hb_iter (sizes), data_size)); 181 } 182 }; 183 184 /* FDSelect */ 185 struct FDSelect0 { 186 bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const 187 { 188 TRACE_SANITIZE (this); 189 if (unlikely (!(c->check_struct (this)))) 190 return_trace (false); 191 hb_barrier (); 192 if (unlikely (!c->check_array (fds, c->get_num_glyphs ()))) 193 return_trace (false); 194 195 return_trace (true); 196 } 197 198 unsigned get_fd (hb_codepoint_t glyph) const 199 { return fds[glyph]; } 200 201 hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const 202 { return {fds[glyph], glyph + 1}; } 203 204 unsigned int get_size (unsigned int num_glyphs) const 205 { return HBUINT8::static_size * num_glyphs; } 206 207 HBUINT8 fds[HB_VAR_ARRAY]; 208 209 DEFINE_SIZE_MIN (0); 210 }; 211 212 template <typename GID_TYPE, typename FD_TYPE> 213 struct FDSelect3_4_Range 214 { 215 bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const 216 { 217 TRACE_SANITIZE (this); 218 return_trace (c->check_struct (this) && 219 hb_barrier () && 220 first < c->get_num_glyphs () && (fd < fdcount)); 221 } 222 223 GID_TYPE first; 224 FD_TYPE fd; 225 public: 226 DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size); 227 }; 228 229 template <typename GID_TYPE, typename FD_TYPE> 230 struct FDSelect3_4 231 { 232 unsigned int get_size () const 233 { return GID_TYPE::static_size * 2 + ranges.get_size (); } 234 235 bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const 236 { 237 TRACE_SANITIZE (this); 238 if (unlikely (!(c->check_struct (this) && 239 ranges.sanitize (c, nullptr, fdcount) && 240 hb_barrier () && 241 (nRanges () != 0) && 242 ranges[0].first == 0))) 243 return_trace (false); 244 245 for (unsigned int i = 1; i < nRanges (); i++) 246 if (unlikely (ranges[i - 1].first >= ranges[i].first)) 247 return_trace (false); 248 249 if (unlikely (!(sentinel().sanitize (c) && 250 hb_barrier () && 251 (sentinel() == c->get_num_glyphs ())))) 252 return_trace (false); 253 254 return_trace (true); 255 } 256 257 static int _cmp_range (const void *_key, const void *_item) 258 { 259 hb_codepoint_t glyph = * (hb_codepoint_t *) _key; 260 FDSelect3_4_Range<GID_TYPE, FD_TYPE> *range = (FDSelect3_4_Range<GID_TYPE, FD_TYPE> *) _item; 261 262 if (glyph < range[0].first) return -1; 263 if (glyph < range[1].first) return 0; 264 return +1; 265 } 266 267 unsigned get_fd (hb_codepoint_t glyph) const 268 { 269 auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range); 270 return range ? range->fd : ranges[nRanges () - 1].fd; 271 } 272 273 hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const 274 { 275 auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range); 276 unsigned fd = range ? range->fd : ranges[nRanges () - 1].fd; 277 hb_codepoint_t end = range ? range[1].first : ranges[nRanges () - 1].first; 278 return {fd, end}; 279 } 280 281 GID_TYPE &nRanges () { return ranges.len; } 282 GID_TYPE nRanges () const { return ranges.len; } 283 GID_TYPE &sentinel () { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); } 284 const GID_TYPE &sentinel () const { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); } 285 286 ArrayOf<FDSelect3_4_Range<GID_TYPE, FD_TYPE>, GID_TYPE> ranges; 287 /* GID_TYPE sentinel */ 288 289 DEFINE_SIZE_ARRAY (GID_TYPE::static_size, ranges); 290 }; 291 292 typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3; 293 typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range; 294 295 struct FDSelect 296 { 297 bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs) 298 { 299 TRACE_SERIALIZE (this); 300 unsigned int size = src.get_size (num_glyphs); 301 FDSelect *dest = c->allocate_size<FDSelect> (size, false); 302 if (unlikely (!dest)) return_trace (false); 303 hb_memcpy (dest, &src, size); 304 return_trace (true); 305 } 306 307 unsigned int get_size (unsigned int num_glyphs) const 308 { 309 switch (format) 310 { 311 case 0: hb_barrier (); return format.static_size + u.format0.get_size (num_glyphs); 312 case 3: hb_barrier (); return format.static_size + u.format3.get_size (); 313 default:return 0; 314 } 315 } 316 317 unsigned get_fd (hb_codepoint_t glyph) const 318 { 319 if (this == &Null (FDSelect)) return 0; 320 321 switch (format) 322 { 323 case 0: hb_barrier (); return u.format0.get_fd (glyph); 324 case 3: hb_barrier (); return u.format3.get_fd (glyph); 325 default:return 0; 326 } 327 } 328 /* Returns pair of fd and one after last glyph in range. */ 329 hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const 330 { 331 if (this == &Null (FDSelect)) return {0, 1}; 332 333 switch (format) 334 { 335 case 0: hb_barrier (); return u.format0.get_fd_range (glyph); 336 case 3: hb_barrier (); return u.format3.get_fd_range (glyph); 337 default:return {0, 1}; 338 } 339 } 340 341 bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const 342 { 343 TRACE_SANITIZE (this); 344 if (unlikely (!c->check_struct (this))) 345 return_trace (false); 346 hb_barrier (); 347 348 switch (format) 349 { 350 case 0: hb_barrier (); return_trace (u.format0.sanitize (c, fdcount)); 351 case 3: hb_barrier (); return_trace (u.format3.sanitize (c, fdcount)); 352 default:return_trace (false); 353 } 354 } 355 356 HBUINT8 format; 357 union { 358 FDSelect0 format0; 359 FDSelect3 format3; 360 } u; 361 public: 362 DEFINE_SIZE_MIN (1); 363 }; 364 365 template <typename COUNT> 366 struct Subrs : CFFIndex<COUNT> 367 { 368 typedef COUNT count_type; 369 typedef CFFIndex<COUNT> SUPER; 370 }; 371 372 } /* namespace CFF */ 373 374 #endif /* HB_OT_CFF_COMMON_HH */