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 #include "hb-debug.hh"
  34 #include "hb-blob-private.hh"
  35 #include "hb-face-private.hh"
  36 
  37 
  38 namespace OT {
  39 
  40 
  41 
  42 /*
  43  * Casts
  44  */
  45 
  46 /* Cast to struct T, reference to reference */
  47 template<typename Type, typename TObject>
  48 static inline const Type& CastR(const TObject &X)
  49 { return reinterpret_cast<const Type&> (X); }
  50 template<typename Type, typename TObject>
  51 static inline Type& CastR(TObject &X)
  52 { return reinterpret_cast<Type&> (X); }
  53 
  54 /* Cast to struct T, pointer to pointer */
  55 template<typename Type, typename TObject>
  56 static inline const Type* CastP(const TObject *X)
  57 { return reinterpret_cast<const Type*> (X); }
  58 template<typename Type, typename TObject>
  59 static inline Type* CastP(TObject *X)
  60 { return reinterpret_cast<Type*> (X); }
  61 
  62 /* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
  63  * location pointed to by P plus Ofs bytes. */
  64 template<typename Type>
  65 static inline const Type& StructAtOffset(const void *P, unsigned int offset)
  66 { return * reinterpret_cast<const Type*> ((const char *) P + offset); }
  67 template<typename Type>
  68 static inline Type& StructAtOffset(void *P, unsigned int offset)
  69 { return * reinterpret_cast<Type*> ((char *) P + offset); }
  70 
  71 /* StructAfter<T>(X) returns the struct T& that is placed after X.
  72  * Works with X of variable size also.  X must implement get_size() */
  73 template<typename Type, typename TObject>
  74 static inline const Type& StructAfter(const TObject &X)
  75 { return StructAtOffset<Type>(&X, X.get_size()); }
  76 template<typename Type, typename TObject>
  77 static inline Type& StructAfter(TObject &X)
  78 { return StructAtOffset<Type>(&X, X.get_size()); }
  79 
  80 
  81 
  82 /*
  83  * Size checking
  84  */
  85 
  86 /* Check _assertion in a method environment */
  87 #define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
  88   inline void _instance_assertion_on_line_##_line (void) const \
  89   { \
  90     static_assert ((_assertion), ""); \
  91     ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
  92   }
  93 # define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
  94 # define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
  95 
  96 /* Check that _code compiles in a method environment */
  97 #define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
  98   inline void _compiles_assertion_on_line_##_line (void) const \
  99   { _code; }
 100 # define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
 101 # define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
 102 
 103 
 104 #define DEFINE_SIZE_STATIC(size) \
 105   DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
 106   static const unsigned int static_size = (size); \
 107   static const unsigned int min_size = (size); \
 108   inline unsigned int get_size (void) const { return (size); }
 109 
 110 #define DEFINE_SIZE_UNION(size, _member) \
 111   DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
 112   static const unsigned int min_size = (size)
 113 
 114 #define DEFINE_SIZE_MIN(size) \
 115   DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
 116   static const unsigned int min_size = (size)
 117 
 118 #define DEFINE_SIZE_ARRAY(size, array) \
 119   DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
 120   DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
 121   static const unsigned int min_size = (size)
 122 
 123 #define DEFINE_SIZE_ARRAY2(size, array1, array2) \
 124   DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
 125   DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
 126   static const unsigned int min_size = (size)
 127 
 128 
 129 
 130 /*
 131  * Dispatch
 132  */
 133 
 134 template <typename Context, typename Return, unsigned int MaxDebugDepth>
 135 struct hb_dispatch_context_t
 136 {
 137   static const unsigned int max_debug_depth = MaxDebugDepth;
 138   typedef Return return_t;
 139   template <typename T, typename F>
 140   inline bool may_dispatch (const T *obj, const F *format) { return true; }
 141   static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
 142 };
 143 
 144 
 145 /*
 146  * Sanitize
 147  */
 148 
 149 /* This limits sanitizing time on really broken fonts. */
 150 #ifndef HB_SANITIZE_MAX_EDITS
 151 #define HB_SANITIZE_MAX_EDITS 32
 152 #endif
 153 #ifndef HB_SANITIZE_MAX_OPS_FACTOR
 154 #define HB_SANITIZE_MAX_OPS_FACTOR 8
 155 #endif
 156 #ifndef HB_SANITIZE_MAX_OPS_MIN
 157 #define HB_SANITIZE_MAX_OPS_MIN 16384
 158 #endif
 159 
 160 struct hb_sanitize_context_t :
 161        hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
 162 {
 163   inline hb_sanitize_context_t (void) :
 164         debug_depth (0),
 165         start (nullptr), end (nullptr),
 166         writable (false), edit_count (0), max_ops (0),
 167         blob (nullptr),
 168         num_glyphs (0) {}
 169 
 170   inline const char *get_name (void) { return "SANITIZE"; }
 171   template <typename T, typename F>
 172   inline bool may_dispatch (const T *obj, const F *format)
 173   { return format->sanitize (this); }
 174   template <typename T>
 175   inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
 176   static return_t default_return_value (void) { return true; }
 177   static return_t no_dispatch_return_value (void) { return false; }
 178   bool stop_sublookup_iteration (const return_t r) const { return !r; }
 179 
 180   inline void init (hb_blob_t *b)
 181   {
 182     this->blob = hb_blob_reference (b);
 183     this->writable = false;
 184   }
 185 
 186   inline void start_processing (void)
 187   {
 188     this->start = hb_blob_get_data (this->blob, nullptr);
 189     this->end = this->start + this->blob->length;
 190     assert (this->start <= this->end); /* Must not overflow. */
 191     this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
 192                          (unsigned) HB_SANITIZE_MAX_OPS_MIN);
 193     this->edit_count = 0;
 194     this->debug_depth = 0;
 195 
 196     DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
 197                      "start [%p..%p] (%lu bytes)",
 198                      this->start, this->end,
 199                      (unsigned long) (this->end - this->start));
 200   }
 201 
 202   inline void end_processing (void)
 203   {
 204     DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
 205                      "end [%p..%p] %u edit requests",
 206                      this->start, this->end, this->edit_count);
 207 
 208     hb_blob_destroy (this->blob);
 209     this->blob = nullptr;
 210     this->start = this->end = nullptr;
 211   }
 212 
 213   inline bool check_range (const void *base, unsigned int len) const
 214   {
 215     const char *p = (const char *) base;
 216     bool ok = this->max_ops-- > 0 &&
 217               this->start <= p &&
 218               p <= this->end &&
 219               (unsigned int) (this->end - p) >= len;
 220 
 221     DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
 222        "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
 223        p, p + len, len,
 224        this->start, this->end,
 225        ok ? "OK" : "OUT-OF-RANGE");
 226 
 227     return likely (ok);
 228   }
 229 
 230   inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
 231   {
 232     const char *p = (const char *) base;
 233     bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
 234     unsigned int array_size = record_size * len;
 235     bool ok = !overflows && this->check_range (base, array_size);
 236 
 237     DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
 238        "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
 239        p, p + (record_size * len), record_size, len, (unsigned int) array_size,
 240        this->start, this->end,
 241        overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
 242 
 243     return likely (ok);
 244   }
 245 
 246   template <typename Type>
 247   inline bool check_struct (const Type *obj) const
 248   {
 249     return likely (this->check_range (obj, obj->min_size));
 250   }
 251 
 252   inline bool may_edit (const void *base, unsigned int len)
 253   {
 254     if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
 255       return false;
 256 
 257     const char *p = (const char *) base;
 258     this->edit_count++;
 259 
 260     DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
 261        "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
 262        this->edit_count,
 263        p, p + len, len,
 264        this->start, this->end,
 265        this->writable ? "GRANTED" : "DENIED");
 266 
 267     return this->writable;
 268   }
 269 
 270   template <typename Type, typename ValueType>
 271   inline bool try_set (const Type *obj, const ValueType &v) {
 272     if (this->may_edit (obj, obj->static_size)) {
 273       const_cast<Type *> (obj)->set (v);
 274       return true;
 275     }
 276     return false;
 277   }
 278 
 279   mutable unsigned int debug_depth;
 280   const char *start, *end;
 281   bool writable;
 282   unsigned int edit_count;
 283   mutable int max_ops;
 284   hb_blob_t *blob;
 285   unsigned int num_glyphs;
 286 };
 287 
 288 
 289 
 290 /* Template to sanitize an object. */
 291 template <typename Type>
 292 struct Sanitizer
 293 {
 294   inline Sanitizer (void) {}
 295 
 296   inline hb_blob_t *sanitize (hb_blob_t *blob) {
 297     bool sane;
 298 
 299     /* TODO is_sane() stuff */
 300 
 301     c->init (blob);
 302 
 303   retry:
 304     DEBUG_MSG_FUNC (SANITIZE, c->start, "start");
 305 
 306     c->start_processing ();
 307 
 308     if (unlikely (!c->start)) {
 309       c->end_processing ();
 310       return blob;
 311     }
 312 
 313     Type *t = CastP<Type> (const_cast<char *> (c->start));
 314 
 315     sane = t->sanitize (c);
 316     if (sane) {
 317       if (c->edit_count) {
 318         DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count);
 319 
 320         /* sanitize again to ensure no toe-stepping */
 321         c->edit_count = 0;
 322         sane = t->sanitize (c);
 323         if (c->edit_count) {
 324           DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count);
 325           sane = false;
 326         }
 327       }
 328     } else {
 329       unsigned int edit_count = c->edit_count;
 330       if (edit_count && !c->writable) {
 331         c->start = hb_blob_get_data_writable (blob, nullptr);
 332         c->end = c->start + blob->length;
 333 
 334         if (c->start) {
 335           c->writable = true;
 336           /* ok, we made it writable by relocating.  try again */
 337           DEBUG_MSG_FUNC (SANITIZE, c->start, "retry");
 338           goto retry;
 339         }
 340       }
 341     }
 342 
 343     c->end_processing ();
 344 
 345     DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED");
 346     if (sane)
 347     {
 348       blob->lock ();
 349       return blob;
 350     }
 351     else
 352     {
 353       hb_blob_destroy (blob);
 354       return hb_blob_get_empty ();
 355     }
 356   }
 357 
 358   inline void set_num_glyphs (unsigned int num_glyphs) { c->num_glyphs = num_glyphs; }
 359 
 360   private:
 361   hb_sanitize_context_t c[1];
 362 };
 363 
 364 
 365 
 366 /*
 367  * Serialize
 368  */
 369 
 370 
 371 struct hb_serialize_context_t
 372 {
 373   inline hb_serialize_context_t (void *start_, unsigned int size)
 374   {
 375     this->start = (char *) start_;
 376     this->end = this->start + size;
 377 
 378     this->ran_out_of_room = false;
 379     this->head = this->start;
 380     this->debug_depth = 0;
 381   }
 382 
 383   template <typename Type>
 384   inline Type *start_serialize (void)
 385   {
 386     DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
 387                      "start [%p..%p] (%lu bytes)",
 388                      this->start, this->end,
 389                      (unsigned long) (this->end - this->start));
 390 
 391     return start_embed<Type> ();
 392   }
 393 
 394   inline void end_serialize (void)
 395   {
 396     DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
 397                      "end [%p..%p] serialized %d bytes; %s",
 398                      this->start, this->end,
 399                      (int) (this->head - this->start),
 400                      this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
 401 
 402   }
 403 
 404   template <typename Type>
 405   inline Type *copy (void)
 406   {
 407     assert (!this->ran_out_of_room);
 408     unsigned int len = this->head - this->start;
 409     void *p = malloc (len);
 410     if (p)
 411       memcpy (p, this->start, len);
 412     return reinterpret_cast<Type *> (p);
 413   }
 414 
 415   template <typename Type>
 416   inline Type *allocate_size (unsigned int size)
 417   {
 418     if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
 419       this->ran_out_of_room = true;
 420       return nullptr;
 421     }
 422     memset (this->head, 0, size);
 423     char *ret = this->head;
 424     this->head += size;
 425     return reinterpret_cast<Type *> (ret);
 426   }
 427 
 428   template <typename Type>
 429   inline Type *allocate_min (void)
 430   {
 431     return this->allocate_size<Type> (Type::min_size);
 432   }
 433 
 434   template <typename Type>
 435   inline Type *start_embed (void)
 436   {
 437     Type *ret = reinterpret_cast<Type *> (this->head);
 438     return ret;
 439   }
 440 
 441   template <typename Type>
 442   inline Type *embed (const Type &obj)
 443   {
 444     unsigned int size = obj.get_size ();
 445     Type *ret = this->allocate_size<Type> (size);
 446     if (unlikely (!ret)) return nullptr;
 447     memcpy (ret, obj, size);
 448     return ret;
 449   }
 450 
 451   template <typename Type>
 452   inline Type *extend_min (Type &obj)
 453   {
 454     unsigned int size = obj.min_size;
 455     assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
 456     if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
 457     return reinterpret_cast<Type *> (&obj);
 458   }
 459 
 460   template <typename Type>
 461   inline Type *extend (Type &obj)
 462   {
 463     unsigned int size = obj.get_size ();
 464     assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
 465     if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
 466     return reinterpret_cast<Type *> (&obj);
 467   }
 468 
 469   inline void truncate (void *new_head)
 470   {
 471     assert (this->start < new_head && new_head <= this->head);
 472     this->head = (char *) new_head;
 473   }
 474 
 475   unsigned int debug_depth;
 476   char *start, *end, *head;
 477   bool ran_out_of_room;
 478 };
 479 
 480 template <typename Type>
 481 struct Supplier
 482 {
 483   inline Supplier (const Type *array, unsigned int len_, unsigned int stride_=sizeof(Type))
 484   {
 485     head = array;
 486     len = len_;
 487     stride = stride_;
 488   }
 489   inline const Type operator [] (unsigned int i) const
 490   {
 491     if (unlikely (i >= len)) return Type ();
 492     return * (const Type *) (const void *) ((const char *) head + stride * i);
 493   }
 494 
 495   inline Supplier<Type> & operator += (unsigned int count)
 496   {
 497     if (unlikely (count > len))
 498       count = len;
 499     len -= count;
 500     head = (const Type *) (const void *) ((const char *) head + stride * count);
 501     return *this;
 502   }
 503 
 504   private:
 505   inline Supplier (const Supplier<Type> &); /* Disallow copy */
 506   inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
 507 
 508   unsigned int len;
 509   unsigned int stride;
 510   const Type *head;
 511 };
 512 
 513 
 514 /*
 515  *
 516  * The OpenType Font File: Data Types
 517  */
 518 
 519 
 520 /* "The following data types are used in the OpenType font file.
 521  *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
 522 
 523 /*
 524  * Int types
 525  */
 526 
 527 
 528 template <typename Type, int Bytes> struct BEInt;
 529 
 530 template <typename Type>
 531 struct BEInt<Type, 1>
 532 {
 533   public:
 534   inline void set (Type V)
 535   {
 536     v = V;
 537   }
 538   inline operator Type (void) const
 539   {
 540     return v;
 541   }
 542   private: uint8_t v;
 543 };
 544 template <typename Type>
 545 struct BEInt<Type, 2>
 546 {
 547   public:
 548   inline void set (Type V)
 549   {
 550     v[0] = (V >>  8) & 0xFF;
 551     v[1] = (V      ) & 0xFF;
 552   }
 553   inline operator Type (void) const
 554   {
 555     return (v[0] <<  8)
 556          + (v[1]      );
 557   }
 558   private: uint8_t v[2];
 559 };
 560 template <typename Type>
 561 struct BEInt<Type, 3>
 562 {
 563   public:
 564   inline void set (Type V)
 565   {
 566     v[0] = (V >> 16) & 0xFF;
 567     v[1] = (V >>  8) & 0xFF;
 568     v[2] = (V      ) & 0xFF;
 569   }
 570   inline operator Type (void) const
 571   {
 572     return (v[0] << 16)
 573          + (v[1] <<  8)
 574          + (v[2]      );
 575   }
 576   private: uint8_t v[3];
 577 };
 578 template <typename Type>
 579 struct BEInt<Type, 4>
 580 {
 581   public:
 582   inline void set (Type V)
 583   {
 584     v[0] = (V >> 24) & 0xFF;
 585     v[1] = (V >> 16) & 0xFF;
 586     v[2] = (V >>  8) & 0xFF;
 587     v[3] = (V      ) & 0xFF;
 588   }
 589   inline operator Type (void) const
 590   {
 591     return (v[0] << 24)
 592          + (v[1] << 16)
 593          + (v[2] <<  8)
 594          + (v[3]      );
 595   }
 596   private: uint8_t v[4];
 597 };
 598 
 599 /* Integer types in big-endian order and no alignment requirement */
 600 template <typename Type, unsigned int Size>
 601 struct IntType
 602 {
 603   inline void set (Type i) { v.set (i); }
 604   inline operator Type(void) const { return v; }
 605   inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
 606   inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
 607   static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
 608   template <typename Type2>
 609   inline int cmp (Type2 a) const
 610   {
 611     Type b = v;
 612     if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
 613       return (int) a - (int) b;
 614     else
 615       return a < b ? -1 : a == b ? 0 : +1;
 616   }
 617   inline bool sanitize (hb_sanitize_context_t *c) const
 618   {
 619     TRACE_SANITIZE (this);
 620     return_trace (likely (c->check_struct (this)));
 621   }
 622   protected:
 623   BEInt<Type, Size> v;
 624   public:
 625   DEFINE_SIZE_STATIC (Size);
 626 };
 627 
 628 typedef IntType<uint8_t,  1> HBUINT8;   /* 8-bit unsigned integer. */
 629 typedef IntType<int8_t,   1> HBINT8;    /* 8-bit signed integer. */
 630 typedef IntType<uint16_t, 2> HBUINT16;  /* 16-bit unsigned integer. */
 631 typedef IntType<int16_t,  2> HBINT16;   /* 16-bit signed integer. */
 632 typedef IntType<uint32_t, 4> HBUINT32;  /* 32-bit unsigned integer. */
 633 typedef IntType<int32_t,  4> HBINT32;   /* 32-bit signed integer. */
 634 typedef IntType<uint32_t, 3> HBUINT24;  /* 24-bit unsigned integer. */
 635 
 636 /* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
 637 typedef HBINT16 FWORD;
 638 
 639 /* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
 640 typedef HBUINT16 UFWORD;
 641 
 642 /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
 643 struct F2DOT14 : HBINT16
 644 {
 645   // 16384 means 1<<14
 646   inline float to_float (void) const { return ((int32_t) v) / 16384.f; }
 647   inline void set_float (float f) { v.set (round (f * 16384.f)); }
 648   public:
 649   DEFINE_SIZE_STATIC (2);
 650 };
 651 
 652 /* 32-bit signed fixed-point number (16.16). */
 653 struct Fixed : HBINT32
 654 {
 655   // 65536 means 1<<16
 656   inline float to_float (void) const { return ((int32_t) v) / 65536.f; }
 657   inline void set_float (float f) { v.set (round (f * 65536.f)); }
 658   public:
 659   DEFINE_SIZE_STATIC (4);
 660 };
 661 
 662 /* Date represented in number of seconds since 12:00 midnight, January 1,
 663  * 1904. The value is represented as a signed 64-bit integer. */
 664 struct LONGDATETIME
 665 {
 666   inline bool sanitize (hb_sanitize_context_t *c) const
 667   {
 668     TRACE_SANITIZE (this);
 669     return_trace (likely (c->check_struct (this)));
 670   }
 671   protected:
 672   HBINT32 major;
 673   HBUINT32 minor;
 674   public:
 675   DEFINE_SIZE_STATIC (8);
 676 };
 677 
 678 /* Array of four uint8s (length = 32 bits) used to identify a script, language
 679  * system, feature, or baseline */
 680 struct Tag : HBUINT32
 681 {
 682   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
 683   inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
 684   inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
 685   public:
 686   DEFINE_SIZE_STATIC (4);
 687 };
 688 DEFINE_NULL_DATA (OT, Tag, "    ");
 689 
 690 /* Glyph index number, same as uint16 (length = 16 bits) */
 691 typedef HBUINT16 GlyphID;
 692 
 693 /* Name-table index, same as uint16 (length = 16 bits) */
 694 typedef HBUINT16 NameID;
 695 
 696 /* Script/language-system/feature index */
 697 struct Index : HBUINT16 {
 698   static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
 699 };
 700 DEFINE_NULL_DATA (OT, Index, "\xff\xff");
 701 
 702 /* Offset, Null offset = 0 */
 703 template <typename Type>
 704 struct Offset : Type
 705 {
 706   inline bool is_null (void) const { return 0 == *this; }
 707 
 708   inline void *serialize (hb_serialize_context_t *c, const void *base)
 709   {
 710     void *t = c->start_embed<void> ();
 711     this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
 712     return t;
 713   }
 714 
 715   public:
 716   DEFINE_SIZE_STATIC (sizeof(Type));
 717 };
 718 
 719 typedef Offset<HBUINT16> Offset16;
 720 typedef Offset<HBUINT32> Offset32;
 721 
 722 
 723 /* CheckSum */
 724 struct CheckSum : HBUINT32
 725 {
 726   /* This is reference implementation from the spec. */
 727   static inline uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length)
 728   {
 729     uint32_t Sum = 0L;
 730     assert (0 == (Length & 3));
 731     const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size;
 732 
 733     while (Table < EndPtr)
 734       Sum += *Table++;
 735     return Sum;
 736   }
 737 
 738   /* Note: data should be 4byte aligned and have 4byte padding at the end. */
 739   inline void set_for_data (const void *data, unsigned int length)
 740   { set (CalcTableChecksum ((const HBUINT32 *) data, length)); }
 741 
 742   public:
 743   DEFINE_SIZE_STATIC (4);
 744 };
 745 
 746 
 747 /*
 748  * Version Numbers
 749  */
 750 
 751 template <typename FixedType=HBUINT16>
 752 struct FixedVersion
 753 {
 754   inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; }
 755 
 756   inline bool sanitize (hb_sanitize_context_t *c) const
 757   {
 758     TRACE_SANITIZE (this);
 759     return_trace (c->check_struct (this));
 760   }
 761 
 762   FixedType major;
 763   FixedType minor;
 764   public:
 765   DEFINE_SIZE_STATIC (2 * sizeof(FixedType));
 766 };
 767 
 768 
 769 
 770 /*
 771  * Template subclasses of Offset that do the dereferencing.
 772  * Use: (base+offset)
 773  */
 774 
 775 template <typename Type, typename OffsetType=HBUINT16>
 776 struct OffsetTo : Offset<OffsetType>
 777 {
 778   inline const Type& operator () (const void *base) const
 779   {
 780     unsigned int offset = *this;
 781     if (unlikely (!offset)) return Null(Type);
 782     return StructAtOffset<const Type> (base, offset);
 783   }
 784   inline Type& operator () (void *base) const
 785   {
 786     unsigned int offset = *this;
 787     if (unlikely (!offset)) return Crap(Type);
 788     return StructAtOffset<Type> (base, offset);
 789   }
 790 
 791   inline Type& serialize (hb_serialize_context_t *c, const void *base)
 792   {
 793     return * (Type *) Offset<OffsetType>::serialize (c, base);
 794   }
 795 
 796   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
 797   {
 798     TRACE_SANITIZE (this);
 799     if (unlikely (!c->check_struct (this))) return_trace (false);
 800     unsigned int offset = *this;
 801     if (unlikely (!offset)) return_trace (true);
 802     if (unlikely (!c->check_range (base, offset))) return_trace (false);
 803     const Type &obj = StructAtOffset<Type> (base, offset);
 804     return_trace (likely (obj.sanitize (c)) || neuter (c));
 805   }
 806   template <typename T>
 807   inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
 808   {
 809     TRACE_SANITIZE (this);
 810     if (unlikely (!c->check_struct (this))) return_trace (false);
 811     unsigned int offset = *this;
 812     if (unlikely (!offset)) return_trace (true);
 813     if (unlikely (!c->check_range (base, offset))) return_trace (false);
 814     const Type &obj = StructAtOffset<Type> (base, offset);
 815     return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
 816   }
 817 
 818   /* Set the offset to Null */
 819   inline bool neuter (hb_sanitize_context_t *c) const {
 820     return c->try_set (this, 0);
 821   }
 822   DEFINE_SIZE_STATIC (sizeof(OffsetType));
 823 };
 824 template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {};
 825 template <typename Base, typename OffsetType, typename Type>
 826 static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
 827 template <typename Base, typename OffsetType, typename Type>
 828 static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
 829 
 830 
 831 /*
 832  * Array Types
 833  */
 834 
 835 
 836 /* TODO Use it in ArrayOf, HeadlessArrayOf, and other places around the code base?? */
 837 template <typename Type>
 838 struct UnsizedArrayOf
 839 {
 840   inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; }
 841   inline Type& operator [] (unsigned int i) { return arrayZ[i]; }
 842 
 843   inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
 844   {
 845     TRACE_SANITIZE (this);
 846     if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
 847 
 848     /* Note: for structs that do not reference other structs,
 849      * we do not need to call their sanitize() as we already did
 850      * a bound check on the aggregate array size.  We just include
 851      * a small unreachable expression to make sure the structs
 852      * pointed to do have a simple sanitize(), ie. they do not
 853      * reference other structs via offsets.
 854      */
 855     (void) (false && arrayZ[0].sanitize (c));
 856 
 857     return_trace (true);
 858   }
 859   inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
 860   {
 861     TRACE_SANITIZE (this);
 862     if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
 863     for (unsigned int i = 0; i < count; i++)
 864       if (unlikely (!arrayZ[i].sanitize (c, base)))
 865         return_trace (false);
 866     return_trace (true);
 867   }
 868   template <typename T>
 869   inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
 870   {
 871     TRACE_SANITIZE (this);
 872     if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
 873     for (unsigned int i = 0; i < count; i++)
 874       if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
 875         return_trace (false);
 876     return_trace (true);
 877   }
 878 
 879   inline bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
 880   {
 881     TRACE_SANITIZE (this);
 882     return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count));
 883   }
 884 
 885   public:
 886   Type  arrayZ[VAR];
 887   public:
 888   DEFINE_SIZE_ARRAY (0, arrayZ);
 889 };
 890 
 891 /* Unsized array of offset's */
 892 template <typename Type, typename OffsetType>
 893 struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType> > {};
 894 
 895 /* Unsized array of offsets relative to the beginning of the array itself. */
 896 template <typename Type, typename OffsetType>
 897 struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType>
 898 {
 899   inline const Type& operator [] (unsigned int i) const
 900   {
 901     return this+this->arrayZ[i];
 902   }
 903 
 904   inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
 905   {
 906     TRACE_SANITIZE (this);
 907     return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this)));
 908   }
 909   template <typename T>
 910   inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
 911   {
 912     TRACE_SANITIZE (this);
 913     return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this, user_data)));
 914   }
 915 };
 916 
 917 
 918 /* An array with a number of elements. */
 919 template <typename Type, typename LenType=HBUINT16>
 920 struct ArrayOf
 921 {
 922   const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
 923   {
 924     unsigned int count = len;
 925     if (unlikely (start_offset > count))
 926       count = 0;
 927     else
 928       count -= start_offset;
 929     count = MIN (count, *pcount);
 930     *pcount = count;
 931     return arrayZ + start_offset;
 932   }
 933 
 934   inline const Type& operator [] (unsigned int i) const
 935   {
 936     if (unlikely (i >= len)) return Null(Type);
 937     return arrayZ[i];
 938   }
 939   inline Type& operator [] (unsigned int i)
 940   {
 941     if (unlikely (i >= len)) return Crap(Type);
 942     return arrayZ[i];
 943   }
 944   inline unsigned int get_size (void) const
 945   { return len.static_size + len * Type::static_size; }
 946 
 947   inline bool serialize (hb_serialize_context_t *c,
 948                          unsigned int items_len)
 949   {
 950     TRACE_SERIALIZE (this);
 951     if (unlikely (!c->extend_min (*this))) return_trace (false);
 952     len.set (items_len); /* TODO(serialize) Overflow? */
 953     if (unlikely (!c->extend (*this))) return_trace (false);
 954     return_trace (true);
 955   }
 956 
 957   inline bool serialize (hb_serialize_context_t *c,
 958                          Supplier<Type> &items,
 959                          unsigned int items_len)
 960   {
 961     TRACE_SERIALIZE (this);
 962     if (unlikely (!serialize (c, items_len))) return_trace (false);
 963     for (unsigned int i = 0; i < items_len; i++)
 964       arrayZ[i] = items[i];
 965     items += items_len;
 966     return_trace (true);
 967   }
 968 
 969   inline bool sanitize (hb_sanitize_context_t *c) const
 970   {
 971     TRACE_SANITIZE (this);
 972     if (unlikely (!sanitize_shallow (c))) return_trace (false);
 973 
 974     /* Note: for structs that do not reference other structs,
 975      * we do not need to call their sanitize() as we already did
 976      * a bound check on the aggregate array size.  We just include
 977      * a small unreachable expression to make sure the structs
 978      * pointed to do have a simple sanitize(), ie. they do not
 979      * reference other structs via offsets.
 980      */
 981     (void) (false && arrayZ[0].sanitize (c));
 982 
 983     return_trace (true);
 984   }
 985   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
 986   {
 987     TRACE_SANITIZE (this);
 988     if (unlikely (!sanitize_shallow (c))) return_trace (false);
 989     unsigned int count = len;
 990     for (unsigned int i = 0; i < count; i++)
 991       if (unlikely (!arrayZ[i].sanitize (c, base)))
 992         return_trace (false);
 993     return_trace (true);
 994   }
 995   template <typename T>
 996   inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
 997   {
 998     TRACE_SANITIZE (this);
 999     if (unlikely (!sanitize_shallow (c))) return_trace (false);
1000     unsigned int count = len;
1001     for (unsigned int i = 0; i < count; i++)
1002       if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
1003         return_trace (false);
1004     return_trace (true);
1005   }
1006 
1007   template <typename SearchType>
1008   inline int lsearch (const SearchType &x) const
1009   {
1010     unsigned int count = len;
1011     for (unsigned int i = 0; i < count; i++)
1012       if (!this->arrayZ[i].cmp (x))
1013         return i;
1014     return -1;
1015   }
1016 
1017   inline void qsort (void)
1018   {
1019     ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
1020   }
1021 
1022   private:
1023   inline bool sanitize_shallow (hb_sanitize_context_t *c) const
1024   {
1025     TRACE_SANITIZE (this);
1026     return_trace (len.sanitize (c) && c->check_array (arrayZ, Type::static_size, len));
1027   }
1028 
1029   public:
1030   LenType len;
1031   Type arrayZ[VAR];
1032   public:
1033   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
1034 };
1035 template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
1036 
1037 /* Array of Offset's */
1038 template <typename Type, typename OffsetType=HBUINT16>
1039 struct OffsetArrayOf : ArrayOf<OffsetTo<Type, OffsetType> > {};
1040 
1041 /* Array of offsets relative to the beginning of the array itself. */
1042 template <typename Type>
1043 struct OffsetListOf : OffsetArrayOf<Type>
1044 {
1045   inline const Type& operator [] (unsigned int i) const
1046   {
1047     if (unlikely (i >= this->len)) return Null(Type);
1048     return this+this->arrayZ[i];
1049   }
1050   inline const Type& operator [] (unsigned int i)
1051   {
1052     if (unlikely (i >= this->len)) return Crap(Type);
1053     return this+this->arrayZ[i];
1054   }
1055 
1056   inline bool sanitize (hb_sanitize_context_t *c) const
1057   {
1058     TRACE_SANITIZE (this);
1059     return_trace (OffsetArrayOf<Type>::sanitize (c, this));
1060   }
1061   template <typename T>
1062   inline bool sanitize (hb_sanitize_context_t *c, T user_data) const
1063   {
1064     TRACE_SANITIZE (this);
1065     return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
1066   }
1067 };
1068 
1069 
1070 /* An array starting at second element. */
1071 template <typename Type, typename LenType=HBUINT16>
1072 struct HeadlessArrayOf
1073 {
1074   inline const Type& operator [] (unsigned int i) const
1075   {
1076     if (unlikely (i >= len || !i)) return Null(Type);
1077     return arrayZ[i-1];
1078   }
1079   inline Type& operator [] (unsigned int i)
1080   {
1081     if (unlikely (i >= len || !i)) return Crap(Type);
1082     return arrayZ[i-1];
1083   }
1084   inline unsigned int get_size (void) const
1085   { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
1086 
1087   inline bool serialize (hb_serialize_context_t *c,
1088                          Supplier<Type> &items,
1089                          unsigned int items_len)
1090   {
1091     TRACE_SERIALIZE (this);
1092     if (unlikely (!c->extend_min (*this))) return_trace (false);
1093     len.set (items_len); /* TODO(serialize) Overflow? */
1094     if (unlikely (!items_len)) return_trace (true);
1095     if (unlikely (!c->extend (*this))) return_trace (false);
1096     for (unsigned int i = 0; i < items_len - 1; i++)
1097       arrayZ[i] = items[i];
1098     items += items_len - 1;
1099     return_trace (true);
1100   }
1101 
1102   inline bool sanitize (hb_sanitize_context_t *c) const
1103   {
1104     TRACE_SANITIZE (this);
1105     if (unlikely (!sanitize_shallow (c))) return_trace (false);
1106 
1107     /* Note: for structs that do not reference other structs,
1108      * we do not need to call their sanitize() as we already did
1109      * a bound check on the aggregate array size.  We just include
1110      * a small unreachable expression to make sure the structs
1111      * pointed to do have a simple sanitize(), ie. they do not
1112      * reference other structs via offsets.
1113      */
1114     (void) (false && arrayZ[0].sanitize (c));
1115 
1116     return_trace (true);
1117   }
1118 
1119   private:
1120   inline bool sanitize_shallow (hb_sanitize_context_t *c) const
1121   {
1122     TRACE_SANITIZE (this);
1123     return_trace (len.sanitize (c) &&
1124                   (!len || c->check_array (arrayZ, Type::static_size, len - 1)));
1125   }
1126 
1127   public:
1128   LenType len;
1129   Type arrayZ[VAR];
1130   public:
1131   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
1132 };
1133 
1134 
1135 /*
1136  * An array with sorted elements.  Supports binary searching.
1137  */
1138 template <typename Type, typename LenType=HBUINT16>
1139 struct SortedArrayOf : ArrayOf<Type, LenType>
1140 {
1141   template <typename SearchType>
1142   inline int bsearch (const SearchType &x) const
1143   {
1144     /* Hand-coded bsearch here since this is in the hot inner loop. */
1145     const Type *arr = this->arrayZ;
1146     int min = 0, max = (int) this->len - 1;
1147     while (min <= max)
1148     {
1149       int mid = (min + max) / 2;
1150       int c = arr[mid].cmp (x);
1151       if (c < 0)
1152         max = mid - 1;
1153       else if (c > 0)
1154         min = mid + 1;
1155       else
1156         return mid;
1157     }
1158     return -1;
1159   }
1160 };
1161 
1162 /*
1163  * Binary-search arrays
1164  */
1165 
1166 struct BinSearchHeader
1167 {
1168   inline operator uint32_t (void) const { return len; }
1169 
1170   inline bool sanitize (hb_sanitize_context_t *c) const
1171   {
1172     TRACE_SANITIZE (this);
1173     return_trace (c->check_struct (this));
1174   }
1175 
1176   inline void set (unsigned int v)
1177   {
1178     len.set (v);
1179     assert (len == v);
1180     entrySelector.set (MAX (1u, _hb_bit_storage (v)) - 1);
1181     searchRange.set (16 * (1u << entrySelector));
1182     rangeShift.set (v * 16 > searchRange
1183                     ? 16 * v - searchRange
1184                     : 0);
1185   }
1186 
1187   protected:
1188   HBUINT16      len;
1189   HBUINT16      searchRange;
1190   HBUINT16      entrySelector;
1191   HBUINT16      rangeShift;
1192 
1193   public:
1194   DEFINE_SIZE_STATIC (8);
1195 };
1196 
1197 template <typename Type>
1198 struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
1199 
1200 
1201 /* Lazy struct and blob loaders. */
1202 
1203 /* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
1204 template <typename T>
1205 struct hb_lazy_loader_t
1206 {
1207   inline void init (hb_face_t *face_)
1208   {
1209     face = face_;
1210     instance = nullptr;
1211   }
1212 
1213   inline void fini (void)
1214   {
1215     if (instance && instance != &Null(T))
1216     {
1217       instance->fini();
1218       free (instance);
1219     }
1220   }
1221 
1222   inline const T* get (void) const
1223   {
1224   retry:
1225     T *p = (T *) hb_atomic_ptr_get (&instance);
1226     if (unlikely (!p))
1227     {
1228       p = (T *) calloc (1, sizeof (T));
1229       if (unlikely (!p))
1230         p = const_cast<T *> (&Null(T));
1231       else
1232         p->init (face);
1233       if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)))
1234       {
1235         if (p != &Null(T))
1236           p->fini ();
1237         goto retry;
1238       }
1239     }
1240     return p;
1241   }
1242 
1243   inline const T* operator-> (void) const
1244   {
1245     return get ();
1246   }
1247 
1248   private:
1249   hb_face_t *face;
1250   T *instance;
1251 };
1252 
1253 /* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
1254 template <typename T>
1255 struct hb_table_lazy_loader_t
1256 {
1257   inline void init (hb_face_t *face_)
1258   {
1259     face = face_;
1260     blob = nullptr;
1261   }
1262 
1263   inline void fini (void)
1264   {
1265     hb_blob_destroy (blob);
1266   }
1267 
1268   inline const T* get (void) const
1269   {
1270   retry:
1271     hb_blob_t *blob_ = (hb_blob_t *) hb_atomic_ptr_get (&blob);
1272     if (unlikely (!blob_))
1273     {
1274       blob_ = OT::Sanitizer<T>().sanitize (face->reference_table (T::tableTag));
1275       if (!hb_atomic_ptr_cmpexch (&blob, nullptr, blob_))
1276       {
1277         hb_blob_destroy (blob_);
1278         goto retry;
1279       }
1280       blob = blob_;
1281     }
1282     return blob_->as<T> ();
1283   }
1284 
1285   inline const T* operator-> (void) const
1286   {
1287     return get();
1288   }
1289 
1290   private:
1291   hb_face_t *face;
1292   mutable hb_blob_t *blob;
1293 };
1294 
1295 
1296 } /* namespace OT */
1297 
1298 
1299 #endif /* HB_OPEN_TYPE_PRIVATE_HH */