1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/harfbuzz/src/hb-open-type-private.hh Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,979 @@ 1.4 +/* 1.5 + * Copyright © 2007,2008,2009,2010 Red Hat, Inc. 1.6 + * Copyright © 2012 Google, Inc. 1.7 + * 1.8 + * This is part of HarfBuzz, a text shaping library. 1.9 + * 1.10 + * Permission is hereby granted, without written agreement and without 1.11 + * license or royalty fees, to use, copy, modify, and distribute this 1.12 + * software and its documentation for any purpose, provided that the 1.13 + * above copyright notice and the following two paragraphs appear in 1.14 + * all copies of this software. 1.15 + * 1.16 + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1.17 + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1.18 + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1.19 + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1.20 + * DAMAGE. 1.21 + * 1.22 + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 1.23 + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 1.24 + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 1.25 + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 1.26 + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 1.27 + * 1.28 + * Red Hat Author(s): Behdad Esfahbod 1.29 + * Google Author(s): Behdad Esfahbod 1.30 + */ 1.31 + 1.32 +#ifndef HB_OPEN_TYPE_PRIVATE_HH 1.33 +#define HB_OPEN_TYPE_PRIVATE_HH 1.34 + 1.35 +#include "hb-private.hh" 1.36 + 1.37 + 1.38 +namespace OT { 1.39 + 1.40 + 1.41 + 1.42 +/* 1.43 + * Casts 1.44 + */ 1.45 + 1.46 +/* Cast to struct T, reference to reference */ 1.47 +template<typename Type, typename TObject> 1.48 +inline const Type& CastR(const TObject &X) 1.49 +{ return reinterpret_cast<const Type&> (X); } 1.50 +template<typename Type, typename TObject> 1.51 +inline Type& CastR(TObject &X) 1.52 +{ return reinterpret_cast<Type&> (X); } 1.53 + 1.54 +/* Cast to struct T, pointer to pointer */ 1.55 +template<typename Type, typename TObject> 1.56 +inline const Type* CastP(const TObject *X) 1.57 +{ return reinterpret_cast<const Type*> (X); } 1.58 +template<typename Type, typename TObject> 1.59 +inline Type* CastP(TObject *X) 1.60 +{ return reinterpret_cast<Type*> (X); } 1.61 + 1.62 +/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory 1.63 + * location pointed to by P plus Ofs bytes. */ 1.64 +template<typename Type> 1.65 +inline const Type& StructAtOffset(const void *P, unsigned int offset) 1.66 +{ return * reinterpret_cast<const Type*> ((const char *) P + offset); } 1.67 +template<typename Type> 1.68 +inline Type& StructAtOffset(void *P, unsigned int offset) 1.69 +{ return * reinterpret_cast<Type*> ((char *) P + offset); } 1.70 + 1.71 +/* StructAfter<T>(X) returns the struct T& that is placed after X. 1.72 + * Works with X of variable size also. X must implement get_size() */ 1.73 +template<typename Type, typename TObject> 1.74 +inline const Type& StructAfter(const TObject &X) 1.75 +{ return StructAtOffset<Type>(&X, X.get_size()); } 1.76 +template<typename Type, typename TObject> 1.77 +inline Type& StructAfter(TObject &X) 1.78 +{ return StructAtOffset<Type>(&X, X.get_size()); } 1.79 + 1.80 + 1.81 + 1.82 +/* 1.83 + * Size checking 1.84 + */ 1.85 + 1.86 +/* Check _assertion in a method environment */ 1.87 +#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ 1.88 + inline void _instance_assertion_on_line_##_line (void) const \ 1.89 + { \ 1.90 + ASSERT_STATIC (_assertion); \ 1.91 + ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \ 1.92 + } 1.93 +# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion) 1.94 +# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion) 1.95 + 1.96 +/* Check that _code compiles in a method environment */ 1.97 +#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \ 1.98 + inline void _compiles_assertion_on_line_##_line (void) const \ 1.99 + { _code; } 1.100 +# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code) 1.101 +# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code) 1.102 + 1.103 + 1.104 +#define DEFINE_SIZE_STATIC(size) \ 1.105 + DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \ 1.106 + static const unsigned int static_size = (size); \ 1.107 + static const unsigned int min_size = (size) 1.108 + 1.109 +/* Size signifying variable-sized array */ 1.110 +#define VAR 1 1.111 + 1.112 +#define DEFINE_SIZE_UNION(size, _member) \ 1.113 + DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \ 1.114 + static const unsigned int min_size = (size) 1.115 + 1.116 +#define DEFINE_SIZE_MIN(size) \ 1.117 + DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \ 1.118 + static const unsigned int min_size = (size) 1.119 + 1.120 +#define DEFINE_SIZE_ARRAY(size, array) \ 1.121 + DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \ 1.122 + DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \ 1.123 + static const unsigned int min_size = (size) 1.124 + 1.125 +#define DEFINE_SIZE_ARRAY2(size, array1, array2) \ 1.126 + DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ 1.127 + DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \ 1.128 + static const unsigned int min_size = (size) 1.129 + 1.130 + 1.131 + 1.132 +/* 1.133 + * Null objects 1.134 + */ 1.135 + 1.136 +/* Global nul-content Null pool. Enlarge as necessary. */ 1.137 +/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */ 1.138 +static const void *_NullPool[64 / sizeof (void *)]; 1.139 + 1.140 +/* Generic nul-content Null objects. */ 1.141 +template <typename Type> 1.142 +static inline const Type& Null (void) { 1.143 + ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); 1.144 + return *CastP<Type> (_NullPool); 1.145 +} 1.146 + 1.147 +/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ 1.148 +#define DEFINE_NULL_DATA(Type, data) \ 1.149 +static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \ 1.150 +template <> \ 1.151 +inline const Type& Null<Type> (void) { \ 1.152 + return *CastP<Type> (_Null##Type); \ 1.153 +} /* The following line really exists such that we end in a place needing semicolon */ \ 1.154 +ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) 1.155 + 1.156 +/* Accessor macro. */ 1.157 +#define Null(Type) Null<Type>() 1.158 + 1.159 + 1.160 + 1.161 +/* 1.162 + * Sanitize 1.163 + */ 1.164 + 1.165 +#ifndef HB_DEBUG_SANITIZE 1.166 +#define HB_DEBUG_SANITIZE (HB_DEBUG+0) 1.167 +#endif 1.168 + 1.169 + 1.170 +#define TRACE_SANITIZE(this) \ 1.171 + hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \ 1.172 + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ 1.173 + ""); 1.174 + 1.175 +/* This limits sanitizing time on really broken fonts. */ 1.176 +#ifndef HB_SANITIZE_MAX_EDITS 1.177 +#define HB_SANITIZE_MAX_EDITS 100 1.178 +#endif 1.179 + 1.180 +struct hb_sanitize_context_t 1.181 +{ 1.182 + inline const char *get_name (void) { return "SANITIZE"; } 1.183 + static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; 1.184 + typedef bool return_t; 1.185 + template <typename T> 1.186 + inline return_t dispatch (const T &obj) { return obj.sanitize (this); } 1.187 + static return_t default_return_value (void) { return true; } 1.188 + bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; } 1.189 + 1.190 + inline void init (hb_blob_t *b) 1.191 + { 1.192 + this->blob = hb_blob_reference (b); 1.193 + this->writable = false; 1.194 + } 1.195 + 1.196 + inline void start_processing (void) 1.197 + { 1.198 + this->start = hb_blob_get_data (this->blob, NULL); 1.199 + this->end = this->start + hb_blob_get_length (this->blob); 1.200 + this->edit_count = 0; 1.201 + this->debug_depth = 0; 1.202 + 1.203 + DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1, 1.204 + "start [%p..%p] (%lu bytes)", 1.205 + this->start, this->end, 1.206 + (unsigned long) (this->end - this->start)); 1.207 + } 1.208 + 1.209 + inline void end_processing (void) 1.210 + { 1.211 + DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1, 1.212 + "end [%p..%p] %u edit requests", 1.213 + this->start, this->end, this->edit_count); 1.214 + 1.215 + hb_blob_destroy (this->blob); 1.216 + this->blob = NULL; 1.217 + this->start = this->end = NULL; 1.218 + } 1.219 + 1.220 + inline bool check_range (const void *base, unsigned int len) const 1.221 + { 1.222 + const char *p = (const char *) base; 1.223 + 1.224 + hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace 1.225 + (&this->debug_depth, "SANITIZE", this->blob, NULL, 1.226 + "check_range [%p..%p] (%d bytes) in [%p..%p]", 1.227 + p, p + len, len, 1.228 + this->start, this->end); 1.229 + 1.230 + return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len)); 1.231 + } 1.232 + 1.233 + inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const 1.234 + { 1.235 + const char *p = (const char *) base; 1.236 + bool overflows = _hb_unsigned_int_mul_overflows (len, record_size); 1.237 + 1.238 + hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace 1.239 + (&this->debug_depth, "SANITIZE", this->blob, NULL, 1.240 + "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]", 1.241 + p, p + (record_size * len), record_size, len, (unsigned long) record_size * len, 1.242 + this->start, this->end); 1.243 + 1.244 + return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len))); 1.245 + } 1.246 + 1.247 + template <typename Type> 1.248 + inline bool check_struct (const Type *obj) const 1.249 + { 1.250 + return likely (this->check_range (obj, obj->min_size)); 1.251 + } 1.252 + 1.253 + inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED) 1.254 + { 1.255 + if (this->edit_count >= HB_SANITIZE_MAX_EDITS) 1.256 + return false; 1.257 + 1.258 + const char *p = (const char *) base; 1.259 + this->edit_count++; 1.260 + 1.261 + hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace 1.262 + (&this->debug_depth, "SANITIZE", this->blob, NULL, 1.263 + "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", 1.264 + this->edit_count, 1.265 + p, p + len, len, 1.266 + this->start, this->end, 1.267 + this->writable ? "GRANTED" : "DENIED"); 1.268 + 1.269 + return TRACE_RETURN (this->writable); 1.270 + } 1.271 + 1.272 + mutable unsigned int debug_depth; 1.273 + const char *start, *end; 1.274 + bool writable; 1.275 + unsigned int edit_count; 1.276 + hb_blob_t *blob; 1.277 +}; 1.278 + 1.279 + 1.280 + 1.281 +/* Template to sanitize an object. */ 1.282 +template <typename Type> 1.283 +struct Sanitizer 1.284 +{ 1.285 + static hb_blob_t *sanitize (hb_blob_t *blob) { 1.286 + hb_sanitize_context_t c[1] = {{0}}; 1.287 + bool sane; 1.288 + 1.289 + /* TODO is_sane() stuff */ 1.290 + 1.291 + c->init (blob); 1.292 + 1.293 + retry: 1.294 + DEBUG_MSG_FUNC (SANITIZE, blob, "start"); 1.295 + 1.296 + c->start_processing (); 1.297 + 1.298 + if (unlikely (!c->start)) { 1.299 + c->end_processing (); 1.300 + return blob; 1.301 + } 1.302 + 1.303 + Type *t = CastP<Type> (const_cast<char *> (c->start)); 1.304 + 1.305 + sane = t->sanitize (c); 1.306 + if (sane) { 1.307 + if (c->edit_count) { 1.308 + DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count); 1.309 + 1.310 + /* sanitize again to ensure no toe-stepping */ 1.311 + c->edit_count = 0; 1.312 + sane = t->sanitize (c); 1.313 + if (c->edit_count) { 1.314 + DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count); 1.315 + sane = false; 1.316 + } 1.317 + } 1.318 + } else { 1.319 + unsigned int edit_count = c->edit_count; 1.320 + if (edit_count && !c->writable) { 1.321 + c->start = hb_blob_get_data_writable (blob, NULL); 1.322 + c->end = c->start + hb_blob_get_length (blob); 1.323 + 1.324 + if (c->start) { 1.325 + c->writable = true; 1.326 + /* ok, we made it writable by relocating. try again */ 1.327 + DEBUG_MSG_FUNC (SANITIZE, blob, "retry"); 1.328 + goto retry; 1.329 + } 1.330 + } 1.331 + } 1.332 + 1.333 + c->end_processing (); 1.334 + 1.335 + DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED"); 1.336 + if (sane) 1.337 + return blob; 1.338 + else { 1.339 + hb_blob_destroy (blob); 1.340 + return hb_blob_get_empty (); 1.341 + } 1.342 + } 1.343 + 1.344 + static const Type* lock_instance (hb_blob_t *blob) { 1.345 + hb_blob_make_immutable (blob); 1.346 + const char *base = hb_blob_get_data (blob, NULL); 1.347 + return unlikely (!base) ? &Null(Type) : CastP<Type> (base); 1.348 + } 1.349 +}; 1.350 + 1.351 + 1.352 + 1.353 +/* 1.354 + * Serialize 1.355 + */ 1.356 + 1.357 +#ifndef HB_DEBUG_SERIALIZE 1.358 +#define HB_DEBUG_SERIALIZE (HB_DEBUG+0) 1.359 +#endif 1.360 + 1.361 + 1.362 +#define TRACE_SERIALIZE(this) \ 1.363 + hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \ 1.364 + (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ 1.365 + ""); 1.366 + 1.367 + 1.368 +struct hb_serialize_context_t 1.369 +{ 1.370 + inline hb_serialize_context_t (void *start, unsigned int size) 1.371 + { 1.372 + this->start = (char *) start; 1.373 + this->end = this->start + size; 1.374 + 1.375 + this->ran_out_of_room = false; 1.376 + this->head = this->start; 1.377 + this->debug_depth = 0; 1.378 + } 1.379 + 1.380 + template <typename Type> 1.381 + inline Type *start_serialize (void) 1.382 + { 1.383 + DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1, 1.384 + "start [%p..%p] (%lu bytes)", 1.385 + this->start, this->end, 1.386 + (unsigned long) (this->end - this->start)); 1.387 + 1.388 + return start_embed<Type> (); 1.389 + } 1.390 + 1.391 + inline void end_serialize (void) 1.392 + { 1.393 + DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1, 1.394 + "end [%p..%p] serialized %d bytes; %s", 1.395 + this->start, this->end, 1.396 + (int) (this->head - this->start), 1.397 + this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room"); 1.398 + 1.399 + } 1.400 + 1.401 + template <typename Type> 1.402 + inline Type *copy (void) 1.403 + { 1.404 + assert (!this->ran_out_of_room); 1.405 + unsigned int len = this->head - this->start; 1.406 + void *p = malloc (len); 1.407 + if (p) 1.408 + memcpy (p, this->start, len); 1.409 + return reinterpret_cast<Type *> (p); 1.410 + } 1.411 + 1.412 + template <typename Type> 1.413 + inline Type *allocate_size (unsigned int size) 1.414 + { 1.415 + if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) { 1.416 + this->ran_out_of_room = true; 1.417 + return NULL; 1.418 + } 1.419 + memset (this->head, 0, size); 1.420 + char *ret = this->head; 1.421 + this->head += size; 1.422 + return reinterpret_cast<Type *> (ret); 1.423 + } 1.424 + 1.425 + template <typename Type> 1.426 + inline Type *allocate_min (void) 1.427 + { 1.428 + return this->allocate_size<Type> (Type::min_size); 1.429 + } 1.430 + 1.431 + template <typename Type> 1.432 + inline Type *start_embed (void) 1.433 + { 1.434 + Type *ret = reinterpret_cast<Type *> (this->head); 1.435 + return ret; 1.436 + } 1.437 + 1.438 + template <typename Type> 1.439 + inline Type *embed (const Type &obj) 1.440 + { 1.441 + unsigned int size = obj.get_size (); 1.442 + Type *ret = this->allocate_size<Type> (size); 1.443 + if (unlikely (!ret)) return NULL; 1.444 + memcpy (ret, obj, size); 1.445 + return ret; 1.446 + } 1.447 + 1.448 + template <typename Type> 1.449 + inline Type *extend_min (Type &obj) 1.450 + { 1.451 + unsigned int size = obj.min_size; 1.452 + assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 1.453 + if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; 1.454 + return reinterpret_cast<Type *> (&obj); 1.455 + } 1.456 + 1.457 + template <typename Type> 1.458 + inline Type *extend (Type &obj) 1.459 + { 1.460 + unsigned int size = obj.get_size (); 1.461 + assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 1.462 + if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; 1.463 + return reinterpret_cast<Type *> (&obj); 1.464 + } 1.465 + 1.466 + inline void truncate (void *head) 1.467 + { 1.468 + assert (this->start < head && head <= this->head); 1.469 + this->head = (char *) head; 1.470 + } 1.471 + 1.472 + unsigned int debug_depth; 1.473 + char *start, *end, *head; 1.474 + bool ran_out_of_room; 1.475 +}; 1.476 + 1.477 +template <typename Type> 1.478 +struct Supplier 1.479 +{ 1.480 + inline Supplier (const Type *array, unsigned int len_) 1.481 + { 1.482 + head = array; 1.483 + len = len_; 1.484 + } 1.485 + inline const Type operator [] (unsigned int i) const 1.486 + { 1.487 + if (unlikely (i >= len)) return Type (); 1.488 + return head[i]; 1.489 + } 1.490 + 1.491 + inline void advance (unsigned int count) 1.492 + { 1.493 + if (unlikely (count > len)) 1.494 + count = len; 1.495 + len -= count; 1.496 + head += count; 1.497 + } 1.498 + 1.499 + private: 1.500 + inline Supplier (const Supplier<Type> &); /* Disallow copy */ 1.501 + inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */ 1.502 + 1.503 + unsigned int len; 1.504 + const Type *head; 1.505 +}; 1.506 + 1.507 + 1.508 + 1.509 + 1.510 +/* 1.511 + * 1.512 + * The OpenType Font File: Data Types 1.513 + */ 1.514 + 1.515 + 1.516 +/* "The following data types are used in the OpenType font file. 1.517 + * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */ 1.518 + 1.519 +/* 1.520 + * Int types 1.521 + */ 1.522 + 1.523 + 1.524 +template <typename Type, int Bytes> struct BEInt; 1.525 + 1.526 +template <typename Type> 1.527 +struct BEInt<Type, 2> 1.528 +{ 1.529 + public: 1.530 + inline void set (Type i) { hb_be_uint16_put (v,i); } 1.531 + inline operator Type (void) const { return hb_be_uint16_get (v); } 1.532 + inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); } 1.533 + inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); } 1.534 + private: uint8_t v[2]; 1.535 +}; 1.536 +template <typename Type> 1.537 +struct BEInt<Type, 4> 1.538 +{ 1.539 + public: 1.540 + inline void set (Type i) { hb_be_uint32_put (v,i); } 1.541 + inline operator Type (void) const { return hb_be_uint32_get (v); } 1.542 + inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); } 1.543 + inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); } 1.544 + private: uint8_t v[4]; 1.545 +}; 1.546 +template <typename Type> 1.547 +struct BEInt<Type, 3> 1.548 +{ 1.549 + public: 1.550 + inline void set (Type i) { hb_be_uint24_put (v,i); } 1.551 + inline operator Type (void) const { return hb_be_uint24_get (v); } 1.552 + inline bool operator == (const BEInt<Type, 3>& o) const { return hb_be_uint24_eq (v, o.v); } 1.553 + inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); } 1.554 + private: uint8_t v[3]; 1.555 +}; 1.556 + 1.557 +/* Integer types in big-endian order and no alignment requirement */ 1.558 +template <typename Type, unsigned int Size> 1.559 +struct IntType 1.560 +{ 1.561 + inline void set (Type i) { v.set (i); } 1.562 + inline operator Type(void) const { return v; } 1.563 + inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v; } 1.564 + inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v; } 1.565 + static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); } 1.566 + inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; } 1.567 + inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } 1.568 + inline bool sanitize (hb_sanitize_context_t *c) { 1.569 + TRACE_SANITIZE (this); 1.570 + return TRACE_RETURN (likely (c->check_struct (this))); 1.571 + } 1.572 + protected: 1.573 + BEInt<Type, Size> v; 1.574 + public: 1.575 + DEFINE_SIZE_STATIC (Size); 1.576 +}; 1.577 + 1.578 +typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */ 1.579 +typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */ 1.580 +typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */ 1.581 +typedef IntType<int32_t, 4> LONG; /* 32-bit signed integer. */ 1.582 +typedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */ 1.583 + 1.584 +/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ 1.585 +typedef SHORT FWORD; 1.586 + 1.587 +/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ 1.588 +typedef USHORT UFWORD; 1.589 + 1.590 +/* Date represented in number of seconds since 12:00 midnight, January 1, 1.591 + * 1904. The value is represented as a signed 64-bit integer. */ 1.592 +struct LONGDATETIME 1.593 +{ 1.594 + inline bool sanitize (hb_sanitize_context_t *c) { 1.595 + TRACE_SANITIZE (this); 1.596 + return TRACE_RETURN (likely (c->check_struct (this))); 1.597 + } 1.598 + protected: 1.599 + LONG major; 1.600 + ULONG minor; 1.601 + public: 1.602 + DEFINE_SIZE_STATIC (8); 1.603 +}; 1.604 + 1.605 +/* Array of four uint8s (length = 32 bits) used to identify a script, language 1.606 + * system, feature, or baseline */ 1.607 +struct Tag : ULONG 1.608 +{ 1.609 + /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ 1.610 + inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); } 1.611 + inline operator char* (void) { return reinterpret_cast<char *> (&this->v); } 1.612 + public: 1.613 + DEFINE_SIZE_STATIC (4); 1.614 +}; 1.615 +DEFINE_NULL_DATA (Tag, " "); 1.616 + 1.617 +/* Glyph index number, same as uint16 (length = 16 bits) */ 1.618 +typedef USHORT GlyphID; 1.619 + 1.620 +/* Script/language-system/feature index */ 1.621 +struct Index : USHORT { 1.622 + static const unsigned int NOT_FOUND_INDEX = 0xFFFF; 1.623 +}; 1.624 +DEFINE_NULL_DATA (Index, "\xff\xff"); 1.625 + 1.626 +/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */ 1.627 +struct Offset : USHORT 1.628 +{ 1.629 + inline bool is_null (void) const { return 0 == *this; } 1.630 + public: 1.631 + DEFINE_SIZE_STATIC (2); 1.632 +}; 1.633 + 1.634 +/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */ 1.635 +struct LongOffset : ULONG 1.636 +{ 1.637 + inline bool is_null (void) const { return 0 == *this; } 1.638 + public: 1.639 + DEFINE_SIZE_STATIC (4); 1.640 +}; 1.641 + 1.642 + 1.643 +/* CheckSum */ 1.644 +struct CheckSum : ULONG 1.645 +{ 1.646 + /* This is reference implementation from the spec. */ 1.647 + static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length) 1.648 + { 1.649 + uint32_t Sum = 0L; 1.650 + const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size; 1.651 + 1.652 + while (Table < EndPtr) 1.653 + Sum += *Table++; 1.654 + return Sum; 1.655 + } 1.656 + 1.657 + /* Note: data should be 4byte aligned and have 4byte padding at the end. */ 1.658 + inline void set_for_data (const void *data, unsigned int length) 1.659 + { set (CalcTableChecksum ((const ULONG *) data, length)); } 1.660 + 1.661 + public: 1.662 + DEFINE_SIZE_STATIC (4); 1.663 +}; 1.664 + 1.665 + 1.666 +/* 1.667 + * Version Numbers 1.668 + */ 1.669 + 1.670 +struct FixedVersion 1.671 +{ 1.672 + inline uint32_t to_int (void) const { return (major << 16) + minor; } 1.673 + 1.674 + inline bool sanitize (hb_sanitize_context_t *c) { 1.675 + TRACE_SANITIZE (this); 1.676 + return TRACE_RETURN (c->check_struct (this)); 1.677 + } 1.678 + 1.679 + USHORT major; 1.680 + USHORT minor; 1.681 + public: 1.682 + DEFINE_SIZE_STATIC (4); 1.683 +}; 1.684 + 1.685 + 1.686 + 1.687 +/* 1.688 + * Template subclasses of Offset and LongOffset that do the dereferencing. 1.689 + * Use: (base+offset) 1.690 + */ 1.691 + 1.692 +template <typename OffsetType, typename Type> 1.693 +struct GenericOffsetTo : OffsetType 1.694 +{ 1.695 + inline const Type& operator () (const void *base) const 1.696 + { 1.697 + unsigned int offset = *this; 1.698 + if (unlikely (!offset)) return Null(Type); 1.699 + return StructAtOffset<Type> (base, offset); 1.700 + } 1.701 + 1.702 + inline Type& serialize (hb_serialize_context_t *c, void *base) 1.703 + { 1.704 + Type *t = c->start_embed<Type> (); 1.705 + this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ 1.706 + return *t; 1.707 + } 1.708 + 1.709 + inline bool sanitize (hb_sanitize_context_t *c, void *base) { 1.710 + TRACE_SANITIZE (this); 1.711 + if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); 1.712 + unsigned int offset = *this; 1.713 + if (unlikely (!offset)) return TRACE_RETURN (true); 1.714 + Type &obj = StructAtOffset<Type> (base, offset); 1.715 + return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); 1.716 + } 1.717 + template <typename T> 1.718 + inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 1.719 + TRACE_SANITIZE (this); 1.720 + if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); 1.721 + unsigned int offset = *this; 1.722 + if (unlikely (!offset)) return TRACE_RETURN (true); 1.723 + Type &obj = StructAtOffset<Type> (base, offset); 1.724 + return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); 1.725 + } 1.726 + 1.727 + inline bool try_set (hb_sanitize_context_t *c, const OffsetType &v) { 1.728 + if (c->may_edit (this, this->static_size)) { 1.729 + this->set (v); 1.730 + return true; 1.731 + } 1.732 + return false; 1.733 + } 1.734 + /* Set the offset to Null */ 1.735 + inline bool neuter (hb_sanitize_context_t *c) { 1.736 + if (c->may_edit (this, this->static_size)) { 1.737 + this->set (0); /* 0 is Null offset */ 1.738 + return true; 1.739 + } 1.740 + return false; 1.741 + } 1.742 +}; 1.743 +template <typename Base, typename OffsetType, typename Type> 1.744 +inline const Type& operator + (const Base &base, const GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); } 1.745 +template <typename Base, typename OffsetType, typename Type> 1.746 +inline Type& operator + (Base &base, GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); } 1.747 + 1.748 +template <typename Type> 1.749 +struct OffsetTo : GenericOffsetTo<Offset, Type> {}; 1.750 + 1.751 +template <typename Type> 1.752 +struct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {}; 1.753 + 1.754 + 1.755 +/* 1.756 + * Array Types 1.757 + */ 1.758 + 1.759 +template <typename LenType, typename Type> 1.760 +struct GenericArrayOf 1.761 +{ 1.762 + const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const 1.763 + { 1.764 + unsigned int count = len; 1.765 + if (unlikely (start_offset > count)) 1.766 + count = 0; 1.767 + else 1.768 + count -= start_offset; 1.769 + count = MIN (count, *pcount); 1.770 + *pcount = count; 1.771 + return array + start_offset; 1.772 + } 1.773 + 1.774 + inline const Type& operator [] (unsigned int i) const 1.775 + { 1.776 + if (unlikely (i >= len)) return Null(Type); 1.777 + return array[i]; 1.778 + } 1.779 + inline Type& operator [] (unsigned int i) 1.780 + { 1.781 + return array[i]; 1.782 + } 1.783 + inline unsigned int get_size (void) const 1.784 + { return len.static_size + len * Type::static_size; } 1.785 + 1.786 + inline bool serialize (hb_serialize_context_t *c, 1.787 + unsigned int items_len) 1.788 + { 1.789 + TRACE_SERIALIZE (this); 1.790 + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); 1.791 + len.set (items_len); /* TODO(serialize) Overflow? */ 1.792 + if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); 1.793 + return TRACE_RETURN (true); 1.794 + } 1.795 + 1.796 + inline bool serialize (hb_serialize_context_t *c, 1.797 + Supplier<Type> &items, 1.798 + unsigned int items_len) 1.799 + { 1.800 + TRACE_SERIALIZE (this); 1.801 + if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false); 1.802 + for (unsigned int i = 0; i < items_len; i++) 1.803 + array[i] = items[i]; 1.804 + items.advance (items_len); 1.805 + return TRACE_RETURN (true); 1.806 + } 1.807 + 1.808 + inline bool sanitize (hb_sanitize_context_t *c) { 1.809 + TRACE_SANITIZE (this); 1.810 + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 1.811 + 1.812 + /* Note: for structs that do not reference other structs, 1.813 + * we do not need to call their sanitize() as we already did 1.814 + * a bound check on the aggregate array size. We just include 1.815 + * a small unreachable expression to make sure the structs 1.816 + * pointed to do have a simple sanitize(), ie. they do not 1.817 + * reference other structs via offsets. 1.818 + */ 1.819 + (void) (false && array[0].sanitize (c)); 1.820 + 1.821 + return TRACE_RETURN (true); 1.822 + } 1.823 + inline bool sanitize (hb_sanitize_context_t *c, void *base) { 1.824 + TRACE_SANITIZE (this); 1.825 + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 1.826 + unsigned int count = len; 1.827 + for (unsigned int i = 0; i < count; i++) 1.828 + if (unlikely (!array[i].sanitize (c, base))) 1.829 + return TRACE_RETURN (false); 1.830 + return TRACE_RETURN (true); 1.831 + } 1.832 + template <typename T> 1.833 + inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 1.834 + TRACE_SANITIZE (this); 1.835 + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 1.836 + unsigned int count = len; 1.837 + for (unsigned int i = 0; i < count; i++) 1.838 + if (unlikely (!array[i].sanitize (c, base, user_data))) 1.839 + return TRACE_RETURN (false); 1.840 + return TRACE_RETURN (true); 1.841 + } 1.842 + 1.843 + private: 1.844 + inline bool sanitize_shallow (hb_sanitize_context_t *c) { 1.845 + TRACE_SANITIZE (this); 1.846 + return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len)); 1.847 + } 1.848 + 1.849 + public: 1.850 + LenType len; 1.851 + Type array[VAR]; 1.852 + public: 1.853 + DEFINE_SIZE_ARRAY (sizeof (LenType), array); 1.854 +}; 1.855 + 1.856 +/* An array with a USHORT number of elements. */ 1.857 +template <typename Type> 1.858 +struct ArrayOf : GenericArrayOf<USHORT, Type> {}; 1.859 + 1.860 +/* An array with a ULONG number of elements. */ 1.861 +template <typename Type> 1.862 +struct LongArrayOf : GenericArrayOf<ULONG, Type> {}; 1.863 + 1.864 +/* Array of Offset's */ 1.865 +template <typename Type> 1.866 +struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; 1.867 + 1.868 +/* Array of LongOffset's */ 1.869 +template <typename Type> 1.870 +struct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {}; 1.871 + 1.872 +/* LongArray of LongOffset's */ 1.873 +template <typename Type> 1.874 +struct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {}; 1.875 + 1.876 +/* Array of offsets relative to the beginning of the array itself. */ 1.877 +template <typename Type> 1.878 +struct OffsetListOf : OffsetArrayOf<Type> 1.879 +{ 1.880 + inline const Type& operator [] (unsigned int i) const 1.881 + { 1.882 + if (unlikely (i >= this->len)) return Null(Type); 1.883 + return this+this->array[i]; 1.884 + } 1.885 + 1.886 + inline bool sanitize (hb_sanitize_context_t *c) { 1.887 + TRACE_SANITIZE (this); 1.888 + return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); 1.889 + } 1.890 + template <typename T> 1.891 + inline bool sanitize (hb_sanitize_context_t *c, T user_data) { 1.892 + TRACE_SANITIZE (this); 1.893 + return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); 1.894 + } 1.895 +}; 1.896 + 1.897 + 1.898 +/* An array with a USHORT number of elements, 1.899 + * starting at second element. */ 1.900 +template <typename Type> 1.901 +struct HeadlessArrayOf 1.902 +{ 1.903 + inline const Type& operator [] (unsigned int i) const 1.904 + { 1.905 + if (unlikely (i >= len || !i)) return Null(Type); 1.906 + return array[i-1]; 1.907 + } 1.908 + inline unsigned int get_size (void) const 1.909 + { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } 1.910 + 1.911 + inline bool serialize (hb_serialize_context_t *c, 1.912 + Supplier<Type> &items, 1.913 + unsigned int items_len) 1.914 + { 1.915 + TRACE_SERIALIZE (this); 1.916 + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); 1.917 + len.set (items_len); /* TODO(serialize) Overflow? */ 1.918 + if (unlikely (!items_len)) return TRACE_RETURN (true); 1.919 + if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); 1.920 + for (unsigned int i = 0; i < items_len - 1; i++) 1.921 + array[i] = items[i]; 1.922 + items.advance (items_len - 1); 1.923 + return TRACE_RETURN (true); 1.924 + } 1.925 + 1.926 + inline bool sanitize_shallow (hb_sanitize_context_t *c) { 1.927 + return c->check_struct (this) 1.928 + && c->check_array (this, Type::static_size, len); 1.929 + } 1.930 + 1.931 + inline bool sanitize (hb_sanitize_context_t *c) { 1.932 + TRACE_SANITIZE (this); 1.933 + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 1.934 + 1.935 + /* Note: for structs that do not reference other structs, 1.936 + * we do not need to call their sanitize() as we already did 1.937 + * a bound check on the aggregate array size. We just include 1.938 + * a small unreachable expression to make sure the structs 1.939 + * pointed to do have a simple sanitize(), ie. they do not 1.940 + * reference other structs via offsets. 1.941 + */ 1.942 + (void) (false && array[0].sanitize (c)); 1.943 + 1.944 + return TRACE_RETURN (true); 1.945 + } 1.946 + 1.947 + USHORT len; 1.948 + Type array[VAR]; 1.949 + public: 1.950 + DEFINE_SIZE_ARRAY (sizeof (USHORT), array); 1.951 +}; 1.952 + 1.953 + 1.954 +/* An array with sorted elements. Supports binary searching. */ 1.955 +template <typename Type> 1.956 +struct SortedArrayOf : ArrayOf<Type> { 1.957 + 1.958 + template <typename SearchType> 1.959 + inline int search (const SearchType &x) const 1.960 + { 1.961 + /* Hand-coded bsearch here since this is in the hot inner loop. */ 1.962 + int min = 0, max = (int) this->len - 1; 1.963 + while (min <= max) 1.964 + { 1.965 + int mid = (min + max) / 2; 1.966 + int c = this->array[mid].cmp (x); 1.967 + if (c < 0) 1.968 + max = mid - 1; 1.969 + else if (c > 0) 1.970 + min = mid + 1; 1.971 + else 1.972 + return mid; 1.973 + } 1.974 + return -1; 1.975 + } 1.976 +}; 1.977 + 1.978 + 1.979 +} /* namespace OT */ 1.980 + 1.981 + 1.982 +#endif /* HB_OPEN_TYPE_PRIVATE_HH */