1 /* 2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. 3 * Copyright © 2012 Google, Inc. 4 * 5 * This is part of HarfBuzz, a text shaping library. 6 * 7 * Permission is hereby granted, without written agreement and without 8 * license or royalty fees, to use, copy, modify, and distribute this 9 * software and its documentation for any purpose, provided that the 10 * above copyright notice and the following two paragraphs appear in 11 * all copies of this software. 12 * 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 17 * DAMAGE. 18 * 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 24 * 25 * Red Hat Author(s): Behdad Esfahbod 26 * Google Author(s): Behdad Esfahbod 27 */ 28 29 #ifndef HB_OPEN_TYPE_PRIVATE_HH 30 #define HB_OPEN_TYPE_PRIVATE_HH 31 32 #include "hb-private.hh" 33 34 35 namespace OT { 36 37 38 39 /* 40 * Casts 41 */ 42 43 /* Cast to struct T, reference to reference */ 44 template<typename Type, typename TObject> 45 static inline const Type& CastR(const TObject &X) 46 { return reinterpret_cast<const Type&> (X); } 47 template<typename Type, typename TObject> 48 static inline Type& CastR(TObject &X) 49 { return reinterpret_cast<Type&> (X); } 50 51 /* Cast to struct T, pointer to pointer */ 52 template<typename Type, typename TObject> 53 static inline const Type* CastP(const TObject *X) 54 { return reinterpret_cast<const Type*> (X); } 55 template<typename Type, typename TObject> 56 static inline Type* CastP(TObject *X) 57 { return reinterpret_cast<Type*> (X); } 58 59 /* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory 60 * location pointed to by P plus Ofs bytes. */ 61 template<typename Type> 62 static inline const Type& StructAtOffset(const void *P, unsigned int offset) 63 { return * reinterpret_cast<const Type*> ((const char *) P + offset); } 64 template<typename Type> 65 static inline Type& StructAtOffset(void *P, unsigned int offset) 66 { return * reinterpret_cast<Type*> ((char *) P + offset); } 67 68 /* StructAfter<T>(X) returns the struct T& that is placed after X. 69 * Works with X of variable size also. X must implement get_size() */ 70 template<typename Type, typename TObject> 71 static inline const Type& StructAfter(const TObject &X) 72 { return StructAtOffset<Type>(&X, X.get_size()); } 73 template<typename Type, typename TObject> 74 static inline Type& StructAfter(TObject &X) 75 { return StructAtOffset<Type>(&X, X.get_size()); } 76 77 78 79 /* 80 * Size checking 81 */ 82 83 /* Check _assertion in a method environment */ 84 #define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ 85 inline void _instance_assertion_on_line_##_line (void) const \ 86 { \ 87 ASSERT_STATIC (_assertion); \ 88 ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \ 89 } 90 # define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion) 91 # define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion) 92 93 /* Check that _code compiles in a method environment */ 94 #define _DEFINE_COMPILES_ASSERTION1(_line, _code) \ 95 inline void _compiles_assertion_on_line_##_line (void) const \ 96 { _code; } 97 # define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code) 98 # define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code) 99 100 101 #define DEFINE_SIZE_STATIC(size) \ 102 DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \ 103 static const unsigned int static_size = (size); \ 104 static const unsigned int min_size = (size) 105 106 /* Size signifying variable-sized array */ 107 #define VAR 1 108 109 #define DEFINE_SIZE_UNION(size, _member) \ 110 DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \ 111 static const unsigned int min_size = (size) 112 113 #define DEFINE_SIZE_MIN(size) \ 114 DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \ 115 static const unsigned int min_size = (size) 116 117 #define DEFINE_SIZE_ARRAY(size, array) \ 118 DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \ 119 DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \ 120 static const unsigned int min_size = (size) 121 122 #define DEFINE_SIZE_ARRAY2(size, array1, array2) \ 123 DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ 124 DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \ 125 static const unsigned int min_size = (size) 126 127 128 129 /* 130 * Null objects 131 */ 132 133 /* Global nul-content Null pool. Enlarge as necessary. */ 134 /* TODO This really should be a extern HB_INTERNAL and defined somewhere... */ 135 static const void *_NullPool[(256+8) / sizeof (void *)]; 136 137 /* Generic nul-content Null objects. */ 138 template <typename Type> 139 static inline const Type& Null (void) { 140 ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); 141 return *CastP<Type> (_NullPool); 142 } 143 144 /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ 145 #define DEFINE_NULL_DATA(Type, data) \ 146 static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \ 147 template <> \ 148 /*static*/ inline const Type& Null<Type> (void) { \ 149 return *CastP<Type> (_Null##Type); \ 150 } /* The following line really exists such that we end in a place needing semicolon */ \ 151 ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) 152 153 /* Accessor macro. */ 154 #define Null(Type) Null<Type>() 155 156 157 /* 158 * Dispatch 159 */ 160 161 template <typename Context, typename Return, unsigned int MaxDebugDepth> 162 struct hb_dispatch_context_t 163 { 164 static const unsigned int max_debug_depth = MaxDebugDepth; 165 typedef Return return_t; 166 template <typename T, typename F> 167 inline bool may_dispatch (const T *obj, const F *format) { return true; } 168 static return_t no_dispatch_return_value (void) { return Context::default_return_value (); } 169 }; 170 171 172 /* 173 * Sanitize 174 */ 175 176 #ifndef HB_DEBUG_SANITIZE 177 #define HB_DEBUG_SANITIZE (HB_DEBUG+0) 178 #endif 179 180 181 #define TRACE_SANITIZE(this) \ 182 hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \ 183 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ 184 ""); 185 186 /* This limits sanitizing time on really broken fonts. */ 187 #ifndef HB_SANITIZE_MAX_EDITS 188 #define HB_SANITIZE_MAX_EDITS 100 189 #endif 190 191 struct hb_sanitize_context_t : 192 hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE> 193 { 194 inline hb_sanitize_context_t (void) : 195 debug_depth (0), 196 start (NULL), end (NULL), 197 writable (false), edit_count (0), 198 blob (NULL) {} 199 200 inline const char *get_name (void) { return "SANITIZE"; } 201 template <typename T, typename F> 202 inline bool may_dispatch (const T *obj, const F *format) 203 { return format->sanitize (this); } 204 template <typename T> 205 inline return_t dispatch (const T &obj) { return obj.sanitize (this); } 206 static return_t default_return_value (void) { return true; } 207 static return_t no_dispatch_return_value (void) { return false; } 208 bool stop_sublookup_iteration (const return_t r) const { return !r; } 209 210 inline void init (hb_blob_t *b) 211 { 212 this->blob = hb_blob_reference (b); 213 this->writable = false; 214 } 215 216 inline void start_processing (void) 217 { 218 this->start = hb_blob_get_data (this->blob, NULL); 219 this->end = this->start + hb_blob_get_length (this->blob); 220 assert (this->start <= this->end); /* Must not overflow. */ 221 this->edit_count = 0; 222 this->debug_depth = 0; 223 224 DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1, 225 "start [%p..%p] (%lu bytes)", 226 this->start, this->end, 227 (unsigned long) (this->end - this->start)); 228 } 229 230 inline void end_processing (void) 231 { 232 DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1, 233 "end [%p..%p] %u edit requests", 234 this->start, this->end, this->edit_count); 235 236 hb_blob_destroy (this->blob); 237 this->blob = NULL; 238 this->start = this->end = NULL; 239 } 240 241 inline bool check_range (const void *base, unsigned int len) const 242 { 243 const char *p = (const char *) base; 244 bool ok = this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len; 245 246 DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, 247 "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s", 248 p, p + len, len, 249 this->start, this->end, 250 ok ? "OK" : "OUT-OF-RANGE"); 251 252 return likely (ok); 253 } 254 255 inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const 256 { 257 const char *p = (const char *) base; 258 bool overflows = _hb_unsigned_int_mul_overflows (len, record_size); 259 unsigned int array_size = record_size * len; 260 bool ok = !overflows && this->check_range (base, array_size); 261 262 DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, 263 "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s", 264 p, p + (record_size * len), record_size, len, (unsigned int) array_size, 265 this->start, this->end, 266 overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE"); 267 268 return likely (ok); 269 } 270 271 template <typename Type> 272 inline bool check_struct (const Type *obj) const 273 { 274 return likely (this->check_range (obj, obj->min_size)); 275 } 276 277 inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED) 278 { 279 if (this->edit_count >= HB_SANITIZE_MAX_EDITS) 280 return false; 281 282 const char *p = (const char *) base; 283 this->edit_count++; 284 285 DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, 286 "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", 287 this->edit_count, 288 p, p + len, len, 289 this->start, this->end, 290 this->writable ? "GRANTED" : "DENIED"); 291 292 return this->writable; 293 } 294 295 template <typename Type, typename ValueType> 296 inline bool try_set (const Type *obj, const ValueType &v) { 297 if (this->may_edit (obj, obj->static_size)) { 298 const_cast<Type *> (obj)->set (v); 299 return true; 300 } 301 return false; 302 } 303 304 mutable unsigned int debug_depth; 305 const char *start, *end; 306 bool writable; 307 unsigned int edit_count; 308 hb_blob_t *blob; 309 }; 310 311 312 313 /* Template to sanitize an object. */ 314 template <typename Type> 315 struct Sanitizer 316 { 317 static hb_blob_t *sanitize (hb_blob_t *blob) { 318 hb_sanitize_context_t c[1]; 319 bool sane; 320 321 /* TODO is_sane() stuff */ 322 323 c->init (blob); 324 325 retry: 326 DEBUG_MSG_FUNC (SANITIZE, c->start, "start"); 327 328 c->start_processing (); 329 330 if (unlikely (!c->start)) { 331 c->end_processing (); 332 return blob; 333 } 334 335 Type *t = CastP<Type> (const_cast<char *> (c->start)); 336 337 sane = t->sanitize (c); 338 if (sane) { 339 if (c->edit_count) { 340 DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count); 341 342 /* sanitize again to ensure no toe-stepping */ 343 c->edit_count = 0; 344 sane = t->sanitize (c); 345 if (c->edit_count) { 346 DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count); 347 sane = false; 348 } 349 } 350 } else { 351 unsigned int edit_count = c->edit_count; 352 if (edit_count && !c->writable) { 353 c->start = hb_blob_get_data_writable (blob, NULL); 354 c->end = c->start + hb_blob_get_length (blob); 355 356 if (c->start) { 357 c->writable = true; 358 /* ok, we made it writable by relocating. try again */ 359 DEBUG_MSG_FUNC (SANITIZE, c->start, "retry"); 360 goto retry; 361 } 362 } 363 } 364 365 c->end_processing (); 366 367 DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED"); 368 if (sane) 369 return blob; 370 else { 371 hb_blob_destroy (blob); 372 return hb_blob_get_empty (); 373 } 374 } 375 376 static const Type* lock_instance (hb_blob_t *blob) { 377 hb_blob_make_immutable (blob); 378 const char *base = hb_blob_get_data (blob, NULL); 379 return unlikely (!base) ? &Null(Type) : CastP<Type> (base); 380 } 381 }; 382 383 384 385 /* 386 * Serialize 387 */ 388 389 #ifndef HB_DEBUG_SERIALIZE 390 #define HB_DEBUG_SERIALIZE (HB_DEBUG+0) 391 #endif 392 393 394 #define TRACE_SERIALIZE(this) \ 395 hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \ 396 (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ 397 ""); 398 399 400 struct hb_serialize_context_t 401 { 402 inline hb_serialize_context_t (void *start, unsigned int size) 403 { 404 this->start = (char *) start; 405 this->end = this->start + size; 406 407 this->ran_out_of_room = false; 408 this->head = this->start; 409 this->debug_depth = 0; 410 } 411 412 template <typename Type> 413 inline Type *start_serialize (void) 414 { 415 DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1, 416 "start [%p..%p] (%lu bytes)", 417 this->start, this->end, 418 (unsigned long) (this->end - this->start)); 419 420 return start_embed<Type> (); 421 } 422 423 inline void end_serialize (void) 424 { 425 DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1, 426 "end [%p..%p] serialized %d bytes; %s", 427 this->start, this->end, 428 (int) (this->head - this->start), 429 this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room"); 430 431 } 432 433 template <typename Type> 434 inline Type *copy (void) 435 { 436 assert (!this->ran_out_of_room); 437 unsigned int len = this->head - this->start; 438 void *p = malloc (len); 439 if (p) 440 memcpy (p, this->start, len); 441 return reinterpret_cast<Type *> (p); 442 } 443 444 template <typename Type> 445 inline Type *allocate_size (unsigned int size) 446 { 447 if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) { 448 this->ran_out_of_room = true; 449 return NULL; 450 } 451 memset (this->head, 0, size); 452 char *ret = this->head; 453 this->head += size; 454 return reinterpret_cast<Type *> (ret); 455 } 456 457 template <typename Type> 458 inline Type *allocate_min (void) 459 { 460 return this->allocate_size<Type> (Type::min_size); 461 } 462 463 template <typename Type> 464 inline Type *start_embed (void) 465 { 466 Type *ret = reinterpret_cast<Type *> (this->head); 467 return ret; 468 } 469 470 template <typename Type> 471 inline Type *embed (const Type &obj) 472 { 473 unsigned int size = obj.get_size (); 474 Type *ret = this->allocate_size<Type> (size); 475 if (unlikely (!ret)) return NULL; 476 memcpy (ret, obj, size); 477 return ret; 478 } 479 480 template <typename Type> 481 inline Type *extend_min (Type &obj) 482 { 483 unsigned int size = obj.min_size; 484 assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 485 if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; 486 return reinterpret_cast<Type *> (&obj); 487 } 488 489 template <typename Type> 490 inline Type *extend (Type &obj) 491 { 492 unsigned int size = obj.get_size (); 493 assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 494 if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; 495 return reinterpret_cast<Type *> (&obj); 496 } 497 498 inline void truncate (void *head) 499 { 500 assert (this->start < head && head <= this->head); 501 this->head = (char *) head; 502 } 503 504 unsigned int debug_depth; 505 char *start, *end, *head; 506 bool ran_out_of_room; 507 }; 508 509 template <typename Type> 510 struct Supplier 511 { 512 inline Supplier (const Type *array, unsigned int len_) 513 { 514 head = array; 515 len = len_; 516 } 517 inline const Type operator [] (unsigned int i) const 518 { 519 if (unlikely (i >= len)) return Type (); 520 return head[i]; 521 } 522 523 inline void advance (unsigned int count) 524 { 525 if (unlikely (count > len)) 526 count = len; 527 len -= count; 528 head += count; 529 } 530 531 private: 532 inline Supplier (const Supplier<Type> &); /* Disallow copy */ 533 inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */ 534 535 unsigned int len; 536 const Type *head; 537 }; 538 539 540 541 542 /* 543 * 544 * The OpenType Font File: Data Types 545 */ 546 547 548 /* "The following data types are used in the OpenType font file. 549 * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */ 550 551 /* 552 * Int types 553 */ 554 555 556 template <typename Type, int Bytes> struct BEInt; 557 558 template <typename Type> 559 struct BEInt<Type, 1> 560 { 561 public: 562 inline void set (Type V) 563 { 564 v = V; 565 } 566 inline operator Type (void) const 567 { 568 return v; 569 } 570 private: uint8_t v; 571 }; 572 template <typename Type> 573 struct BEInt<Type, 2> 574 { 575 public: 576 inline void set (Type V) 577 { 578 v[0] = (V >> 8) & 0xFF; 579 v[1] = (V ) & 0xFF; 580 } 581 inline operator Type (void) const 582 { 583 return (v[0] << 8) 584 + (v[1] ); 585 } 586 private: uint8_t v[2]; 587 }; 588 template <typename Type> 589 struct BEInt<Type, 3> 590 { 591 public: 592 inline void set (Type V) 593 { 594 v[0] = (V >> 16) & 0xFF; 595 v[1] = (V >> 8) & 0xFF; 596 v[2] = (V ) & 0xFF; 597 } 598 inline operator Type (void) const 599 { 600 return (v[0] << 16) 601 + (v[1] << 8) 602 + (v[2] ); 603 } 604 private: uint8_t v[3]; 605 }; 606 template <typename Type> 607 struct BEInt<Type, 4> 608 { 609 public: 610 inline void set (Type V) 611 { 612 v[0] = (V >> 24) & 0xFF; 613 v[1] = (V >> 16) & 0xFF; 614 v[2] = (V >> 8) & 0xFF; 615 v[3] = (V ) & 0xFF; 616 } 617 inline operator Type (void) const 618 { 619 return (v[0] << 24) 620 + (v[1] << 16) 621 + (v[2] << 8) 622 + (v[3] ); 623 } 624 private: uint8_t v[4]; 625 }; 626 627 /* Integer types in big-endian order and no alignment requirement */ 628 template <typename Type, unsigned int Size> 629 struct IntType 630 { 631 inline void set (Type i) { v.set (i); } 632 inline operator Type(void) const { return v; } 633 inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; } 634 inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); } 635 static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); } 636 inline int cmp (Type a) const 637 { 638 Type b = v; 639 if (sizeof (Type) < sizeof (int)) 640 return (int) a - (int) b; 641 else 642 return a < b ? -1 : a == b ? 0 : +1; 643 } 644 inline bool sanitize (hb_sanitize_context_t *c) const 645 { 646 TRACE_SANITIZE (this); 647 return_trace (likely (c->check_struct (this))); 648 } 649 protected: 650 BEInt<Type, Size> v; 651 public: 652 DEFINE_SIZE_STATIC (Size); 653 }; 654 655 typedef IntType<uint8_t , 1> BYTE; /* 8-bit unsigned integer. */ 656 typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */ 657 typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */ 658 typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */ 659 typedef IntType<int32_t, 4> LONG; /* 32-bit signed integer. */ 660 typedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */ 661 662 /* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ 663 typedef SHORT FWORD; 664 665 /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ 666 typedef USHORT UFWORD; 667 668 /* Date represented in number of seconds since 12:00 midnight, January 1, 669 * 1904. The value is represented as a signed 64-bit integer. */ 670 struct LONGDATETIME 671 { 672 inline bool sanitize (hb_sanitize_context_t *c) const 673 { 674 TRACE_SANITIZE (this); 675 return_trace (likely (c->check_struct (this))); 676 } 677 protected: 678 LONG major; 679 ULONG minor; 680 public: 681 DEFINE_SIZE_STATIC (8); 682 }; 683 684 /* Array of four uint8s (length = 32 bits) used to identify a script, language 685 * system, feature, or baseline */ 686 struct Tag : ULONG 687 { 688 /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ 689 inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); } 690 inline operator char* (void) { return reinterpret_cast<char *> (&this->v); } 691 public: 692 DEFINE_SIZE_STATIC (4); 693 }; 694 DEFINE_NULL_DATA (Tag, " "); 695 696 /* Glyph index number, same as uint16 (length = 16 bits) */ 697 struct GlyphID : USHORT { 698 static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); } 699 inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; } 700 }; 701 702 /* Script/language-system/feature index */ 703 struct Index : USHORT { 704 static const unsigned int NOT_FOUND_INDEX = 0xFFFFu; 705 }; 706 DEFINE_NULL_DATA (Index, "\xff\xff"); 707 708 /* Offset, Null offset = 0 */ 709 template <typename Type=USHORT> 710 struct Offset : Type 711 { 712 inline bool is_null (void) const { return 0 == *this; } 713 public: 714 DEFINE_SIZE_STATIC (sizeof(Type)); 715 }; 716 717 718 /* CheckSum */ 719 struct CheckSum : ULONG 720 { 721 /* This is reference implementation from the spec. */ 722 static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length) 723 { 724 uint32_t Sum = 0L; 725 const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size; 726 727 while (Table < EndPtr) 728 Sum += *Table++; 729 return Sum; 730 } 731 732 /* Note: data should be 4byte aligned and have 4byte padding at the end. */ 733 inline void set_for_data (const void *data, unsigned int length) 734 { set (CalcTableChecksum ((const ULONG *) data, length)); } 735 736 public: 737 DEFINE_SIZE_STATIC (4); 738 }; 739 740 741 /* 742 * Version Numbers 743 */ 744 745 struct FixedVersion 746 { 747 inline uint32_t to_int (void) const { return (major << 16) + minor; } 748 749 inline bool sanitize (hb_sanitize_context_t *c) const 750 { 751 TRACE_SANITIZE (this); 752 return_trace (c->check_struct (this)); 753 } 754 755 USHORT major; 756 USHORT minor; 757 public: 758 DEFINE_SIZE_STATIC (4); 759 }; 760 761 762 763 /* 764 * Template subclasses of Offset that do the dereferencing. 765 * Use: (base+offset) 766 */ 767 768 template <typename Type, typename OffsetType=USHORT> 769 struct OffsetTo : Offset<OffsetType> 770 { 771 inline const Type& operator () (const void *base) const 772 { 773 unsigned int offset = *this; 774 if (unlikely (!offset)) return Null(Type); 775 return StructAtOffset<Type> (base, offset); 776 } 777 778 inline Type& serialize (hb_serialize_context_t *c, const void *base) 779 { 780 Type *t = c->start_embed<Type> (); 781 this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ 782 return *t; 783 } 784 785 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const 786 { 787 TRACE_SANITIZE (this); 788 if (unlikely (!c->check_struct (this))) return_trace (false); 789 unsigned int offset = *this; 790 if (unlikely (!offset)) return_trace (true); 791 const Type &obj = StructAtOffset<Type> (base, offset); 792 return_trace (likely (obj.sanitize (c)) || neuter (c)); 793 } 794 template <typename T> 795 inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const 796 { 797 TRACE_SANITIZE (this); 798 if (unlikely (!c->check_struct (this))) return_trace (false); 799 unsigned int offset = *this; 800 if (unlikely (!offset)) return_trace (true); 801 const Type &obj = StructAtOffset<Type> (base, offset); 802 return_trace (likely (obj.sanitize (c, user_data)) || neuter (c)); 803 } 804 805 /* Set the offset to Null */ 806 inline bool neuter (hb_sanitize_context_t *c) const { 807 return c->try_set (this, 0); 808 } 809 DEFINE_SIZE_STATIC (sizeof(OffsetType)); 810 }; 811 template <typename Base, typename OffsetType, typename Type> 812 static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); } 813 template <typename Base, typename OffsetType, typename Type> 814 static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); } 815 816 817 /* 818 * Array Types 819 */ 820 821 /* An array with a number of elements. */ 822 template <typename Type, typename LenType=USHORT> 823 struct ArrayOf 824 { 825 const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const 826 { 827 unsigned int count = len; 828 if (unlikely (start_offset > count)) 829 count = 0; 830 else 831 count -= start_offset; 832 count = MIN (count, *pcount); 833 *pcount = count; 834 return array + start_offset; 835 } 836 837 inline const Type& operator [] (unsigned int i) const 838 { 839 if (unlikely (i >= len)) return Null(Type); 840 return array[i]; 841 } 842 inline Type& operator [] (unsigned int i) 843 { 844 return array[i]; 845 } 846 inline unsigned int get_size (void) const 847 { return len.static_size + len * Type::static_size; } 848 849 inline bool serialize (hb_serialize_context_t *c, 850 unsigned int items_len) 851 { 852 TRACE_SERIALIZE (this); 853 if (unlikely (!c->extend_min (*this))) return_trace (false); 854 len.set (items_len); /* TODO(serialize) Overflow? */ 855 if (unlikely (!c->extend (*this))) return_trace (false); 856 return_trace (true); 857 } 858 859 inline bool serialize (hb_serialize_context_t *c, 860 Supplier<Type> &items, 861 unsigned int items_len) 862 { 863 TRACE_SERIALIZE (this); 864 if (unlikely (!serialize (c, items_len))) return_trace (false); 865 for (unsigned int i = 0; i < items_len; i++) 866 array[i] = items[i]; 867 items.advance (items_len); 868 return_trace (true); 869 } 870 871 inline bool sanitize (hb_sanitize_context_t *c) const 872 { 873 TRACE_SANITIZE (this); 874 if (unlikely (!sanitize_shallow (c))) return_trace (false); 875 876 /* Note: for structs that do not reference other structs, 877 * we do not need to call their sanitize() as we already did 878 * a bound check on the aggregate array size. We just include 879 * a small unreachable expression to make sure the structs 880 * pointed to do have a simple sanitize(), ie. they do not 881 * reference other structs via offsets. 882 */ 883 (void) (false && array[0].sanitize (c)); 884 885 return_trace (true); 886 } 887 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const 888 { 889 TRACE_SANITIZE (this); 890 if (unlikely (!sanitize_shallow (c))) return_trace (false); 891 unsigned int count = len; 892 for (unsigned int i = 0; i < count; i++) 893 if (unlikely (!array[i].sanitize (c, base))) 894 return_trace (false); 895 return_trace (true); 896 } 897 template <typename T> 898 inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const 899 { 900 TRACE_SANITIZE (this); 901 if (unlikely (!sanitize_shallow (c))) return_trace (false); 902 unsigned int count = len; 903 for (unsigned int i = 0; i < count; i++) 904 if (unlikely (!array[i].sanitize (c, base, user_data))) 905 return_trace (false); 906 return_trace (true); 907 } 908 909 template <typename SearchType> 910 inline int lsearch (const SearchType &x) const 911 { 912 unsigned int count = len; 913 for (unsigned int i = 0; i < count; i++) 914 if (!this->array[i].cmp (x)) 915 return i; 916 return -1; 917 } 918 919 private: 920 inline bool sanitize_shallow (hb_sanitize_context_t *c) const 921 { 922 TRACE_SANITIZE (this); 923 return_trace (c->check_struct (this) && c->check_array (array, Type::static_size, len)); 924 } 925 926 public: 927 LenType len; 928 Type array[VAR]; 929 public: 930 DEFINE_SIZE_ARRAY (sizeof (LenType), array); 931 }; 932 933 /* Array of Offset's */ 934 template <typename Type> 935 struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; 936 937 /* Array of offsets relative to the beginning of the array itself. */ 938 template <typename Type> 939 struct OffsetListOf : OffsetArrayOf<Type> 940 { 941 inline const Type& operator [] (unsigned int i) const 942 { 943 if (unlikely (i >= this->len)) return Null(Type); 944 return this+this->array[i]; 945 } 946 947 inline bool sanitize (hb_sanitize_context_t *c) const 948 { 949 TRACE_SANITIZE (this); 950 return_trace (OffsetArrayOf<Type>::sanitize (c, this)); 951 } 952 template <typename T> 953 inline bool sanitize (hb_sanitize_context_t *c, T user_data) const 954 { 955 TRACE_SANITIZE (this); 956 return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data)); 957 } 958 }; 959 960 961 /* An array starting at second element. */ 962 template <typename Type, typename LenType=USHORT> 963 struct HeadlessArrayOf 964 { 965 inline const Type& operator [] (unsigned int i) const 966 { 967 if (unlikely (i >= len || !i)) return Null(Type); 968 return array[i-1]; 969 } 970 inline unsigned int get_size (void) const 971 { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } 972 973 inline bool serialize (hb_serialize_context_t *c, 974 Supplier<Type> &items, 975 unsigned int items_len) 976 { 977 TRACE_SERIALIZE (this); 978 if (unlikely (!c->extend_min (*this))) return_trace (false); 979 len.set (items_len); /* TODO(serialize) Overflow? */ 980 if (unlikely (!items_len)) return_trace (true); 981 if (unlikely (!c->extend (*this))) return_trace (false); 982 for (unsigned int i = 0; i < items_len - 1; i++) 983 array[i] = items[i]; 984 items.advance (items_len - 1); 985 return_trace (true); 986 } 987 988 inline bool sanitize_shallow (hb_sanitize_context_t *c) const 989 { 990 return c->check_struct (this) 991 && c->check_array (this, Type::static_size, len); 992 } 993 994 inline bool sanitize (hb_sanitize_context_t *c) const 995 { 996 TRACE_SANITIZE (this); 997 if (unlikely (!sanitize_shallow (c))) return_trace (false); 998 999 /* Note: for structs that do not reference other structs, 1000 * we do not need to call their sanitize() as we already did 1001 * a bound check on the aggregate array size. We just include 1002 * a small unreachable expression to make sure the structs 1003 * pointed to do have a simple sanitize(), ie. they do not 1004 * reference other structs via offsets. 1005 */ 1006 (void) (false && array[0].sanitize (c)); 1007 1008 return_trace (true); 1009 } 1010 1011 LenType len; 1012 Type array[VAR]; 1013 public: 1014 DEFINE_SIZE_ARRAY (sizeof (LenType), array); 1015 }; 1016 1017 1018 /* An array with sorted elements. Supports binary searching. */ 1019 template <typename Type, typename LenType=USHORT> 1020 struct SortedArrayOf : ArrayOf<Type, LenType> 1021 { 1022 template <typename SearchType> 1023 inline int bsearch (const SearchType &x) const 1024 { 1025 /* Hand-coded bsearch here since this is in the hot inner loop. */ 1026 int min = 0, max = (int) this->len - 1; 1027 while (min <= max) 1028 { 1029 int mid = (min + max) / 2; 1030 int c = this->array[mid].cmp (x); 1031 if (c < 0) 1032 max = mid - 1; 1033 else if (c > 0) 1034 min = mid + 1; 1035 else 1036 return mid; 1037 } 1038 return -1; 1039 } 1040 }; 1041 1042 1043 } /* namespace OT */ 1044 1045 1046 #endif /* HB_OPEN_TYPE_PRIVATE_HH */