From 9ece604d9b558f77e87494af4d5fef9885497301 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Mon, 26 Aug 2013 14:25:57 +0300 Subject: Add stripped version of HarfBuzz-NG 0.9.19 sources to 3rdparty Change-Id: I06fbf58131ebce51ce95921d8dfd65dd3d3e236f Reviewed-by: Lars Knoll --- src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh | 132 ++ src/3rdparty/harfbuzz-ng/src/hb-blob.cc | 328 +++ src/3rdparty/harfbuzz-ng/src/hb-blob.h | 127 + .../harfbuzz-ng/src/hb-buffer-deserialize-json.hh | 643 +++++ .../harfbuzz-ng/src/hb-buffer-deserialize-text.hh | 571 +++++ src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh | 202 ++ .../harfbuzz-ng/src/hb-buffer-serialize.cc | 336 +++ src/3rdparty/harfbuzz-ng/src/hb-buffer.cc | 1077 +++++++++ src/3rdparty/harfbuzz-ng/src/hb-buffer.h | 323 +++ src/3rdparty/harfbuzz-ng/src/hb-cache-private.hh | 74 + src/3rdparty/harfbuzz-ng/src/hb-common.cc | 434 ++++ src/3rdparty/harfbuzz-ng/src/hb-common.h | 336 +++ src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc | 128 + src/3rdparty/harfbuzz-ng/src/hb-font-private.hh | 478 ++++ src/3rdparty/harfbuzz-ng/src/hb-font.cc | 1008 ++++++++ src/3rdparty/harfbuzz-ng/src/hb-font.h | 454 ++++ src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh | 130 ++ src/3rdparty/harfbuzz-ng/src/hb-object-private.hh | 227 ++ .../harfbuzz-ng/src/hb-open-file-private.hh | 261 +++ .../harfbuzz-ng/src/hb-open-type-private.hh | 981 ++++++++ src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh | 149 ++ src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh | 97 + src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh | 92 + .../harfbuzz-ng/src/hb-ot-layout-common-private.hh | 1170 ++++++++++ .../harfbuzz-ng/src/hb-ot-layout-gdef-table.hh | 431 ++++ .../harfbuzz-ng/src/hb-ot-layout-gpos-table.hh | 1629 +++++++++++++ .../harfbuzz-ng/src/hb-ot-layout-gsub-table.hh | 1427 ++++++++++++ .../src/hb-ot-layout-gsubgpos-private.hh | 2449 ++++++++++++++++++++ .../harfbuzz-ng/src/hb-ot-layout-private.hh | 296 +++ src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc | 910 ++++++++ src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h | 293 +++ src/3rdparty/harfbuzz-ng/src/hb-ot-map-private.hh | 247 ++ src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc | 275 +++ src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh | 69 + src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh | 134 ++ .../src/hb-ot-shape-complex-arabic-fallback.hh | 260 +++ .../src/hb-ot-shape-complex-arabic-table.hh | 942 ++++++++ .../harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc | 356 +++ .../harfbuzz-ng/src/hb-ot-shape-complex-default.cc | 220 ++ .../src/hb-ot-shape-complex-indic-machine.hh | 1443 ++++++++++++ .../src/hb-ot-shape-complex-indic-private.hh | 151 ++ .../src/hb-ot-shape-complex-indic-table.cc | 869 +++++++ .../harfbuzz-ng/src/hb-ot-shape-complex-indic.cc | 1673 +++++++++++++ .../src/hb-ot-shape-complex-myanmar-machine.hh | 391 ++++ .../harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc | 534 +++++ .../harfbuzz-ng/src/hb-ot-shape-complex-private.hh | 359 +++ .../src/hb-ot-shape-complex-sea-machine.hh | 224 ++ .../harfbuzz-ng/src/hb-ot-shape-complex-sea.cc | 384 +++ .../harfbuzz-ng/src/hb-ot-shape-complex-thai.cc | 378 +++ .../src/hb-ot-shape-fallback-private.hh | 49 + .../harfbuzz-ng/src/hb-ot-shape-fallback.cc | 456 ++++ .../src/hb-ot-shape-normalize-private.hh | 70 + .../harfbuzz-ng/src/hb-ot-shape-normalize.cc | 408 ++++ .../harfbuzz-ng/src/hb-ot-shape-private.hh | 87 + src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc | 667 ++++++ src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc | 722 ++++++ src/3rdparty/harfbuzz-ng/src/hb-ot-tag.h | 59 + src/3rdparty/harfbuzz-ng/src/hb-ot.h | 49 + src/3rdparty/harfbuzz-ng/src/hb-private.hh | 909 ++++++++ src/3rdparty/harfbuzz-ng/src/hb-set-private.hh | 335 +++ src/3rdparty/harfbuzz-ng/src/hb-set.cc | 227 ++ src/3rdparty/harfbuzz-ng/src/hb-set.h | 152 ++ .../harfbuzz-ng/src/hb-shape-plan-private.hh | 60 + src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc | 314 +++ src/3rdparty/harfbuzz-ng/src/hb-shape-plan.h | 89 + src/3rdparty/harfbuzz-ng/src/hb-shape.cc | 275 +++ src/3rdparty/harfbuzz-ng/src/hb-shape.h | 81 + .../harfbuzz-ng/src/hb-shaper-impl-private.hh | 43 + src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh | 55 + src/3rdparty/harfbuzz-ng/src/hb-shaper-private.hh | 109 + src/3rdparty/harfbuzz-ng/src/hb-shaper.cc | 109 + src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh | 317 +++ src/3rdparty/harfbuzz-ng/src/hb-unicode.cc | 435 ++++ src/3rdparty/harfbuzz-ng/src/hb-unicode.h | 357 +++ src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh | 204 ++ src/3rdparty/harfbuzz-ng/src/hb-version.h | 66 + src/3rdparty/harfbuzz-ng/src/hb-warning.cc | 66 + src/3rdparty/harfbuzz-ng/src/hb.h | 45 + 78 files changed, 32917 insertions(+) create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-blob.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-blob.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-buffer.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-buffer.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-cache-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-common.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-common.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-font-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-font.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-font.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-object-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-map-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-default.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-sea-machine.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-tag.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-set-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-set.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-set.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-shape-plan-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-shape-plan.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-shape.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-shape.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-shaper-impl-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-shaper-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-shaper.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-unicode.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-unicode.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-version.h create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-warning.cc create mode 100644 src/3rdparty/harfbuzz-ng/src/hb.h (limited to 'src/3rdparty/harfbuzz-ng/src') diff --git a/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh new file mode 100644 index 0000000000..9cc3bc5587 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh @@ -0,0 +1,132 @@ +/* + * Copyright © 2007 Chris Wilson + * Copyright © 2009,2010 Red Hat, Inc. + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Contributor(s): + * Chris Wilson + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_ATOMIC_PRIVATE_HH +#define HB_ATOMIC_PRIVATE_HH + +#include "hb-private.hh" + + +/* atomic_int */ + +/* We need external help for these */ + +#if 0 + + +#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) + +#define WIN32_LEAN_AND_MEAN +#include + +#if defined(__MINGW32__) && !defined(MemoryBarrier) +static inline void _HBMemoryBarrier (void) { + long dummy = 0; + InterlockedExchange (&dummy, 1); +} +# define MemoryBarrier _HBMemoryBarrier +#endif + +typedef LONG hb_atomic_int_t; +#define hb_atomic_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V)) + +#define hb_atomic_ptr_get(P) (MemoryBarrier (), (void *) *(P)) +#define hb_atomic_ptr_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O)) + + +#elif !defined(HB_NO_MT) && defined(__APPLE__) + +#include +#ifdef __MAC_OS_X_MIN_REQUIRED +#include +#elif defined(__IPHONE_OS_MIN_REQUIRED) +#include +#endif + +typedef int32_t hb_atomic_int_t; +#define hb_atomic_int_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V)) + +#define hb_atomic_ptr_get(P) (OSMemoryBarrier (), (void *) *(P)) +#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100) +#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P)) +#else +#if __ppc64__ || __x86_64__ +#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P)) +#else +#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P)) +#endif +#endif + + +#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) + +typedef int hb_atomic_int_t; +#define hb_atomic_int_add(AI, V) __sync_fetch_and_add (&(AI), (V)) + +#define hb_atomic_ptr_get(P) (void *) (__sync_synchronize (), *(P)) +#define hb_atomic_ptr_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N)) + + +#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS) + +#include +#include + +typedef unsigned int hb_atomic_int_t; +#define hb_atomic_int_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V)) + +#define hb_atomic_ptr_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P)) +#define hb_atomic_ptr_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false) + + +#elif !defined(HB_NO_MT) + +#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ +typedef volatile int hb_atomic_int_t; +#define hb_atomic_int_add(AI, V) (((AI) += (V)) - (V)) + +#define hb_atomic_ptr_get(P) ((void *) *(P)) +#define hb_atomic_ptr_cmpexch(P,O,N) (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false) + + +#else /* HB_NO_MT */ + +typedef int hb_atomic_int_t; +#define hb_atomic_int_add(AI, V) (((AI) += (V)) - (V)) + +#define hb_atomic_ptr_get(P) ((void *) *(P)) +#define hb_atomic_ptr_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) + +#endif + +/* TODO Add tracing. */ + +#endif /* HB_ATOMIC_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc new file mode 100644 index 0000000000..dfd134b776 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc @@ -0,0 +1,328 @@ +/* + * Copyright © 2009 Red Hat, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + */ + +/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */ +#define _POSIX_C_SOURCE 199309L + +#include "hb-private.hh" + +#include "hb-blob.h" +#include "hb-object-private.hh" + +#ifdef HAVE_SYS_MMAN_H +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include +#endif /* HAVE_SYS_MMAN_H */ + +#include +#include + + + +#ifndef HB_DEBUG_BLOB +#define HB_DEBUG_BLOB (HB_DEBUG+0) +#endif + + +struct hb_blob_t { + hb_object_header_t header; + ASSERT_POD (); + + bool immutable; + + const char *data; + unsigned int length; + hb_memory_mode_t mode; + + void *user_data; + hb_destroy_func_t destroy; +}; + + +static bool _try_writable (hb_blob_t *blob); + +static void +_hb_blob_destroy_user_data (hb_blob_t *blob) +{ + if (blob->destroy) { + blob->destroy (blob->user_data); + blob->user_data = NULL; + blob->destroy = NULL; + } +} + +hb_blob_t * +hb_blob_create (const char *data, + unsigned int length, + hb_memory_mode_t mode, + void *user_data, + hb_destroy_func_t destroy) +{ + hb_blob_t *blob; + + if (!length || !(blob = hb_object_create ())) { + if (destroy) + destroy (user_data); + return hb_blob_get_empty (); + } + + blob->data = data; + blob->length = length; + blob->mode = mode; + + blob->user_data = user_data; + blob->destroy = destroy; + + if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { + blob->mode = HB_MEMORY_MODE_READONLY; + if (!_try_writable (blob)) { + hb_blob_destroy (blob); + return hb_blob_get_empty (); + } + } + + return blob; +} + +hb_blob_t * +hb_blob_create_sub_blob (hb_blob_t *parent, + unsigned int offset, + unsigned int length) +{ + hb_blob_t *blob; + + if (!length || offset >= parent->length) + return hb_blob_get_empty (); + + hb_blob_make_immutable (parent); + + blob = hb_blob_create (parent->data + offset, + MIN (length, parent->length - offset), + HB_MEMORY_MODE_READONLY, + hb_blob_reference (parent), + (hb_destroy_func_t) hb_blob_destroy); + + return blob; +} + +hb_blob_t * +hb_blob_get_empty (void) +{ + static const hb_blob_t _hb_blob_nil = { + HB_OBJECT_HEADER_STATIC, + + true, /* immutable */ + + NULL, /* data */ + 0, /* length */ + HB_MEMORY_MODE_READONLY, /* mode */ + + NULL, /* user_data */ + NULL /* destroy */ + }; + + return const_cast (&_hb_blob_nil); +} + +hb_blob_t * +hb_blob_reference (hb_blob_t *blob) +{ + return hb_object_reference (blob); +} + +void +hb_blob_destroy (hb_blob_t *blob) +{ + if (!hb_object_destroy (blob)) return; + + _hb_blob_destroy_user_data (blob); + + free (blob); +} + +hb_bool_t +hb_blob_set_user_data (hb_blob_t *blob, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace) +{ + return hb_object_set_user_data (blob, key, data, destroy, replace); +} + +void * +hb_blob_get_user_data (hb_blob_t *blob, + hb_user_data_key_t *key) +{ + return hb_object_get_user_data (blob, key); +} + + +void +hb_blob_make_immutable (hb_blob_t *blob) +{ + if (hb_object_is_inert (blob)) + return; + + blob->immutable = true; +} + +hb_bool_t +hb_blob_is_immutable (hb_blob_t *blob) +{ + return blob->immutable; +} + + +unsigned int +hb_blob_get_length (hb_blob_t *blob) +{ + return blob->length; +} + +const char * +hb_blob_get_data (hb_blob_t *blob, unsigned int *length) +{ + if (length) + *length = blob->length; + + return blob->data; +} + +char * +hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) +{ + if (!_try_writable (blob)) { + if (length) + *length = 0; + + return NULL; + } + + if (length) + *length = blob->length; + + return const_cast (blob->data); +} + + +static hb_bool_t +_try_make_writable_inplace_unix (hb_blob_t *blob) +{ +#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT) + uintptr_t pagesize = -1, mask, length; + const char *addr; + +#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) + pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE); +#elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) + pagesize = (uintptr_t) sysconf (_SC_PAGESIZE); +#elif defined(HAVE_GETPAGESIZE) + pagesize = (uintptr_t) getpagesize (); +#endif + + if ((uintptr_t) -1L == pagesize) { + DEBUG_MSG_FUNC (BLOB, blob, "failed to get pagesize: %s", strerror (errno)); + return false; + } + DEBUG_MSG_FUNC (BLOB, blob, "pagesize is %lu", (unsigned long) pagesize); + + mask = ~(pagesize-1); + addr = (const char *) (((uintptr_t) blob->data) & mask); + length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask) - addr; + DEBUG_MSG_FUNC (BLOB, blob, + "calling mprotect on [%p..%p] (%lu bytes)", + addr, addr+length, (unsigned long) length); + if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) { + DEBUG_MSG_FUNC (BLOB, blob, "mprotect failed: %s", strerror (errno)); + return false; + } + + blob->mode = HB_MEMORY_MODE_WRITABLE; + + DEBUG_MSG_FUNC (BLOB, blob, + "successfully made [%p..%p] (%lu bytes) writable\n", + addr, addr+length, (unsigned long) length); + return true; +#else + return false; +#endif +} + +static bool +_try_writable_inplace (hb_blob_t *blob) +{ + DEBUG_MSG_FUNC (BLOB, blob, "making writable inplace\n"); + + if (_try_make_writable_inplace_unix (blob)) + return true; + + DEBUG_MSG_FUNC (BLOB, blob, "making writable -> FAILED\n"); + + /* Failed to make writable inplace, mark that */ + blob->mode = HB_MEMORY_MODE_READONLY; + return false; +} + +static bool +_try_writable (hb_blob_t *blob) +{ + if (blob->immutable) + return false; + + if (blob->mode == HB_MEMORY_MODE_WRITABLE) + return true; + + if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE && _try_writable_inplace (blob)) + return true; + + if (blob->mode == HB_MEMORY_MODE_WRITABLE) + return true; + + + DEBUG_MSG_FUNC (BLOB, blob, "current data is -> %p\n", blob->data); + + char *new_data; + + new_data = (char *) malloc (blob->length); + if (unlikely (!new_data)) + return false; + + DEBUG_MSG_FUNC (BLOB, blob, "dupped successfully -> %p\n", blob->data); + + memcpy (new_data, blob->data, blob->length); + _hb_blob_destroy_user_data (blob); + blob->mode = HB_MEMORY_MODE_WRITABLE; + blob->data = new_data; + blob->user_data = new_data; + blob->destroy = free; + + return true; +} + + diff --git a/src/3rdparty/harfbuzz-ng/src/hb-blob.h b/src/3rdparty/harfbuzz-ng/src/hb-blob.h new file mode 100644 index 0000000000..d3d0f41b11 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.h @@ -0,0 +1,127 @@ +/* + * Copyright © 2009 Red Hat, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + */ + +#ifndef HB_H_IN +#error "Include instead." +#endif + +#ifndef HB_BLOB_H +#define HB_BLOB_H + +#include "hb-common.h" + +HB_BEGIN_DECLS + + +/* + * Note re various memory-modes: + * + * - In no case shall the HarfBuzz client modify memory + * that is passed to HarfBuzz in a blob. If there is + * any such possibility, MODE_DUPLICATE should be used + * such that HarfBuzz makes a copy immediately, + * + * - Use MODE_READONLY otherse, unless you really really + * really know what you are doing, + * + * - MODE_WRITABLE is appropriate if you relaly made a + * copy of data solely for the purpose of passing to + * HarfBuzz and doing that just once (no reuse!), + * + * - If the font is mmap()ed, it's ok to use + * READONLY_MAY_MAKE_WRITABLE, however, there were + * design problems with that mode, so HarfBuzz do not + * really use it anymore. If not sure, use MODE_READONLY. + */ +typedef enum { + HB_MEMORY_MODE_DUPLICATE, + HB_MEMORY_MODE_READONLY, + HB_MEMORY_MODE_WRITABLE, + HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE +} hb_memory_mode_t; + +typedef struct hb_blob_t hb_blob_t; + +hb_blob_t * +hb_blob_create (const char *data, + unsigned int length, + hb_memory_mode_t mode, + void *user_data, + hb_destroy_func_t destroy); + +/* Always creates with MEMORY_MODE_READONLY. + * Even if the parent blob is writable, we don't + * want the user of the sub-blob to be able to + * modify the parent data as that data may be + * shared among multiple sub-blobs. + */ +hb_blob_t * +hb_blob_create_sub_blob (hb_blob_t *parent, + unsigned int offset, + unsigned int length); + +hb_blob_t * +hb_blob_get_empty (void); + +hb_blob_t * +hb_blob_reference (hb_blob_t *blob); + +void +hb_blob_destroy (hb_blob_t *blob); + +hb_bool_t +hb_blob_set_user_data (hb_blob_t *blob, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + + +void * +hb_blob_get_user_data (hb_blob_t *blob, + hb_user_data_key_t *key); + + +void +hb_blob_make_immutable (hb_blob_t *blob); + +hb_bool_t +hb_blob_is_immutable (hb_blob_t *blob); + + +unsigned int +hb_blob_get_length (hb_blob_t *blob); + +const char * +hb_blob_get_data (hb_blob_t *blob, unsigned int *length); + +char * +hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length); + + +HB_END_DECLS + +#endif /* HB_BLOB_H */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh new file mode 100644 index 0000000000..a49dc2ac50 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh @@ -0,0 +1,643 @@ + +#line 1 "hb-buffer-deserialize-json.rl" +/* + * Copyright © 2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BUFFER_DESERIALIZE_JSON_HH +#define HB_BUFFER_DESERIALIZE_JSON_HH + +#include "hb-private.hh" + + +#line 36 "hb-buffer-deserialize-json.hh" +static const unsigned char _deserialize_json_trans_keys[] = { + 0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, + 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, + 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, + 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, + 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, + 65u, 122u, 34u, 122u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0 +}; + +static const char _deserialize_json_key_spans[] = { + 0, 115, 26, 7, 2, 1, 50, 49, + 10, 117, 117, 117, 1, 50, 49, 10, + 117, 117, 1, 1, 50, 49, 117, 117, + 2, 1, 50, 49, 10, 117, 117, 1, + 50, 49, 10, 117, 117, 1, 50, 49, + 58, 89, 117, 117, 85, 115, 0 +}; + +static const short _deserialize_json_index_offsets[] = { + 0, 0, 116, 143, 151, 154, 156, 207, + 257, 268, 386, 504, 622, 624, 675, 725, + 736, 854, 972, 974, 976, 1027, 1077, 1195, + 1313, 1316, 1318, 1369, 1419, 1430, 1548, 1666, + 1668, 1719, 1769, 1780, 1898, 2016, 2018, 2069, + 2119, 2178, 2268, 2386, 2504, 2590, 2706 +}; + +static const char _deserialize_json_indicies[] = { + 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 1, 3, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 4, 1, + 5, 1, 6, 7, 1, 1, 8, 1, + 9, 10, 1, 11, 1, 11, 11, 11, + 11, 11, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 11, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 12, 1, + 12, 12, 12, 12, 12, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 12, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 13, 1, 1, 14, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 1, 16, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 1, 18, 18, 18, + 18, 18, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 18, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 19, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 20, 1, 21, 21, 21, 21, 21, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 21, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 22, + 1, 18, 18, 18, 18, 18, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 18, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 19, 1, 1, 1, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 20, 1, 23, + 1, 23, 23, 23, 23, 23, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 23, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 24, 1, 24, 24, 24, 24, + 24, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 24, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 25, 1, 1, 26, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 1, 28, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 1, 30, 30, 30, 30, 30, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 30, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 31, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 32, 1, 30, + 30, 30, 30, 30, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 30, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 31, 1, 1, 1, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 32, 1, 33, 1, 34, + 1, 34, 34, 34, 34, 34, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 34, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 35, 1, 35, 35, 35, 35, + 35, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 35, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 36, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 1, 38, 38, + 38, 38, 38, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 38, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 39, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 40, 1, 38, 38, 38, 38, + 38, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 38, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 39, + 1, 1, 1, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 40, 1, 42, 43, 1, 44, 1, 44, + 44, 44, 44, 44, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 44, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 45, 1, 45, 45, 45, 45, 45, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 45, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 46, 1, + 1, 47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 1, 49, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 1, 51, + 51, 51, 51, 51, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 51, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 52, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 53, 1, 51, 51, 51, + 51, 51, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 51, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 52, 1, 1, 1, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 53, 1, 54, 1, 54, 54, 54, + 54, 54, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 54, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 55, 1, + 55, 55, 55, 55, 55, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 55, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 56, 1, 1, 57, + 58, 58, 58, 58, 58, 58, 58, 58, + 58, 1, 59, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 1, 61, 61, 61, + 61, 61, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 61, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 62, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 63, 1, 61, 61, 61, 61, 61, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 61, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 62, 1, + 1, 1, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 63, + 1, 64, 1, 64, 64, 64, 64, 64, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 64, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 65, 1, 65, 65, + 65, 65, 65, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 65, 1, 66, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 67, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 1, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 1, 1, 1, 1, 1, 1, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 1, 70, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 71, 71, + 1, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 1, 1, 1, 1, 1, + 1, 1, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 1, 1, 1, 1, + 71, 1, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 1, 72, 72, 72, + 72, 72, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 72, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 73, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 74, 1, 72, 72, 72, 72, 72, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 72, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 73, 1, + 1, 1, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 74, + 1, 76, 76, 76, 76, 76, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 76, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 77, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 78, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 0 +}; + +static const char _deserialize_json_trans_targs[] = { + 1, 0, 2, 2, 3, 4, 18, 24, + 37, 5, 12, 6, 7, 8, 9, 11, + 9, 11, 10, 2, 44, 10, 44, 13, + 14, 15, 16, 17, 16, 17, 10, 2, + 44, 19, 20, 21, 22, 23, 10, 2, + 44, 23, 25, 31, 26, 27, 28, 29, + 30, 29, 30, 10, 2, 44, 32, 33, + 34, 35, 36, 35, 36, 10, 2, 44, + 38, 39, 40, 42, 43, 41, 10, 41, + 10, 2, 44, 43, 44, 45, 46 +}; + +static const char _deserialize_json_trans_actions[] = { + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 2, + 0, 0, 3, 3, 4, 0, 5, 0, + 0, 2, 2, 2, 0, 0, 6, 6, + 7, 0, 0, 0, 2, 2, 8, 8, + 9, 0, 0, 0, 0, 0, 2, 2, + 2, 0, 0, 10, 10, 11, 0, 0, + 2, 2, 2, 0, 0, 12, 12, 13, + 0, 0, 0, 2, 2, 2, 14, 0, + 15, 15, 16, 0, 0, 0, 0 +}; + +static const int deserialize_json_start = 1; +static const int deserialize_json_first_final = 44; +static const int deserialize_json_error = 0; + +static const int deserialize_json_en_main = 1; + + +#line 97 "hb-buffer-deserialize-json.rl" + + +static hb_bool_t +_hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer, + const char *buf, + unsigned int buf_len, + const char **end_ptr, + hb_font_t *font) +{ + const char *p = buf, *pe = buf + buf_len; + + /* Ensure we have positions. */ + (void) hb_buffer_get_glyph_positions (buffer, NULL); + + while (p < pe && ISSPACE (*p)) + p++; + if (p < pe && *p == (buffer->len ? ',' : '[')) + { + *end_ptr = ++p; + } + + const char *tok = NULL; + int cs; + hb_glyph_info_t info; + hb_glyph_position_t pos; + +#line 466 "hb-buffer-deserialize-json.hh" + { + cs = deserialize_json_start; + } + +#line 471 "hb-buffer-deserialize-json.hh" + { + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _deserialize_json_trans_keys + (cs<<1); + _inds = _deserialize_json_indicies + _deserialize_json_index_offsets[cs]; + + _slen = _deserialize_json_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=(*p) && + (*p) <= _keys[1] ? + (*p) - _keys[0] : _slen ]; + + cs = _deserialize_json_trans_targs[_trans]; + + if ( _deserialize_json_trans_actions[_trans] == 0 ) + goto _again; + + switch ( _deserialize_json_trans_actions[_trans] ) { + case 1: +#line 38 "hb-buffer-deserialize-json.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} + break; + case 5: +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 2: +#line 51 "hb-buffer-deserialize-json.rl" + { + tok = p; +} + break; + case 14: +#line 55 "hb-buffer-deserialize-json.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 15: +#line 62 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.codepoint)) return false; } + break; + case 8: +#line 63 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 10: +#line 64 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 12: +#line 65 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 3: +#line 66 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 6: +#line 67 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } + break; + case 16: +#line 62 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.codepoint)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 9: +#line 63 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 64 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 13: +#line 65 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 4: +#line 66 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 7: +#line 67 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 624 "hb-buffer-deserialize-json.hh" + } + +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + _out: {} + } + +#line 125 "hb-buffer-deserialize-json.rl" + + + *end_ptr = p; + + return p == pe && *(p-1) != ']'; +} + +#endif /* HB_BUFFER_DESERIALIZE_JSON_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh new file mode 100644 index 0000000000..7a46ab278b --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh @@ -0,0 +1,571 @@ + +#line 1 "hb-buffer-deserialize-text.rl" +/* + * Copyright © 2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BUFFER_DESERIALIZE_TEXT_HH +#define HB_BUFFER_DESERIALIZE_TEXT_HH + +#include "hb-private.hh" + + +#line 36 "hb-buffer-deserialize-text.hh" +static const unsigned char _deserialize_text_trans_keys[] = { + 0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, + 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, + 9u, 122u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, + 9u, 124u, 9u, 124u, 9u, 124u, 0 +}; + +static const char _deserialize_text_key_spans[] = { + 0, 114, 13, 10, 13, 10, 10, 13, + 10, 1, 13, 10, 14, 116, 116, 0, + 114, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116 +}; + +static const short _deserialize_text_index_offsets[] = { + 0, 0, 115, 129, 140, 154, 165, 176, + 190, 201, 203, 217, 228, 243, 360, 477, + 478, 593, 710, 827, 944, 1061, 1178, 1295, + 1412, 1529, 1646 +}; + +static const char _deserialize_text_indicies[] = { + 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 1, + 1, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 1, 1, 1, 1, 1, + 1, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 1, 5, 1, 1, 6, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 1, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 1, 10, 1, 1, + 11, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 1, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 1, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 1, 17, 1, 1, 18, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 1, 20, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 1, 22, 1, 23, 1, 1, 24, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 1, 26, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 1, 22, 1, 1, + 1, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 1, 28, 28, 28, 28, + 28, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 28, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 29, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 30, 1, 1, 31, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 32, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 33, + 1, 34, 34, 34, 34, 34, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 34, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 35, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 36, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 1, 1, 1, 1, 1, 1, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 1, 28, 28, 28, 28, 28, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 28, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 29, 1, 1, 1, + 1, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 1, 1, 1, 30, 1, + 1, 31, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 32, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 33, 1, 38, + 38, 38, 38, 38, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 38, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 39, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 40, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 41, 1, 42, 42, 42, 42, + 42, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 42, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 43, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 44, + 1, 42, 42, 42, 42, 42, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 42, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 43, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 44, 1, 38, 38, + 38, 38, 38, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 38, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 39, 1, 1, 1, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 40, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 41, 1, 45, 45, 45, 45, 45, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 45, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 46, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 47, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 48, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 49, 1, + 50, 50, 50, 50, 50, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 50, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 51, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 52, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 53, 1, 50, 50, 50, + 50, 50, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 50, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 51, + 1, 1, 1, 1, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 52, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 53, 1, 45, 45, 45, 45, 45, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 45, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 46, 1, 1, 1, + 1, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 1, 1, 1, 1, 1, + 1, 47, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 48, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 49, 1, 28, + 28, 28, 28, 28, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 28, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 29, 1, 55, 55, 1, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 1, 1, 1, 30, 1, 1, 31, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 1, 1, 32, 1, 55, 1, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 1, 33, 1, 0 +}; + +static const char _deserialize_text_trans_targs[] = { + 1, 0, 13, 17, 26, 3, 18, 21, + 18, 21, 5, 19, 20, 19, 20, 22, + 25, 8, 9, 12, 9, 12, 10, 11, + 23, 24, 23, 24, 14, 2, 6, 7, + 15, 16, 14, 15, 16, 17, 14, 4, + 15, 16, 14, 15, 16, 14, 2, 7, + 15, 16, 14, 2, 15, 16, 25, 26 +}; + +static const char _deserialize_text_trans_actions[] = { + 0, 0, 1, 1, 1, 2, 2, 2, + 0, 0, 2, 2, 2, 0, 0, 2, + 2, 2, 2, 2, 0, 0, 3, 2, + 2, 2, 0, 0, 4, 5, 5, 5, + 4, 4, 0, 0, 0, 0, 6, 7, + 6, 6, 8, 8, 8, 9, 10, 10, + 9, 9, 11, 12, 11, 11, 0, 0 +}; + +static const char _deserialize_text_eof_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, + 0, 4, 6, 8, 8, 6, 9, 11, + 11, 9, 4 +}; + +static const int deserialize_text_start = 1; +static const int deserialize_text_first_final = 13; +static const int deserialize_text_error = 0; + +static const int deserialize_text_en_main = 1; + + +#line 91 "hb-buffer-deserialize-text.rl" + + +static hb_bool_t +_hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer, + const char *buf, + unsigned int buf_len, + const char **end_ptr, + hb_font_t *font) +{ + const char *p = buf, *pe = buf + buf_len; + + /* Ensure we have positions. */ + (void) hb_buffer_get_glyph_positions (buffer, NULL); + + while (p < pe && ISSPACE (*p)) + p++; + if (p < pe && *p == (buffer->len ? '|' : '[')) + { + *end_ptr = ++p; + } + + const char *eof = pe, *tok = NULL; + int cs; + hb_glyph_info_t info; + hb_glyph_position_t pos; + +#line 343 "hb-buffer-deserialize-text.hh" + { + cs = deserialize_text_start; + } + +#line 348 "hb-buffer-deserialize-text.hh" + { + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _deserialize_text_trans_keys + (cs<<1); + _inds = _deserialize_text_indicies + _deserialize_text_index_offsets[cs]; + + _slen = _deserialize_text_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=(*p) && + (*p) <= _keys[1] ? + (*p) - _keys[0] : _slen ]; + + cs = _deserialize_text_trans_targs[_trans]; + + if ( _deserialize_text_trans_actions[_trans] == 0 ) + goto _again; + + switch ( _deserialize_text_trans_actions[_trans] ) { + case 2: +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} + break; + case 5: +#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 10: +#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 3: +#line 63 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 12: +#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 7: +#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 1: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} + break; + case 4: +#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 9: +#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 6: +#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 8: +#line 66 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 480 "hb-buffer-deserialize-text.hh" + } + +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + if ( p == eof ) + { + switch ( _deserialize_text_eof_actions[cs] ) { + case 4: +#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 9: +#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 6: +#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 8: +#line 66 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 557 "hb-buffer-deserialize-text.hh" + } + } + + _out: {} + } + +#line 119 "hb-buffer-deserialize-text.rl" + + + *end_ptr = p; + + return p == pe && *(p-1) != ']'; +} + +#endif /* HB_BUFFER_DESERIALIZE_TEXT_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh new file mode 100644 index 0000000000..a8cf770244 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh @@ -0,0 +1,202 @@ +/* + * Copyright © 1998-2004 David Turner and Werner Lemberg + * Copyright © 2004,2007,2009,2010 Red Hat, Inc. + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Owen Taylor, Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BUFFER_PRIVATE_HH +#define HB_BUFFER_PRIVATE_HH + +#include "hb-private.hh" +#include "hb-buffer.h" +#include "hb-object-private.hh" +#include "hb-unicode-private.hh" + + +ASSERT_STATIC (sizeof (hb_glyph_info_t) == 20); +ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)); + + +/* + * hb_buffer_t + */ + +struct hb_buffer_t { + hb_object_header_t header; + ASSERT_POD (); + + /* Information about how the text in the buffer should be treated */ + + hb_unicode_funcs_t *unicode; /* Unicode functions */ + hb_segment_properties_t props; /* Script, language, direction */ + hb_buffer_flags_t flags; /* BOT / EOT / etc. */ + + /* Buffer contents */ + + hb_buffer_content_type_t content_type; + + bool in_error; /* Allocation failed */ + bool have_output; /* Whether we have an output buffer going on */ + bool have_positions; /* Whether we have positions */ + + unsigned int idx; /* Cursor into ->info and ->pos arrays */ + unsigned int len; /* Length of ->info and ->pos arrays */ + unsigned int out_len; /* Length of ->out array if have_output */ + + unsigned int allocated; /* Length of allocated arrays */ + hb_glyph_info_t *info; + hb_glyph_info_t *out_info; + hb_glyph_position_t *pos; + + inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; } + inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; } + + inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; } + inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; } + + inline hb_glyph_info_t &prev (void) { return out_info[out_len - 1]; } + inline hb_glyph_info_t prev (void) const { return info[out_len - 1]; } + + inline bool has_separate_output (void) const { return info != out_info; } + + unsigned int serial; + + /* These reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ + uint8_t allocated_var_bytes[8]; + const char *allocated_var_owner[8]; + + /* Text before / after the main buffer contents. + * Always in Unicode, and ordered outward. + * Index 0 is for "pre-context", 1 for "post-context". */ + static const unsigned int CONTEXT_LENGTH = 5; + hb_codepoint_t context[2][CONTEXT_LENGTH]; + unsigned int context_len[2]; + + + /* Methods */ + + HB_INTERNAL void reset (void); + HB_INTERNAL void clear (void); + + inline unsigned int backtrack_len (void) const + { return have_output? out_len : idx; } + inline unsigned int next_serial (void) { return serial++; } + + HB_INTERNAL void allocate_var (unsigned int byte_i, unsigned int count, const char *owner); + HB_INTERNAL void deallocate_var (unsigned int byte_i, unsigned int count, const char *owner); + HB_INTERNAL void assert_var (unsigned int byte_i, unsigned int count, const char *owner); + HB_INTERNAL void deallocate_var_all (void); + + HB_INTERNAL void add (hb_codepoint_t codepoint, + unsigned int cluster); + HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info); + + HB_INTERNAL void reverse_range (unsigned int start, unsigned int end); + HB_INTERNAL void reverse (void); + HB_INTERNAL void reverse_clusters (void); + HB_INTERNAL void guess_segment_properties (void); + + HB_INTERNAL void swap_buffers (void); + HB_INTERNAL void remove_output (void); + HB_INTERNAL void clear_output (void); + HB_INTERNAL void clear_positions (void); + + HB_INTERNAL void replace_glyphs (unsigned int num_in, + unsigned int num_out, + const hb_codepoint_t *glyph_data); + + HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index); + /* Makes a copy of the glyph at idx to output and replace glyph_index */ + HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index); + HB_INTERNAL void output_info (const hb_glyph_info_t &glyph_info); + /* Copies glyph at idx to output but doesn't advance idx */ + HB_INTERNAL void copy_glyph (void); + /* Copies glyph at idx to output and advance idx. + * If there's no output, just advance idx. */ + inline void + next_glyph (void) + { + if (have_output) + { + if (unlikely (out_info != info || out_len != idx)) { + if (unlikely (!make_room_for (1, 1))) return; + out_info[out_len] = info[idx]; + } + out_len++; + } + + idx++; + } + + /* Advance idx without copying to output. */ + inline void skip_glyph (void) { idx++; } + + inline void reset_masks (hb_mask_t mask) + { + for (unsigned int j = 0; j < len; j++) + info[j].mask = mask; + } + inline void add_masks (hb_mask_t mask) + { + for (unsigned int j = 0; j < len; j++) + info[j].mask |= mask; + } + HB_INTERNAL void set_masks (hb_mask_t value, + hb_mask_t mask, + unsigned int cluster_start, + unsigned int cluster_end); + + HB_INTERNAL void merge_clusters (unsigned int start, + unsigned int end); + HB_INTERNAL void merge_out_clusters (unsigned int start, + unsigned int end); + + /* Internal methods */ + HB_INTERNAL bool enlarge (unsigned int size); + + inline bool ensure (unsigned int size) + { return likely (size < allocated) ? true : enlarge (size); } + + HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out); + + HB_INTERNAL void *get_scratch_buffer (unsigned int *size); + + inline void clear_context (unsigned int side) { context_len[side] = 0; } +}; + + +#define HB_BUFFER_XALLOCATE_VAR(b, func, var, owner) \ + b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \ + sizeof (b->info[0].var), owner) +#define HB_BUFFER_ALLOCATE_VAR(b, var) \ + HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var (), #var) +#define HB_BUFFER_DEALLOCATE_VAR(b, var) \ + HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var (), #var) +#define HB_BUFFER_ASSERT_VAR(b, var) \ + HB_BUFFER_XALLOCATE_VAR (b, assert_var, var (), #var) + + +#endif /* HB_BUFFER_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc new file mode 100644 index 0000000000..dc47ba73e0 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc @@ -0,0 +1,336 @@ +/* + * Copyright © 2012,2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-buffer-private.hh" + + +static const char *serialize_formats[] = { + "text", + "json", + NULL +}; + +const char ** +hb_buffer_serialize_list_formats (void) +{ + return serialize_formats; +} + +hb_buffer_serialize_format_t +hb_buffer_serialize_format_from_string (const char *str, int len) +{ + /* Upper-case it. */ + return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020); +} + +const char * +hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) +{ + switch (format) + { + case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0]; + case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1]; + default: + case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return NULL; + } +} + +static unsigned int +_hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, + unsigned int *buf_consumed, + hb_font_t *font, + hb_buffer_serialize_flags_t flags) +{ + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); + + *buf_consumed = 0; + for (unsigned int i = start; i < end; i++) + { + char b[1024]; + char *p = b; + + /* In the following code, we know b is large enough that no overflow can happen. */ + +#define APPEND(s) HB_STMT_START { strcpy (p, s); p += strlen (s); } HB_STMT_END + + if (i) + *p++ = ','; + + *p++ = '{'; + + APPEND ("\"g\":"); + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES)) + { + char g[128]; + hb_font_glyph_to_string (font, info[i].codepoint, g, sizeof (g)); + *p++ = '"'; + for (char *q = g; *q; q++) { + if (*q == '"') + *p++ = '\\'; + *p++ = *q; + } + *p++ = '"'; + } + else + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint); + + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster); + } + + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) + { + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d", + pos[i].x_offset, pos[i].y_offset); + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d", + pos[i].x_advance, pos[i].y_advance); + } + + *p++ = '}'; + + if (buf_size > (p - b)) + { + unsigned int l = p - b; + memcpy (buf, b, l); + buf += l; + buf_size -= l; + *buf_consumed += l; + *buf = '\0'; + } else + return i - start; + } + + return end - start; +} + +static unsigned int +_hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, + unsigned int *buf_consumed, + hb_font_t *font, + hb_buffer_serialize_flags_t flags) +{ + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); + + *buf_consumed = 0; + for (unsigned int i = start; i < end; i++) + { + char b[1024]; + char *p = b; + + /* In the following code, we know b is large enough that no overflow can happen. */ + + if (i) + *p++ = '|'; + + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES)) + { + hb_font_glyph_to_string (font, info[i].codepoint, p, 128); + p += strlen (p); + } + else + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint); + + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster); + } + + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) + { + if (pos[i].x_offset || pos[i].y_offset) + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", pos[i].x_offset, pos[i].y_offset); + + *p++ = '+'; + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance); + if (pos->y_advance) + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance); + } + + if (buf_size > (p - b)) + { + unsigned int l = p - b; + memcpy (buf, b, l); + buf += l; + buf_size -= l; + *buf_consumed += l; + *buf = '\0'; + } else + return i - start; + } + + return end - start; +} + +/* Returns number of items, starting at start, that were serialized. */ +unsigned int +hb_buffer_serialize_glyphs (hb_buffer_t *buffer, + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, + unsigned int *buf_consumed, /* May be NULL */ + hb_font_t *font, /* May be NULL */ + hb_buffer_serialize_format_t format, + hb_buffer_serialize_flags_t flags) +{ + assert (start <= end && end <= buffer->len); + + unsigned int sconsumed; + if (!buf_consumed) + buf_consumed = &sconsumed; + *buf_consumed = 0; + + assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || + buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); + + if (unlikely (start == end)) + return 0; + + if (!font) + font = hb_font_get_empty (); + + switch (format) + { + case HB_BUFFER_SERIALIZE_FORMAT_TEXT: + return _hb_buffer_serialize_glyphs_text (buffer, start, end, + buf, buf_size, buf_consumed, + font, flags); + + case HB_BUFFER_SERIALIZE_FORMAT_JSON: + return _hb_buffer_serialize_glyphs_json (buffer, start, end, + buf, buf_size, buf_consumed, + font, flags); + + default: + case HB_BUFFER_SERIALIZE_FORMAT_INVALID: + return 0; + + } +} + + +static hb_bool_t +parse_uint (const char *pp, const char *end, uint32_t *pv) +{ + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); + strncpy (buf, pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + uint32_t v; + + errno = 0; + v = strtol (p, &pend, 10); + if (errno || p == pend || pend - p != end - pp) + return false; + + *pv = v; + return true; +} + +static hb_bool_t +parse_int (const char *pp, const char *end, int32_t *pv) +{ + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); + strncpy (buf, pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + int32_t v; + + errno = 0; + v = strtol (p, &pend, 10); + if (errno || p == pend || pend - p != end - pp) + return false; + + *pv = v; + return true; +} + +#include "hb-buffer-deserialize-json.hh" +#include "hb-buffer-deserialize-text.hh" + +hb_bool_t +hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, + const char *buf, + int buf_len, /* -1 means nul-terminated */ + const char **end_ptr, /* May be NULL */ + hb_font_t *font, /* May be NULL */ + hb_buffer_serialize_format_t format) +{ + const char *end; + if (!end_ptr) + end_ptr = &end; + *end_ptr = buf; + + assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || + buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); + + if (buf_len == -1) + buf_len = strlen (buf); + + if (!buf_len) + { + *end_ptr = buf; + return false; + } + + hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); + + if (!font) + font = hb_font_get_empty (); + + switch (format) + { + case HB_BUFFER_SERIALIZE_FORMAT_TEXT: + return _hb_buffer_deserialize_glyphs_text (buffer, + buf, buf_len, end_ptr, + font); + + case HB_BUFFER_SERIALIZE_FORMAT_JSON: + return _hb_buffer_deserialize_glyphs_json (buffer, + buf, buf_len, end_ptr, + font); + + default: + case HB_BUFFER_SERIALIZE_FORMAT_INVALID: + return false; + + } +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc new file mode 100644 index 0000000000..c0ca484f94 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc @@ -0,0 +1,1077 @@ +/* + * Copyright © 1998-2004 David Turner and Werner Lemberg + * Copyright © 2004,2007,2009,2010 Red Hat, Inc. + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Owen Taylor, Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-buffer-private.hh" +#include "hb-utf-private.hh" + + +#ifndef HB_DEBUG_BUFFER +#define HB_DEBUG_BUFFER (HB_DEBUG+0) +#endif + + +hb_bool_t +hb_segment_properties_equal (const hb_segment_properties_t *a, + const hb_segment_properties_t *b) +{ + return a->direction == b->direction && + a->script == b->script && + a->language == b->language && + a->reserved1 == b->reserved1 && + a->reserved2 == b->reserved2; + +} + +unsigned int +hb_segment_properties_hash (const hb_segment_properties_t *p) +{ + return (unsigned int) p->direction ^ + (unsigned int) p->script ^ + (intptr_t) (p->language); +} + + + +/* Here is how the buffer works internally: + * + * There are two info pointers: info and out_info. They always have + * the same allocated size, but different lengths. + * + * As an optimization, both info and out_info may point to the + * same piece of memory, which is owned by info. This remains the + * case as long as out_len doesn't exceed i at any time. + * In that case, swap_buffers() is no-op and the glyph operations operate + * mostly in-place. + * + * As soon as out_info gets longer than info, out_info is moved over + * to an alternate buffer (which we reuse the pos buffer for!), and its + * current contents (out_len entries) are copied to the new place. + * This should all remain transparent to the user. swap_buffers() then + * switches info and out_info. + */ + + + +/* Internal API */ + +bool +hb_buffer_t::enlarge (unsigned int size) +{ + if (unlikely (in_error)) + return false; + + unsigned int new_allocated = allocated; + hb_glyph_position_t *new_pos = NULL; + hb_glyph_info_t *new_info = NULL; + bool separate_out = out_info != info; + + if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0])))) + goto done; + + while (size >= new_allocated) + new_allocated += (new_allocated >> 1) + 32; + + ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0])); + if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0])))) + goto done; + + new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0])); + new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0])); + +done: + if (unlikely (!new_pos || !new_info)) + in_error = true; + + if (likely (new_pos)) + pos = new_pos; + + if (likely (new_info)) + info = new_info; + + out_info = separate_out ? (hb_glyph_info_t *) pos : info; + if (likely (!in_error)) + allocated = new_allocated; + + return likely (!in_error); +} + +bool +hb_buffer_t::make_room_for (unsigned int num_in, + unsigned int num_out) +{ + if (unlikely (!ensure (out_len + num_out))) return false; + + if (out_info == info && + out_len + num_out > idx + num_in) + { + assert (have_output); + + out_info = (hb_glyph_info_t *) pos; + memcpy (out_info, info, out_len * sizeof (out_info[0])); + } + + return true; +} + +void * +hb_buffer_t::get_scratch_buffer (unsigned int *size) +{ + have_output = false; + have_positions = false; + + out_len = 0; + out_info = info; + + *size = allocated * sizeof (pos[0]); + return pos; +} + + + +/* HarfBuzz-Internal API */ + +void +hb_buffer_t::reset (void) +{ + if (unlikely (hb_object_is_inert (this))) + return; + + hb_unicode_funcs_destroy (unicode); + unicode = hb_unicode_funcs_get_default (); + + clear (); +} + +void +hb_buffer_t::clear (void) +{ + if (unlikely (hb_object_is_inert (this))) + return; + + hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; + props = default_props; + flags = HB_BUFFER_FLAGS_DEFAULT; + + content_type = HB_BUFFER_CONTENT_TYPE_INVALID; + in_error = false; + have_output = false; + have_positions = false; + + idx = 0; + len = 0; + out_len = 0; + out_info = info; + + serial = 0; + memset (allocated_var_bytes, 0, sizeof allocated_var_bytes); + memset (allocated_var_owner, 0, sizeof allocated_var_owner); + + memset (context, 0, sizeof context); + memset (context_len, 0, sizeof context_len); +} + +void +hb_buffer_t::add (hb_codepoint_t codepoint, + unsigned int cluster) +{ + hb_glyph_info_t *glyph; + + if (unlikely (!ensure (len + 1))) return; + + glyph = &info[len]; + + memset (glyph, 0, sizeof (*glyph)); + glyph->codepoint = codepoint; + glyph->mask = 1; + glyph->cluster = cluster; + + len++; +} + +void +hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info) +{ + if (unlikely (!ensure (len + 1))) return; + + info[len] = glyph_info; + + len++; +} + + +void +hb_buffer_t::remove_output (void) +{ + if (unlikely (hb_object_is_inert (this))) + return; + + have_output = false; + have_positions = false; + + out_len = 0; + out_info = info; +} + +void +hb_buffer_t::clear_output (void) +{ + if (unlikely (hb_object_is_inert (this))) + return; + + have_output = true; + have_positions = false; + + out_len = 0; + out_info = info; +} + +void +hb_buffer_t::clear_positions (void) +{ + if (unlikely (hb_object_is_inert (this))) + return; + + have_output = false; + have_positions = true; + + out_len = 0; + out_info = info; + + memset (pos, 0, sizeof (pos[0]) * len); +} + +void +hb_buffer_t::swap_buffers (void) +{ + if (unlikely (in_error)) return; + + assert (have_output); + have_output = false; + + if (out_info != info) + { + hb_glyph_info_t *tmp_string; + tmp_string = info; + info = out_info; + out_info = tmp_string; + pos = (hb_glyph_position_t *) out_info; + } + + unsigned int tmp; + tmp = len; + len = out_len; + out_len = tmp; + + idx = 0; +} + + +void +hb_buffer_t::replace_glyphs (unsigned int num_in, + unsigned int num_out, + const uint32_t *glyph_data) +{ + if (unlikely (!make_room_for (num_in, num_out))) return; + + merge_clusters (idx, idx + num_in); + + hb_glyph_info_t orig_info = info[idx]; + hb_glyph_info_t *pinfo = &out_info[out_len]; + for (unsigned int i = 0; i < num_out; i++) + { + *pinfo = orig_info; + pinfo->codepoint = glyph_data[i]; + pinfo++; + } + + idx += num_in; + out_len += num_out; +} + +void +hb_buffer_t::output_glyph (hb_codepoint_t glyph_index) +{ + if (unlikely (!make_room_for (0, 1))) return; + + out_info[out_len] = info[idx]; + out_info[out_len].codepoint = glyph_index; + + out_len++; +} + +void +hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info) +{ + if (unlikely (!make_room_for (0, 1))) return; + + out_info[out_len] = glyph_info; + + out_len++; +} + +void +hb_buffer_t::copy_glyph (void) +{ + if (unlikely (!make_room_for (0, 1))) return; + + out_info[out_len] = info[idx]; + + out_len++; +} + +void +hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index) +{ + if (unlikely (out_info != info || out_len != idx)) { + if (unlikely (!make_room_for (1, 1))) return; + out_info[out_len] = info[idx]; + } + out_info[out_len].codepoint = glyph_index; + + idx++; + out_len++; +} + + +void +hb_buffer_t::set_masks (hb_mask_t value, + hb_mask_t mask, + unsigned int cluster_start, + unsigned int cluster_end) +{ + hb_mask_t not_mask = ~mask; + value &= mask; + + if (!mask) + return; + + if (cluster_start == 0 && cluster_end == (unsigned int)-1) { + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + info[i].mask = (info[i].mask & not_mask) | value; + return; + } + + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end) + info[i].mask = (info[i].mask & not_mask) | value; +} + +void +hb_buffer_t::reverse_range (unsigned int start, + unsigned int end) +{ + unsigned int i, j; + + if (start == end - 1) + return; + + for (i = start, j = end - 1; i < j; i++, j--) { + hb_glyph_info_t t; + + t = info[i]; + info[i] = info[j]; + info[j] = t; + } + + if (pos) { + for (i = start, j = end - 1; i < j; i++, j--) { + hb_glyph_position_t t; + + t = pos[i]; + pos[i] = pos[j]; + pos[j] = t; + } + } +} + +void +hb_buffer_t::reverse (void) +{ + if (unlikely (!len)) + return; + + reverse_range (0, len); +} + +void +hb_buffer_t::reverse_clusters (void) +{ + unsigned int i, start, count, last_cluster; + + if (unlikely (!len)) + return; + + reverse (); + + count = len; + start = 0; + last_cluster = info[0].cluster; + for (i = 1; i < count; i++) { + if (last_cluster != info[i].cluster) { + reverse_range (start, i); + start = i; + last_cluster = info[i].cluster; + } + } + reverse_range (start, i); +} + +void +hb_buffer_t::merge_clusters (unsigned int start, + unsigned int end) +{ + if (unlikely (end - start < 2)) + return; + + unsigned int cluster = info[start].cluster; + + for (unsigned int i = start + 1; i < end; i++) + cluster = MIN (cluster, info[i].cluster); + + /* Extend end */ + while (end < len && info[end - 1].cluster == info[end].cluster) + end++; + + /* Extend start */ + while (idx < start && info[start - 1].cluster == info[start].cluster) + start--; + + /* If we hit the start of buffer, continue in out-buffer. */ + if (idx == start) + for (unsigned i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--) + out_info[i - 1].cluster = cluster; + + for (unsigned int i = start; i < end; i++) + info[i].cluster = cluster; +} +void +hb_buffer_t::merge_out_clusters (unsigned int start, + unsigned int end) +{ + if (unlikely (end - start < 2)) + return; + + unsigned int cluster = out_info[start].cluster; + + for (unsigned int i = start + 1; i < end; i++) + cluster = MIN (cluster, out_info[i].cluster); + + /* Extend start */ + while (start && out_info[start - 1].cluster == out_info[start].cluster) + start--; + + /* Extend end */ + while (end < out_len && out_info[end - 1].cluster == out_info[end].cluster) + end++; + + /* If we hit the end of out-buffer, continue in buffer. */ + if (end == out_len) + for (unsigned i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++) + info[i].cluster = cluster; + + for (unsigned int i = start; i < end; i++) + out_info[i].cluster = cluster; +} + +void +hb_buffer_t::guess_segment_properties (void) +{ + assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || + (!len && content_type == HB_BUFFER_CONTENT_TYPE_INVALID)); + + /* If script is set to INVALID, guess from buffer contents */ + if (props.script == HB_SCRIPT_INVALID) { + for (unsigned int i = 0; i < len; i++) { + hb_script_t script = unicode->script (info[i].codepoint); + if (likely (script != HB_SCRIPT_COMMON && + script != HB_SCRIPT_INHERITED && + script != HB_SCRIPT_UNKNOWN)) { + props.script = script; + break; + } + } + } + + /* If direction is set to INVALID, guess from script */ + if (props.direction == HB_DIRECTION_INVALID) { + props.direction = hb_script_get_horizontal_direction (props.script); + } + + /* If language is not set, use default language from locale */ + if (props.language == HB_LANGUAGE_INVALID) { + /* TODO get_default_for_script? using $LANGUAGE */ + props.language = hb_language_get_default (); + } +} + + +static inline void +dump_var_allocation (const hb_buffer_t *buffer) +{ + char buf[80]; + for (unsigned int i = 0; i < 8; i++) + buf[i] = '0' + buffer->allocated_var_bytes[7 - i]; + buf[8] = '\0'; + DEBUG_MSG (BUFFER, buffer, + "Current var allocation: %s", + buf); +} + +void hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const char *owner) +{ + assert (byte_i < 8 && byte_i + count <= 8); + + if (DEBUG_ENABLED (BUFFER)) + dump_var_allocation (this); + DEBUG_MSG (BUFFER, this, + "Allocating var bytes %d..%d for %s", + byte_i, byte_i + count - 1, owner); + + for (unsigned int i = byte_i; i < byte_i + count; i++) { + assert (!allocated_var_bytes[i]); + allocated_var_bytes[i]++; + allocated_var_owner[i] = owner; + } +} + +void hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner) +{ + if (DEBUG_ENABLED (BUFFER)) + dump_var_allocation (this); + + DEBUG_MSG (BUFFER, this, + "Deallocating var bytes %d..%d for %s", + byte_i, byte_i + count - 1, owner); + + assert (byte_i < 8 && byte_i + count <= 8); + for (unsigned int i = byte_i; i < byte_i + count; i++) { + assert (allocated_var_bytes[i]); + assert (0 == strcmp (allocated_var_owner[i], owner)); + allocated_var_bytes[i]--; + } +} + +void hb_buffer_t::assert_var (unsigned int byte_i, unsigned int count, const char *owner) +{ + if (DEBUG_ENABLED (BUFFER)) + dump_var_allocation (this); + + DEBUG_MSG (BUFFER, this, + "Asserting var bytes %d..%d for %s", + byte_i, byte_i + count - 1, owner); + + assert (byte_i < 8 && byte_i + count <= 8); + for (unsigned int i = byte_i; i < byte_i + count; i++) { + assert (allocated_var_bytes[i]); + assert (0 == strcmp (allocated_var_owner[i], owner)); + } +} + +void hb_buffer_t::deallocate_var_all (void) +{ + memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes)); + memset (allocated_var_owner, 0, sizeof (allocated_var_owner)); +} + +/* Public API */ + +hb_buffer_t * +hb_buffer_create (void) +{ + hb_buffer_t *buffer; + + if (!(buffer = hb_object_create ())) + return hb_buffer_get_empty (); + + buffer->reset (); + + return buffer; +} + +hb_buffer_t * +hb_buffer_get_empty (void) +{ + static const hb_buffer_t _hb_buffer_nil = { + HB_OBJECT_HEADER_STATIC, + + const_cast (&_hb_unicode_funcs_nil), + HB_SEGMENT_PROPERTIES_DEFAULT, + HB_BUFFER_FLAGS_DEFAULT, + + HB_BUFFER_CONTENT_TYPE_INVALID, + true, /* in_error */ + true, /* have_output */ + true /* have_positions */ + + /* Zero is good enough for everything else. */ + }; + + return const_cast (&_hb_buffer_nil); +} + +hb_buffer_t * +hb_buffer_reference (hb_buffer_t *buffer) +{ + return hb_object_reference (buffer); +} + +void +hb_buffer_destroy (hb_buffer_t *buffer) +{ + if (!hb_object_destroy (buffer)) return; + + hb_unicode_funcs_destroy (buffer->unicode); + + free (buffer->info); + free (buffer->pos); + + free (buffer); +} + +hb_bool_t +hb_buffer_set_user_data (hb_buffer_t *buffer, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace) +{ + return hb_object_set_user_data (buffer, key, data, destroy, replace); +} + +void * +hb_buffer_get_user_data (hb_buffer_t *buffer, + hb_user_data_key_t *key) +{ + return hb_object_get_user_data (buffer, key); +} + + +void +hb_buffer_set_content_type (hb_buffer_t *buffer, + hb_buffer_content_type_t content_type) +{ + buffer->content_type = content_type; +} + +hb_buffer_content_type_t +hb_buffer_get_content_type (hb_buffer_t *buffer) +{ + return buffer->content_type; +} + + +void +hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, + hb_unicode_funcs_t *unicode) +{ + if (unlikely (hb_object_is_inert (buffer))) + return; + + if (!unicode) + unicode = hb_unicode_funcs_get_default (); + + + hb_unicode_funcs_reference (unicode); + hb_unicode_funcs_destroy (buffer->unicode); + buffer->unicode = unicode; +} + +hb_unicode_funcs_t * +hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) +{ + return buffer->unicode; +} + +void +hb_buffer_set_direction (hb_buffer_t *buffer, + hb_direction_t direction) + +{ + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->props.direction = direction; +} + +hb_direction_t +hb_buffer_get_direction (hb_buffer_t *buffer) +{ + return buffer->props.direction; +} + +void +hb_buffer_set_script (hb_buffer_t *buffer, + hb_script_t script) +{ + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->props.script = script; +} + +hb_script_t +hb_buffer_get_script (hb_buffer_t *buffer) +{ + return buffer->props.script; +} + +void +hb_buffer_set_language (hb_buffer_t *buffer, + hb_language_t language) +{ + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->props.language = language; +} + +hb_language_t +hb_buffer_get_language (hb_buffer_t *buffer) +{ + return buffer->props.language; +} + +void +hb_buffer_set_segment_properties (hb_buffer_t *buffer, + const hb_segment_properties_t *props) +{ + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->props = *props; +} + +void +hb_buffer_get_segment_properties (hb_buffer_t *buffer, + hb_segment_properties_t *props) +{ + *props = buffer->props; +} + + +void +hb_buffer_set_flags (hb_buffer_t *buffer, + hb_buffer_flags_t flags) +{ + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->flags = flags; +} + +hb_buffer_flags_t +hb_buffer_get_flags (hb_buffer_t *buffer) +{ + return buffer->flags; +} + + +void +hb_buffer_reset (hb_buffer_t *buffer) +{ + buffer->reset (); +} + +void +hb_buffer_clear_contents (hb_buffer_t *buffer) +{ + buffer->clear (); +} + +hb_bool_t +hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) +{ + return buffer->ensure (size); +} + +hb_bool_t +hb_buffer_allocation_successful (hb_buffer_t *buffer) +{ + return !buffer->in_error; +} + +void +hb_buffer_add (hb_buffer_t *buffer, + hb_codepoint_t codepoint, + unsigned int cluster) +{ + buffer->add (codepoint, cluster); + buffer->clear_context (1); +} + +hb_bool_t +hb_buffer_set_length (hb_buffer_t *buffer, + unsigned int length) +{ + if (unlikely (hb_object_is_inert (buffer))) + return length == 0; + + if (!buffer->ensure (length)) + return false; + + /* Wipe the new space */ + if (length > buffer->len) { + memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len)); + if (buffer->have_positions) + memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len)); + } + + buffer->len = length; + + if (!length) + buffer->clear_context (0); + buffer->clear_context (1); + + return true; +} + +unsigned int +hb_buffer_get_length (hb_buffer_t *buffer) +{ + return buffer->len; +} + +/* Return value valid as long as buffer not modified */ +hb_glyph_info_t * +hb_buffer_get_glyph_infos (hb_buffer_t *buffer, + unsigned int *length) +{ + if (length) + *length = buffer->len; + + return (hb_glyph_info_t *) buffer->info; +} + +/* Return value valid as long as buffer not modified */ +hb_glyph_position_t * +hb_buffer_get_glyph_positions (hb_buffer_t *buffer, + unsigned int *length) +{ + if (!buffer->have_positions) + buffer->clear_positions (); + + if (length) + *length = buffer->len; + + return (hb_glyph_position_t *) buffer->pos; +} + +void +hb_buffer_reverse (hb_buffer_t *buffer) +{ + buffer->reverse (); +} + +void +hb_buffer_reverse_clusters (hb_buffer_t *buffer) +{ + buffer->reverse_clusters (); +} + +void +hb_buffer_guess_segment_properties (hb_buffer_t *buffer) +{ + buffer->guess_segment_properties (); +} + +template +static inline void +hb_buffer_add_utf (hb_buffer_t *buffer, + const T *text, + int text_length, + unsigned int item_offset, + int item_length) +{ + assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || + (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID)); + + if (unlikely (hb_object_is_inert (buffer))) + return; + + if (text_length == -1) + text_length = hb_utf_strlen (text); + + if (item_length == -1) + item_length = text_length - item_offset; + + buffer->ensure (buffer->len + item_length * sizeof (T) / 4); + + /* If buffer is empty and pre-context provided, install it. + * This check is written this way, to make sure people can + * provide pre-context in one add_utf() call, then provide + * text in a follow-up call. See: + * + * https://bugzilla.mozilla.org/show_bug.cgi?id=801410#c13 + */ + if (!buffer->len && item_offset > 0) + { + /* Add pre-context */ + buffer->clear_context (0); + const T *prev = text + item_offset; + const T *start = text; + while (start < prev && buffer->context_len[0] < buffer->CONTEXT_LENGTH) + { + hb_codepoint_t u; + prev = hb_utf_prev (prev, start, &u); + buffer->context[0][buffer->context_len[0]++] = u; + } + } + + const T *next = text + item_offset; + const T *end = next + item_length; + while (next < end) + { + hb_codepoint_t u; + const T *old_next = next; + next = hb_utf_next (next, end, &u); + buffer->add (u, old_next - (const T *) text); + } + + /* Add post-context */ + buffer->clear_context (1); + end = text + text_length; + while (next < end && buffer->context_len[1] < buffer->CONTEXT_LENGTH) + { + hb_codepoint_t u; + next = hb_utf_next (next, end, &u); + buffer->context[1][buffer->context_len[1]++] = u; + } + + buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; +} + +void +hb_buffer_add_utf8 (hb_buffer_t *buffer, + const char *text, + int text_length, + unsigned int item_offset, + int item_length) +{ + hb_buffer_add_utf (buffer, (const uint8_t *) text, text_length, item_offset, item_length); +} + +void +hb_buffer_add_utf16 (hb_buffer_t *buffer, + const uint16_t *text, + int text_length, + unsigned int item_offset, + int item_length) +{ + hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); +} + +void +hb_buffer_add_utf32 (hb_buffer_t *buffer, + const uint32_t *text, + int text_length, + unsigned int item_offset, + int item_length) +{ + hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); +} + + +static int +compare_info_codepoint (const hb_glyph_info_t *pa, + const hb_glyph_info_t *pb) +{ + return (int) pb->codepoint - (int) pa->codepoint; +} + +static inline void +normalize_glyphs_cluster (hb_buffer_t *buffer, + unsigned int start, + unsigned int end, + bool backward) +{ + hb_glyph_position_t *pos = buffer->pos; + + /* Total cluster advance */ + hb_position_t total_x_advance = 0, total_y_advance = 0; + for (unsigned int i = start; i < end; i++) + { + total_x_advance += pos[i].x_advance; + total_y_advance += pos[i].y_advance; + } + + hb_position_t x_advance = 0, y_advance = 0; + for (unsigned int i = start; i < end; i++) + { + pos[i].x_offset += x_advance; + pos[i].y_offset += y_advance; + + x_advance += pos[i].x_advance; + y_advance += pos[i].y_advance; + + pos[i].x_advance = 0; + pos[i].y_advance = 0; + } + + if (backward) + { + /* Transfer all cluster advance to the last glyph. */ + pos[end - 1].x_advance = total_x_advance; + pos[end - 1].y_advance = total_y_advance; + + hb_bubble_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start); + } else { + /* Transfer all cluster advance to the first glyph. */ + pos[start].x_advance += total_x_advance; + pos[start].y_advance += total_y_advance; + for (unsigned int i = start + 1; i < end; i++) { + pos[i].x_offset -= total_x_advance; + pos[i].y_offset -= total_y_advance; + } + hb_bubble_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1); + } +} + +void +hb_buffer_normalize_glyphs (hb_buffer_t *buffer) +{ + assert (buffer->have_positions); + assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); + + bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); + + unsigned int count = buffer->len; + if (unlikely (!count)) return; + hb_glyph_info_t *info = buffer->info; + + unsigned int start = 0; + unsigned int end; + for (end = start + 1; end < count; end++) + if (info[start].cluster != info[end].cluster) { + normalize_glyphs_cluster (buffer, start, end, backward); + start = end; + } + normalize_glyphs_cluster (buffer, start, end, backward); +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h new file mode 100644 index 0000000000..55a4045719 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h @@ -0,0 +1,323 @@ +/* + * Copyright © 1998-2004 David Turner and Werner Lemberg + * Copyright © 2004,2007,2009 Red Hat, Inc. + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Owen Taylor, Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_H_IN +#error "Include instead." +#endif + +#ifndef HB_BUFFER_H +#define HB_BUFFER_H + +#include "hb-common.h" +#include "hb-unicode.h" +#include "hb-font.h" + +HB_BEGIN_DECLS + + +typedef struct hb_glyph_info_t { + hb_codepoint_t codepoint; + hb_mask_t mask; + uint32_t cluster; + + /*< private >*/ + hb_var_int_t var1; + hb_var_int_t var2; +} hb_glyph_info_t; + +typedef struct hb_glyph_position_t { + hb_position_t x_advance; + hb_position_t y_advance; + hb_position_t x_offset; + hb_position_t y_offset; + + /*< private >*/ + hb_var_int_t var; +} hb_glyph_position_t; + + +typedef struct hb_segment_properties_t { + hb_direction_t direction; + hb_script_t script; + hb_language_t language; + /*< private >*/ + void *reserved1; + void *reserved2; +} hb_segment_properties_t; + +#define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \ + HB_SCRIPT_INVALID, \ + HB_LANGUAGE_INVALID, \ + NULL, \ + NULL} + +hb_bool_t +hb_segment_properties_equal (const hb_segment_properties_t *a, + const hb_segment_properties_t *b); + +unsigned int +hb_segment_properties_hash (const hb_segment_properties_t *p); + + + +/* + * hb_buffer_t + */ + +typedef struct hb_buffer_t hb_buffer_t; + +hb_buffer_t * +hb_buffer_create (void); + +hb_buffer_t * +hb_buffer_get_empty (void); + +hb_buffer_t * +hb_buffer_reference (hb_buffer_t *buffer); + +void +hb_buffer_destroy (hb_buffer_t *buffer); + +hb_bool_t +hb_buffer_set_user_data (hb_buffer_t *buffer, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + +void * +hb_buffer_get_user_data (hb_buffer_t *buffer, + hb_user_data_key_t *key); + + +typedef enum { + HB_BUFFER_CONTENT_TYPE_INVALID = 0, + HB_BUFFER_CONTENT_TYPE_UNICODE, + HB_BUFFER_CONTENT_TYPE_GLYPHS +} hb_buffer_content_type_t; + +void +hb_buffer_set_content_type (hb_buffer_t *buffer, + hb_buffer_content_type_t content_type); + +hb_buffer_content_type_t +hb_buffer_get_content_type (hb_buffer_t *buffer); + + +void +hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, + hb_unicode_funcs_t *unicode_funcs); + +hb_unicode_funcs_t * +hb_buffer_get_unicode_funcs (hb_buffer_t *buffer); + +void +hb_buffer_set_direction (hb_buffer_t *buffer, + hb_direction_t direction); + +hb_direction_t +hb_buffer_get_direction (hb_buffer_t *buffer); + +void +hb_buffer_set_script (hb_buffer_t *buffer, + hb_script_t script); + +hb_script_t +hb_buffer_get_script (hb_buffer_t *buffer); + +void +hb_buffer_set_language (hb_buffer_t *buffer, + hb_language_t language); + + +hb_language_t +hb_buffer_get_language (hb_buffer_t *buffer); + +void +hb_buffer_set_segment_properties (hb_buffer_t *buffer, + const hb_segment_properties_t *props); + +void +hb_buffer_get_segment_properties (hb_buffer_t *buffer, + hb_segment_properties_t *props); + +void +hb_buffer_guess_segment_properties (hb_buffer_t *buffer); + + +typedef enum { + HB_BUFFER_FLAGS_DEFAULT = 0x00000000, + HB_BUFFER_FLAG_BOT = 0x00000001, /* Beginning-of-text */ + HB_BUFFER_FLAG_EOT = 0x00000002, /* End-of-text */ + HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004 +} hb_buffer_flags_t; + +void +hb_buffer_set_flags (hb_buffer_t *buffer, + hb_buffer_flags_t flags); + +hb_buffer_flags_t +hb_buffer_get_flags (hb_buffer_t *buffer); + + +/* Resets the buffer. Afterwards it's as if it was just created, + * except that it has a larger buffer allocated perhaps... */ +void +hb_buffer_reset (hb_buffer_t *buffer); + +/* Like reset, but does NOT clear unicode_funcs. */ +void +hb_buffer_clear_contents (hb_buffer_t *buffer); + +/* Returns false if allocation failed */ +hb_bool_t +hb_buffer_pre_allocate (hb_buffer_t *buffer, + unsigned int size); + + +/* Returns false if allocation has failed before */ +hb_bool_t +hb_buffer_allocation_successful (hb_buffer_t *buffer); + +void +hb_buffer_reverse (hb_buffer_t *buffer); + +void +hb_buffer_reverse_clusters (hb_buffer_t *buffer); + + +/* Filling the buffer in */ + +void +hb_buffer_add (hb_buffer_t *buffer, + hb_codepoint_t codepoint, + unsigned int cluster); + +void +hb_buffer_add_utf8 (hb_buffer_t *buffer, + const char *text, + int text_length, + unsigned int item_offset, + int item_length); + +void +hb_buffer_add_utf16 (hb_buffer_t *buffer, + const uint16_t *text, + int text_length, + unsigned int item_offset, + int item_length); + +void +hb_buffer_add_utf32 (hb_buffer_t *buffer, + const uint32_t *text, + int text_length, + unsigned int item_offset, + int item_length); + + +/* Clears any new items added at the end */ +hb_bool_t +hb_buffer_set_length (hb_buffer_t *buffer, + unsigned int length); + +/* Return value valid as long as buffer not modified */ +unsigned int +hb_buffer_get_length (hb_buffer_t *buffer); + +/* Getting glyphs out of the buffer */ + +/* Return value valid as long as buffer not modified */ +hb_glyph_info_t * +hb_buffer_get_glyph_infos (hb_buffer_t *buffer, + unsigned int *length); + +/* Return value valid as long as buffer not modified */ +hb_glyph_position_t * +hb_buffer_get_glyph_positions (hb_buffer_t *buffer, + unsigned int *length); + + +/* Reorders a glyph buffer to have canonical in-cluster glyph order / position. + * The resulting clusters should behave identical to pre-reordering clusters. + * NOTE: This has nothing to do with Unicode normalization. */ +void +hb_buffer_normalize_glyphs (hb_buffer_t *buffer); + + +/* + * Serialize + */ + +typedef enum { + HB_BUFFER_SERIALIZE_FLAGS_DEFAULT = 0x00000000, + HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001, + HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002, + HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004 +} hb_buffer_serialize_flags_t; + +typedef enum { + HB_BUFFER_SERIALIZE_FORMAT_TEXT = HB_TAG('T','E','X','T'), + HB_BUFFER_SERIALIZE_FORMAT_JSON = HB_TAG('J','S','O','N'), + HB_BUFFER_SERIALIZE_FORMAT_INVALID = HB_TAG_NONE +} hb_buffer_serialize_format_t; + +/* len=-1 means str is NUL-terminated. */ +hb_buffer_serialize_format_t +hb_buffer_serialize_format_from_string (const char *str, int len); + +const char * +hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format); + +const char ** +hb_buffer_serialize_list_formats (void); + +/* Returns number of items, starting at start, that were serialized. */ +unsigned int +hb_buffer_serialize_glyphs (hb_buffer_t *buffer, + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, + unsigned int *buf_consumed, /* May be NULL */ + hb_font_t *font, /* May be NULL */ + hb_buffer_serialize_format_t format, + hb_buffer_serialize_flags_t flags); + +hb_bool_t +hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, + const char *buf, + int buf_len, /* -1 means nul-terminated */ + const char **end_ptr, /* May be NULL */ + hb_font_t *font, /* May be NULL */ + hb_buffer_serialize_format_t format); + + +HB_END_DECLS + +#endif /* HB_BUFFER_H */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cache-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-cache-private.hh new file mode 100644 index 0000000000..19b70b7e39 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-cache-private.hh @@ -0,0 +1,74 @@ +/* + * Copyright © 2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_CACHE_PRIVATE_HH +#define HB_CACHE_PRIVATE_HH + +#include "hb-private.hh" + + +/* Implements a lock-free cache for int->int functions. */ + +template +struct hb_cache_t +{ + ASSERT_STATIC (key_bits >= cache_bits); + ASSERT_STATIC (key_bits + value_bits - cache_bits < 8 * sizeof (unsigned int)); + + inline void clear (void) + { + memset (values, 255, sizeof (values)); + } + + inline bool get (unsigned int key, unsigned int *value) + { + unsigned int k = key & ((1<> value_bits) != (key >> cache_bits)) + return false; + *value = v & ((1<> key_bits) || (value >> value_bits))) + return false; /* Overflows */ + unsigned int k = key & ((1<>cache_bits)< hb_cmap_cache_t; +typedef hb_cache_t<16, 24, 8> hb_advance_cache_t; + + +#endif /* HB_CACHE_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.cc b/src/3rdparty/harfbuzz-ng/src/hb-common.cc new file mode 100644 index 0000000000..7c6d26290d --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-common.cc @@ -0,0 +1,434 @@ +/* + * Copyright © 2009,2010 Red Hat, Inc. + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-private.hh" + +#include "hb-version.h" + +#include "hb-mutex-private.hh" +#include "hb-object-private.hh" + +#include + + +/* hb_options_t */ + +hb_options_union_t _hb_options; + +void +_hb_options_init (void) +{ + hb_options_union_t u; + u.i = 0; + u.opts.initialized = 1; + + char *c = getenv ("HB_OPTIONS"); + u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible"); + + /* This is idempotent and threadsafe. */ + _hb_options = u; +} + + +/* hb_tag_t */ + +hb_tag_t +hb_tag_from_string (const char *s, int len) +{ + char tag[4]; + unsigned int i; + + if (!s || !len || !*s) + return HB_TAG_NONE; + + if (len < 0 || len > 4) + len = 4; + for (i = 0; i < (unsigned) len && s[i]; i++) + tag[i] = s[i]; + for (; i < 4; i++) + tag[i] = ' '; + + return HB_TAG_CHAR4 (tag); +} + +void +hb_tag_to_string (hb_tag_t tag, char *buf) +{ + buf[0] = (char) (uint8_t) (tag >> 24); + buf[1] = (char) (uint8_t) (tag >> 16); + buf[2] = (char) (uint8_t) (tag >> 8); + buf[3] = (char) (uint8_t) (tag >> 0); +} + + +/* hb_direction_t */ + +const char direction_strings[][4] = { + "ltr", + "rtl", + "ttb", + "btt" +}; + +hb_direction_t +hb_direction_from_string (const char *str, int len) +{ + if (unlikely (!str || !len || !*str)) + return HB_DIRECTION_INVALID; + + /* Lets match loosely: just match the first letter, such that + * all of "ltr", "left-to-right", etc work! + */ + char c = TOLOWER (str[0]); + for (unsigned int i = 0; i < ARRAY_LENGTH (direction_strings); i++) + if (c == direction_strings[i][0]) + return (hb_direction_t) (HB_DIRECTION_LTR + i); + + return HB_DIRECTION_INVALID; +} + +const char * +hb_direction_to_string (hb_direction_t direction) +{ + if (likely ((unsigned int) (direction - HB_DIRECTION_LTR) + < ARRAY_LENGTH (direction_strings))) + return direction_strings[direction - HB_DIRECTION_LTR]; + + return "invalid"; +} + + +/* hb_language_t */ + +struct hb_language_impl_t { + const char s[1]; +}; + +static const char canon_map[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0, + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0, + '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, '-', + 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0 +}; + +static hb_bool_t +lang_equal (hb_language_t v1, + const void *v2) +{ + const unsigned char *p1 = (const unsigned char *) v1; + const unsigned char *p2 = (const unsigned char *) v2; + + while (*p1 && *p1 == canon_map[*p2]) + p1++, p2++; + + return *p1 == canon_map[*p2]; +} + +#if 0 +static unsigned int +lang_hash (const void *key) +{ + const unsigned char *p = key; + unsigned int h = 0; + while (canon_map[*p]) + { + h = (h << 5) - h + canon_map[*p]; + p++; + } + + return h; +} +#endif + + +struct hb_language_item_t { + + struct hb_language_item_t *next; + hb_language_t lang; + + inline bool operator == (const char *s) const { + return lang_equal (lang, s); + } + + inline hb_language_item_t & operator = (const char *s) { + lang = (hb_language_t) strdup (s); + for (unsigned char *p = (unsigned char *) lang; *p; p++) + *p = canon_map[*p]; + + return *this; + } + + void finish (void) { free (lang); } +}; + + +/* Thread-safe lock-free language list */ + +static hb_language_item_t *langs; + +static inline +void free_langs (void) +{ + while (langs) { + hb_language_item_t *next = langs->next; + langs->finish (); + free (langs); + langs = next; + } +} + +static hb_language_item_t * +lang_find_or_insert (const char *key) +{ +retry: + hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs); + + for (hb_language_item_t *lang = first_lang; lang; lang = lang->next) + if (*lang == key) + return lang; + + /* Not found; allocate one. */ + hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t)); + if (unlikely (!lang)) + return NULL; + lang->next = first_lang; + *lang = key; + + if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) { + free (lang); + goto retry; + } + +#ifdef HAVE_ATEXIT + if (!first_lang) + atexit (free_langs); /* First person registers atexit() callback. */ +#endif + + return lang; +} + + +hb_language_t +hb_language_from_string (const char *str, int len) +{ + if (!str || !len || !*str) + return HB_LANGUAGE_INVALID; + + if (len >= 0) { + char strbuf[64]; + len = MIN (len, (int) sizeof (strbuf) - 1); + str = (char *) memcpy (strbuf, str, len); + strbuf[len] = '\0'; + } + + hb_language_item_t *item = lang_find_or_insert (str); + + return likely (item) ? item->lang : HB_LANGUAGE_INVALID; +} + +const char * +hb_language_to_string (hb_language_t language) +{ + /* This is actually NULL-safe! */ + return language->s; +} + +hb_language_t +hb_language_get_default (void) +{ + static hb_language_t default_language = HB_LANGUAGE_INVALID; + + hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language); + if (unlikely (language == HB_LANGUAGE_INVALID)) { + language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1); + hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language); + } + + return default_language; +} + + +/* hb_script_t */ + +hb_script_t +hb_script_from_iso15924_tag (hb_tag_t tag) +{ + if (unlikely (tag == HB_TAG_NONE)) + return HB_SCRIPT_INVALID; + + /* Be lenient, adjust case (one capital letter followed by three small letters) */ + tag = (tag & 0xDFDFDFDF) | 0x00202020; + + switch (tag) { + + /* These graduated from the 'Q' private-area codes, but + * the old code is still aliased by Unicode, and the Qaai + * one in use by ICU. */ + case HB_TAG('Q','a','a','i'): return HB_SCRIPT_INHERITED; + case HB_TAG('Q','a','a','c'): return HB_SCRIPT_COPTIC; + + /* Script variants from http://unicode.org/iso15924/ */ + case HB_TAG('C','y','r','s'): return HB_SCRIPT_CYRILLIC; + case HB_TAG('L','a','t','f'): return HB_SCRIPT_LATIN; + case HB_TAG('L','a','t','g'): return HB_SCRIPT_LATIN; + case HB_TAG('S','y','r','e'): return HB_SCRIPT_SYRIAC; + case HB_TAG('S','y','r','j'): return HB_SCRIPT_SYRIAC; + case HB_TAG('S','y','r','n'): return HB_SCRIPT_SYRIAC; + } + + /* If it looks right, just use the tag as a script */ + if (((uint32_t) tag & 0xE0E0E0E0) == 0x40606060) + return (hb_script_t) tag; + + /* Otherwise, return unknown */ + return HB_SCRIPT_UNKNOWN; +} + +hb_script_t +hb_script_from_string (const char *s, int len) +{ + return hb_script_from_iso15924_tag (hb_tag_from_string (s, len)); +} + +hb_tag_t +hb_script_to_iso15924_tag (hb_script_t script) +{ + return (hb_tag_t) script; +} + +hb_direction_t +hb_script_get_horizontal_direction (hb_script_t script) +{ + /* http://goo.gl/x9ilM */ + switch ((hb_tag_t) script) + { + /* Unicode-1.1 additions */ + case HB_SCRIPT_ARABIC: + case HB_SCRIPT_HEBREW: + + /* Unicode-3.0 additions */ + case HB_SCRIPT_SYRIAC: + case HB_SCRIPT_THAANA: + + /* Unicode-4.0 additions */ + case HB_SCRIPT_CYPRIOT: + + /* Unicode-4.1 additions */ + case HB_SCRIPT_KHAROSHTHI: + + /* Unicode-5.0 additions */ + case HB_SCRIPT_PHOENICIAN: + case HB_SCRIPT_NKO: + + /* Unicode-5.1 additions */ + case HB_SCRIPT_LYDIAN: + + /* Unicode-5.2 additions */ + case HB_SCRIPT_AVESTAN: + case HB_SCRIPT_IMPERIAL_ARAMAIC: + case HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: + case HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: + case HB_SCRIPT_OLD_SOUTH_ARABIAN: + case HB_SCRIPT_OLD_TURKIC: + case HB_SCRIPT_SAMARITAN: + + /* Unicode-6.0 additions */ + case HB_SCRIPT_MANDAIC: + + /* Unicode-6.1 additions */ + case HB_SCRIPT_MEROITIC_CURSIVE: + case HB_SCRIPT_MEROITIC_HIEROGLYPHS: + + return HB_DIRECTION_RTL; + } + + return HB_DIRECTION_LTR; +} + + +/* hb_user_data_array_t */ + +bool +hb_user_data_array_t::set (hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace) +{ + if (!key) + return false; + + if (replace) { + if (!data && !destroy) { + items.remove (key, lock); + return true; + } + } + hb_user_data_item_t item = {key, data, destroy}; + bool ret = !!items.replace_or_insert (item, lock, replace); + + return ret; +} + +void * +hb_user_data_array_t::get (hb_user_data_key_t *key) +{ + hb_user_data_item_t item = {NULL }; + + return items.find (key, &item, lock) ? item.data : NULL; +} + + +/* hb_version */ + +void +hb_version (unsigned int *major, + unsigned int *minor, + unsigned int *micro) +{ + *major = HB_VERSION_MAJOR; + *minor = HB_VERSION_MINOR; + *micro = HB_VERSION_MICRO; +} + +const char * +hb_version_string (void) +{ + return HB_VERSION_STRING; +} + +hb_bool_t +hb_version_check (unsigned int major, + unsigned int minor, + unsigned int micro) +{ + return HB_VERSION_CHECK (major, minor, micro); +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.h b/src/3rdparty/harfbuzz-ng/src/hb-common.h new file mode 100644 index 0000000000..8699bf632e --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-common.h @@ -0,0 +1,336 @@ +/* + * Copyright © 2007,2008,2009 Red Hat, Inc. + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_H_IN +#error "Include instead." +#endif + +#ifndef HB_COMMON_H +#define HB_COMMON_H + +#ifndef HB_BEGIN_DECLS +# ifdef __cplusplus +# define HB_BEGIN_DECLS extern "C" { +# define HB_END_DECLS } +# else /* !__cplusplus */ +# define HB_BEGIN_DECLS +# define HB_END_DECLS +# endif /* !__cplusplus */ +#endif + +#if !defined (HB_DONT_DEFINE_STDINT) + +#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \ + defined (_sgi) || defined (__sun) || defined (sun) || \ + defined (__digital__) || defined (__HP_cc) +# include +#elif defined (_AIX) +# include +/* VS 2010 (_MSC_VER 1600) has stdint.h */ +#elif defined (_MSC_VER) && _MSC_VER < 1600 +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +# include +#endif + +#endif + +HB_BEGIN_DECLS + + +typedef int hb_bool_t; + +typedef uint32_t hb_codepoint_t; +typedef int32_t hb_position_t; +typedef uint32_t hb_mask_t; + +typedef union _hb_var_int_t { + uint32_t u32; + int32_t i32; + uint16_t u16[2]; + int16_t i16[2]; + uint8_t u8[4]; + int8_t i8[4]; +} hb_var_int_t; + + +/* hb_tag_t */ + +typedef uint32_t hb_tag_t; + +#define HB_TAG(a,b,c,d) ((hb_tag_t)((((uint8_t)(a))<<24)|(((uint8_t)(b))<<16)|(((uint8_t)(c))<<8)|((uint8_t)(d)))) +#define HB_UNTAG(tag) ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag)) + +#define HB_TAG_NONE HB_TAG(0,0,0,0) + +/* len=-1 means str is NUL-terminated. */ +hb_tag_t +hb_tag_from_string (const char *str, int len); + +/* buf should have 4 bytes. */ +void +hb_tag_to_string (hb_tag_t tag, char *buf); + + +/* hb_direction_t */ + +typedef enum { + HB_DIRECTION_INVALID = 0, + HB_DIRECTION_LTR = 4, + HB_DIRECTION_RTL, + HB_DIRECTION_TTB, + HB_DIRECTION_BTT +} hb_direction_t; + +/* len=-1 means str is NUL-terminated */ +hb_direction_t +hb_direction_from_string (const char *str, int len); + +const char * +hb_direction_to_string (hb_direction_t direction); + +#define HB_DIRECTION_IS_HORIZONTAL(dir) ((((unsigned int) (dir)) & ~1U) == 4) +#define HB_DIRECTION_IS_VERTICAL(dir) ((((unsigned int) (dir)) & ~1U) == 6) +#define HB_DIRECTION_IS_FORWARD(dir) ((((unsigned int) (dir)) & ~2U) == 4) +#define HB_DIRECTION_IS_BACKWARD(dir) ((((unsigned int) (dir)) & ~2U) == 5) +#define HB_DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4) +#define HB_DIRECTION_REVERSE(dir) ((hb_direction_t) (((unsigned int) (dir)) ^ 1)) /* Direction must be valid */ + + +/* hb_language_t */ + +typedef struct hb_language_impl_t *hb_language_t; + +/* len=-1 means str is NUL-terminated */ +hb_language_t +hb_language_from_string (const char *str, int len); + +const char * +hb_language_to_string (hb_language_t language); + +#define HB_LANGUAGE_INVALID ((hb_language_t) NULL) + +hb_language_t +hb_language_get_default (void); + + +/* hb_script_t */ + +/* http://unicode.org/iso15924/ */ +/* http://goo.gl/x9ilM */ +/* Unicode Character Database property: Script (sc) */ +typedef enum +{ + /*1.1*/ HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), + /*1.1*/ HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), + /*5.0*/ HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), + + /*1.1*/ HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), + /*1.1*/ HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), + /*1.1*/ HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), + /*1.1*/ HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), + /*1.1*/ HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), + /*1.1*/ HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), + /*1.1*/ HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), + /*1.1*/ HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), + /*1.1*/ HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), + /*1.1*/ HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), + /*1.1*/ HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), + /*1.1*/ HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), + /*1.1*/ HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), + /*1.1*/ HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), + /*1.1*/ HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), + /*1.1*/ HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), + /*1.1*/ HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), + /*1.1*/ HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), + /*1.1*/ HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), + /*1.1*/ HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), + /*1.1*/ HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), + /*1.1*/ HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), + + /*2.0*/ HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), + + /*3.0*/ HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), + /*3.0*/ HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), + /*3.0*/ HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), + /*3.0*/ HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), + /*3.0*/ HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), + /*3.0*/ HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), + /*3.0*/ HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), + /*3.0*/ HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), + /*3.0*/ HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), + /*3.0*/ HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), + /*3.0*/ HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), + /*3.0*/ HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), + /*3.0*/ HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), + /*3.0*/ HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), + + /*3.1*/ HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), + /*3.1*/ HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), + /*3.1*/ HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), + + /*3.2*/ HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), + /*3.2*/ HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), + /*3.2*/ HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), + /*3.2*/ HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), + + /*4.0*/ HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), + /*4.0*/ HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), + /*4.0*/ HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), + /*4.0*/ HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), + /*4.0*/ HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), + /*4.0*/ HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), + /*4.0*/ HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), + + /*4.1*/ HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), + /*4.1*/ HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), + /*4.1*/ HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), + /*4.1*/ HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), + /*4.1*/ HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), + /*4.1*/ HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), + /*4.1*/ HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), + /*4.1*/ HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), + + /*5.0*/ HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), + /*5.0*/ HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), + /*5.0*/ HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), + /*5.0*/ HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), + /*5.0*/ HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), + + /*5.1*/ HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), + /*5.1*/ HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), + /*5.1*/ HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), + /*5.1*/ HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), + /*5.1*/ HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), + /*5.1*/ HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), + /*5.1*/ HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), + /*5.1*/ HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), + /*5.1*/ HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), + /*5.1*/ HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), + /*5.1*/ HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), + + /*5.2*/ HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), + /*5.2*/ HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), + /*5.2*/ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), + /*5.2*/ HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), + /*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), + /*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), + /*5.2*/ HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), + /*5.2*/ HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), + /*5.2*/ HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), + /*5.2*/ HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), + /*5.2*/ HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), + /*5.2*/ HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), + /*5.2*/ HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), + /*5.2*/ HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), + /*5.2*/ HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), + + /*6.0*/ HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), + /*6.0*/ HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), + /*6.0*/ HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), + + /*6.1*/ HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), + /*6.1*/ HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), + /*6.1*/ HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), + /*6.1*/ HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), + /*6.1*/ HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), + /*6.1*/ HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), + /*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), + + /* No script set. */ + /*---*/ HB_SCRIPT_INVALID = HB_TAG_NONE +} hb_script_t; + +/* Deprecated misspellings. */ +#define HB_SCRIPT_CANADIAN_ABORIGINAL HB_SCRIPT_CANADIAN_SYLLABICS + +/* These are moved out of hb_script_t because glib-mkenums chokes otherwise. */ +#if 0 + /*7.0*/ HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), + /*7.0*/ HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), + /*7.0*/ HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), + /*7.0*/ HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), + /*7.0*/ HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), + /*7.0*/ HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), + /*7.0*/ HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), + /*7.0*/ HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), + /*7.0*/ HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), + /*7.0*/ HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), + /*7.0*/ HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), + /*7.0*/ HB_SCRIPT_MODI = ??? + /*7.0*/ HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), + /*7.0*/ HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), + /*7.0*/ HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), + /*7.0*/ HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), + /*7.0*/ HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), + /*7.0*/ HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), + /*7.0*/ HB_SCRIPT_PAU_CIN_HAU = ??? + /*7.0*/ HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), + /*7.0*/ HB_SCRIPT_SIDDHAM = ??? + /*7.0*/ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), + /*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), +#endif + + +/* Script functions */ + +hb_script_t +hb_script_from_iso15924_tag (hb_tag_t tag); + +/* suger for tag_from_string() then script_from_iso15924_tag */ +/* len=-1 means s is NUL-terminated */ +hb_script_t +hb_script_from_string (const char *s, int len); + +hb_tag_t +hb_script_to_iso15924_tag (hb_script_t script); + +hb_direction_t +hb_script_get_horizontal_direction (hb_script_t script); + + +/* User data */ + +typedef struct hb_user_data_key_t { + /*< private >*/ + char unused; +} hb_user_data_key_t; + +typedef void (*hb_destroy_func_t) (void *user_data); + + +HB_END_DECLS + +#endif /* HB_COMMON_H */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc new file mode 100644 index 0000000000..1a1fcfbda1 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc @@ -0,0 +1,128 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#define HB_SHAPER fallback +#include "hb-shaper-impl-private.hh" + + +/* + * shaper face data + */ + +struct hb_fallback_shaper_face_data_t {}; + +hb_fallback_shaper_face_data_t * +_hb_fallback_shaper_face_data_create (hb_face_t *face HB_UNUSED) +{ + return (hb_fallback_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED; +} + +void +_hb_fallback_shaper_face_data_destroy (hb_fallback_shaper_face_data_t *data HB_UNUSED) +{ +} + + +/* + * shaper font data + */ + +struct hb_fallback_shaper_font_data_t {}; + +hb_fallback_shaper_font_data_t * +_hb_fallback_shaper_font_data_create (hb_font_t *font HB_UNUSED) +{ + return (hb_fallback_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; +} + +void +_hb_fallback_shaper_font_data_destroy (hb_fallback_shaper_font_data_t *data HB_UNUSED) +{ +} + + +/* + * shaper shape_plan data + */ + +struct hb_fallback_shaper_shape_plan_data_t {}; + +hb_fallback_shaper_shape_plan_data_t * +_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, + const hb_feature_t *user_features HB_UNUSED, + unsigned int num_user_features HB_UNUSED) +{ + return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; +} + +void +_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shaper_shape_plan_data_t *data HB_UNUSED) +{ +} + + +/* + * shaper + */ + +hb_bool_t +_hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, + hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features HB_UNUSED, + unsigned int num_features HB_UNUSED) +{ + hb_codepoint_t space; + font->get_glyph (' ', 0, &space); + + buffer->clear_positions (); + + unsigned int count = buffer->len; + + for (unsigned int i = 0; i < count; i++) + { + if (buffer->unicode->is_default_ignorable (buffer->info[i].codepoint)) { + buffer->info[i].codepoint = space; + buffer->pos[i].x_advance = 0; + buffer->pos[i].y_advance = 0; + continue; + } + font->get_glyph (buffer->info[i].codepoint, 0, &buffer->info[i].codepoint); + font->get_glyph_advance_for_direction (buffer->info[i].codepoint, + buffer->props.direction, + &buffer->pos[i].x_advance, + &buffer->pos[i].y_advance); + font->subtract_glyph_origin_for_direction (buffer->info[i].codepoint, + buffer->props.direction, + &buffer->pos[i].x_offset, + &buffer->pos[i].y_offset); + } + + if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + hb_buffer_reverse (buffer); + + return true; +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh new file mode 100644 index 0000000000..acea1d724e --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh @@ -0,0 +1,478 @@ +/* + * Copyright © 2009 Red Hat, Inc. + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_FONT_PRIVATE_HH +#define HB_FONT_PRIVATE_HH + +#include "hb-private.hh" + +#include "hb-font.h" +#include "hb-object-private.hh" +#include "hb-shaper-private.hh" +#include "hb-shape-plan-private.hh" + + + +/* + * hb_font_funcs_t + */ + +#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ + HB_FONT_FUNC_IMPLEMENT (glyph) \ + HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ + HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ + HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \ + HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \ + HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \ + HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \ + HB_FONT_FUNC_IMPLEMENT (glyph_extents) \ + HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \ + HB_FONT_FUNC_IMPLEMENT (glyph_name) \ + HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \ + /* ^--- Add new callbacks here */ + +struct hb_font_funcs_t { + hb_object_header_t header; + ASSERT_POD (); + + hb_bool_t immutable; + + /* Don't access these directly. Call hb_font_get_*() instead. */ + + struct { +#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + } get; + + struct { +#define HB_FONT_FUNC_IMPLEMENT(name) void *name; + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + } user_data; + + struct { +#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name; + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + } destroy; +}; + + +/* + * hb_face_t + */ + +struct hb_face_t { + hb_object_header_t header; + ASSERT_POD (); + + hb_bool_t immutable; + + hb_reference_table_func_t reference_table_func; + void *user_data; + hb_destroy_func_t destroy; + + unsigned int index; + mutable unsigned int upem; + mutable unsigned int num_glyphs; + + struct hb_shaper_data_t shaper_data; + + struct plan_node_t { + hb_shape_plan_t *shape_plan; + plan_node_t *next; + } *shape_plans; + + + inline hb_blob_t *reference_table (hb_tag_t tag) const + { + hb_blob_t *blob; + + if (unlikely (!this || !reference_table_func)) + return hb_blob_get_empty (); + + blob = reference_table_func (/*XXX*/const_cast (this), tag, user_data); + if (unlikely (!blob)) + return hb_blob_get_empty (); + + return blob; + } + + inline HB_PURE_FUNC unsigned int get_upem (void) const + { + if (unlikely (!upem)) + load_upem (); + return upem; + } + + inline unsigned int get_num_glyphs (void) const + { + if (unlikely (num_glyphs == (unsigned int) -1)) + load_num_glyphs (); + return num_glyphs; + } + + private: + HB_INTERNAL void load_upem (void) const; + HB_INTERNAL void load_num_glyphs (void) const; +}; + +#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS +#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face); +#include "hb-shaper-list.hh" +#undef HB_SHAPER_IMPLEMENT +#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS + + +/* + * hb_font_t + */ + +struct hb_font_t { + hb_object_header_t header; + ASSERT_POD (); + + hb_bool_t immutable; + + hb_font_t *parent; + hb_face_t *face; + + int x_scale; + int y_scale; + + unsigned int x_ppem; + unsigned int y_ppem; + + hb_font_funcs_t *klass; + void *user_data; + hb_destroy_func_t destroy; + + struct hb_shaper_data_t shaper_data; + + + /* Convert from font-space to user-space */ + inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); } + inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); } + + /* Convert from parent-font user-space to our user-space */ + inline hb_position_t parent_scale_x_distance (hb_position_t v) { + if (unlikely (parent && parent->x_scale != x_scale)) + return v * (int64_t) this->x_scale / this->parent->x_scale; + return v; + } + inline hb_position_t parent_scale_y_distance (hb_position_t v) { + if (unlikely (parent && parent->y_scale != y_scale)) + return v * (int64_t) this->y_scale / this->parent->y_scale; + return v; + } + inline hb_position_t parent_scale_x_position (hb_position_t v) { + return parent_scale_x_distance (v); + } + inline hb_position_t parent_scale_y_position (hb_position_t v) { + return parent_scale_y_distance (v); + } + + inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) { + *x = parent_scale_x_distance (*x); + *y = parent_scale_y_distance (*y); + } + inline void parent_scale_position (hb_position_t *x, hb_position_t *y) { + *x = parent_scale_x_position (*x); + *y = parent_scale_y_position (*y); + } + + + /* Public getters */ + + inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph) + { + *glyph = 0; + return klass->get.glyph (this, user_data, + unicode, variation_selector, glyph, + klass->user_data.glyph); + } + + inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) + { + return klass->get.glyph_h_advance (this, user_data, + glyph, + klass->user_data.glyph_h_advance); + } + + inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) + { + return klass->get.glyph_v_advance (this, user_data, + glyph, + klass->user_data.glyph_v_advance); + } + + inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + *x = *y = 0; + return klass->get.glyph_h_origin (this, user_data, + glyph, x, y, + klass->user_data.glyph_h_origin); + } + + inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + *x = *y = 0; + return klass->get.glyph_v_origin (this, user_data, + glyph, x, y, + klass->user_data.glyph_v_origin); + } + + inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) + { + return klass->get.glyph_h_kerning (this, user_data, + left_glyph, right_glyph, + klass->user_data.glyph_h_kerning); + } + + inline hb_position_t get_glyph_v_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) + { + return klass->get.glyph_v_kerning (this, user_data, + left_glyph, right_glyph, + klass->user_data.glyph_v_kerning); + } + + inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph, + hb_glyph_extents_t *extents) + { + memset (extents, 0, sizeof (*extents)); + return klass->get.glyph_extents (this, user_data, + glyph, + extents, + klass->user_data.glyph_extents); + } + + inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, + hb_position_t *x, hb_position_t *y) + { + *x = *y = 0; + return klass->get.glyph_contour_point (this, user_data, + glyph, point_index, + x, y, + klass->user_data.glyph_contour_point); + } + + inline hb_bool_t get_glyph_name (hb_codepoint_t glyph, + char *name, unsigned int size) + { + if (size) *name = '\0'; + return klass->get.glyph_name (this, user_data, + glyph, + name, size, + klass->user_data.glyph_name); + } + + inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph) + { + *glyph = 0; + if (len == -1) len = strlen (name); + return klass->get.glyph_from_name (this, user_data, + name, len, + glyph, + klass->user_data.glyph_from_name); + } + + + /* A bit higher-level, and with fallback */ + + inline void get_glyph_advance_for_direction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) + { + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { + *x = get_glyph_h_advance (glyph); + *y = 0; + } else { + *x = 0; + *y = get_glyph_v_advance (glyph); + } + } + + /* Internal only */ + inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + *x = get_glyph_h_advance (glyph) / 2; + + /* TODO use font_metics.ascent */ + *y = y_scale; + } + + inline void get_glyph_origin_for_direction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) + { + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) + { + if (!get_glyph_h_origin (glyph, x, y) && + get_glyph_v_origin (glyph, x, y)) + { + hb_position_t dx, dy; + guess_v_origin_minus_h_origin (glyph, &dx, &dy); + *x -= dx; *y -= dy; + } + } + else + { + if (!get_glyph_v_origin (glyph, x, y) && + get_glyph_h_origin (glyph, x, y)) + { + hb_position_t dx, dy; + guess_v_origin_minus_h_origin (glyph, &dx, &dy); + *x += dx; *y += dy; + } + } + } + + inline void add_glyph_origin_for_direction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) + { + hb_position_t origin_x, origin_y; + + get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); + + *x += origin_x; + *y += origin_y; + } + + inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) + { + hb_position_t origin_x, origin_y; + + get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); + + *x -= origin_x; + *y -= origin_y; + } + + inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) + { + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { + *x = get_glyph_h_kerning (first_glyph, second_glyph); + *y = 0; + } else { + *x = 0; + *y = get_glyph_v_kerning (first_glyph, second_glyph); + } + } + + inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph, + hb_direction_t direction, + hb_glyph_extents_t *extents) + { + hb_bool_t ret = get_glyph_extents (glyph, extents); + + if (ret) + subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing); + + return ret; + } + + inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) + { + hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y); + + if (ret) + subtract_glyph_origin_for_direction (glyph, direction, x, y); + + return ret; + } + + /* Generates gidDDD if glyph has no name. */ + inline void + glyph_to_string (hb_codepoint_t glyph, + char *s, unsigned int size) + { + if (get_glyph_name (glyph, s, size)) return; + + snprintf (s, size, "gid%u", glyph); + } + + /* Parses gidDDD and uniUUUU strings automatically. */ + inline hb_bool_t + glyph_from_string (const char *s, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph) + { + if (get_glyph_from_name (s, len, glyph)) return true; + + if (len == -1) len = strlen (s); + + /* Straight glyph index. */ + if (hb_codepoint_parse (s, len, 10, glyph)) + return true; + + if (len > 3) + { + /* gidDDD syntax for glyph indices. */ + if (0 == strncmp (s, "gid", 3) && + hb_codepoint_parse (s + 3, len - 3, 10, glyph)) + return true; + + /* uniUUUU and other Unicode character indices. */ + hb_codepoint_t unichar; + if (0 == strncmp (s, "uni", 3) && + hb_codepoint_parse (s + 3, len - 3, 16, &unichar) && + get_glyph (unichar, 0, glyph)) + return true; + } + + return false; + } + + private: + inline hb_position_t em_scale (int16_t v, int scale) + { + unsigned int upem = face->get_upem (); + return (v * (int64_t) scale + upem / 2) / upem; + } +}; + +#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS +#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font); +#include "hb-shaper-list.hh" +#undef HB_SHAPER_IMPLEMENT +#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS + + +#endif /* HB_FONT_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-font.cc new file mode 100644 index 0000000000..b59fdebaea --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-font.cc @@ -0,0 +1,1008 @@ +/* + * Copyright © 2009 Red Hat, Inc. + * Copyright © 2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-private.hh" + +#include "hb-ot-layout-private.hh" + +#include "hb-font-private.hh" +#include "hb-blob.h" +#include "hb-open-file-private.hh" +#include "hb-ot-head-table.hh" +#include "hb-ot-maxp-table.hh" + +#include "hb-cache-private.hh" + +#include + + + +/* + * hb_font_funcs_t + */ + +static hb_bool_t +hb_font_get_glyph_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + if (font->parent) + return font->parent->get_glyph (unicode, variation_selector, glyph); + + *glyph = 0; + return false; +} + +static hb_position_t +hb_font_get_glyph_h_advance_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) +{ + if (font->parent) + return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); + + return font->x_scale; +} + +static hb_position_t +hb_font_get_glyph_v_advance_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) +{ + if (font->parent) + return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); + + return font->y_scale; +} + +static hb_bool_t +hb_font_get_glyph_h_origin_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + if (font->parent) { + hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y); + if (ret) + font->parent_scale_position (x, y); + return ret; + } + + *x = *y = 0; + return false; +} + +static hb_bool_t +hb_font_get_glyph_v_origin_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + if (font->parent) { + hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y); + if (ret) + font->parent_scale_position (x, y); + return ret; + } + + *x = *y = 0; + return false; +} + +static hb_position_t +hb_font_get_glyph_h_kerning_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t left_glyph, + hb_codepoint_t right_glyph, + void *user_data HB_UNUSED) +{ + if (font->parent) + return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph)); + + return 0; +} + +static hb_position_t +hb_font_get_glyph_v_kerning_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t top_glyph, + hb_codepoint_t bottom_glyph, + void *user_data HB_UNUSED) +{ + if (font->parent) + return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph)); + + return 0; +} + +static hb_bool_t +hb_font_get_glyph_extents_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + void *user_data HB_UNUSED) +{ + if (font->parent) { + hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); + if (ret) { + font->parent_scale_position (&extents->x_bearing, &extents->y_bearing); + font->parent_scale_distance (&extents->width, &extents->height); + } + return ret; + } + + memset (extents, 0, sizeof (*extents)); + return false; +} + +static hb_bool_t +hb_font_get_glyph_contour_point_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + unsigned int point_index, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + if (font->parent) { + hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); + if (ret) + font->parent_scale_position (x, y); + return ret; + } + + *x = *y = 0; + return false; +} + +static hb_bool_t +hb_font_get_glyph_name_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + char *name, unsigned int size, + void *user_data HB_UNUSED) +{ + if (font->parent) + return font->parent->get_glyph_name (glyph, name, size); + + if (size) *name = '\0'; + return false; +} + +static hb_bool_t +hb_font_get_glyph_from_name_nil (hb_font_t *font, + void *font_data HB_UNUSED, + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + if (font->parent) + return font->parent->get_glyph_from_name (name, len, glyph); + + *glyph = 0; + return false; +} + + +static const hb_font_funcs_t _hb_font_funcs_nil = { + HB_OBJECT_HEADER_STATIC, + + true, /* immutable */ + + { +#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil, + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + } +}; + + +hb_font_funcs_t * +hb_font_funcs_create (void) +{ + hb_font_funcs_t *ffuncs; + + if (!(ffuncs = hb_object_create ())) + return hb_font_funcs_get_empty (); + + ffuncs->get = _hb_font_funcs_nil.get; + + return ffuncs; +} + +hb_font_funcs_t * +hb_font_funcs_get_empty (void) +{ + return const_cast (&_hb_font_funcs_nil); +} + +hb_font_funcs_t * +hb_font_funcs_reference (hb_font_funcs_t *ffuncs) +{ + return hb_object_reference (ffuncs); +} + +void +hb_font_funcs_destroy (hb_font_funcs_t *ffuncs) +{ + if (!hb_object_destroy (ffuncs)) return; + +#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \ + ffuncs->destroy.name (ffuncs->user_data.name); + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + + free (ffuncs); +} + +hb_bool_t +hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace) +{ + return hb_object_set_user_data (ffuncs, key, data, destroy, replace); +} + +void * +hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, + hb_user_data_key_t *key) +{ + return hb_object_get_user_data (ffuncs, key); +} + + +void +hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) +{ + if (hb_object_is_inert (ffuncs)) + return; + + ffuncs->immutable = true; +} + +hb_bool_t +hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs) +{ + return ffuncs->immutable; +} + + +#define HB_FONT_FUNC_IMPLEMENT(name) \ + \ +void \ +hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \ + hb_font_get_##name##_func_t func, \ + void *user_data, \ + hb_destroy_func_t destroy) \ +{ \ + if (ffuncs->immutable) { \ + if (destroy) \ + destroy (user_data); \ + return; \ + } \ + \ + if (ffuncs->destroy.name) \ + ffuncs->destroy.name (ffuncs->user_data.name); \ + \ + if (func) { \ + ffuncs->get.name = func; \ + ffuncs->user_data.name = user_data; \ + ffuncs->destroy.name = destroy; \ + } else { \ + ffuncs->get.name = hb_font_get_##name##_nil; \ + ffuncs->user_data.name = NULL; \ + ffuncs->destroy.name = NULL; \ + } \ +} + +HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + + +/* Public getters */ + +hb_bool_t +hb_font_get_glyph (hb_font_t *font, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph) +{ + return font->get_glyph (unicode, variation_selector, glyph); +} + +hb_position_t +hb_font_get_glyph_h_advance (hb_font_t *font, + hb_codepoint_t glyph) +{ + return font->get_glyph_h_advance (glyph); +} + +hb_position_t +hb_font_get_glyph_v_advance (hb_font_t *font, + hb_codepoint_t glyph) +{ + return font->get_glyph_v_advance (glyph); +} + +hb_bool_t +hb_font_get_glyph_h_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) +{ + return font->get_glyph_h_origin (glyph, x, y); +} + +hb_bool_t +hb_font_get_glyph_v_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) +{ + return font->get_glyph_v_origin (glyph, x, y); +} + +hb_position_t +hb_font_get_glyph_h_kerning (hb_font_t *font, + hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) +{ + return font->get_glyph_h_kerning (left_glyph, right_glyph); +} + +hb_position_t +hb_font_get_glyph_v_kerning (hb_font_t *font, + hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) +{ + return font->get_glyph_v_kerning (left_glyph, right_glyph); +} + +hb_bool_t +hb_font_get_glyph_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents) +{ + return font->get_glyph_extents (glyph, extents); +} + +hb_bool_t +hb_font_get_glyph_contour_point (hb_font_t *font, + hb_codepoint_t glyph, unsigned int point_index, + hb_position_t *x, hb_position_t *y) +{ + return font->get_glyph_contour_point (glyph, point_index, x, y); +} + +hb_bool_t +hb_font_get_glyph_name (hb_font_t *font, + hb_codepoint_t glyph, + char *name, unsigned int size) +{ + return font->get_glyph_name (glyph, name, size); +} + +hb_bool_t +hb_font_get_glyph_from_name (hb_font_t *font, + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph) +{ + return font->get_glyph_from_name (name, len, glyph); +} + + +/* A bit higher-level, and with fallback */ + +void +hb_font_get_glyph_advance_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) +{ + return font->get_glyph_advance_for_direction (glyph, direction, x, y); +} + +void +hb_font_get_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) +{ + return font->get_glyph_origin_for_direction (glyph, direction, x, y); +} + +void +hb_font_add_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) +{ + return font->add_glyph_origin_for_direction (glyph, direction, x, y); +} + +void +hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) +{ + return font->subtract_glyph_origin_for_direction (glyph, direction, x, y); +} + +void +hb_font_get_glyph_kerning_for_direction (hb_font_t *font, + hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) +{ + return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y); +} + +hb_bool_t +hb_font_get_glyph_extents_for_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_glyph_extents_t *extents) +{ + return font->get_glyph_extents_for_origin (glyph, direction, extents); +} + +hb_bool_t +hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, + hb_codepoint_t glyph, unsigned int point_index, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) +{ + return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y); +} + +/* Generates gidDDD if glyph has no name. */ +void +hb_font_glyph_to_string (hb_font_t *font, + hb_codepoint_t glyph, + char *s, unsigned int size) +{ + font->glyph_to_string (glyph, s, size); +} + +/* Parses gidDDD and uniUUUU strings automatically. */ +hb_bool_t +hb_font_glyph_from_string (hb_font_t *font, + const char *s, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph) +{ + return font->glyph_from_string (s, len, glyph); +} + + +/* + * hb_face_t + */ + +static const hb_face_t _hb_face_nil = { + HB_OBJECT_HEADER_STATIC, + + true, /* immutable */ + + NULL, /* reference_table_func */ + NULL, /* user_data */ + NULL, /* destroy */ + + 0, /* index */ + 1000, /* upem */ + 0, /* num_glyphs */ + + { +#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, +#include "hb-shaper-list.hh" +#undef HB_SHAPER_IMPLEMENT + }, + + NULL, /* shape_plans */ +}; + + +hb_face_t * +hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, + void *user_data, + hb_destroy_func_t destroy) +{ + hb_face_t *face; + + if (!reference_table_func || !(face = hb_object_create ())) { + if (destroy) + destroy (user_data); + return hb_face_get_empty (); + } + + face->reference_table_func = reference_table_func; + face->user_data = user_data; + face->destroy = destroy; + + face->upem = 0; + face->num_glyphs = (unsigned int) -1; + + return face; +} + + +typedef struct hb_face_for_data_closure_t { + hb_blob_t *blob; + unsigned int index; +} hb_face_for_data_closure_t; + +static hb_face_for_data_closure_t * +_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index) +{ + hb_face_for_data_closure_t *closure; + + closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t)); + if (unlikely (!closure)) + return NULL; + + closure->blob = blob; + closure->index = index; + + return closure; +} + +static void +_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure) +{ + hb_blob_destroy (closure->blob); + free (closure); +} + +static hb_blob_t * +_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) +{ + hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data; + + if (tag == HB_TAG_NONE) + return hb_blob_reference (data->blob); + + const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer::lock_instance (data->blob); + const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); + + const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag); + + hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length); + + return blob; +} + +hb_face_t * +hb_face_create (hb_blob_t *blob, + unsigned int index) +{ + hb_face_t *face; + + if (unlikely (!blob || !hb_blob_get_length (blob))) + return hb_face_get_empty (); + + hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer::sanitize (hb_blob_reference (blob)), index); + + if (unlikely (!closure)) + return hb_face_get_empty (); + + face = hb_face_create_for_tables (_hb_face_for_data_reference_table, + closure, + (hb_destroy_func_t) _hb_face_for_data_closure_destroy); + + hb_face_set_index (face, index); + + return face; +} + +hb_face_t * +hb_face_get_empty (void) +{ + return const_cast (&_hb_face_nil); +} + + +hb_face_t * +hb_face_reference (hb_face_t *face) +{ + return hb_object_reference (face); +} + +void +hb_face_destroy (hb_face_t *face) +{ + if (!hb_object_destroy (face)) return; + + for (hb_face_t::plan_node_t *node = face->shape_plans; node; ) + { + hb_face_t::plan_node_t *next = node->next; + hb_shape_plan_destroy (node->shape_plan); + free (node); + node = next; + } + +#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face); +#include "hb-shaper-list.hh" +#undef HB_SHAPER_IMPLEMENT + + if (face->destroy) + face->destroy (face->user_data); + + free (face); +} + +hb_bool_t +hb_face_set_user_data (hb_face_t *face, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace) +{ + return hb_object_set_user_data (face, key, data, destroy, replace); +} + +void * +hb_face_get_user_data (hb_face_t *face, + hb_user_data_key_t *key) +{ + return hb_object_get_user_data (face, key); +} + +void +hb_face_make_immutable (hb_face_t *face) +{ + if (hb_object_is_inert (face)) + return; + + face->immutable = true; +} + +hb_bool_t +hb_face_is_immutable (hb_face_t *face) +{ + return face->immutable; +} + + +hb_blob_t * +hb_face_reference_table (hb_face_t *face, + hb_tag_t tag) +{ + return face->reference_table (tag); +} + +hb_blob_t * +hb_face_reference_blob (hb_face_t *face) +{ + return face->reference_table (HB_TAG_NONE); +} + +void +hb_face_set_index (hb_face_t *face, + unsigned int index) +{ + if (hb_object_is_inert (face)) + return; + + face->index = index; +} + +unsigned int +hb_face_get_index (hb_face_t *face) +{ + return face->index; +} + +void +hb_face_set_upem (hb_face_t *face, + unsigned int upem) +{ + if (hb_object_is_inert (face)) + return; + + face->upem = upem; +} + +unsigned int +hb_face_get_upem (hb_face_t *face) +{ + return face->get_upem (); +} + +void +hb_face_t::load_upem (void) const +{ + hb_blob_t *head_blob = OT::Sanitizer::sanitize (reference_table (HB_OT_TAG_head)); + const OT::head *head_table = OT::Sanitizer::lock_instance (head_blob); + upem = head_table->get_upem (); + hb_blob_destroy (head_blob); +} + +void +hb_face_set_glyph_count (hb_face_t *face, + unsigned int glyph_count) +{ + if (hb_object_is_inert (face)) + return; + + face->num_glyphs = glyph_count; +} + +unsigned int +hb_face_get_glyph_count (hb_face_t *face) +{ + return face->get_num_glyphs (); +} + +void +hb_face_t::load_num_glyphs (void) const +{ + hb_blob_t *maxp_blob = OT::Sanitizer::sanitize (reference_table (HB_OT_TAG_maxp)); + const OT::maxp *maxp_table = OT::Sanitizer::lock_instance (maxp_blob); + num_glyphs = maxp_table->get_num_glyphs (); + hb_blob_destroy (maxp_blob); +} + + +/* + * hb_font_t + */ + +hb_font_t * +hb_font_create (hb_face_t *face) +{ + hb_font_t *font; + + if (unlikely (!face)) + face = hb_face_get_empty (); + if (unlikely (hb_object_is_inert (face))) + return hb_font_get_empty (); + if (!(font = hb_object_create ())) + return hb_font_get_empty (); + + hb_face_make_immutable (face); + font->face = hb_face_reference (face); + font->klass = hb_font_funcs_get_empty (); + + return font; +} + +hb_font_t * +hb_font_create_sub_font (hb_font_t *parent) +{ + if (unlikely (!parent)) + return hb_font_get_empty (); + + hb_font_t *font = hb_font_create (parent->face); + + if (unlikely (hb_object_is_inert (font))) + return font; + + hb_font_make_immutable (parent); + font->parent = hb_font_reference (parent); + + font->x_scale = parent->x_scale; + font->y_scale = parent->y_scale; + font->x_ppem = parent->x_ppem; + font->y_ppem = parent->y_ppem; + + return font; +} + +hb_font_t * +hb_font_get_empty (void) +{ + static const hb_font_t _hb_font_nil = { + HB_OBJECT_HEADER_STATIC, + + true, /* immutable */ + + NULL, /* parent */ + const_cast (&_hb_face_nil), + + 0, /* x_scale */ + 0, /* y_scale */ + + 0, /* x_ppem */ + 0, /* y_ppem */ + + const_cast (&_hb_font_funcs_nil), /* klass */ + NULL, /* user_data */ + NULL, /* destroy */ + + { +#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, +#include "hb-shaper-list.hh" +#undef HB_SHAPER_IMPLEMENT + } + }; + + return const_cast (&_hb_font_nil); +} + +hb_font_t * +hb_font_reference (hb_font_t *font) +{ + return hb_object_reference (font); +} + +void +hb_font_destroy (hb_font_t *font) +{ + if (!hb_object_destroy (font)) return; + +#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font); +#include "hb-shaper-list.hh" +#undef HB_SHAPER_IMPLEMENT + + if (font->destroy) + font->destroy (font->user_data); + + hb_font_destroy (font->parent); + hb_face_destroy (font->face); + hb_font_funcs_destroy (font->klass); + + free (font); +} + +hb_bool_t +hb_font_set_user_data (hb_font_t *font, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace) +{ + return hb_object_set_user_data (font, key, data, destroy, replace); +} + +void * +hb_font_get_user_data (hb_font_t *font, + hb_user_data_key_t *key) +{ + return hb_object_get_user_data (font, key); +} + +void +hb_font_make_immutable (hb_font_t *font) +{ + if (hb_object_is_inert (font)) + return; + + font->immutable = true; +} + +hb_bool_t +hb_font_is_immutable (hb_font_t *font) +{ + return font->immutable; +} + +hb_font_t * +hb_font_get_parent (hb_font_t *font) +{ + return font->parent; +} + +hb_face_t * +hb_font_get_face (hb_font_t *font) +{ + return font->face; +} + + +void +hb_font_set_funcs (hb_font_t *font, + hb_font_funcs_t *klass, + void *user_data, + hb_destroy_func_t destroy) +{ + if (font->immutable) { + if (destroy) + destroy (user_data); + return; + } + + if (font->destroy) + font->destroy (font->user_data); + + if (!klass) + klass = hb_font_funcs_get_empty (); + + hb_font_funcs_reference (klass); + hb_font_funcs_destroy (font->klass); + font->klass = klass; + font->user_data = user_data; + font->destroy = destroy; +} + +void +hb_font_set_funcs_data (hb_font_t *font, + void *user_data, + hb_destroy_func_t destroy) +{ + /* Destroy user_data? */ + if (font->immutable) { + if (destroy) + destroy (user_data); + return; + } + + if (font->destroy) + font->destroy (font->user_data); + + font->user_data = user_data; + font->destroy = destroy; +} + + +void +hb_font_set_scale (hb_font_t *font, + int x_scale, + int y_scale) +{ + if (font->immutable) + return; + + font->x_scale = x_scale; + font->y_scale = y_scale; +} + +void +hb_font_get_scale (hb_font_t *font, + int *x_scale, + int *y_scale) +{ + if (x_scale) *x_scale = font->x_scale; + if (y_scale) *y_scale = font->y_scale; +} + +void +hb_font_set_ppem (hb_font_t *font, + unsigned int x_ppem, + unsigned int y_ppem) +{ + if (font->immutable) + return; + + font->x_ppem = x_ppem; + font->y_ppem = y_ppem; +} + +void +hb_font_get_ppem (hb_font_t *font, + unsigned int *x_ppem, + unsigned int *y_ppem) +{ + if (x_ppem) *x_ppem = font->x_ppem; + if (y_ppem) *y_ppem = font->y_ppem; +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.h b/src/3rdparty/harfbuzz-ng/src/hb-font.h new file mode 100644 index 0000000000..88d489551e --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-font.h @@ -0,0 +1,454 @@ +/* + * Copyright © 2009 Red Hat, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + */ + +#ifndef HB_H_IN +#error "Include instead." +#endif + +#ifndef HB_FONT_H +#define HB_FONT_H + +#include "hb-common.h" +#include "hb-blob.h" + +HB_BEGIN_DECLS + + +typedef struct hb_face_t hb_face_t; +typedef struct hb_font_t hb_font_t; + +/* + * hb_face_t + */ + +hb_face_t * +hb_face_create (hb_blob_t *blob, + unsigned int index); + +typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag, void *user_data); + +/* calls destroy() when not needing user_data anymore */ +hb_face_t * +hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, + void *user_data, + hb_destroy_func_t destroy); + +hb_face_t * +hb_face_get_empty (void); + +hb_face_t * +hb_face_reference (hb_face_t *face); + +void +hb_face_destroy (hb_face_t *face); + +hb_bool_t +hb_face_set_user_data (hb_face_t *face, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + + +void * +hb_face_get_user_data (hb_face_t *face, + hb_user_data_key_t *key); + +void +hb_face_make_immutable (hb_face_t *face); + +hb_bool_t +hb_face_is_immutable (hb_face_t *face); + + +hb_blob_t * +hb_face_reference_table (hb_face_t *face, + hb_tag_t tag); + +hb_blob_t * +hb_face_reference_blob (hb_face_t *face); + +void +hb_face_set_index (hb_face_t *face, + unsigned int index); + +unsigned int +hb_face_get_index (hb_face_t *face); + +void +hb_face_set_upem (hb_face_t *face, + unsigned int upem); + +unsigned int +hb_face_get_upem (hb_face_t *face); + +void +hb_face_set_glyph_count (hb_face_t *face, + unsigned int glyph_count); + +unsigned int +hb_face_get_glyph_count (hb_face_t *face); + + +/* + * hb_font_funcs_t + */ + +typedef struct hb_font_funcs_t hb_font_funcs_t; + +hb_font_funcs_t * +hb_font_funcs_create (void); + +hb_font_funcs_t * +hb_font_funcs_get_empty (void); + +hb_font_funcs_t * +hb_font_funcs_reference (hb_font_funcs_t *ffuncs); + +void +hb_font_funcs_destroy (hb_font_funcs_t *ffuncs); + +hb_bool_t +hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + + +void * +hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, + hb_user_data_key_t *key); + + +void +hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs); + +hb_bool_t +hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs); + + +/* glyph extents */ + +typedef struct hb_glyph_extents_t +{ + hb_position_t x_bearing; + hb_position_t y_bearing; + hb_position_t width; + hb_position_t height; +} hb_glyph_extents_t; + + +/* func types */ + +typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data); + + +typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + void *user_data); +typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t; +typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t; + +typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y, + void *user_data); +typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t; +typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t; + +typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, + void *user_data); +typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t; +typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t; + + +typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + void *user_data); +typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, unsigned int point_index, + hb_position_t *x, hb_position_t *y, + void *user_data); + + +typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + char *name, unsigned int size, + void *user_data); +typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data, + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph, + void *user_data); + + +/* func setters */ + +void +hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_func_t glyph_func, + void *user_data, hb_destroy_func_t destroy); + +void +hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_advance_func_t func, + void *user_data, hb_destroy_func_t destroy); +void +hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_advance_func_t func, + void *user_data, hb_destroy_func_t destroy); + +void +hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_origin_func_t func, + void *user_data, hb_destroy_func_t destroy); +void +hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_origin_func_t func, + void *user_data, hb_destroy_func_t destroy); + +void +hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_kerning_func_t func, + void *user_data, hb_destroy_func_t destroy); +void +hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_kerning_func_t func, + void *user_data, hb_destroy_func_t destroy); + +void +hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_extents_func_t func, + void *user_data, hb_destroy_func_t destroy); +void +hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_contour_point_func_t func, + void *user_data, hb_destroy_func_t destroy); + +void +hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_name_func_t glyph_func, + void *user_data, hb_destroy_func_t destroy); +void +hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_from_name_func_t glyph_func, + void *user_data, hb_destroy_func_t destroy); + + +/* func dispatch */ + +hb_bool_t +hb_font_get_glyph (hb_font_t *font, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph); + +hb_position_t +hb_font_get_glyph_h_advance (hb_font_t *font, + hb_codepoint_t glyph); +hb_position_t +hb_font_get_glyph_v_advance (hb_font_t *font, + hb_codepoint_t glyph); + +hb_bool_t +hb_font_get_glyph_h_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y); +hb_bool_t +hb_font_get_glyph_v_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y); + +hb_position_t +hb_font_get_glyph_h_kerning (hb_font_t *font, + hb_codepoint_t left_glyph, hb_codepoint_t right_glyph); +hb_position_t +hb_font_get_glyph_v_kerning (hb_font_t *font, + hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); + +hb_bool_t +hb_font_get_glyph_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents); + +hb_bool_t +hb_font_get_glyph_contour_point (hb_font_t *font, + hb_codepoint_t glyph, unsigned int point_index, + hb_position_t *x, hb_position_t *y); + +hb_bool_t +hb_font_get_glyph_name (hb_font_t *font, + hb_codepoint_t glyph, + char *name, unsigned int size); +hb_bool_t +hb_font_get_glyph_from_name (hb_font_t *font, + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph); + + +/* high-level funcs, with fallback */ + +void +hb_font_get_glyph_advance_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); +void +hb_font_get_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); +void +hb_font_add_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); +void +hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); + +void +hb_font_get_glyph_kerning_for_direction (hb_font_t *font, + hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); + +hb_bool_t +hb_font_get_glyph_extents_for_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_glyph_extents_t *extents); + +hb_bool_t +hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, + hb_codepoint_t glyph, unsigned int point_index, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); + +/* Generates gidDDD if glyph has no name. */ +void +hb_font_glyph_to_string (hb_font_t *font, + hb_codepoint_t glyph, + char *s, unsigned int size); +/* Parses gidDDD and uniUUUU strings automatically. */ +hb_bool_t +hb_font_glyph_from_string (hb_font_t *font, + const char *s, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph); + + +/* + * hb_font_t + */ + +/* Fonts are very light-weight objects */ + +hb_font_t * +hb_font_create (hb_face_t *face); + +hb_font_t * +hb_font_create_sub_font (hb_font_t *parent); + +hb_font_t * +hb_font_get_empty (void); + +hb_font_t * +hb_font_reference (hb_font_t *font); + +void +hb_font_destroy (hb_font_t *font); + +hb_bool_t +hb_font_set_user_data (hb_font_t *font, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + + +void * +hb_font_get_user_data (hb_font_t *font, + hb_user_data_key_t *key); + +void +hb_font_make_immutable (hb_font_t *font); + +hb_bool_t +hb_font_is_immutable (hb_font_t *font); + +hb_font_t * +hb_font_get_parent (hb_font_t *font); + +hb_face_t * +hb_font_get_face (hb_font_t *font); + + +void +hb_font_set_funcs (hb_font_t *font, + hb_font_funcs_t *klass, + void *font_data, + hb_destroy_func_t destroy); + +/* Be *very* careful with this function! */ +void +hb_font_set_funcs_data (hb_font_t *font, + void *font_data, + hb_destroy_func_t destroy); + + +void +hb_font_set_scale (hb_font_t *font, + int x_scale, + int y_scale); + +void +hb_font_get_scale (hb_font_t *font, + int *x_scale, + int *y_scale); + +/* + * A zero value means "no hinting in that direction" + */ +void +hb_font_set_ppem (hb_font_t *font, + unsigned int x_ppem, + unsigned int y_ppem); + +void +hb_font_get_ppem (hb_font_t *font, + unsigned int *x_ppem, + unsigned int *y_ppem); + + +HB_END_DECLS + +#endif /* HB_FONT_H */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh new file mode 100644 index 0000000000..0fb21c2e86 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh @@ -0,0 +1,130 @@ +/* + * Copyright © 2007 Chris Wilson + * Copyright © 2009,2010 Red Hat, Inc. + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Contributor(s): + * Chris Wilson + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_MUTEX_PRIVATE_HH +#define HB_MUTEX_PRIVATE_HH + +#include "hb-private.hh" + + +/* mutex */ + +/* We need external help for these */ + +#if 0 + + +#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) + +#define WIN32_LEAN_AND_MEAN +#include +typedef CRITICAL_SECTION hb_mutex_impl_t; +#define HB_MUTEX_IMPL_INIT { NULL, 0, 0, NULL, NULL, 0 } +#define hb_mutex_impl_init(M) InitializeCriticalSection (M) +#define hb_mutex_impl_lock(M) EnterCriticalSection (M) +#define hb_mutex_impl_unlock(M) LeaveCriticalSection (M) +#define hb_mutex_impl_finish(M) DeleteCriticalSection (M) + + +#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__)) + +#include +typedef pthread_mutex_t hb_mutex_impl_t; +#define HB_MUTEX_IMPL_INIT PTHREAD_MUTEX_INITIALIZER +#define hb_mutex_impl_init(M) pthread_mutex_init (M, NULL) +#define hb_mutex_impl_lock(M) pthread_mutex_lock (M) +#define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M) +#define hb_mutex_impl_finish(M) pthread_mutex_destroy (M) + + +#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD) +# include +# define HB_SCHED_YIELD() sched_yield () +#else +# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END +#endif + +/* This actually is not a totally awful implementation. */ +typedef volatile int hb_mutex_impl_t; +#define HB_MUTEX_IMPL_INIT 0 +#define hb_mutex_impl_init(M) *(M) = 0 +#define hb_mutex_impl_lock(M) HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END +#define hb_mutex_impl_unlock(M) __sync_lock_release (M) +#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END + + +#elif !defined(HB_NO_MT) + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD) +# include +# define HB_SCHED_YIELD() sched_yield () +#else +# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END +#endif + +#define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */ +typedef volatile int hb_mutex_impl_t; +#define HB_MUTEX_IMPL_INIT 0 +#define hb_mutex_impl_init(M) *(M) = 0 +#define hb_mutex_impl_lock(M) HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END +#define hb_mutex_impl_unlock(M) (*(M))--; +#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END + + +#else /* HB_NO_MT */ + +typedef int hb_mutex_impl_t; +#define HB_MUTEX_IMPL_INIT 0 +#define hb_mutex_impl_init(M) HB_STMT_START {} HB_STMT_END +#define hb_mutex_impl_lock(M) HB_STMT_START {} HB_STMT_END +#define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END +#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END + +#endif + + +#define HB_MUTEX_INIT {HB_MUTEX_IMPL_INIT} +struct hb_mutex_t +{ + /* TODO Add tracing. */ + + hb_mutex_impl_t m; + + inline void init (void) { hb_mutex_impl_init (&m); } + inline void lock (void) { hb_mutex_impl_lock (&m); } + inline void unlock (void) { hb_mutex_impl_unlock (&m); } + inline void finish (void) { hb_mutex_impl_finish (&m); } +}; + + +#endif /* HB_MUTEX_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-object-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-object-private.hh new file mode 100644 index 0000000000..8a9ae34dbe --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-object-private.hh @@ -0,0 +1,227 @@ +/* + * Copyright © 2007 Chris Wilson + * Copyright © 2009,2010 Red Hat, Inc. + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Contributor(s): + * Chris Wilson + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OBJECT_PRIVATE_HH +#define HB_OBJECT_PRIVATE_HH + +#include "hb-private.hh" + +#include "hb-atomic-private.hh" +#include "hb-mutex-private.hh" + + +/* Debug */ + +#ifndef HB_DEBUG_OBJECT +#define HB_DEBUG_OBJECT (HB_DEBUG+0) +#endif + + +/* reference_count */ + +#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1) +#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE} +struct hb_reference_count_t +{ + hb_atomic_int_t ref_count; + + inline void init (int v) { ref_count = v; } + inline int inc (void) { return hb_atomic_int_add (const_cast (ref_count), 1); } + inline int dec (void) { return hb_atomic_int_add (const_cast (ref_count), -1); } + inline void finish (void) { ref_count = HB_REFERENCE_COUNT_INVALID_VALUE; } + + inline bool is_invalid (void) const { return ref_count == HB_REFERENCE_COUNT_INVALID_VALUE; } + +}; + + +/* user_data */ + +#define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT} +struct hb_user_data_array_t +{ + /* TODO Add tracing. */ + + struct hb_user_data_item_t { + hb_user_data_key_t *key; + void *data; + hb_destroy_func_t destroy; + + inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; } + inline bool operator == (hb_user_data_item_t &other) const { return key == other.key; } + + void finish (void) { if (destroy) destroy (data); } + }; + + hb_mutex_t lock; + hb_lockable_set_t items; + + inline void init (void) { lock.init (); items.init (); } + + HB_INTERNAL bool set (hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + + HB_INTERNAL void *get (hb_user_data_key_t *key); + + inline void finish (void) { items.finish (lock); lock.finish (); } +}; + + +/* object_header */ + +struct hb_object_header_t +{ + hb_reference_count_t ref_count; + hb_user_data_array_t user_data; + +#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_INIT} + + static inline void *create (unsigned int size) { + hb_object_header_t *obj = (hb_object_header_t *) calloc (1, size); + + if (likely (obj)) + obj->init (); + + return obj; + } + + inline void init (void) { + ref_count.init (1); + user_data.init (); + } + + inline bool is_inert (void) const { + return unlikely (ref_count.is_invalid ()); + } + + inline void reference (void) { + if (unlikely (!this || this->is_inert ())) + return; + ref_count.inc (); + } + + inline bool destroy (void) { + if (unlikely (!this || this->is_inert ())) + return false; + if (ref_count.dec () != 1) + return false; + + ref_count.finish (); /* Do this before user_data */ + user_data.finish (); + + return true; + } + + inline bool set_user_data (hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy_func, + hb_bool_t replace) { + if (unlikely (!this || this->is_inert ())) + return false; + + return user_data.set (key, data, destroy_func, replace); + } + + inline void *get_user_data (hb_user_data_key_t *key) { + if (unlikely (!this || this->is_inert ())) + return NULL; + + return user_data.get (key); + } + + inline void trace (const char *function) const { + if (unlikely (!this)) return; + /* TODO We cannot use DEBUG_MSG_FUNC here since that one currently only + * prints the class name and throws away the template info. */ + DEBUG_MSG (OBJECT, (void *) this, + "%s refcount=%d", + function, + this ? ref_count.ref_count : 0); + } + + private: + ASSERT_POD (); +}; + + +/* object */ + +template +static inline void hb_object_trace (const Type *obj, const char *function) +{ + obj->header.trace (function); +} +template +static inline Type *hb_object_create (void) +{ + Type *obj = (Type *) hb_object_header_t::create (sizeof (Type)); + hb_object_trace (obj, HB_FUNC); + return obj; +} +template +static inline bool hb_object_is_inert (const Type *obj) +{ + return unlikely (obj->header.is_inert ()); +} +template +static inline Type *hb_object_reference (Type *obj) +{ + hb_object_trace (obj, HB_FUNC); + obj->header.reference (); + return obj; +} +template +static inline bool hb_object_destroy (Type *obj) +{ + hb_object_trace (obj, HB_FUNC); + return obj->header.destroy (); +} +template +static inline bool hb_object_set_user_data (Type *obj, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace) +{ + return obj->header.set_user_data (key, data, destroy, replace); +} + +template +static inline void *hb_object_get_user_data (Type *obj, + hb_user_data_key_t *key) +{ + return obj->header.get_user_data (key); +} + + +#endif /* HB_OBJECT_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh new file mode 100644 index 0000000000..250504ae20 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh @@ -0,0 +1,261 @@ +/* + * Copyright © 2007,2008,2009 Red Hat, Inc. + * Copyright © 2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OPEN_FILE_PRIVATE_HH +#define HB_OPEN_FILE_PRIVATE_HH + +#include "hb-open-type-private.hh" + + +namespace OT { + + +/* + * + * The OpenType Font File + * + */ + + +/* + * Organization of an OpenType Font + */ + +struct OpenTypeFontFile; +struct OffsetTable; +struct TTCHeader; + + +typedef struct TableRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + + Tag tag; /* 4-byte identifier. */ + CheckSum checkSum; /* CheckSum for this table. */ + ULONG offset; /* Offset from beginning of TrueType font + * file. */ + ULONG length; /* Length of this table. */ + public: + DEFINE_SIZE_STATIC (16); +} OpenTypeTable; + +typedef struct OffsetTable +{ + friend struct OpenTypeFontFile; + + inline unsigned int get_table_count (void) const + { return numTables; } + inline const TableRecord& get_table (unsigned int i) const + { + if (unlikely (i >= numTables)) return Null(TableRecord); + return tables[i]; + } + inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const + { + Tag t; + t.set (tag); + unsigned int count = numTables; + for (unsigned int i = 0; i < count; i++) + { + if (t == tables[i].tag) + { + if (table_index) *table_index = i; + return true; + } + } + if (table_index) *table_index = Index::NOT_FOUND_INDEX; + return false; + } + inline const TableRecord& get_table_by_tag (hb_tag_t tag) const + { + unsigned int table_index; + find_table_index (tag, &table_index); + return get_table (table_index); + } + + public: + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables)); + } + + protected: + Tag sfnt_version; /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */ + USHORT numTables; /* Number of tables. */ + USHORT searchRange; /* (Maximum power of 2 <= numTables) x 16 */ + USHORT entrySelector; /* Log2(maximum power of 2 <= numTables). */ + USHORT rangeShift; /* NumTables x 16-searchRange. */ + TableRecord tables[VAR]; /* TableRecord entries. numTables items */ + public: + DEFINE_SIZE_ARRAY (12, tables); +} OpenTypeFontFace; + + +/* + * TrueType Collections + */ + +struct TTCHeaderVersion1 +{ + friend struct TTCHeader; + + inline unsigned int get_face_count (void) const { return table.len; } + inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; } + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (table.sanitize (c, this)); + } + + protected: + Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ + FixedVersion version; /* Version of the TTC Header (1.0), + * 0x00010000 */ + LongOffsetLongArrayOf + table; /* Array of offsets to the OffsetTable for each font + * from the beginning of the file */ + public: + DEFINE_SIZE_ARRAY (12, table); +}; + +struct TTCHeader +{ + friend struct OpenTypeFontFile; + + private: + + inline unsigned int get_face_count (void) const + { + switch (u.header.version.major) { + case 2: /* version 2 is compatible with version 1 */ + case 1: return u.version1.get_face_count (); + default:return 0; + } + } + inline const OpenTypeFontFace& get_face (unsigned int i) const + { + switch (u.header.version.major) { + case 2: /* version 2 is compatible with version 1 */ + case 1: return u.version1.get_face (i); + default:return Null(OpenTypeFontFace); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + if (unlikely (!u.header.version.sanitize (c))) return TRACE_RETURN (false); + switch (u.header.version.major) { + case 2: /* version 2 is compatible with version 1 */ + case 1: return TRACE_RETURN (u.version1.sanitize (c)); + default:return TRACE_RETURN (true); + } + } + + protected: + union { + struct { + Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ + FixedVersion version; /* Version of the TTC Header (1.0 or 2.0), + * 0x00010000 or 0x00020000 */ + } header; + TTCHeaderVersion1 version1; + } u; +}; + + +/* + * OpenType Font File + */ + +struct OpenTypeFontFile +{ + static const hb_tag_t CFFTag = HB_TAG ('O','T','T','O'); /* OpenType with Postscript outlines */ + static const hb_tag_t TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ); /* OpenType with TrueType outlines */ + static const hb_tag_t TTCTag = HB_TAG ('t','t','c','f'); /* TrueType Collection */ + static const hb_tag_t TrueTag = HB_TAG ('t','r','u','e'); /* Obsolete Apple TrueType */ + static const hb_tag_t Typ1Tag = HB_TAG ('t','y','p','1'); /* Obsolete Apple Type1 font in SFNT container */ + + inline hb_tag_t get_tag (void) const { return u.tag; } + + inline unsigned int get_face_count (void) const + { + switch (u.tag) { + case CFFTag: /* All the non-collection tags */ + case TrueTag: + case Typ1Tag: + case TrueTypeTag: return 1; + case TTCTag: return u.ttcHeader.get_face_count (); + default: return 0; + } + } + inline const OpenTypeFontFace& get_face (unsigned int i) const + { + switch (u.tag) { + /* Note: for non-collection SFNT data we ignore index. This is because + * Apple dfont container is a container of SFNT's. So each SFNT is a + * non-TTC, but the index is more than zero. */ + case CFFTag: /* All the non-collection tags */ + case TrueTag: + case Typ1Tag: + case TrueTypeTag: return u.fontFace; + case TTCTag: return u.ttcHeader.get_face (i); + default: return Null(OpenTypeFontFace); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + if (unlikely (!u.tag.sanitize (c))) return TRACE_RETURN (false); + switch (u.tag) { + case CFFTag: /* All the non-collection tags */ + case TrueTag: + case Typ1Tag: + case TrueTypeTag: return TRACE_RETURN (u.fontFace.sanitize (c)); + case TTCTag: return TRACE_RETURN (u.ttcHeader.sanitize (c)); + default: return TRACE_RETURN (true); + } + } + + protected: + union { + Tag tag; /* 4-byte identifier. */ + OpenTypeFontFace fontFace; + TTCHeader ttcHeader; + } u; + public: + DEFINE_SIZE_UNION (4, tag); +}; + + +} /* namespace OT */ + + +#endif /* HB_OPEN_FILE_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh new file mode 100644 index 0000000000..ee3a21dc3b --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh @@ -0,0 +1,981 @@ +/* + * Copyright © 2007,2008,2009,2010 Red Hat, Inc. + * Copyright © 2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OPEN_TYPE_PRIVATE_HH +#define HB_OPEN_TYPE_PRIVATE_HH + +#include "hb-private.hh" + +#include "hb-blob.h" + + +namespace OT { + + + +/* + * Casts + */ + +/* Cast to struct T, reference to reference */ +template +inline const Type& CastR(const TObject &X) +{ return reinterpret_cast (X); } +template +inline Type& CastR(TObject &X) +{ return reinterpret_cast (X); } + +/* Cast to struct T, pointer to pointer */ +template +inline const Type* CastP(const TObject *X) +{ return reinterpret_cast (X); } +template +inline Type* CastP(TObject *X) +{ return reinterpret_cast (X); } + +/* StructAtOffset(P,Ofs) returns the struct T& that is placed at memory + * location pointed to by P plus Ofs bytes. */ +template +inline const Type& StructAtOffset(const void *P, unsigned int offset) +{ return * reinterpret_cast ((const char *) P + offset); } +template +inline Type& StructAtOffset(void *P, unsigned int offset) +{ return * reinterpret_cast ((char *) P + offset); } + +/* StructAfter(X) returns the struct T& that is placed after X. + * Works with X of variable size also. X must implement get_size() */ +template +inline const Type& StructAfter(const TObject &X) +{ return StructAtOffset(&X, X.get_size()); } +template +inline Type& StructAfter(TObject &X) +{ return StructAtOffset(&X, X.get_size()); } + + + +/* + * Size checking + */ + +/* Check _assertion in a method environment */ +#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ + inline void _instance_assertion_on_line_##_line (void) const \ + { \ + ASSERT_STATIC (_assertion); \ + ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \ + } +# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion) +# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion) + +/* Check that _code compiles in a method environment */ +#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \ + inline void _compiles_assertion_on_line_##_line (void) const \ + { _code; } +# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code) +# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code) + + +#define DEFINE_SIZE_STATIC(size) \ + DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \ + static const unsigned int static_size = (size); \ + static const unsigned int min_size = (size) + +/* Size signifying variable-sized array */ +#define VAR 1 + +#define DEFINE_SIZE_UNION(size, _member) \ + DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \ + static const unsigned int min_size = (size) + +#define DEFINE_SIZE_MIN(size) \ + DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \ + static const unsigned int min_size = (size) + +#define DEFINE_SIZE_ARRAY(size, array) \ + DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \ + DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \ + static const unsigned int min_size = (size) + +#define DEFINE_SIZE_ARRAY2(size, array1, array2) \ + DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ + DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \ + static const unsigned int min_size = (size) + + + +/* + * Null objects + */ + +/* Global nul-content Null pool. Enlarge as necessary. */ +/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */ +static const void *_NullPool[64 / sizeof (void *)]; + +/* Generic nul-content Null objects. */ +template +static inline const Type& Null (void) { + ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); + return *CastP (_NullPool); +} + +/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ +#define DEFINE_NULL_DATA(Type, data) \ +static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \ +template <> \ +inline const Type& Null (void) { \ + return *CastP (_Null##Type); \ +} /* The following line really exists such that we end in a place needing semicolon */ \ +ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) + +/* Accessor macro. */ +#define Null(Type) Null() + + + +/* + * Sanitize + */ + +#ifndef HB_DEBUG_SANITIZE +#define HB_DEBUG_SANITIZE (HB_DEBUG+0) +#endif + + +#define TRACE_SANITIZE(this) \ + hb_auto_trace_t trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + ""); + +/* This limits sanitizing time on really broken fonts. */ +#ifndef HB_SANITIZE_MAX_EDITS +#define HB_SANITIZE_MAX_EDITS 100 +#endif + +struct hb_sanitize_context_t +{ + inline const char *get_name (void) { return "SANITIZE"; } + static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; + typedef bool return_t; + template + inline return_t dispatch (const T &obj) { return obj.sanitize (this); } + static return_t default_return_value (void) { return true; } + bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; } + + inline void init (hb_blob_t *b) + { + this->blob = hb_blob_reference (b); + this->writable = false; + } + + inline void start_processing (void) + { + this->start = hb_blob_get_data (this->blob, NULL); + this->end = this->start + hb_blob_get_length (this->blob); + this->edit_count = 0; + this->debug_depth = 0; + + DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1, + "start [%p..%p] (%lu bytes)", + this->start, this->end, + (unsigned long) (this->end - this->start)); + } + + inline void end_processing (void) + { + DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1, + "end [%p..%p] %u edit requests", + this->start, this->end, this->edit_count); + + hb_blob_destroy (this->blob); + this->blob = NULL; + this->start = this->end = NULL; + } + + inline bool check_range (const void *base, unsigned int len) const + { + const char *p = (const char *) base; + + hb_auto_trace_t trace + (&this->debug_depth, "SANITIZE", this->blob, NULL, + "check_range [%p..%p] (%d bytes) in [%p..%p]", + p, p + len, len, + this->start, this->end); + + return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len)); + } + + inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const + { + const char *p = (const char *) base; + bool overflows = _hb_unsigned_int_mul_overflows (len, record_size); + + hb_auto_trace_t trace + (&this->debug_depth, "SANITIZE", this->blob, NULL, + "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]", + p, p + (record_size * len), record_size, len, (unsigned long) record_size * len, + this->start, this->end); + + return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len))); + } + + template + inline bool check_struct (const Type *obj) const + { + return likely (this->check_range (obj, obj->min_size)); + } + + inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED) + { + if (this->edit_count >= HB_SANITIZE_MAX_EDITS) + return false; + + const char *p = (const char *) base; + this->edit_count++; + + hb_auto_trace_t trace + (&this->debug_depth, "SANITIZE", this->blob, NULL, + "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", + this->edit_count, + p, p + len, len, + this->start, this->end, + this->writable ? "GRANTED" : "DENIED"); + + return TRACE_RETURN (this->writable); + } + + mutable unsigned int debug_depth; + const char *start, *end; + bool writable; + unsigned int edit_count; + hb_blob_t *blob; +}; + + + +/* Template to sanitize an object. */ +template +struct Sanitizer +{ + static hb_blob_t *sanitize (hb_blob_t *blob) { + hb_sanitize_context_t c[1] = {{0}}; + bool sane; + + /* TODO is_sane() stuff */ + + c->init (blob); + + retry: + DEBUG_MSG_FUNC (SANITIZE, blob, "start"); + + c->start_processing (); + + if (unlikely (!c->start)) { + c->end_processing (); + return blob; + } + + Type *t = CastP (const_cast (c->start)); + + sane = t->sanitize (c); + if (sane) { + if (c->edit_count) { + DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count); + + /* sanitize again to ensure no toe-stepping */ + c->edit_count = 0; + sane = t->sanitize (c); + if (c->edit_count) { + DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count); + sane = false; + } + } + } else { + unsigned int edit_count = c->edit_count; + if (edit_count && !c->writable) { + c->start = hb_blob_get_data_writable (blob, NULL); + c->end = c->start + hb_blob_get_length (blob); + + if (c->start) { + c->writable = true; + /* ok, we made it writable by relocating. try again */ + DEBUG_MSG_FUNC (SANITIZE, blob, "retry"); + goto retry; + } + } + } + + c->end_processing (); + + DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED"); + if (sane) + return blob; + else { + hb_blob_destroy (blob); + return hb_blob_get_empty (); + } + } + + static const Type* lock_instance (hb_blob_t *blob) { + hb_blob_make_immutable (blob); + const char *base = hb_blob_get_data (blob, NULL); + return unlikely (!base) ? &Null(Type) : CastP (base); + } +}; + + + +/* + * Serialize + */ + +#ifndef HB_DEBUG_SERIALIZE +#define HB_DEBUG_SERIALIZE (HB_DEBUG+0) +#endif + + +#define TRACE_SERIALIZE(this) \ + hb_auto_trace_t trace \ + (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ + ""); + + +struct hb_serialize_context_t +{ + inline hb_serialize_context_t (void *start, unsigned int size) + { + this->start = (char *) start; + this->end = this->start + size; + + this->ran_out_of_room = false; + this->head = this->start; + this->debug_depth = 0; + } + + template + inline Type *start_serialize (void) + { + DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1, + "start [%p..%p] (%lu bytes)", + this->start, this->end, + (unsigned long) (this->end - this->start)); + + return start_embed (); + } + + inline void end_serialize (void) + { + DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1, + "end [%p..%p] serialized %d bytes; %s", + this->start, this->end, + (int) (this->head - this->start), + this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room"); + + } + + template + inline Type *copy (void) + { + assert (!this->ran_out_of_room); + unsigned int len = this->head - this->start; + void *p = malloc (len); + if (p) + memcpy (p, this->start, len); + return reinterpret_cast (p); + } + + template + inline Type *allocate_size (unsigned int size) + { + if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) { + this->ran_out_of_room = true; + return NULL; + } + memset (this->head, 0, size); + char *ret = this->head; + this->head += size; + return reinterpret_cast (ret); + } + + template + inline Type *allocate_min (void) + { + return this->allocate_size (Type::min_size); + } + + template + inline Type *start_embed (void) + { + Type *ret = reinterpret_cast (this->head); + return ret; + } + + template + inline Type *embed (const Type &obj) + { + unsigned int size = obj.get_size (); + Type *ret = this->allocate_size (size); + if (unlikely (!ret)) return NULL; + memcpy (ret, obj, size); + return ret; + } + + template + inline Type *extend_min (Type &obj) + { + unsigned int size = obj.min_size; + assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); + if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return NULL; + return reinterpret_cast (&obj); + } + + template + inline Type *extend (Type &obj) + { + unsigned int size = obj.get_size (); + assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); + if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return NULL; + return reinterpret_cast (&obj); + } + + inline void truncate (void *head) + { + assert (this->start < head && head <= this->head); + this->head = (char *) head; + } + + unsigned int debug_depth; + char *start, *end, *head; + bool ran_out_of_room; +}; + +template +struct Supplier +{ + inline Supplier (const Type *array, unsigned int len_) + { + head = array; + len = len_; + } + inline const Type operator [] (unsigned int i) const + { + if (unlikely (i >= len)) return Type (); + return head[i]; + } + + inline void advance (unsigned int count) + { + if (unlikely (count > len)) + count = len; + len -= count; + head += count; + } + + private: + inline Supplier (const Supplier &); /* Disallow copy */ + inline Supplier& operator= (const Supplier &); /* Disallow copy */ + + unsigned int len; + const Type *head; +}; + + + + +/* + * + * The OpenType Font File: Data Types + */ + + +/* "The following data types are used in the OpenType font file. + * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */ + +/* + * Int types + */ + + +template struct BEInt; + +template +struct BEInt +{ + public: + inline void set (Type i) { hb_be_uint16_put (v,i); } + inline operator Type (void) const { return hb_be_uint16_get (v); } + inline bool operator == (const BEInt& o) const { return hb_be_uint16_eq (v, o.v); } + inline bool operator != (const BEInt& o) const { return !(*this == o); } + private: uint8_t v[2]; +}; +template +struct BEInt +{ + public: + inline void set (Type i) { hb_be_uint32_put (v,i); } + inline operator Type (void) const { return hb_be_uint32_get (v); } + inline bool operator == (const BEInt& o) const { return hb_be_uint32_eq (v, o.v); } + inline bool operator != (const BEInt& o) const { return !(*this == o); } + private: uint8_t v[4]; +}; +template +struct BEInt +{ + public: + inline void set (Type i) { hb_be_uint24_put (v,i); } + inline operator Type (void) const { return hb_be_uint24_get (v); } + inline bool operator == (const BEInt& o) const { return hb_be_uint24_eq (v, o.v); } + inline bool operator != (const BEInt& o) const { return !(*this == o); } + private: uint8_t v[3]; +}; + +/* Integer types in big-endian order and no alignment requirement */ +template +struct IntType +{ + inline void set (Type i) { v.set (i); } + inline operator Type(void) const { return v; } + inline bool operator == (const IntType &o) const { return v == o.v; } + inline bool operator != (const IntType &o) const { return v != o.v; } + static inline int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } + inline int cmp (IntType va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; } + inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (likely (c->check_struct (this))); + } + protected: + BEInt v; + public: + DEFINE_SIZE_STATIC (Size); +}; + +typedef IntType USHORT; /* 16-bit unsigned integer. */ +typedef IntType SHORT; /* 16-bit signed integer. */ +typedef IntType ULONG; /* 32-bit unsigned integer. */ +typedef IntType LONG; /* 32-bit signed integer. */ +typedef IntType UINT24; /* 24-bit unsigned integer. */ + +/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ +typedef SHORT FWORD; + +/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ +typedef USHORT UFWORD; + +/* Date represented in number of seconds since 12:00 midnight, January 1, + * 1904. The value is represented as a signed 64-bit integer. */ +struct LONGDATETIME +{ + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (likely (c->check_struct (this))); + } + private: + LONG major; + ULONG minor; + public: + DEFINE_SIZE_STATIC (8); +}; + +/* Array of four uint8s (length = 32 bits) used to identify a script, language + * system, feature, or baseline */ +struct Tag : ULONG +{ + /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ + inline operator const char* (void) const { return reinterpret_cast (&this->v); } + inline operator char* (void) { return reinterpret_cast (&this->v); } + public: + DEFINE_SIZE_STATIC (4); +}; +DEFINE_NULL_DATA (Tag, " "); + +/* Glyph index number, same as uint16 (length = 16 bits) */ +typedef USHORT GlyphID; + +/* Script/language-system/feature index */ +struct Index : USHORT { + static const unsigned int NOT_FOUND_INDEX = 0xFFFF; +}; +DEFINE_NULL_DATA (Index, "\xff\xff"); + +/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */ +struct Offset : USHORT +{ + inline bool is_null (void) const { return 0 == *this; } + public: + DEFINE_SIZE_STATIC (2); +}; + +/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */ +struct LongOffset : ULONG +{ + inline bool is_null (void) const { return 0 == *this; } + public: + DEFINE_SIZE_STATIC (4); +}; + + +/* CheckSum */ +struct CheckSum : ULONG +{ + /* This is reference implementation from the spec. */ + static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length) + { + uint32_t Sum = 0L; + const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size; + + while (Table < EndPtr) + Sum += *Table++; + return Sum; + } + + /* Note: data should be 4byte aligned and have 4byte padding at the end. */ + inline void set_for_data (const void *data, unsigned int length) + { set (CalcTableChecksum ((const ULONG *) data, length)); } + + public: + DEFINE_SIZE_STATIC (4); +}; + + +/* + * Version Numbers + */ + +struct FixedVersion +{ + inline uint32_t to_int (void) const { return (major << 16) + minor; } + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + + USHORT major; + USHORT minor; + public: + DEFINE_SIZE_STATIC (4); +}; + + + +/* + * Template subclasses of Offset and LongOffset that do the dereferencing. + * Use: (base+offset) + */ + +template +struct GenericOffsetTo : OffsetType +{ + inline const Type& operator () (const void *base) const + { + unsigned int offset = *this; + if (unlikely (!offset)) return Null(Type); + return StructAtOffset (base, offset); + } + + inline Type& serialize (hb_serialize_context_t *c, void *base) + { + Type *t = c->start_embed (); + this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ + return *t; + } + + inline bool sanitize (hb_sanitize_context_t *c, void *base) { + TRACE_SANITIZE (this); + if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); + unsigned int offset = *this; + if (unlikely (!offset)) return TRACE_RETURN (true); + Type &obj = StructAtOffset (base, offset); + return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); + } + template + inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { + TRACE_SANITIZE (this); + if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); + unsigned int offset = *this; + if (unlikely (!offset)) return TRACE_RETURN (true); + Type &obj = StructAtOffset (base, offset); + return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); + } + + inline bool try_set (hb_sanitize_context_t *c, const OffsetType &v) { + if (c->may_edit (this, this->static_size)) { + this->set (v); + return true; + } + return false; + } + /* Set the offset to Null */ + inline bool neuter (hb_sanitize_context_t *c) { + if (c->may_edit (this, this->static_size)) { + this->set (0); /* 0 is Null offset */ + return true; + } + return false; + } +}; +template +inline const Type& operator + (const Base &base, const GenericOffsetTo &offset) { return offset (base); } +template +inline Type& operator + (Base &base, GenericOffsetTo &offset) { return offset (base); } + +template +struct OffsetTo : GenericOffsetTo {}; + +template +struct LongOffsetTo : GenericOffsetTo {}; + + +/* + * Array Types + */ + +template +struct GenericArrayOf +{ + const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const + { + unsigned int count = len; + if (unlikely (start_offset > count)) + count = 0; + else + count -= start_offset; + count = MIN (count, *pcount); + *pcount = count; + return array + start_offset; + } + + inline const Type& operator [] (unsigned int i) const + { + if (unlikely (i >= len)) return Null(Type); + return array[i]; + } + inline Type& operator [] (unsigned int i) + { + return array[i]; + } + inline unsigned int get_size (void) const + { return len.static_size + len * Type::static_size; } + + inline bool serialize (hb_serialize_context_t *c, + unsigned int items_len) + { + TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + len.set (items_len); /* TODO(serialize) Overflow? */ + if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + + inline bool serialize (hb_serialize_context_t *c, + Supplier &items, + unsigned int items_len) + { + TRACE_SERIALIZE (this); + if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < items_len; i++) + array[i] = items[i]; + items.advance (items_len); + return TRACE_RETURN (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + + /* Note: for structs that do not reference other structs, + * we do not need to call their sanitize() as we already did + * a bound check on the aggregate array size. We just include + * a small unreachable expression to make sure the structs + * pointed to do have a simple sanitize(), ie. they do not + * reference other structs via offsets. + */ + (void) (false && array[0].sanitize (c)); + + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c, void *base) { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + if (unlikely (!array[i].sanitize (c, base))) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + template + inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + if (unlikely (!array[i].sanitize (c, base, user_data))) + return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + + private: + inline bool sanitize_shallow (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len)); + } + + public: + LenType len; + Type array[VAR]; + public: + DEFINE_SIZE_ARRAY (sizeof (LenType), array); +}; + +/* An array with a USHORT number of elements. */ +template +struct ArrayOf : GenericArrayOf {}; + +/* An array with a ULONG number of elements. */ +template +struct LongArrayOf : GenericArrayOf {}; + +/* Array of Offset's */ +template +struct OffsetArrayOf : ArrayOf > {}; + +/* Array of LongOffset's */ +template +struct LongOffsetArrayOf : ArrayOf > {}; + +/* LongArray of LongOffset's */ +template +struct LongOffsetLongArrayOf : LongArrayOf > {}; + +/* Array of offsets relative to the beginning of the array itself. */ +template +struct OffsetListOf : OffsetArrayOf +{ + inline const Type& operator [] (unsigned int i) const + { + if (unlikely (i >= this->len)) return Null(Type); + return this+this->array[i]; + } + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (OffsetArrayOf::sanitize (c, this)); + } + template + inline bool sanitize (hb_sanitize_context_t *c, T user_data) { + TRACE_SANITIZE (this); + return TRACE_RETURN (OffsetArrayOf::sanitize (c, this, user_data)); + } +}; + + +/* An array with a USHORT number of elements, + * starting at second element. */ +template +struct HeadlessArrayOf +{ + inline const Type& operator [] (unsigned int i) const + { + if (unlikely (i >= len || !i)) return Null(Type); + return array[i-1]; + } + inline unsigned int get_size (void) const + { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } + + inline bool serialize (hb_serialize_context_t *c, + Supplier &items, + unsigned int items_len) + { + TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + len.set (items_len); /* TODO(serialize) Overflow? */ + if (unlikely (!items_len)) return TRACE_RETURN (true); + if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < items_len - 1; i++) + array[i] = items[i]; + items.advance (items_len - 1); + return TRACE_RETURN (true); + } + + inline bool sanitize_shallow (hb_sanitize_context_t *c) { + return c->check_struct (this) + && c->check_array (this, Type::static_size, len); + } + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + + /* Note: for structs that do not reference other structs, + * we do not need to call their sanitize() as we already did + * a bound check on the aggregate array size. We just include + * a small unreachable expression to make sure the structs + * pointed to do have a simple sanitize(), ie. they do not + * reference other structs via offsets. + */ + (void) (false && array[0].sanitize (c)); + + return TRACE_RETURN (true); + } + + USHORT len; + Type array[VAR]; + public: + DEFINE_SIZE_ARRAY (sizeof (USHORT), array); +}; + + +/* An array with sorted elements. Supports binary searching. */ +template +struct SortedArrayOf : ArrayOf { + + template + inline int search (const SearchType &x) const + { + /* Hand-coded bsearch here since this is in the hot inner loop. */ + int min = 0, max = (int) this->len - 1; + while (min <= max) + { + int mid = (min + max) / 2; + int c = this->array[mid].cmp (x); + if (c < 0) + max = mid - 1; + else if (c > 0) + min = mid + 1; + else + return mid; + } + return -1; + } +}; + + +} /* namespace OT */ + + +#endif /* HB_OPEN_TYPE_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh new file mode 100644 index 0000000000..3a9451295d --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh @@ -0,0 +1,149 @@ +/* + * Copyright © 2010 Red Hat, Inc. + * Copyright © 2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_HEAD_TABLE_HH +#define HB_OT_HEAD_TABLE_HH + +#include "hb-open-type-private.hh" + + +namespace OT { + + +/* + * head -- Font Header + */ + +#define HB_OT_TAG_head HB_TAG('h','e','a','d') + +struct head +{ + static const hb_tag_t Tag = HB_OT_TAG_head; + + inline unsigned int get_upem (void) const { + unsigned int upem = unitsPerEm; + /* If no valid head table found, assume 1000, which matches typical Type1 usage. */ + return 16 <= upem && upem <= 16384 ? upem : 1000; + } + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); + } + + protected: + FixedVersion version; /* Version of the head table--currently + * 0x00010000 for version 1.0. */ + FixedVersion fontRevision; /* Set by font manufacturer. */ + ULONG checkSumAdjustment; /* To compute: set it to 0, sum the + * entire font as ULONG, then store + * 0xB1B0AFBA - sum. */ + ULONG magicNumber; /* Set to 0x5F0F3CF5. */ + USHORT flags; /* Bit 0: Baseline for font at y=0; + * Bit 1: Left sidebearing point at x=0; + * Bit 2: Instructions may depend on point size; + * Bit 3: Force ppem to integer values for all + * internal scaler math; may use fractional + * ppem sizes if this bit is clear; + * Bit 4: Instructions may alter advance width + * (the advance widths might not scale linearly); + + * Bits 5-10: These should be set according to + * Apple's specification. However, they are not + * implemented in OpenType. + * Bit 5: This bit should be set in fonts that are + * intended to e laid out vertically, and in + * which the glyphs have been drawn such that an + * x-coordinate of 0 corresponds to the desired + * vertical baseline. + * Bit 6: This bit must be set to zero. + * Bit 7: This bit should be set if the font + * requires layout for correct linguistic + * rendering (e.g. Arabic fonts). + * Bit 8: This bit should be set for a GX font + * which has one or more metamorphosis effects + * designated as happening by default. + * Bit 9: This bit should be set if the font + * contains any strong right-to-left glyphs. + * Bit 10: This bit should be set if the font + * contains Indic-style rearrangement effects. + + * Bit 11: Font data is 'lossless,' as a result + * of having been compressed and decompressed + * with the Agfa MicroType Express engine. + * Bit 12: Font converted (produce compatible metrics) + * Bit 13: Font optimized for ClearType™. + * Note, fonts that rely on embedded bitmaps (EBDT) + * for rendering should not be considered optimized + * for ClearType, and therefore should keep this bit + * cleared. + * Bit 14: Last Resort font. If set, indicates that + * the glyphs encoded in the cmap subtables are simply + * generic symbolic representations of code point + * ranges and don’t truly represent support for those + * code points. If unset, indicates that the glyphs + * encoded in the cmap subtables represent proper + * support for those code points. + * Bit 15: Reserved, set to 0. */ + USHORT unitsPerEm; /* Valid range is from 16 to 16384. This value + * should be a power of 2 for fonts that have + * TrueType outlines. */ + LONGDATETIME created; /* Number of seconds since 12:00 midnight, + January 1, 1904. 64-bit integer */ + LONGDATETIME modified; /* Number of seconds since 12:00 midnight, + January 1, 1904. 64-bit integer */ + SHORT xMin; /* For all glyph bounding boxes. */ + SHORT yMin; /* For all glyph bounding boxes. */ + SHORT xMax; /* For all glyph bounding boxes. */ + SHORT yMax; /* For all glyph bounding boxes. */ + USHORT macStyle; /* Bit 0: Bold (if set to 1); + * Bit 1: Italic (if set to 1) + * Bit 2: Underline (if set to 1) + * Bit 3: Outline (if set to 1) + * Bit 4: Shadow (if set to 1) + * Bit 5: Condensed (if set to 1) + * Bit 6: Extended (if set to 1) + * Bits 7-15: Reserved (set to 0). */ + USHORT lowestRecPPEM; /* Smallest readable size in pixels. */ + SHORT fontDirectionHint; /* Deprecated (Set to 2). + * 0: Fully mixed directional glyphs; + * 1: Only strongly left to right; + * 2: Like 1 but also contains neutrals; + * -1: Only strongly right to left; + * -2: Like -1 but also contains neutrals. */ + SHORT indexToLocFormat; /* 0 for short offsets, 1 for long. */ + SHORT glyphDataFormat; /* 0 for current format. */ + public: + DEFINE_SIZE_STATIC (54); +}; + + +} /* namespace OT */ + + +#endif /* HB_OT_HEAD_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh new file mode 100644 index 0000000000..2b89c4e020 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh @@ -0,0 +1,97 @@ +/* + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_HHEA_TABLE_HH +#define HB_OT_HHEA_TABLE_HH + +#include "hb-open-type-private.hh" + + +namespace OT { + + +/* + * hhea -- The Horizontal Header Table + */ + +#define HB_OT_TAG_hhea HB_TAG('h','h','e','a') + + +struct hhea +{ + static const hb_tag_t Tag = HB_OT_TAG_hhea; + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); + } + + protected: + FixedVersion version; /* 0x00010000 for version 1.0. */ + FWORD ascender; /* Typographic ascent. + * (Distance from baseline of highest + * ascender) */ + FWORD descender; /* Typographic descent. + * (Distance from baseline of lowest + * descender) */ + FWORD lineGap; /* Typographic line gap. Negative + * LineGap values are treated as zero + * in Windows 3.1, System 6, and + * System 7. */ + UFWORD advanceWidthMax; /* Maximum advance width value in + * 'hmtx' table. */ + FWORD minLeftSideBearing; /* Minimum left sidebearing value in + * 'hmtx' table. */ + FWORD minRightSideBearing; /* Minimum right sidebearing value; + * calculated as Min(aw - lsb - + * (xMax - xMin)). */ + FWORD xMaxExtent; /* Max(lsb + (xMax - xMin)). */ + SHORT caretSlopeRise; /* Used to calculate the slope of the + * cursor (rise/run); 1 for vertical. */ + SHORT caretSlopeRun; /* 0 for vertical. */ + SHORT caretOffset; /* The amount by which a slanted + * highlight on a glyph needs + * to be shifted to produce the + * best appearance. Set to 0 for + * non--slanted fonts */ + SHORT reserved1; /* set to 0 */ + SHORT reserved2; /* set to 0 */ + SHORT reserved3; /* set to 0 */ + SHORT reserved4; /* set to 0 */ + SHORT metricDataFormat; /* 0 for current format. */ + USHORT numberOfHMetrics; /* Number of hMetric entries in 'hmtx' + * table */ + public: + DEFINE_SIZE_STATIC (36); +}; + + +} /* namespace OT */ + + +#endif /* HB_OT_HHEA_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh new file mode 100644 index 0000000000..b94337d0be --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh @@ -0,0 +1,92 @@ +/* + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_HMTX_TABLE_HH +#define HB_OT_HMTX_TABLE_HH + +#include "hb-open-type-private.hh" + + +namespace OT { + + +/* + * hmtx -- The Horizontal Metrics Table + */ + +#define HB_OT_TAG_hmtx HB_TAG('h','m','t','x') + + +struct LongHorMetric +{ + USHORT advanceWidth; + SHORT lsb; + public: + DEFINE_SIZE_STATIC (4); +}; + +struct hmtx +{ + static const hb_tag_t Tag = HB_OT_TAG_hmtx; + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + /* We don't check for anything specific here. The users of the + * struct do all the hard work... */ + return TRACE_RETURN (true); + } + + protected: + LongHorMetric longHorMetric[VAR]; /* Paired advance width and left side + * bearing values for each glyph. The + * value numOfHMetrics comes from + * the 'hhea' table. If the font is + * monospaced, only one entry need + * be in the array, but that entry is + * required. The last entry applies to + * all subsequent glyphs. */ + SHORT leftSideBearingX[VAR]; /* Here the advanceWidth is assumed + * to be the same as the advanceWidth + * for the last entry above. The + * number of entries in this array is + * derived from numGlyphs (from 'maxp' + * table) minus numberOfHMetrics. This + * generally is used with a run of + * monospaced glyphs (e.g., Kanji + * fonts or Courier fonts). Only one + * run is allowed and it must be at + * the end. This allows a monospaced + * font to vary the left side bearing + * values for each glyph. */ + public: + DEFINE_SIZE_ARRAY2 (0, longHorMetric, leftSideBearingX); +}; + + +} /* namespace OT */ + + +#endif /* HB_OT_HMTX_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh new file mode 100644 index 0000000000..2f6e80468e --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh @@ -0,0 +1,1170 @@ +/* + * Copyright © 2007,2008,2009 Red Hat, Inc. + * Copyright © 2010,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH +#define HB_OT_LAYOUT_COMMON_PRIVATE_HH + +#include "hb-ot-layout-private.hh" +#include "hb-open-type-private.hh" +#include "hb-set-private.hh" + + +namespace OT { + + +#define NOT_COVERED ((unsigned int) -1) +#define MAX_NESTING_LEVEL 8 + + + +/* + * + * OpenType Layout Common Table Formats + * + */ + + +/* + * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList + */ + +template +struct Record +{ + inline int cmp (hb_tag_t a) const { + return tag.cmp (a); + } + + struct sanitize_closure_t { + hb_tag_t tag; + void *list_base; + }; + inline bool sanitize (hb_sanitize_context_t *c, void *base) { + TRACE_SANITIZE (this); + const sanitize_closure_t closure = {tag, base}; + return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure)); + } + + Tag tag; /* 4-byte Tag identifier */ + OffsetTo + offset; /* Offset from beginning of object holding + * the Record */ + public: + DEFINE_SIZE_STATIC (6); +}; + +template +struct RecordArrayOf : SortedArrayOf > { + inline const Tag& get_tag (unsigned int i) const + { + /* We cheat slightly and don't define separate Null objects + * for Record types. Instead, we return the correct Null(Tag) + * here. */ + if (unlikely (i >= this->len)) return Null(Tag); + return (*this)[i].tag; + } + inline unsigned int get_tags (unsigned int start_offset, + unsigned int *record_count /* IN/OUT */, + hb_tag_t *record_tags /* OUT */) const + { + if (record_count) { + const Record *arr = this->sub_array (start_offset, record_count); + unsigned int count = *record_count; + for (unsigned int i = 0; i < count; i++) + record_tags[i] = arr[i].tag; + } + return this->len; + } + inline bool find_index (hb_tag_t tag, unsigned int *index) const + { + int i = this->search (tag); + if (i != -1) { + if (index) *index = i; + return true; + } else { + if (index) *index = Index::NOT_FOUND_INDEX; + return false; + } + } +}; + +template +struct RecordListOf : RecordArrayOf +{ + inline const Type& operator [] (unsigned int i) const + { return this+RecordArrayOf::operator [](i).offset; } + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (RecordArrayOf::sanitize (c, this)); + } +}; + + +struct RangeRecord +{ + inline int cmp (hb_codepoint_t g) const { + return g < start ? -1 : g <= end ? 0 : +1 ; + } + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this)); + } + + inline bool intersects (const hb_set_t *glyphs) const { + return glyphs->intersects (start, end); + } + + template + inline void add_coverage (set_t *glyphs) const { + glyphs->add_range (start, end); + } + + GlyphID start; /* First GlyphID in the range */ + GlyphID end; /* Last GlyphID in the range */ + USHORT value; /* Value */ + public: + DEFINE_SIZE_STATIC (6); +}; +DEFINE_NULL_DATA (RangeRecord, "\000\001"); + + +struct IndexArray : ArrayOf +{ + inline unsigned int get_indexes (unsigned int start_offset, + unsigned int *_count /* IN/OUT */, + unsigned int *_indexes /* OUT */) const + { + if (_count) { + const USHORT *arr = this->sub_array (start_offset, _count); + unsigned int count = *_count; + for (unsigned int i = 0; i < count; i++) + _indexes[i] = arr[i]; + } + return this->len; + } +}; + + +struct Script; +struct LangSys; +struct Feature; + + +struct LangSys +{ + inline unsigned int get_feature_count (void) const + { return featureIndex.len; } + inline hb_tag_t get_feature_index (unsigned int i) const + { return featureIndex[i]; } + inline unsigned int get_feature_indexes (unsigned int start_offset, + unsigned int *feature_count /* IN/OUT */, + unsigned int *feature_indexes /* OUT */) const + { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); } + + inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; } + inline unsigned int get_required_feature_index (void) const + { + if (reqFeatureIndex == 0xffff) + return Index::NOT_FOUND_INDEX; + return reqFeatureIndex;; + } + + inline bool sanitize (hb_sanitize_context_t *c, + const Record::sanitize_closure_t * = NULL) { + TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c)); + } + + Offset lookupOrder; /* = Null (reserved for an offset to a + * reordering table) */ + USHORT reqFeatureIndex;/* Index of a feature required for this + * language system--if no required features + * = 0xFFFF */ + IndexArray featureIndex; /* Array of indices into the FeatureList */ + public: + DEFINE_SIZE_ARRAY (6, featureIndex); +}; +DEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF"); + + +struct Script +{ + inline unsigned int get_lang_sys_count (void) const + { return langSys.len; } + inline const Tag& get_lang_sys_tag (unsigned int i) const + { return langSys.get_tag (i); } + inline unsigned int get_lang_sys_tags (unsigned int start_offset, + unsigned int *lang_sys_count /* IN/OUT */, + hb_tag_t *lang_sys_tags /* OUT */) const + { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); } + inline const LangSys& get_lang_sys (unsigned int i) const + { + if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys (); + return this+langSys[i].offset; + } + inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const + { return langSys.find_index (tag, index); } + + inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; } + inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } + + inline bool sanitize (hb_sanitize_context_t *c, + const Record