1 | /* |
2 | * Copyright © 2007,2008,2009 Red Hat, Inc. |
3 | * Copyright © 2011,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_HH |
30 | #define HB_HH |
31 | |
32 | #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC |
33 | #if defined(_MSC_VER) |
34 | #pragma warning( disable: 4068 ) /* Unknown pragma */ |
35 | #endif |
36 | #if defined(__GNUC__) || defined(__clang__) |
37 | /* Rules: |
38 | * |
39 | * - All pragmas are declared GCC even if they are clang ones. Otherwise GCC |
40 | * nags, even though we instruct it to ignore -Wunknown-pragmas. ¯\_(ツ)_/¯ |
41 | * |
42 | * - Within each category, keep sorted. |
43 | * |
44 | * - Warnings whose scope can be expanded in future compiler versions shall |
45 | * be declared as "warning". Otherwise, either ignored or error. |
46 | */ |
47 | |
48 | /* Setup. Don't sort order within this category. */ |
49 | #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING |
50 | #pragma GCC diagnostic warning "-Wall" |
51 | #pragma GCC diagnostic warning "-Wextra" |
52 | #endif |
53 | #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED |
54 | #pragma GCC diagnostic ignored "-Wpragmas" |
55 | #pragma GCC diagnostic ignored "-Wunknown-pragmas" |
56 | #pragma GCC diagnostic ignored "-Wunknown-warning-option" |
57 | #endif |
58 | #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING |
59 | //#pragma GCC diagnostic warning "-Weverything" |
60 | #endif |
61 | |
62 | /* Error. Should never happen. */ |
63 | #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR |
64 | #pragma GCC diagnostic error "-Wc++11-narrowing" |
65 | #pragma GCC diagnostic error "-Wcast-align" |
66 | #pragma GCC diagnostic error "-Wcast-function-type" |
67 | #pragma GCC diagnostic error "-Wdelete-non-virtual-dtor" |
68 | #pragma GCC diagnostic error "-Wformat-security" |
69 | #pragma GCC diagnostic error "-Wimplicit-function-declaration" |
70 | #pragma GCC diagnostic error "-Winit-self" |
71 | #pragma GCC diagnostic error "-Wmissing-braces" |
72 | #pragma GCC diagnostic error "-Wmissing-declarations" |
73 | #pragma GCC diagnostic error "-Wmissing-prototypes" |
74 | #pragma GCC diagnostic error "-Wnested-externs" |
75 | #pragma GCC diagnostic error "-Wold-style-definition" |
76 | #pragma GCC diagnostic error "-Wpointer-arith" |
77 | #pragma GCC diagnostic error "-Wredundant-decls" |
78 | #pragma GCC diagnostic error "-Wreorder" |
79 | #pragma GCC diagnostic error "-Wsign-compare" |
80 | #pragma GCC diagnostic error "-Wstrict-prototypes" |
81 | #pragma GCC diagnostic error "-Wstring-conversion" |
82 | #pragma GCC diagnostic error "-Wswitch-enum" |
83 | #pragma GCC diagnostic error "-Wtautological-overlap-compare" |
84 | #pragma GCC diagnostic error "-Wunneeded-internal-declaration" |
85 | #pragma GCC diagnostic error "-Wunused" |
86 | #pragma GCC diagnostic error "-Wunused-local-typedefs" |
87 | #pragma GCC diagnostic error "-Wunused-value" |
88 | #pragma GCC diagnostic error "-Wunused-variable" |
89 | #pragma GCC diagnostic error "-Wvla" |
90 | #pragma GCC diagnostic error "-Wwrite-strings" |
91 | #endif |
92 | |
93 | /* Warning. To be investigated if happens. */ |
94 | #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING |
95 | #pragma GCC diagnostic warning "-Wbuiltin-macro-redefined" |
96 | #pragma GCC diagnostic warning "-Wdisabled-optimization" |
97 | #pragma GCC diagnostic warning "-Wformat=2" |
98 | #pragma GCC diagnostic warning "-Wignored-pragma-optimize" |
99 | #pragma GCC diagnostic warning "-Wlogical-op" |
100 | #pragma GCC diagnostic warning "-Wmaybe-uninitialized" |
101 | #pragma GCC diagnostic warning "-Wmissing-format-attribute" |
102 | #pragma GCC diagnostic warning "-Wundef" |
103 | #endif |
104 | |
105 | /* Ignored currently, but should be fixed at some point. */ |
106 | #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED |
107 | #pragma GCC diagnostic ignored "-Wconversion" // TODO fix |
108 | #pragma GCC diagnostic ignored "-Wformat-signedness" // TODO fix |
109 | #pragma GCC diagnostic ignored "-Wshadow" // TODO fix |
110 | #pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" // TODO fix |
111 | #pragma GCC diagnostic ignored "-Wunused-parameter" // TODO fix |
112 | #endif |
113 | |
114 | /* Ignored intentionally. */ |
115 | #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED |
116 | #pragma GCC diagnostic ignored "-Wclass-memaccess" |
117 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" |
118 | #pragma GCC diagnostic ignored "-Wformat-zero-length" |
119 | #pragma GCC diagnostic ignored "-Wmissing-field-initializers" |
120 | #pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang |
121 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" |
122 | #pragma GCC diagnostic ignored "-Wtype-limits" |
123 | #endif |
124 | |
125 | #endif |
126 | #endif |
127 | |
128 | #ifdef HAVE_CONFIG_H |
129 | #include "config.h" |
130 | #endif |
131 | |
132 | /* |
133 | * Following added based on what AC_USE_SYSTEM_EXTENSIONS adds to |
134 | * config.h.in. Copied here for the convenience of those embedding |
135 | * HarfBuzz and not using our build system. |
136 | */ |
137 | /* Enable extensions on AIX 3, Interix. */ |
138 | #ifndef _ALL_SOURCE |
139 | # define _ALL_SOURCE 1 |
140 | #endif |
141 | /* Enable GNU extensions on systems that have them. */ |
142 | #ifndef _GNU_SOURCE |
143 | # define _GNU_SOURCE 1 |
144 | #endif |
145 | /* Enable threading extensions on Solaris. */ |
146 | #ifndef _POSIX_PTHREAD_SEMANTICS |
147 | # define _POSIX_PTHREAD_SEMANTICS 1 |
148 | #endif |
149 | /* Enable extensions on HP NonStop. */ |
150 | #ifndef _TANDEM_SOURCE |
151 | # define _TANDEM_SOURCE 1 |
152 | #endif |
153 | /* Enable general extensions on Solaris. */ |
154 | #ifndef __EXTENSIONS__ |
155 | # define __EXTENSIONS__ 1 |
156 | #endif |
157 | |
158 | #if defined (_MSC_VER) && defined (HB_DLL_EXPORT) |
159 | #define HB_EXTERN __declspec (dllexport) extern |
160 | #endif |
161 | |
162 | #include "hb.h" |
163 | #define HB_H_IN |
164 | #include "hb-ot.h" |
165 | #define HB_OT_H_IN |
166 | #include "hb-aat.h" |
167 | #define HB_AAT_H_IN |
168 | |
169 | #include "hb-aat.h" |
170 | |
171 | #include <math.h> |
172 | #include <stdlib.h> |
173 | #include <stddef.h> |
174 | #include <string.h> |
175 | #include <assert.h> |
176 | #include <errno.h> |
177 | #include <stdio.h> |
178 | #include <stdarg.h> |
179 | |
180 | #if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__) |
181 | #include <intrin.h> |
182 | #endif |
183 | |
184 | #define HB_PASTE1(a,b) a##b |
185 | #define HB_PASTE(a,b) HB_PASTE1(a,b) |
186 | |
187 | |
188 | /* Compile-time custom allocator support. */ |
189 | |
190 | #if defined(hb_malloc_impl) \ |
191 | && defined(hb_calloc_impl) \ |
192 | && defined(hb_realloc_impl) \ |
193 | && defined(hb_free_impl) |
194 | extern "C" void* hb_malloc_impl(size_t size); |
195 | extern "C" void* hb_calloc_impl(size_t nmemb, size_t size); |
196 | extern "C" void* hb_realloc_impl(void *ptr, size_t size); |
197 | extern "C" void hb_free_impl(void *ptr); |
198 | #define malloc hb_malloc_impl |
199 | #define calloc hb_calloc_impl |
200 | #define realloc hb_realloc_impl |
201 | #define free hb_free_impl |
202 | |
203 | #if defined(hb_memalign_impl) |
204 | extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size); |
205 | #define posix_memalign hb_memalign_impl |
206 | #else |
207 | #undef HAVE_POSIX_MEMALIGN |
208 | #endif |
209 | |
210 | #endif |
211 | |
212 | |
213 | /* |
214 | * Compiler attributes |
215 | */ |
216 | |
217 | #if __cplusplus < 201103L |
218 | |
219 | #ifndef nullptr |
220 | #define nullptr NULL |
221 | #endif |
222 | |
223 | #ifndef constexpr |
224 | #define constexpr const |
225 | #endif |
226 | |
227 | #ifndef static_assert |
228 | #define static_assert(e, msg) \ |
229 | HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1] |
230 | #endif // static_assert |
231 | |
232 | #if defined(__GNUC__) |
233 | #if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) |
234 | #define thread_local __thread |
235 | #endif |
236 | #else |
237 | #define thread_local |
238 | #endif |
239 | |
240 | template <typename T> |
241 | struct _hb_alignof |
242 | { |
243 | struct s |
244 | { |
245 | char c; |
246 | T t; |
247 | }; |
248 | static constexpr size_t value = offsetof (s, t); |
249 | }; |
250 | #ifndef alignof |
251 | #define alignof(x) (_hb_alignof<x>::value) |
252 | #endif |
253 | |
254 | /* https://github.com/harfbuzz/harfbuzz/issues/1127 */ |
255 | #ifndef explicit_operator |
256 | #define explicit_operator operator |
257 | #endif |
258 | |
259 | #else /* __cplusplus >= 201103L */ |
260 | |
261 | /* https://github.com/harfbuzz/harfbuzz/issues/1127 */ |
262 | #ifndef explicit_operator |
263 | #define explicit_operator explicit operator |
264 | #endif |
265 | |
266 | #endif /* __cplusplus < 201103L */ |
267 | |
268 | |
269 | #if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__) |
270 | #define likely(expr) (__builtin_expect (!!(expr), 1)) |
271 | #define unlikely(expr) (__builtin_expect (!!(expr), 0)) |
272 | #else |
273 | #define likely(expr) (expr) |
274 | #define unlikely(expr) (expr) |
275 | #endif |
276 | |
277 | #if !defined(__GNUC__) && !defined(__clang__) |
278 | #undef __attribute__ |
279 | #define __attribute__(x) |
280 | #endif |
281 | |
282 | #if defined(__GNUC__) && (__GNUC__ >= 3) |
283 | #define HB_PURE_FUNC __attribute__((pure)) |
284 | #define HB_CONST_FUNC __attribute__((const)) |
285 | #define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx))) |
286 | #else |
287 | #define HB_PURE_FUNC |
288 | #define HB_CONST_FUNC |
289 | #define HB_PRINTF_FUNC(format_idx, arg_idx) |
290 | #endif |
291 | #if defined(__GNUC__) && (__GNUC__ >= 4) |
292 | #define HB_UNUSED __attribute__((unused)) |
293 | #elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */ |
294 | #define HB_UNUSED __pragma(warning(suppress: 4100 4101)) |
295 | #else |
296 | #define HB_UNUSED |
297 | #endif |
298 | |
299 | #ifndef HB_INTERNAL |
300 | # if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC) |
301 | # define HB_INTERNAL __attribute__((__visibility__("hidden"))) |
302 | # elif defined(__MINGW32__) |
303 | /* We use -export-symbols on mingw32, since it does not support visibility attributes. */ |
304 | # define HB_INTERNAL |
305 | # elif defined (_MSC_VER) && defined (HB_DLL_EXPORT) |
306 | /* We do not try to export internal symbols on Visual Studio */ |
307 | # define HB_INTERNAL |
308 | #else |
309 | # define HB_INTERNAL |
310 | # define HB_NO_VISIBILITY 1 |
311 | # endif |
312 | #endif |
313 | |
314 | #if defined(__GNUC__) && (__GNUC__ >= 3) |
315 | #define HB_FUNC __PRETTY_FUNCTION__ |
316 | #elif defined(_MSC_VER) |
317 | #define HB_FUNC __FUNCSIG__ |
318 | #else |
319 | #define HB_FUNC __func__ |
320 | #endif |
321 | |
322 | #if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5140) |
323 | /* https://github.com/harfbuzz/harfbuzz/issues/630 */ |
324 | #define __restrict |
325 | #endif |
326 | |
327 | /* |
328 | * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411 |
329 | * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch |
330 | * cases that fall through without a break or return statement. HB_FALLTHROUGH |
331 | * is only needed on cases that have code: |
332 | * |
333 | * switch (foo) { |
334 | * case 1: // These cases have no code. No fallthrough annotations are needed. |
335 | * case 2: |
336 | * case 3: |
337 | * foo = 4; // This case has code, so a fallthrough annotation is needed: |
338 | * HB_FALLTHROUGH; |
339 | * default: |
340 | * return foo; |
341 | * } |
342 | */ |
343 | #if defined(__clang__) && __cplusplus >= 201103L |
344 | /* clang's fallthrough annotations are only available starting in C++11. */ |
345 | # define HB_FALLTHROUGH [[clang::fallthrough]] |
346 | #elif defined(__GNUC__) && (__GNUC__ >= 7) |
347 | /* GNU fallthrough attribute is available from GCC7 */ |
348 | # define HB_FALLTHROUGH __attribute__((fallthrough)) |
349 | #elif defined(_MSC_VER) |
350 | /* |
351 | * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis): |
352 | * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx |
353 | */ |
354 | # include <sal.h> |
355 | # define HB_FALLTHROUGH __fallthrough |
356 | #else |
357 | # define HB_FALLTHROUGH /* FALLTHROUGH */ |
358 | #endif |
359 | |
360 | #if defined(__clang__) |
361 | /* Disable certain sanitizer errors. */ |
362 | /* https://github.com/harfbuzz/harfbuzz/issues/1247 */ |
363 | #define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW __attribute__((no_sanitize("signed-integer-overflow"))) |
364 | #else |
365 | #define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW |
366 | #endif |
367 | |
368 | |
369 | #ifdef _WIN32 |
370 | /* We need Windows Vista for both Uniscribe backend and for |
371 | * MemoryBarrier. We don't support compiling on Windows XP, |
372 | * though we run on it fine. */ |
373 | # if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600 |
374 | # undef _WIN32_WINNT |
375 | # endif |
376 | # ifndef _WIN32_WINNT |
377 | # if !defined(WINAPI_FAMILY) || !(WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) |
378 | # define _WIN32_WINNT 0x0600 |
379 | # endif |
380 | # endif |
381 | # ifndef WIN32_LEAN_AND_MEAN |
382 | # define WIN32_LEAN_AND_MEAN 1 |
383 | # endif |
384 | # ifndef STRICT |
385 | # define STRICT 1 |
386 | # endif |
387 | |
388 | # if defined(_WIN32_WCE) |
389 | /* Some things not defined on Windows CE. */ |
390 | # define vsnprintf _vsnprintf |
391 | # define getenv(Name) nullptr |
392 | # if _WIN32_WCE < 0x800 |
393 | # define setlocale(Category, Locale) "C" |
394 | static int errno = 0; /* Use something better? */ |
395 | # endif |
396 | # elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) |
397 | # define getenv(Name) nullptr |
398 | # endif |
399 | # if defined(_MSC_VER) && _MSC_VER < 1900 |
400 | # define snprintf _snprintf |
401 | # endif |
402 | #endif |
403 | |
404 | #if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT) |
405 | /* atexit() is only safe to be called from shared libraries on certain |
406 | * platforms. Whitelist. |
407 | * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */ |
408 | # if defined(__linux) && defined(__GLIBC_PREREQ) |
409 | # if __GLIBC_PREREQ(2,3) |
410 | /* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */ |
411 | # define HB_USE_ATEXIT 1 |
412 | # endif |
413 | # elif defined(_MSC_VER) || defined(__MINGW32__) |
414 | /* For MSVC: |
415 | * https://msdn.microsoft.com/en-us/library/tze57ck3.aspx |
416 | * https://msdn.microsoft.com/en-us/library/zk17ww08.aspx |
417 | * mingw32 headers say atexit is safe to use in shared libraries. |
418 | */ |
419 | # define HB_USE_ATEXIT 1 |
420 | # elif defined(__ANDROID__) |
421 | /* This is available since Android NKD r8 or r8b: |
422 | * https://issuetracker.google.com/code/p/android/issues/detail?id=6455 |
423 | */ |
424 | # define HB_USE_ATEXIT 1 |
425 | # elif defined(__APPLE__) |
426 | /* For macOS and related platforms, the atexit man page indicates |
427 | * that it will be invoked when the library is unloaded, not only |
428 | * at application exit. |
429 | */ |
430 | # define HB_USE_ATEXIT 1 |
431 | # endif |
432 | #endif |
433 | #ifdef HB_NO_ATEXIT |
434 | # undef HB_USE_ATEXIT |
435 | #endif |
436 | #ifndef HB_USE_ATEXIT |
437 | # define HB_USE_ATEXIT 0 |
438 | #endif |
439 | |
440 | #define HB_STMT_START do |
441 | #define HB_STMT_END while (0) |
442 | |
443 | /* Static-assert as expression. */ |
444 | template <unsigned int cond> class hb_assert_constant_t; |
445 | template <> class hb_assert_constant_t<1> {}; |
446 | #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>)) |
447 | |
448 | /* Lets assert int types. Saves trouble down the road. */ |
449 | static_assert ((sizeof (int8_t) == 1), "" ); |
450 | static_assert ((sizeof (uint8_t) == 1), "" ); |
451 | static_assert ((sizeof (int16_t) == 2), "" ); |
452 | static_assert ((sizeof (uint16_t) == 2), "" ); |
453 | static_assert ((sizeof (int32_t) == 4), "" ); |
454 | static_assert ((sizeof (uint32_t) == 4), "" ); |
455 | static_assert ((sizeof (int64_t) == 8), "" ); |
456 | static_assert ((sizeof (uint64_t) == 8), "" ); |
457 | static_assert ((sizeof (hb_codepoint_t) == 4), "" ); |
458 | static_assert ((sizeof (hb_position_t) == 4), "" ); |
459 | static_assert ((sizeof (hb_mask_t) == 4), "" ); |
460 | static_assert ((sizeof (hb_var_int_t) == 4), "" ); |
461 | |
462 | |
463 | #if __cplusplus >= 201103L |
464 | |
465 | /* We only enable these with C++11 or later, since earlier language |
466 | * does not allow structs with constructors in unions, and we need |
467 | * those. */ |
468 | |
469 | #define HB_NO_COPY_ASSIGN(TypeName) \ |
470 | TypeName(const TypeName&); \ |
471 | void operator=(const TypeName&) |
472 | #define HB_NO_COPY_ASSIGN_TEMPLATE(TypeName, T) \ |
473 | TypeName(const TypeName<T>&); \ |
474 | void operator=(const TypeName<T>&) |
475 | #define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \ |
476 | TypeName(const TypeName<T1, T2>&); \ |
477 | void operator=(const TypeName<T1, T2>&) |
478 | #define HB_NO_CREATE_COPY_ASSIGN(TypeName) \ |
479 | TypeName(); \ |
480 | TypeName(const TypeName&); \ |
481 | void operator=(const TypeName&) |
482 | #define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) \ |
483 | TypeName(); \ |
484 | TypeName(const TypeName<T>&); \ |
485 | void operator=(const TypeName<T>&) |
486 | #define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \ |
487 | TypeName(); \ |
488 | TypeName(const TypeName<T1, T2>&); \ |
489 | void operator=(const TypeName<T1, T2>&) |
490 | |
491 | #else /* __cpluspplus >= 201103L */ |
492 | |
493 | #define HB_NO_COPY_ASSIGN(TypeName) static_assert (true, "") |
494 | #define HB_NO_COPY_ASSIGN_TEMPLATE(TypeName, T) static_assert (true, "") |
495 | #define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "") |
496 | #define HB_NO_CREATE_COPY_ASSIGN(TypeName) static_assert (true, "") |
497 | #define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) static_assert (true, "") |
498 | #define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "") |
499 | |
500 | #endif /* __cpluspplus >= 201103L */ |
501 | |
502 | |
503 | /* |
504 | * Compiler-assisted vectorization parameters. |
505 | */ |
506 | |
507 | /* |
508 | * Disable vectorization for now. To correctly use them, we should |
509 | * use posix_memalign() to allocate in hb_vector_t. Otherwise, can |
510 | * cause misaligned access. |
511 | * |
512 | * https://bugs.chromium.org/p/chromium/issues/detail?id=860184 |
513 | */ |
514 | #if !defined(HB_VECTOR_SIZE) |
515 | # define HB_VECTOR_SIZE 0 |
516 | #endif |
517 | |
518 | /* The `vector_size' attribute was introduced in gcc 3.1. */ |
519 | #if !defined(HB_VECTOR_SIZE) |
520 | # if defined( __GNUC__ ) && ( __GNUC__ >= 4 ) |
521 | # define HB_VECTOR_SIZE 128 |
522 | # else |
523 | # define HB_VECTOR_SIZE 0 |
524 | # endif |
525 | #endif |
526 | static_assert (0 == (HB_VECTOR_SIZE & (HB_VECTOR_SIZE - 1)), "HB_VECTOR_SIZE is not power of 2." ); |
527 | static_assert (0 == (HB_VECTOR_SIZE % 64), "HB_VECTOR_SIZE is not multiple of 64." ); |
528 | #if HB_VECTOR_SIZE |
529 | typedef uint64_t hb_vector_size_impl_t __attribute__((vector_size (HB_VECTOR_SIZE / 8))); |
530 | #else |
531 | typedef uint64_t hb_vector_size_impl_t; |
532 | #endif |
533 | |
534 | |
535 | /* HB_NDEBUG disables some sanity checks that are very safe to disable and |
536 | * should be disabled in production systems. If NDEBUG is defined, enable |
537 | * HB_NDEBUG; but if it's desirable that normal assert()s (which are very |
538 | * light-weight) to be enabled, then HB_DEBUG can be defined to disable |
539 | * the costlier checks. */ |
540 | #ifdef NDEBUG |
541 | #define HB_NDEBUG 1 |
542 | #endif |
543 | |
544 | |
545 | /* Flags */ |
546 | |
547 | /* Enable bitwise ops on enums marked as flags_t */ |
548 | /* To my surprise, looks like the function resolver is happy to silently cast |
549 | * one enum to another... So this doesn't provide the type-checking that I |
550 | * originally had in mind... :(. |
551 | * |
552 | * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163 |
553 | */ |
554 | #ifdef _MSC_VER |
555 | # pragma warning(disable:4200) |
556 | # pragma warning(disable:4800) |
557 | #endif |
558 | #define HB_MARK_AS_FLAG_T(T) \ |
559 | extern "C++" { \ |
560 | static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \ |
561 | static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \ |
562 | static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \ |
563 | static inline T operator ~ (T r) { return T (~(unsigned int) r); } \ |
564 | static inline T& operator |= (T &l, T r) { l = l | r; return l; } \ |
565 | static inline T& operator &= (T& l, T r) { l = l & r; return l; } \ |
566 | static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \ |
567 | } \ |
568 | static_assert (true, "") |
569 | |
570 | /* Useful for set-operations on small enums. |
571 | * For example, for testing "x ∈ {x1, x2, x3}" use: |
572 | * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) |
573 | */ |
574 | #define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x))) |
575 | #define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0) |
576 | #define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x)) |
577 | #define FLAG64(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x))) |
578 | #define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0) |
579 | |
580 | |
581 | /* Size signifying variable-sized array */ |
582 | #define VAR 1 |
583 | |
584 | |
585 | /* fallback for round() */ |
586 | static inline double |
587 | _hb_round (double x) |
588 | { |
589 | if (x >= 0) |
590 | return floor (x + 0.5); |
591 | else |
592 | return ceil (x - 0.5); |
593 | } |
594 | #if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND) |
595 | #define round(x) _hb_round(x) |
596 | #endif |
597 | |
598 | |
599 | /* fallback for posix_memalign() */ |
600 | static inline int |
601 | _hb_memalign(void **memptr, size_t alignment, size_t size) |
602 | { |
603 | if (unlikely (0 != (alignment & (alignment - 1)) || |
604 | !alignment || |
605 | 0 != (alignment & (sizeof (void *) - 1)))) |
606 | return EINVAL; |
607 | |
608 | char *p = (char *) malloc (size + alignment - 1); |
609 | if (unlikely (!p)) |
610 | return ENOMEM; |
611 | |
612 | size_t off = (size_t) p & (alignment - 1); |
613 | if (off) |
614 | p += alignment - off; |
615 | |
616 | *memptr = (void *) p; |
617 | |
618 | return 0; |
619 | } |
620 | #if !defined(posix_memalign) && !defined(HAVE_POSIX_MEMALIGN) |
621 | #define posix_memalign _hb_memalign |
622 | #endif |
623 | |
624 | |
625 | /* |
626 | * For lack of a better place, put Zawgyi script hack here. |
627 | * https://github.com/harfbuzz/harfbuzz/issues/1162 |
628 | */ |
629 | |
630 | #define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g')) |
631 | |
632 | |
633 | /* Some really basic things everyone wants. */ |
634 | template <typename T> struct hb_remove_const { typedef T value; }; |
635 | template <typename T> struct hb_remove_const<const T> { typedef T value; }; |
636 | #define hb_remove_const(T) hb_remove_const<T>::value |
637 | template <typename T> struct hb_remove_reference { typedef T value; }; |
638 | template <typename T> struct hb_remove_reference<T &> { typedef T value; }; |
639 | #define hb_remove_reference(T) hb_remove_reference<T>::value |
640 | template <typename T> struct hb_remove_pointer { typedef T value; }; |
641 | template <typename T> struct hb_remove_pointer<T *> { typedef T value; }; |
642 | #define hb_remove_pointer(T) hb_remove_pointer<T>::value |
643 | |
644 | |
645 | /* Headers we include for everyone. Keep topologically sorted by dependency. |
646 | * They express dependency amongst themselves, but no other file should include |
647 | * them directly.*/ |
648 | #include "hb-atomic.hh" |
649 | #include "hb-mutex.hh" |
650 | #include "hb-null.hh" |
651 | #include "hb-dsalgs.hh" // Requires: hb-null |
652 | #include "hb-iter.hh" // Requires: hb-null |
653 | #include "hb-debug.hh" // Requires: hb-atomic hb-dsalgs |
654 | #include "hb-array.hh" // Requires: hb-dsalgs hb-iter hb-null |
655 | #include "hb-vector.hh" // Requires: hb-array hb-null |
656 | #include "hb-object.hh" // Requires: hb-atomic hb-mutex hb-vector |
657 | |
658 | #endif /* HB_HH */ |
659 | |