--- old/make/lib/Awt2dLibraries.gmk 2019-02-28 12:03:44.834503193 -0800 +++ new/make/lib/Awt2dLibraries.gmk 2019-02-28 12:03:44.718503195 -0800 @@ -536,7 +536,8 @@ ifeq ($(call isTargetOs, windows), false) HARFBUZZ_CFLAGS += -DGETPAGESIZE -DHAVE_MPROTECT -DHAVE_PTHREAD \ - -DHAVE_SYSCONF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H + -DHAVE_SYSCONF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H \ + -DHB_NO_PRAGMA_GCC_DIAGNOSTIC endif ifeq ($(call isTargetOs, linux macosx), true) HARFBUZZ_CFLAGS += -DHAVE_INTEL_ATOMIC_PRIMITIVES @@ -613,8 +614,7 @@ type-limits missing-field-initializers implicit-fallthrough \ strict-aliasing undef unused-function, \ DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \ - maybe-uninitialized \ - missing-attributes class-memaccess, \ + maybe-uninitialized class-memaccess, \ DISABLED_WARNINGS_clang := unused-value incompatible-pointer-types \ tautological-constant-out-of-range-compare int-to-pointer-cast \ sign-compare undef missing-field-initializers, \ @@ -624,8 +624,8 @@ E_ENUM_VAL_OVERFLOWS_INT_MAX, \ DISABLED_WARNINGS_CXX_solstudio := \ truncwarn wvarhidenmem wvarhidemem wbadlkginit identexpected \ - hidevf w_novirtualdescr arrowrtn2, \ - DISABLED_WARNINGS_microsoft := 4267 4244 4018 4090 4996 4146 4334 4819 4101, \ + hidevf w_novirtualdescr arrowrtn2 refmemnoconstr_aggr unknownpragma, \ + DISABLED_WARNINGS_microsoft := 4267 4244 4018 4090 4996 4146 4334 4819 4101 4068 4805 4138, \ LDFLAGS := $(subst -Xlinker -z -Xlinker defs,, \ $(subst -Wl$(COMMA)-z$(COMMA)defs,,$(LDFLAGS_JDKLIB))) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ --- old/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc 2019-02-28 12:03:45.210503187 -0800 +++ new/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc 2019-02-28 12:03:45.110503188 -0800 @@ -36,8 +36,32 @@ #define HB_UNUSED #endif + +static hb_bool_t +hb_jdk_get_nominal_glyph (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t unicode, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + + JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data; + JNIEnv* env = jdkFontInfo->env; + jobject font2D = jdkFontInfo->font2D; + *glyph = (hb_codepoint_t)env->CallIntMethod( + font2D, sunFontIDs.f2dCharToGlyphMID, unicode); + if (env->ExceptionOccurred()) + { + env->ExceptionClear(); + } + if ((int)*glyph < 0) { + *glyph = 0; + } + return (*glyph != 0); +} + static hb_bool_t -hb_jdk_get_glyph (hb_font_t *font HB_UNUSED, +hb_jdk_get_variation_glyph (hb_font_t *font HB_UNUSED, void *font_data, hb_codepoint_t unicode, hb_codepoint_t variation_selector, @@ -48,14 +72,9 @@ JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data; JNIEnv* env = jdkFontInfo->env; jobject font2D = jdkFontInfo->font2D; - if (variation_selector == 0) { - *glyph = (hb_codepoint_t)env->CallIntMethod( - font2D, sunFontIDs.f2dCharToGlyphMID, unicode); - } else { - *glyph = (hb_codepoint_t)env->CallIntMethod( - font2D, sunFontIDs.f2dCharToVariationGlyphMID, - unicode, variation_selector); - } + *glyph = (hb_codepoint_t)env->CallIntMethod( + font2D, sunFontIDs.f2dCharToVariationGlyphMID, + unicode, variation_selector); if (env->ExceptionOccurred()) { env->ExceptionClear(); @@ -251,7 +270,8 @@ if (!jdk_ffuncs) { ff = hb_font_funcs_create(); - hb_font_funcs_set_glyph_func(ff, hb_jdk_get_glyph, NULL, NULL); + hb_font_funcs_set_nominal_glyph_func(ff, hb_jdk_get_nominal_glyph, NULL, NULL); + hb_font_funcs_set_variation_glyph_func(ff, hb_jdk_get_variation_glyph, NULL, NULL); hb_font_funcs_set_glyph_h_advance_func(ff, hb_jdk_get_glyph_h_advance, NULL, NULL); hb_font_funcs_set_glyph_v_advance_func(ff, --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc 2019-02-28 12:03:45.566503181 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc 2019-02-28 12:03:45.466503183 -0800 @@ -25,14 +25,20 @@ * Red Hat Author(s): Behdad Esfahbod */ -/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */ + +/* https://github.com/harfbuzz/harfbuzz/issues/1308 + * http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html + * https://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html + */ #ifndef _POSIX_C_SOURCE +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-macros" #define _POSIX_C_SOURCE 200809L +#pragma GCC diagnostic pop #endif -#include "hb-private.hh" -#include "hb-debug.hh" -#include "hb-blob-private.hh" +#include "hb.hh" +#include "hb-blob.hh" #ifdef HAVE_SYS_MMAN_H #ifdef HAVE_UNISTD_H @@ -47,6 +53,19 @@ /** + * SECTION: hb-blob + * @title: hb-blob + * @short_description: Binary data containers + * @include: hb.h + * + * Blobs wrap a chunk of binary data to handle lifecycle management of data + * while it is passed between client and HarfBuzz. Blobs are primarily used + * to create font faces, but also to access font face tables, as well as + * pass around other binary data. + **/ + + +/** * hb_blob_create: (skip) * @data: Pointer to blob data. * @length: Length of @data in bytes. @@ -130,7 +149,7 @@ { hb_blob_t *blob; - if (!length || offset >= parent->length) + if (!length || !parent || offset >= parent->length) return hb_blob_get_empty (); hb_blob_make_immutable (parent); @@ -181,22 +200,9 @@ * Since: 0.9.2 **/ hb_blob_t * -hb_blob_get_empty (void) +hb_blob_get_empty () { - static const hb_blob_t _hb_blob_nil = { - HB_OBJECT_HEADER_STATIC, - - true, /* immutable */ - - nullptr, /* data */ - 0, /* length */ - HB_MEMORY_MODE_READONLY, /* mode */ - - nullptr, /* user_data */ - nullptr /* destroy */ - }; - - return const_cast (&_hb_blob_nil); + return const_cast (&Null(hb_blob_t)); } /** @@ -291,10 +297,10 @@ void hb_blob_make_immutable (hb_blob_t *blob) { - if (hb_object_is_inert (blob)) + if (hb_object_is_immutable (blob)) return; - blob->immutable = true; + hb_object_make_immutable (blob); } /** @@ -310,7 +316,7 @@ hb_bool_t hb_blob_is_immutable (hb_blob_t *blob) { - return blob->immutable; + return hb_object_is_immutable (blob); } @@ -384,7 +390,7 @@ bool -hb_blob_t::try_make_writable_inplace_unix (void) +hb_blob_t::try_make_writable_inplace_unix () { #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT) uintptr_t pagesize = -1, mask, length; @@ -427,7 +433,7 @@ } bool -hb_blob_t::try_make_writable_inplace (void) +hb_blob_t::try_make_writable_inplace () { DEBUG_MSG_FUNC (BLOB, this, "making writable inplace\n"); @@ -442,9 +448,9 @@ } bool -hb_blob_t::try_make_writable (void) +hb_blob_t::try_make_writable () { - if (this->immutable) + if (hb_object_is_immutable (this)) return false; if (this->mode == HB_MEMORY_MODE_WRITABLE) @@ -487,11 +493,11 @@ # include #endif -#if defined(_WIN32) || defined(__CYGWIN__) +#ifdef _WIN32 # include #else -# ifndef _O_BINARY -# define _O_BINARY 0 +# ifndef O_BINARY +# define O_BINARY 0 # endif #endif @@ -503,17 +509,19 @@ { char *contents; unsigned long length; -#if defined(_WIN32) || defined(__CYGWIN__) +#ifdef _WIN32 HANDLE mapping; #endif }; +#if (defined(HAVE_MMAP) || defined(_WIN32)) && !defined(HB_NO_MMAP) static void -_hb_mapped_file_destroy (hb_mapped_file_t *file) +_hb_mapped_file_destroy (void *file_) { + hb_mapped_file_t *file = (hb_mapped_file_t *) file_; #ifdef HAVE_MMAP munmap (file->contents, file->length); -#elif defined(_WIN32) || defined(__CYGWIN__) +#elif defined(_WIN32) UnmapViewOfFile (file->contents); CloseHandle (file->mapping); #else @@ -522,6 +530,7 @@ free (file); } +#endif /** * hb_blob_create_from_file: @@ -540,7 +549,7 @@ hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t)); if (unlikely (!file)) return hb_blob_get_empty (); - int fd = open (file_name, O_RDONLY | _O_BINARY, 0); + int fd = open (file_name, O_RDONLY | O_BINARY, 0); if (unlikely (fd == -1)) goto fail_without_close; struct stat st; @@ -563,21 +572,54 @@ fail_without_close: free (file); -#elif (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_MMAP) +#elif defined(_WIN32) && !defined(HB_NO_MMAP) hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t)); if (unlikely (!file)) return hb_blob_get_empty (); - HANDLE fd = CreateFile (file_name, GENERIC_READ, FILE_SHARE_READ, nullptr, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, - nullptr); + HANDLE fd; + unsigned int size = strlen (file_name) + 1; + wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size); + if (unlikely (wchar_file_name == nullptr)) goto fail_without_close; + mbstowcs (wchar_file_name, file_name, size); +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) + { + CREATEFILE2_EXTENDED_PARAMETERS ceparams = { 0 }; + ceparams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + ceparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0xFFFF; + ceparams.dwFileFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0xFFF00000; + ceparams.dwSecurityQosFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0x000F0000; + ceparams.lpSecurityAttributes = nullptr; + ceparams.hTemplateFile = nullptr; + fd = CreateFile2 (wchar_file_name, GENERIC_READ, FILE_SHARE_READ, + OPEN_EXISTING, &ceparams); + } +#else + fd = CreateFileW (wchar_file_name, GENERIC_READ, FILE_SHARE_READ, nullptr, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, + nullptr); +#endif + free (wchar_file_name); if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close; +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) + { + LARGE_INTEGER length; + GetFileSizeEx (fd, &length); + file->length = length.LowPart; + file->mapping = CreateFileMappingFromApp (fd, nullptr, PAGE_READONLY, length.QuadPart, nullptr); + } +#else file->length = (unsigned long) GetFileSize (fd, nullptr); file->mapping = CreateFileMapping (fd, nullptr, PAGE_READONLY, 0, 0, nullptr); +#endif if (unlikely (file->mapping == nullptr)) goto fail; +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) + file->contents = (char *) MapViewOfFileFromApp (file->mapping, FILE_MAP_READ, 0, 0); +#else file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0); +#endif if (unlikely (file->contents == nullptr)) goto fail; CloseHandle (fd); --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh 2019-02-28 12:03:45.882503176 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh 2019-02-28 12:03:45.782503177 -0800 @@ -29,7 +29,7 @@ #ifndef HB_BUFFER_DESERIALIZE_JSON_HH #define HB_BUFFER_DESERIALIZE_JSON_HH -#include "hb-private.hh" +#include "hb.hh" #line 36 "hb-buffer-deserialize-json.hh" --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh 2019-02-28 12:03:46.242503170 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh 2019-02-28 12:03:46.118503172 -0800 @@ -29,7 +29,7 @@ #ifndef HB_BUFFER_DESERIALIZE_TEXT_HH #define HB_BUFFER_DESERIALIZE_TEXT_HH -#include "hb-private.hh" +#include "hb.hh" #line 36 "hb-buffer-deserialize-text.hh" --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-serialize.cc 2019-02-28 12:03:46.554503165 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-serialize.cc 2019-02-28 12:03:46.454503166 -0800 @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-buffer-private.hh" +#include "hb-buffer.hh" static const char *serialize_formats[] = { @@ -44,7 +44,7 @@ * Since: 0.9.7 **/ const char ** -hb_buffer_serialize_list_formats (void) +hb_buffer_serialize_list_formats () { return serialize_formats; } @@ -246,7 +246,7 @@ if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS) { - if (info[i].mask &HB_GLYPH_FLAG_DEFINED) + if (info[i].mask & HB_GLYPH_FLAG_DEFINED) p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED)); } @@ -440,8 +440,8 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, const char *buf, int buf_len, /* -1 means nul-terminated */ - const char **end_ptr, /* May be nullptr */ - hb_font_t *font, /* May be nullptr */ + const char **end_ptr, /* May be NULL */ + hb_font_t *font, /* May be NULL */ hb_buffer_serialize_format_t format) { const char *end; --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.cc 2019-02-28 12:03:46.886503159 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.cc 2019-02-28 12:03:46.766503161 -0800 @@ -27,20 +27,21 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-buffer-private.hh" -#include "hb-utf-private.hh" +#include "hb-buffer.hh" +#include "hb-utf.hh" /** * SECTION: hb-buffer - * @title: Buffers + * @title: hb-buffer * @short_description: Input and output buffers * @include: hb.h * * Buffers serve dual role in HarfBuzz; they hold the input characters that are - * passed hb_shape(), and after shaping they hold the output glyphs. + * passed to hb_shape(), and after shaping they hold the output glyphs. **/ + /** * hb_segment_properties_equal: * @a: first #hb_segment_properties_t to compare. @@ -124,14 +125,14 @@ hb_glyph_info_t *new_info = nullptr; bool separate_out = out_info != info; - if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0])))) + if (unlikely (hb_unsigned_mul_overflows (size, sizeof (info[0])))) goto done; while (size >= new_allocated) new_allocated += (new_allocated >> 1) + 32; static_assert ((sizeof (info[0]) == sizeof (pos[0])), ""); - if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0])))) + if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0])))) goto done; new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0])); @@ -182,7 +183,11 @@ if (idx + count > len) { /* Under memory failure we might expose this area. At least - * clean it up. Oh well... */ + * clean it up. Oh well... + * + * Ideally, we should at least set Default_Ignorable bits on + * these, as well as consistent cluster values. But the former + * is layering violation... */ memset (info + len, 0, (idx + count - len) * sizeof (info[0])); } len += count; @@ -210,23 +215,24 @@ /* HarfBuzz-Internal API */ void -hb_buffer_t::reset (void) +hb_buffer_t::reset () { - if (unlikely (hb_object_is_inert (this))) + if (unlikely (hb_object_is_immutable (this))) return; hb_unicode_funcs_destroy (unicode); - unicode = hb_unicode_funcs_get_default (); + unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ()); flags = HB_BUFFER_FLAG_DEFAULT; replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; + invisible = 0; clear (); } void -hb_buffer_t::clear (void) +hb_buffer_t::clear () { - if (unlikely (hb_object_is_inert (this))) + if (unlikely (hb_object_is_immutable (this))) return; hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; @@ -281,9 +287,9 @@ void -hb_buffer_t::remove_output (void) +hb_buffer_t::remove_output () { - if (unlikely (hb_object_is_inert (this))) + if (unlikely (hb_object_is_immutable (this))) return; have_output = false; @@ -294,9 +300,9 @@ } void -hb_buffer_t::clear_output (void) +hb_buffer_t::clear_output () { - if (unlikely (hb_object_is_inert (this))) + if (unlikely (hb_object_is_immutable (this))) return; have_output = true; @@ -307,9 +313,9 @@ } void -hb_buffer_t::clear_positions (void) +hb_buffer_t::clear_positions () { - if (unlikely (hb_object_is_inert (this))) + if (unlikely (hb_object_is_immutable (this))) return; have_output = false; @@ -322,7 +328,7 @@ } void -hb_buffer_t::swap_buffers (void) +hb_buffer_t::swap_buffers () { if (unlikely (!successful)) return; @@ -354,6 +360,8 @@ { if (unlikely (!make_room_for (num_in, num_out))) return; + assert (idx + num_in <= len); + merge_clusters (idx, idx + num_in); hb_glyph_info_t orig_info = info[idx]; @@ -369,37 +377,6 @@ 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++; -} - bool hb_buffer_t::move_to (unsigned int i) { @@ -429,8 +406,14 @@ unsigned int count = out_len - i; /* This will blow in our face if memory allocation fails later - * in this same lookup... */ - if (unlikely (idx < count && !shift_forward (count + 32))) return false; + * in this same lookup... + * + * We used to shift with extra 32 items, instead of the 0 below. + * But that would leave empty slots in the buffer in case of allocation + * failures. Setting to zero for now to avoid other problems (see + * comments in shift_forward(). This can cause O(N^2) behavior more + * severely than adding 32 empty slots can... */ + if (unlikely (idx < count && !shift_forward (count + 0))) return false; assert (idx >= count); @@ -442,19 +425,6 @@ return true; } -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, @@ -510,7 +480,7 @@ } void -hb_buffer_t::reverse (void) +hb_buffer_t::reverse () { if (unlikely (!len)) return; @@ -519,7 +489,7 @@ } void -hb_buffer_t::reverse_clusters (void) +hb_buffer_t::reverse_clusters () { unsigned int i, start, count, last_cluster; @@ -666,7 +636,7 @@ } void -hb_buffer_t::guess_segment_properties (void) +hb_buffer_t::guess_segment_properties () { assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || (!len && content_type == HB_BUFFER_CONTENT_TYPE_INVALID)); @@ -701,6 +671,29 @@ /* Public API */ +DEFINE_NULL_INSTANCE (hb_buffer_t) = +{ + HB_OBJECT_HEADER_STATIC, + + const_cast (&_hb_Null_hb_unicode_funcs_t), + HB_BUFFER_FLAG_DEFAULT, + HB_BUFFER_CLUSTER_LEVEL_DEFAULT, + HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, + 0, /* invisible */ + HB_BUFFER_SCRATCH_FLAG_DEFAULT, + HB_BUFFER_MAX_LEN_DEFAULT, + HB_BUFFER_MAX_OPS_DEFAULT, + + HB_BUFFER_CONTENT_TYPE_INVALID, + HB_SEGMENT_PROPERTIES_DEFAULT, + false, /* successful */ + true, /* have_output */ + true /* have_positions */ + + /* Zero is good enough for everything else. */ +}; + + /** * hb_buffer_create: (Xconstructor) * @@ -716,7 +709,7 @@ * Since: 0.9.2 **/ hb_buffer_t * -hb_buffer_create (void) +hb_buffer_create () { hb_buffer_t *buffer; @@ -741,29 +734,9 @@ * Since: 0.9.2 **/ hb_buffer_t * -hb_buffer_get_empty (void) +hb_buffer_get_empty () { - static const hb_buffer_t _hb_buffer_nil = { - HB_OBJECT_HEADER_STATIC, - - const_cast (&_hb_unicode_funcs_nil), - HB_BUFFER_FLAG_DEFAULT, - HB_BUFFER_CLUSTER_LEVEL_DEFAULT, - HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, - HB_BUFFER_SCRATCH_FLAG_DEFAULT, - HB_BUFFER_MAX_LEN_DEFAULT, - HB_BUFFER_MAX_OPS_DEFAULT, - - HB_BUFFER_CONTENT_TYPE_INVALID, - HB_SEGMENT_PROPERTIES_DEFAULT, - false, /* successful */ - true, /* have_output */ - true /* have_positions */ - - /* Zero is good enough for everything else. */ - }; - - return const_cast (&_hb_buffer_nil); + return const_cast (&Null(hb_buffer_t)); } /** @@ -900,13 +873,12 @@ hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, hb_unicode_funcs_t *unicode_funcs) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; if (!unicode_funcs) unicode_funcs = hb_unicode_funcs_get_default (); - hb_unicode_funcs_reference (unicode_funcs); hb_unicode_funcs_destroy (buffer->unicode); buffer->unicode = unicode_funcs; @@ -948,7 +920,7 @@ hb_direction_t direction) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->props.direction = direction; @@ -992,7 +964,7 @@ hb_buffer_set_script (hb_buffer_t *buffer, hb_script_t script) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->props.script = script; @@ -1027,7 +999,7 @@ * are orthogonal to the scripts, and though they are related, they are * different concepts and should not be confused with each other. * - * Use hb_language_from_string() to convert from ISO 639 language codes to + * Use hb_language_from_string() to convert from BCP 47 language tags to * #hb_language_t. * * Since: 0.9.2 @@ -1036,7 +1008,7 @@ hb_buffer_set_language (hb_buffer_t *buffer, hb_language_t language) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->props.language = language; @@ -1074,7 +1046,7 @@ hb_buffer_set_segment_properties (hb_buffer_t *buffer, const hb_segment_properties_t *props) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->props = *props; @@ -1110,7 +1082,7 @@ hb_buffer_set_flags (hb_buffer_t *buffer, hb_buffer_flags_t flags) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->flags = flags; @@ -1146,7 +1118,7 @@ hb_buffer_set_cluster_level (hb_buffer_t *buffer, hb_buffer_cluster_level_t cluster_level) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->cluster_level = cluster_level; @@ -1185,7 +1157,7 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, hb_codepoint_t replacement) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return; buffer->replacement = replacement; @@ -1210,6 +1182,46 @@ /** + * hb_buffer_set_invisible_glyph: + * @buffer: an #hb_buffer_t. + * @invisible: the invisible #hb_codepoint_t + * + * Sets the #hb_codepoint_t that replaces invisible characters in + * the shaping result. If set to zero (default), the glyph for the + * U+0020 SPACE character is used. Otherwise, this value is used + * verbatim. + * + * Since: 2.0.0 + **/ +void +hb_buffer_set_invisible_glyph (hb_buffer_t *buffer, + hb_codepoint_t invisible) +{ + if (unlikely (hb_object_is_immutable (buffer))) + return; + + buffer->invisible = invisible; +} + +/** + * hb_buffer_get_invisible_glyph: + * @buffer: an #hb_buffer_t. + * + * See hb_buffer_set_invisible_glyph(). + * + * Return value: + * The @buffer invisible #hb_codepoint_t. + * + * Since: 2.0.0 + **/ +hb_codepoint_t +hb_buffer_get_invisible_glyph (hb_buffer_t *buffer) +{ + return buffer->invisible; +} + + +/** * hb_buffer_reset: * @buffer: an #hb_buffer_t. * @@ -1317,7 +1329,7 @@ hb_buffer_set_length (hb_buffer_t *buffer, unsigned int length) { - if (unlikely (hb_object_is_inert (buffer))) + if (unlikely (hb_object_is_immutable (buffer))) return length == 0; if (!buffer->ensure (length)) @@ -1498,6 +1510,8 @@ * it will be set to the process's default language as returned by * hb_language_get_default(). This may change in the future by * taking buffer script into consideration when choosing a language. + * Note that hb_language_get_default() is NOT threadsafe the first time + * it is called. See documentation for that function for details. * * Since: 0.9.7 **/ @@ -1521,7 +1535,7 @@ 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))) + if (unlikely (hb_object_is_immutable (buffer))) return; if (text_length == -1) @@ -1652,7 +1666,7 @@ unsigned int item_offset, int item_length) { - hb_buffer_add_utf > (buffer, text, text_length, item_offset, item_length); + hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); } /** @@ -1713,7 +1727,7 @@ unsigned int item_offset, int item_length) { - hb_buffer_add_utf > (buffer, text, text_length, item_offset, item_length); + hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); } @@ -1886,6 +1900,10 @@ /** * hb_buffer_diff: + * @buffer: a buffer. + * @reference: other buffer to compare to. + * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1. + * @position_fuzz: allowed absolute difference in position values. * * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.h 2019-02-28 12:03:47.230503153 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.h 2019-02-28 12:03:47.130503155 -0800 @@ -44,7 +44,6 @@ * hb_glyph_info_t: * @codepoint: either a Unicode code point (before shaping) or a glyph index * (after shaping). - * @mask: * @cluster: the index of the character in the original text that corresponds * to this #hb_glyph_info_t, or whatever the client passes to * hb_buffer_add(). More than one #hb_glyph_info_t can have the same @@ -59,11 +58,13 @@ * * The #hb_glyph_info_t is the structure that holds information about the * glyphs and their relation to input text. - * */ -typedef struct hb_glyph_info_t { +typedef struct hb_glyph_info_t +{ hb_codepoint_t codepoint; - hb_mask_t mask; /* Holds hb_glyph_flags_t after hb_shape(), plus other things. */ + /*< private >*/ + hb_mask_t mask; + /*< public >*/ uint32_t cluster; /*< private >*/ @@ -88,6 +89,9 @@ * of each line after line-breaking, or limiting * the reshaping to a small piece around the * breaking point only. + * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags. + * + * Since: 1.5.0 */ typedef enum { /*< flags >*/ HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001, @@ -298,7 +302,15 @@ HB_EXTERN hb_buffer_flags_t hb_buffer_get_flags (hb_buffer_t *buffer); -/* +/** + * hb_buffer_cluster_level_t: + * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES: Return cluster values grouped by graphemes into + * monotone order. + * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS: Return cluster values grouped into monotone order. + * @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: Don't group cluster values. + * @HB_BUFFER_CLUSTER_LEVEL_DEFAULT: Default cluster level, + * equal to @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES. + * * Since: 0.9.42 */ typedef enum { @@ -332,6 +344,13 @@ HB_EXTERN hb_codepoint_t hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer); +HB_EXTERN void +hb_buffer_set_invisible_glyph (hb_buffer_t *buffer, + hb_codepoint_t invisible); + +HB_EXTERN hb_codepoint_t +hb_buffer_get_invisible_glyph (hb_buffer_t *buffer); + HB_EXTERN void hb_buffer_reset (hb_buffer_t *buffer); --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.cc 2019-02-28 12:03:47.586503148 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.cc 2019-02-28 12:03:47.486503149 -0800 @@ -26,10 +26,9 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-private.hh" +#include "hb.hh" -#include "hb-mutex-private.hh" -#include "hb-object-private.hh" +#include "hb-machinery.hh" #include #ifdef HAVE_XLOCALE_H @@ -37,22 +36,51 @@ #endif +/** + * SECTION:hb-common + * @title: hb-common + * @short_description: Common data types + * @include: hb.h + * + * Common data types used across HarfBuzz are defined here. + **/ + + /* hb_options_t */ -hb_options_union_t _hb_options; +hb_atomic_int_t _hb_options; void -_hb_options_init (void) +_hb_options_init () { hb_options_union_t u; u.i = 0; - u.opts.initialized = 1; + u.opts.initialized = true; + + const char *c = getenv ("HB_OPTIONS"); + if (c) + { + while (*c) + { + const char *p = strchr (c, ':'); + if (!p) + p = c + strlen (c); + +#define OPTION(name, symbol) \ + if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) u.opts.symbol = true; + + OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible); + OPTION ("aat", aat); + +#undef OPTION + + c = *p ? p + 1 : p; + } - 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_options.set_relaxed (u.i); } @@ -176,7 +204,7 @@ 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', + 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 @@ -219,11 +247,10 @@ struct hb_language_item_t *next; hb_language_t lang; - inline bool operator == (const char *s) const { - return lang_equal (lang, s); - } + bool operator == (const char *s) const + { return lang_equal (lang, s); } - inline hb_language_item_t & operator = (const char *s) { + hb_language_item_t & operator = (const char *s) { /* If a custom allocated is used calling strdup() pairs badly with a call to the custom free() in fini() below. Therefore don't call strdup(), implement its behavior. @@ -240,21 +267,21 @@ return *this; } - void fini (void) { free ((void *) lang); } + void fini () { free ((void *) lang); } }; /* Thread-safe lock-free language list */ -static hb_language_item_t *langs; +static hb_atomic_ptr_t langs; -#ifdef HB_USE_ATEXIT +#if HB_USE_ATEXIT static void -free_langs (void) +free_langs () { retry: - hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs); - if (!hb_atomic_ptr_cmpexch (&langs, first_lang, nullptr)) + hb_language_item_t *first_lang = langs; + if (unlikely (!langs.cmpexch (first_lang, nullptr))) goto retry; while (first_lang) { @@ -270,7 +297,7 @@ lang_find_or_insert (const char *key) { retry: - hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs); + hb_language_item_t *first_lang = langs; for (hb_language_item_t *lang = first_lang; lang; lang = lang->next) if (*lang == key) @@ -288,13 +315,14 @@ return nullptr; } - if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) { + if (unlikely (!langs.cmpexch (first_lang, lang))) + { lang->fini (); free (lang); goto retry; } -#ifdef HB_USE_ATEXIT +#if HB_USE_ATEXIT if (!first_lang) atexit (free_langs); /* First person registers atexit() callback. */ #endif @@ -306,14 +334,14 @@ /** * hb_language_from_string: * @str: (array length=len) (element-type uint8_t): a string representing - * ISO 639 language code + * a BCP 47 language tag * @len: length of the @str, or -1 if it is %NULL-terminated. * - * Converts @str representing an ISO 639 language code to the corresponding + * Converts @str representing a BCP 47 language tag to the corresponding * #hb_language_t. * * Return value: (transfer none): - * The #hb_language_t corresponding to the ISO 639 language code. + * The #hb_language_t corresponding to the BCP 47 language tag. * * Since: 0.9.2 **/ @@ -361,24 +389,32 @@ /** * hb_language_get_default: * + * Get default language from current locale. * + * Note that the first time this function is called, it calls + * "setlocale (LC_CTYPE, nullptr)" to fetch current locale. The underlying + * setlocale function is, in many implementations, NOT threadsafe. To avoid + * problems, call this function once before multiple threads can call it. + * This function is only used from hb_buffer_guess_segment_properties() by + * HarfBuzz itself. * * Return value: (transfer none): * * Since: 0.9.2 **/ hb_language_t -hb_language_get_default (void) +hb_language_get_default () { - static hb_language_t default_language = HB_LANGUAGE_INVALID; + static hb_atomic_ptr_t default_language; - hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language); - if (unlikely (language == HB_LANGUAGE_INVALID)) { + hb_language_t language = default_language; + if (unlikely (language == HB_LANGUAGE_INVALID)) + { language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1); - (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language); + (void) default_language.cmpexch (HB_LANGUAGE_INVALID, language); } - return default_language; + return language; } @@ -530,7 +566,6 @@ /* Unicode-8.0 additions */ case HB_SCRIPT_HATRAN: - case HB_SCRIPT_OLD_HUNGARIAN: /* Unicode-9.0 additions */ case HB_SCRIPT_ADLAM: @@ -544,7 +579,9 @@ /* https://github.com/harfbuzz/harfbuzz/issues/1000 */ + case HB_SCRIPT_OLD_HUNGARIAN: case HB_SCRIPT_OLD_ITALIC: + case HB_SCRIPT_RUNIC: return HB_DIRECTION_INVALID; } @@ -587,6 +624,19 @@ /* hb_version */ + +/** + * SECTION:hb-version + * @title: hb-version + * @short_description: Information about the version of HarfBuzz in use + * @include: hb.h + * + * These functions and macros allow accessing version of the HarfBuzz + * library used at compile- as well as run-time, and to direct code + * conditionally based on those versions, again, at compile- or run-time. + **/ + + /** * hb_version: * @major: (out): Library major version component. @@ -617,7 +667,7 @@ * Since: 0.9.2 **/ const char * -hb_version_string (void) +hb_version_string () { return HB_VERSION_STRING; } @@ -729,48 +779,48 @@ #ifdef USE_XLOCALE -static HB_LOCALE_T C_locale; - -#ifdef HB_USE_ATEXIT -static void -free_C_locale (void) -{ -retry: - HB_LOCALE_T locale = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale); - - if (!hb_atomic_ptr_cmpexch (&C_locale, locale, nullptr)) - goto retry; - - if (locale) - HB_FREE_LOCALE (locale); -} +#if HB_USE_ATEXIT +static void free_static_C_locale (); #endif -static HB_LOCALE_T -get_C_locale (void) +static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t { -retry: - HB_LOCALE_T C = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale); - - if (unlikely (!C)) + static HB_LOCALE_T create () { - C = HB_CREATE_LOCALE ("C"); - - if (!hb_atomic_ptr_cmpexch (&C_locale, nullptr, C)) - { - HB_FREE_LOCALE (C_locale); - goto retry; - } + HB_LOCALE_T C_locale = HB_CREATE_LOCALE ("C"); -#ifdef HB_USE_ATEXIT - atexit (free_C_locale); /* First person registers atexit() callback. */ +#if HB_USE_ATEXIT + atexit (free_static_C_locale); #endif + + return C_locale; + } + static void destroy (HB_LOCALE_T p) + { + HB_FREE_LOCALE (p); } + static HB_LOCALE_T get_null () + { + return nullptr; + } +} static_C_locale; - return C; +#if HB_USE_ATEXIT +static +void free_static_C_locale () +{ + static_C_locale.free_instance (); } #endif +static HB_LOCALE_T +get_C_locale () +{ + return static_C_locale.get_unconst (); +} +#endif /* USE_XLOCALE */ + static bool parse_float (const char **pp, const char *end, float *pv) { @@ -846,7 +896,7 @@ } const char *p = *pp; - while (*pp < end && ISALNUM(**pp)) + while (*pp < end && (ISALNUM(**pp) || **pp == '_')) (*pp)++; if (p == *pp || *pp - p > 4) @@ -875,15 +925,15 @@ bool has_start; - feature->start = 0; - feature->end = (unsigned int) -1; + feature->start = HB_FEATURE_GLOBAL_START; + feature->end = HB_FEATURE_GLOBAL_END; if (!parse_char (pp, end, '[')) return true; has_start = parse_uint (pp, end, &feature->start); - if (parse_char (pp, end, ':')) { + if (parse_char (pp, end, ':') || parse_char (pp, end, ';')) { parse_uint (pp, end, &feature->end); } else { if (has_start) @@ -1063,10 +1113,19 @@ while (len && s[len - 1] == ' ') len--; s[len++] = '='; - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value)); + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value)); assert (len < ARRAY_LENGTH (s)); len = MIN (len, size - 1); memcpy (buf, s, len); buf[len] = '\0'; } + +/* If there is no visibility control, then hb-static.cc will NOT + * define anything. Instead, we get it to define one set in here + * only, so only libharfbuzz.so defines them, not other libs. */ +#ifdef HB_NO_VISIBILITY +#undef HB_NO_VISIBILITY +#include "hb-static.cc" +#define HB_NO_VISIBILITY 1 +#endif --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.h 2019-02-28 12:03:47.910503142 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.h 2019-02-28 12:03:47.810503144 -0800 @@ -33,6 +33,10 @@ #ifndef HB_COMMON_H #define HB_COMMON_H +#ifndef HB_EXTERN +#define HB_EXTERN extern +#endif + #ifndef HB_BEGIN_DECLS # ifdef __cplusplus # define HB_BEGIN_DECLS extern "C" { @@ -63,6 +67,23 @@ # include #endif +#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define HB_DEPRECATED __attribute__((__deprecated__)) +#elif defined(_MSC_VER) && (_MSC_VER >= 1300) +#define HB_DEPRECATED __declspec(deprecated) +#else +#define HB_DEPRECATED +#endif + +#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define HB_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead"))) +#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320) +#define HB_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead")) +#else +#define HB_DEPRECATED_FOR(f) HB_DEPRECATED +#endif + + HB_BEGIN_DECLS @@ -86,8 +107,8 @@ typedef uint32_t hb_tag_t; -#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint8_t)(c1))<<24)|(((uint8_t)(c2))<<16)|(((uint8_t)(c3))<<8)|((uint8_t)(c4)))) -#define HB_UNTAG(tag) ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag)) +#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF))) +#define HB_UNTAG(tag) (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&0xFF) #define HB_TAG_NONE HB_TAG(0,0,0,0) #define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff) @@ -340,13 +361,15 @@ HB_SCRIPT_INVALID = HB_TAG_NONE, /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t - * without risking undefined behavior. Include both a signed and unsigned max, - * since technically enums are int, and indeed, hb_script_t ends up being signed. + * without risking undefined behavior. We have two, for historical reasons. + * HB_TAG_MAX used to be unsigned, but that was invalid Ansi C, so was changed + * to _HB_SCRIPT_MAX_VALUE to be equal to HB_TAG_MAX_SIGNED as well. + * * See this thread for technicalities: * * https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html */ - _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX, /*< skip >*/ + _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX_SIGNED, /*< skip >*/ _HB_SCRIPT_MAX_VALUE_SIGNED = HB_TAG_MAX_SIGNED /*< skip >*/ } hb_script_t; @@ -379,6 +402,19 @@ /* Font features and variations. */ +/** + * HB_FEATURE_GLOBAL_START + * + * Since: 2.0.0 + */ +#define HB_FEATURE_GLOBAL_START 0 +/** + * HB_FEATURE_GLOBAL_END + * + * Since: 2.0.0 + */ +#define HB_FEATURE_GLOBAL_END ((unsigned int) -1) + typedef struct hb_feature_t { hb_tag_t tag; uint32_t value; @@ -412,6 +448,50 @@ hb_variation_to_string (hb_variation_t *variation, char *buf, unsigned int size); +/** + * hb_color_t: + * + * Data type for holding color values. + * + * Since: 2.1.0 + */ +typedef uint32_t hb_color_t; + +#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a))) + +/** + * hb_color_get_alpha: + * + * + * + * Since: 2.1.0 + */ +#define hb_color_get_alpha(color) ((color) & 0xFF) +/** + * hb_color_get_red: + * + * + * + * Since: 2.1.0 + */ +#define hb_color_get_red(color) (((color) >> 8) & 0xFF) +/** + * hb_color_get_green: + * + * + * + * Since: 2.1.0 + */ +#define hb_color_get_green(color) (((color) >> 16) & 0xFF) +/** + * hb_color_get_blue: + * + * + * + * Since: 2.1.0 + */ +#define hb_color_get_blue(color) (((color) >> 24) & 0xFF) + HB_END_DECLS --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc 2019-02-28 12:03:48.238503137 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc 2019-02-28 12:03:48.138503139 -0800 @@ -26,15 +26,23 @@ * Google Author(s): Behdad Esfahbod */ -#define HB_SHAPER coretext - -#include "hb-private.hh" -#include "hb-debug.hh" -#include "hb-shaper-impl-private.hh" +#include "hb.hh" +#include "hb-shaper-impl.hh" #include "hb-coretext.h" +#include "hb-aat-layout.hh" #include + +/** + * SECTION:hb-coretext + * @title: hb-coretext + * @short_description: CoreText integration + * @include: hb-coretext.h + * + * Functions for using HarfBuzz with the CoreText fonts. + **/ + /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f @@ -91,13 +99,8 @@ } -HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face) -HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font, - fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5 -) - static CTFontDescriptorRef -get_last_resort_font_desc (void) +get_last_resort_font_desc () { // TODO Handle allocation failures? CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0); @@ -211,7 +214,7 @@ } CFURLRef original_url = nullptr; -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 +#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060 ATSFontRef atsFont; FSRef fsref; OSStatus status; @@ -241,7 +244,7 @@ * process in Blink. This can be detected by the new file URL location * that the newly found font points to. */ CFURLRef new_url = nullptr; -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 +#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060 atsFont = CTFontGetPlatformFont (new_ct_font, NULL); status = ATSFontGetFileReference (atsFont, &fsref); if (status == noErr) @@ -270,7 +273,7 @@ return ct_font; } -hb_coretext_shaper_face_data_t * +hb_coretext_face_data_t * _hb_coretext_shaper_face_data_create (hb_face_t *face) { CGFontRef cg_font = create_cg_font (face); @@ -281,11 +284,11 @@ return nullptr; } - return (hb_coretext_shaper_face_data_t *) cg_font; + return (hb_coretext_face_data_t *) cg_font; } void -_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) +_hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data) { CFRelease ((CGFontRef) data); } @@ -302,17 +305,17 @@ CGFontRef hb_coretext_face_get_cg_font (hb_face_t *face) { - if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr; - return (CGFontRef) HB_SHAPER_DATA_GET (face); + return (CGFontRef) (const void *) face->data.coretext; } -hb_coretext_shaper_font_data_t * +hb_coretext_font_data_t * _hb_coretext_shaper_font_data_create (hb_font_t *font) { hb_face_t *face = font->face; - if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr; - CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); + const hb_coretext_face_data_t *face_data = face->data.coretext; + if (unlikely (!face_data)) return nullptr; + CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext; CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem)); @@ -322,15 +325,47 @@ return nullptr; } - return (hb_coretext_shaper_font_data_t *) ct_font; + return (hb_coretext_font_data_t *) ct_font; } void -_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) +_hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data) { CFRelease ((CTFontRef) data); } +static const hb_coretext_font_data_t * +hb_coretext_font_data_sync (hb_font_t *font) +{ +retry: + const hb_coretext_font_data_t *data = font->data.coretext; + if (unlikely (!data)) return nullptr; + + if (fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) > .5) + { + /* XXX-MT-bug + * Note that evaluating condition above can be dangerous if another thread + * got here first and destructed data. That's, as always, bad use pattern. + * If you modify the font (change font size), other threads must not be + * using it at the same time. However, since this check is delayed to + * when one actually tries to shape something, this is a XXX race condition + * (and the only one we have that I know of) right now. Ie. you modify the + * font size in one thread, then (supposedly safely) try to use it from two + * or more threads and BOOM! I'm not sure how to fix this. We want RCU. + */ + + /* Drop and recreate. */ + /* If someone dropped it in the mean time, throw it away and don't touch it. + * Otherwise, destruct it. */ + if (likely (font->data.coretext.cmpexch (const_cast (data), nullptr))) + _hb_coretext_shaper_font_data_destroy (const_cast (data)); + else + goto retry; + } + return font->data.coretext; +} + + /* * Since: 1.7.2 */ @@ -343,13 +378,13 @@ hb_font_t *font = hb_font_create (face); hb_face_destroy (face); - if (unlikely (hb_object_is_inert (font))) + if (unlikely (hb_object_is_immutable (font))) return font; hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font))); /* Let there be dragons here... */ - HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font); + font->data.coretext.cmpexch (nullptr, (hb_coretext_font_data_t *) CFRetain (ct_font)); return font; } @@ -357,31 +392,8 @@ CTFontRef hb_coretext_font_get_ct_font (hb_font_t *font) { - if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr; - return (CTFontRef) HB_SHAPER_DATA_GET (font); -} - - - -/* - * shaper shape_plan data - */ - -struct hb_coretext_shaper_shape_plan_data_t {}; - -hb_coretext_shaper_shape_plan_data_t * -_hb_coretext_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, - const int *coords HB_UNUSED, - unsigned int num_coords HB_UNUSED) -{ - return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; -} - -void -_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED) -{ + const hb_coretext_font_data_t *data = hb_coretext_font_data_sync (font); + return data ? (CTFontRef) data : nullptr; } @@ -432,183 +444,6 @@ }; -/* The following enum members are added in OS X 10.8. */ -#define kAltHalfWidthTextSelector 6 -#define kAltProportionalTextSelector 5 -#define kAlternateHorizKanaOffSelector 1 -#define kAlternateHorizKanaOnSelector 0 -#define kAlternateKanaType 34 -#define kAlternateVertKanaOffSelector 3 -#define kAlternateVertKanaOnSelector 2 -#define kCaseSensitiveLayoutOffSelector 1 -#define kCaseSensitiveLayoutOnSelector 0 -#define kCaseSensitiveLayoutType 33 -#define kCaseSensitiveSpacingOffSelector 3 -#define kCaseSensitiveSpacingOnSelector 2 -#define kContextualAlternatesOffSelector 1 -#define kContextualAlternatesOnSelector 0 -#define kContextualAlternatesType 36 -#define kContextualLigaturesOffSelector 19 -#define kContextualLigaturesOnSelector 18 -#define kContextualSwashAlternatesOffSelector 5 -#define kContextualSwashAlternatesOnSelector 4 -#define kDefaultLowerCaseSelector 0 -#define kDefaultUpperCaseSelector 0 -#define kHistoricalLigaturesOffSelector 21 -#define kHistoricalLigaturesOnSelector 20 -#define kHojoCharactersSelector 12 -#define kJIS2004CharactersSelector 11 -#define kLowerCasePetiteCapsSelector 2 -#define kLowerCaseSmallCapsSelector 1 -#define kLowerCaseType 37 -#define kMathematicalGreekOffSelector 11 -#define kMathematicalGreekOnSelector 10 -#define kNLCCharactersSelector 13 -#define kQuarterWidthTextSelector 4 -#define kScientificInferiorsSelector 4 -#define kStylisticAltEightOffSelector 17 -#define kStylisticAltEightOnSelector 16 -#define kStylisticAltEighteenOffSelector 37 -#define kStylisticAltEighteenOnSelector 36 -#define kStylisticAltElevenOffSelector 23 -#define kStylisticAltElevenOnSelector 22 -#define kStylisticAltFifteenOffSelector 31 -#define kStylisticAltFifteenOnSelector 30 -#define kStylisticAltFiveOffSelector 11 -#define kStylisticAltFiveOnSelector 10 -#define kStylisticAltFourOffSelector 9 -#define kStylisticAltFourOnSelector 8 -#define kStylisticAltFourteenOffSelector 29 -#define kStylisticAltFourteenOnSelector 28 -#define kStylisticAltNineOffSelector 19 -#define kStylisticAltNineOnSelector 18 -#define kStylisticAltNineteenOffSelector 39 -#define kStylisticAltNineteenOnSelector 38 -#define kStylisticAltOneOffSelector 3 -#define kStylisticAltOneOnSelector 2 -#define kStylisticAltSevenOffSelector 15 -#define kStylisticAltSevenOnSelector 14 -#define kStylisticAltSeventeenOffSelector 35 -#define kStylisticAltSeventeenOnSelector 34 -#define kStylisticAltSixOffSelector 13 -#define kStylisticAltSixOnSelector 12 -#define kStylisticAltSixteenOffSelector 33 -#define kStylisticAltSixteenOnSelector 32 -#define kStylisticAltTenOffSelector 21 -#define kStylisticAltTenOnSelector 20 -#define kStylisticAltThirteenOffSelector 27 -#define kStylisticAltThirteenOnSelector 26 -#define kStylisticAltThreeOffSelector 7 -#define kStylisticAltThreeOnSelector 6 -#define kStylisticAltTwelveOffSelector 25 -#define kStylisticAltTwelveOnSelector 24 -#define kStylisticAltTwentyOffSelector 41 -#define kStylisticAltTwentyOnSelector 40 -#define kStylisticAltTwoOffSelector 5 -#define kStylisticAltTwoOnSelector 4 -#define kStylisticAlternativesType 35 -#define kSwashAlternatesOffSelector 3 -#define kSwashAlternatesOnSelector 2 -#define kThirdWidthTextSelector 3 -#define kTraditionalNamesCharactersSelector 14 -#define kUpperCasePetiteCapsSelector 2 -#define kUpperCaseSmallCapsSelector 1 -#define kUpperCaseType 38 - -/* Table data courtesy of Apple. */ -static const struct feature_mapping_t { - FourCharCode otFeatureTag; - uint16_t aatFeatureType; - uint16_t selectorToEnable; - uint16_t selectorToDisable; -} feature_mappings[] = { - { 'c2pc', kUpperCaseType, kUpperCasePetiteCapsSelector, kDefaultUpperCaseSelector }, - { 'c2sc', kUpperCaseType, kUpperCaseSmallCapsSelector, kDefaultUpperCaseSelector }, - { 'calt', kContextualAlternatesType, kContextualAlternatesOnSelector, kContextualAlternatesOffSelector }, - { 'case', kCaseSensitiveLayoutType, kCaseSensitiveLayoutOnSelector, kCaseSensitiveLayoutOffSelector }, - { 'clig', kLigaturesType, kContextualLigaturesOnSelector, kContextualLigaturesOffSelector }, - { 'cpsp', kCaseSensitiveLayoutType, kCaseSensitiveSpacingOnSelector, kCaseSensitiveSpacingOffSelector }, - { 'cswh', kContextualAlternatesType, kContextualSwashAlternatesOnSelector, kContextualSwashAlternatesOffSelector }, - { 'dlig', kLigaturesType, kRareLigaturesOnSelector, kRareLigaturesOffSelector }, - { 'expt', kCharacterShapeType, kExpertCharactersSelector, 16 }, - { 'frac', kFractionsType, kDiagonalFractionsSelector, kNoFractionsSelector }, - { 'fwid', kTextSpacingType, kMonospacedTextSelector, 7 }, - { 'halt', kTextSpacingType, kAltHalfWidthTextSelector, 7 }, - { 'hist', kLigaturesType, kHistoricalLigaturesOnSelector, kHistoricalLigaturesOffSelector }, - { 'hkna', kAlternateKanaType, kAlternateHorizKanaOnSelector, kAlternateHorizKanaOffSelector, }, - { 'hlig', kLigaturesType, kHistoricalLigaturesOnSelector, kHistoricalLigaturesOffSelector }, - { 'hngl', kTransliterationType, kHanjaToHangulSelector, kNoTransliterationSelector }, - { 'hojo', kCharacterShapeType, kHojoCharactersSelector, 16 }, - { 'hwid', kTextSpacingType, kHalfWidthTextSelector, 7 }, - { 'ital', kItalicCJKRomanType, kCJKItalicRomanOnSelector, kCJKItalicRomanOffSelector }, - { 'jp04', kCharacterShapeType, kJIS2004CharactersSelector, 16 }, - { 'jp78', kCharacterShapeType, kJIS1978CharactersSelector, 16 }, - { 'jp83', kCharacterShapeType, kJIS1983CharactersSelector, 16 }, - { 'jp90', kCharacterShapeType, kJIS1990CharactersSelector, 16 }, - { 'liga', kLigaturesType, kCommonLigaturesOnSelector, kCommonLigaturesOffSelector }, - { 'lnum', kNumberCaseType, kUpperCaseNumbersSelector, 2 }, - { 'mgrk', kMathematicalExtrasType, kMathematicalGreekOnSelector, kMathematicalGreekOffSelector }, - { 'nlck', kCharacterShapeType, kNLCCharactersSelector, 16 }, - { 'onum', kNumberCaseType, kLowerCaseNumbersSelector, 2 }, - { 'ordn', kVerticalPositionType, kOrdinalsSelector, kNormalPositionSelector }, - { 'palt', kTextSpacingType, kAltProportionalTextSelector, 7 }, - { 'pcap', kLowerCaseType, kLowerCasePetiteCapsSelector, kDefaultLowerCaseSelector }, - { 'pkna', kTextSpacingType, kProportionalTextSelector, 7 }, - { 'pnum', kNumberSpacingType, kProportionalNumbersSelector, 4 }, - { 'pwid', kTextSpacingType, kProportionalTextSelector, 7 }, - { 'qwid', kTextSpacingType, kQuarterWidthTextSelector, 7 }, - { 'ruby', kRubyKanaType, kRubyKanaOnSelector, kRubyKanaOffSelector }, - { 'sinf', kVerticalPositionType, kScientificInferiorsSelector, kNormalPositionSelector }, - { 'smcp', kLowerCaseType, kLowerCaseSmallCapsSelector, kDefaultLowerCaseSelector }, - { 'smpl', kCharacterShapeType, kSimplifiedCharactersSelector, 16 }, - { 'ss01', kStylisticAlternativesType, kStylisticAltOneOnSelector, kStylisticAltOneOffSelector }, - { 'ss02', kStylisticAlternativesType, kStylisticAltTwoOnSelector, kStylisticAltTwoOffSelector }, - { 'ss03', kStylisticAlternativesType, kStylisticAltThreeOnSelector, kStylisticAltThreeOffSelector }, - { 'ss04', kStylisticAlternativesType, kStylisticAltFourOnSelector, kStylisticAltFourOffSelector }, - { 'ss05', kStylisticAlternativesType, kStylisticAltFiveOnSelector, kStylisticAltFiveOffSelector }, - { 'ss06', kStylisticAlternativesType, kStylisticAltSixOnSelector, kStylisticAltSixOffSelector }, - { 'ss07', kStylisticAlternativesType, kStylisticAltSevenOnSelector, kStylisticAltSevenOffSelector }, - { 'ss08', kStylisticAlternativesType, kStylisticAltEightOnSelector, kStylisticAltEightOffSelector }, - { 'ss09', kStylisticAlternativesType, kStylisticAltNineOnSelector, kStylisticAltNineOffSelector }, - { 'ss10', kStylisticAlternativesType, kStylisticAltTenOnSelector, kStylisticAltTenOffSelector }, - { 'ss11', kStylisticAlternativesType, kStylisticAltElevenOnSelector, kStylisticAltElevenOffSelector }, - { 'ss12', kStylisticAlternativesType, kStylisticAltTwelveOnSelector, kStylisticAltTwelveOffSelector }, - { 'ss13', kStylisticAlternativesType, kStylisticAltThirteenOnSelector, kStylisticAltThirteenOffSelector }, - { 'ss14', kStylisticAlternativesType, kStylisticAltFourteenOnSelector, kStylisticAltFourteenOffSelector }, - { 'ss15', kStylisticAlternativesType, kStylisticAltFifteenOnSelector, kStylisticAltFifteenOffSelector }, - { 'ss16', kStylisticAlternativesType, kStylisticAltSixteenOnSelector, kStylisticAltSixteenOffSelector }, - { 'ss17', kStylisticAlternativesType, kStylisticAltSeventeenOnSelector, kStylisticAltSeventeenOffSelector }, - { 'ss18', kStylisticAlternativesType, kStylisticAltEighteenOnSelector, kStylisticAltEighteenOffSelector }, - { 'ss19', kStylisticAlternativesType, kStylisticAltNineteenOnSelector, kStylisticAltNineteenOffSelector }, - { 'ss20', kStylisticAlternativesType, kStylisticAltTwentyOnSelector, kStylisticAltTwentyOffSelector }, - { 'subs', kVerticalPositionType, kInferiorsSelector, kNormalPositionSelector }, - { 'sups', kVerticalPositionType, kSuperiorsSelector, kNormalPositionSelector }, - { 'swsh', kContextualAlternatesType, kSwashAlternatesOnSelector, kSwashAlternatesOffSelector }, - { 'titl', kStyleOptionsType, kTitlingCapsSelector, kNoStyleOptionsSelector }, - { 'tnam', kCharacterShapeType, kTraditionalNamesCharactersSelector, 16 }, - { 'tnum', kNumberSpacingType, kMonospacedNumbersSelector, 4 }, - { 'trad', kCharacterShapeType, kTraditionalCharactersSelector, 16 }, - { 'twid', kTextSpacingType, kThirdWidthTextSelector, 7 }, - { 'unic', kLetterCaseType, 14, 15 }, - { 'valt', kTextSpacingType, kAltProportionalTextSelector, 7 }, - { 'vert', kVerticalSubstitutionType, kSubstituteVerticalFormsOnSelector, kSubstituteVerticalFormsOffSelector }, - { 'vhal', kTextSpacingType, kAltHalfWidthTextSelector, 7 }, - { 'vkna', kAlternateKanaType, kAlternateVertKanaOnSelector, kAlternateVertKanaOffSelector }, - { 'vpal', kTextSpacingType, kAltProportionalTextSelector, 7 }, - { 'vrt2', kVerticalSubstitutionType, kSubstituteVerticalFormsOnSelector, kSubstituteVerticalFormsOffSelector }, - { 'zero', kTypographicExtrasType, kSlashedZeroOnSelector, kSlashedZeroOffSelector }, -}; - -static int -_hb_feature_mapping_cmp (const void *key_, const void *entry_) -{ - unsigned int key = * (unsigned int *) key_; - const feature_mapping_t * entry = (const feature_mapping_t *) entry_; - return key < entry->otFeatureTag ? -1 : - key > entry->otFeatureTag ? 1 : - 0; -} - hb_bool_t _hb_coretext_shape (hb_shape_plan_t *shape_plan, hb_font_t *font, @@ -617,15 +452,15 @@ unsigned int num_features) { hb_face_t *face = font->face; - CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); - CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font); + CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext; + CTFontRef ct_font = (CTFontRef) hb_coretext_font_data_sync (font); CGFloat ct_font_size = CTFontGetSize (ct_font); CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size; CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size; /* Attach marks to their bases, to match the 'ot' shaper. - * Adapted from hb-ot-shape:hb_form_clusters(). + * Adapted from a very old version of hb-ot-shape:hb_form_clusters(). * Note that this only makes us be closer to the 'ot' shaper, * but by no means the same. For example, if there's * B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will @@ -641,8 +476,8 @@ buffer->merge_clusters (i - 1, i + 1); } - hb_auto_t > feature_records; - hb_auto_t > range_records; + hb_vector_t feature_records; + hb_vector_t range_records; /* * Set up features. @@ -651,14 +486,10 @@ if (num_features) { /* Sort features by start/end events. */ - hb_auto_t > feature_events; + hb_vector_t feature_events; for (unsigned int i = 0; i < num_features; i++) { - const feature_mapping_t * mapping = (const feature_mapping_t *) bsearch (&features[i].tag, - feature_mappings, - ARRAY_LENGTH (feature_mappings), - sizeof (feature_mappings[0]), - _hb_feature_mapping_cmp); + const hb_aat_feature_mapping_t * mapping = hb_aat_layout_find_feature_mapping (features[i].tag); if (!mapping) continue; @@ -694,9 +525,9 @@ } /* Scan events and save features for each range. */ - hb_auto_t > active_features; + hb_vector_t active_features; unsigned int last_index = 0; - for (unsigned int i = 0; i < feature_events.len; i++) + for (unsigned int i = 0; i < feature_events.length; i++) { feature_event_t *event = &feature_events[i]; @@ -705,13 +536,13 @@ /* Save a snapshot of active features and the range. */ range_record_t *range = range_records.push (); - if (active_features.len) + if (active_features.length) { CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); /* TODO sort and resolve conflicting features? */ /* active_features.qsort (); */ - for (unsigned int j = 0; j < active_features.len; j++) + for (unsigned int j = 0; j < active_features.length; j++) { CFStringRef keys[] = { kCTFontFeatureTypeIdentifierKey, @@ -767,7 +598,7 @@ } else { active_feature_t *feature = active_features.find (&event->feature); if (feature) - active_features.remove (feature - active_features.arrayZ); + active_features.remove (feature - active_features.arrayZ ()); } } } @@ -824,7 +655,7 @@ CFStringRef string_ref = nullptr; CTLineRef line = nullptr; - if (0) + if (false) { resize_and_retry: DEBUG_MSG (CORETEXT, buffer, "Buffer resize"); @@ -899,7 +730,7 @@ CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), kCTFontAttributeName, ct_font); - if (num_features && range_records.len) + if (num_features && range_records.length) { unsigned int start = 0; range_record_t *last_range = &range_records[0]; @@ -1048,7 +879,7 @@ * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098 */ bool matched = false; - for (unsigned int i = 0; i < range_records.len; i++) + for (unsigned int i = 0; i < range_records.length; i++) if (range_records[i].font && CFEqual (run_ct_font, range_records[i].font)) { matched = true; @@ -1235,7 +1066,7 @@ * * https://crbug.com/419769 */ - if (0) + if (false) { /* Make sure all runs had the expected direction. */ bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); @@ -1311,7 +1142,7 @@ if (line) CFRelease (line); - for (unsigned int i = 0; i < range_records.len; i++) + for (unsigned int i = 0; i < range_records.length; i++) if (range_records[i].font) CFRelease (range_records[i].font); @@ -1323,36 +1154,21 @@ * AAT shaper */ -HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face) -HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font) - /* * shaper face data */ -struct hb_coretext_aat_shaper_face_data_t {}; +struct hb_coretext_aat_face_data_t {}; -hb_coretext_aat_shaper_face_data_t * +hb_coretext_aat_face_data_t * _hb_coretext_aat_shaper_face_data_create (hb_face_t *face) { - static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX}; - - for (unsigned int i = 0; i < ARRAY_LENGTH (tags); i++) - { - hb_blob_t *blob = face->reference_table (tags[i]); - if (hb_blob_get_length (blob)) - { - hb_blob_destroy (blob); - return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr; - } - hb_blob_destroy (blob); - } - - return nullptr; + return hb_aat_layout_has_substitution (face) || hb_aat_layout_has_positioning (face) ? + (hb_coretext_aat_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr; } void -_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED) +_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_face_data_t *data HB_UNUSED) { } @@ -1361,38 +1177,16 @@ * shaper font data */ -struct hb_coretext_aat_shaper_font_data_t {}; +struct hb_coretext_aat_font_data_t {}; -hb_coretext_aat_shaper_font_data_t * +hb_coretext_aat_font_data_t * _hb_coretext_aat_shaper_font_data_create (hb_font_t *font) { - return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr; -} - -void -_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED) -{ -} - - -/* - * shaper shape_plan data - */ - -struct hb_coretext_aat_shaper_shape_plan_data_t {}; - -hb_coretext_aat_shaper_shape_plan_data_t * -_hb_coretext_aat_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, - const int *coords HB_UNUSED, - unsigned int num_coords HB_UNUSED) -{ - return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; + return font->data.coretext ? (hb_coretext_aat_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr; } void -_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED) +_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_font_data_t *data HB_UNUSED) { } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-debug.hh 2019-02-28 12:03:48.614503131 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-debug.hh 2019-02-28 12:03:48.510503132 -0800 @@ -27,13 +27,60 @@ #ifndef HB_DEBUG_HH #define HB_DEBUG_HH -#include "hb-private.hh" +#include "hb.hh" +#include "hb-atomic.hh" +#include "hb-dsalgs.hh" #ifndef HB_DEBUG #define HB_DEBUG 0 #endif + +/* + * Global runtime options. + */ + +struct hb_options_t +{ + bool unused : 1; /* In-case sign bit is here. */ + bool initialized : 1; + bool uniscribe_bug_compatible : 1; + bool aat : 1; +}; + +union hb_options_union_t { + int i; + hb_options_t opts; +}; +static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), ""); + +HB_INTERNAL void +_hb_options_init (); + +extern HB_INTERNAL hb_atomic_int_t _hb_options; + +static inline hb_options_t +hb_options () +{ + /* Make a local copy, so we can access bitfield threadsafely. */ + hb_options_union_t u; + u.i = _hb_options.get_relaxed (); + + if (unlikely (!u.i)) + { + _hb_options_init (); + u.i = _hb_options.get_relaxed (); + } + + return u.opts; +} + + +/* + * Debug output (needs enabling at compile time.) + */ + static inline bool _hb_debug (unsigned int level, unsigned int max_level) @@ -126,7 +173,7 @@ fprintf (stderr, "\n"); } -template <> inline void +template <> inline void HB_PRINTF_FUNC(7, 0) _hb_debug_msg_va<0> (const char *what HB_UNUSED, const void *obj HB_UNUSED, const char *func HB_UNUSED, @@ -145,7 +192,7 @@ int level_dir, const char *message, ...) HB_PRINTF_FUNC(7, 8); -template static inline void +template static inline void HB_PRINTF_FUNC(7, 8) _hb_debug_msg (const char *what, const void *obj, const char *func, @@ -169,7 +216,7 @@ int level_dir HB_UNUSED, const char *message HB_UNUSED, ...) HB_PRINTF_FUNC(7, 8); -template <> inline void +template <> inline void HB_PRINTF_FUNC(7, 8) _hb_debug_msg<0> (const char *what HB_UNUSED, const void *obj HB_UNUSED, const char *func HB_UNUSED, @@ -237,7 +284,7 @@ _hb_debug_msg_va (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap); va_end (ap); } - inline ~hb_auto_trace_t (void) + ~hb_auto_trace_t () { _hb_warn_no_return (returned); if (!returned) { @@ -246,14 +293,16 @@ if (plevel) --*plevel; } - inline ret_t ret (ret_t v, unsigned int line = 0) + ret_t ret (ret_t v, + const char *func = "", + unsigned int line = 0) { if (unlikely (returned)) { fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n"); return v; } - _hb_debug_msg (what, obj, nullptr, true, plevel ? *plevel : 1, -1, + _hb_debug_msg (what, obj, func, true, plevel ? *plevel : 1, -1, "return %s (line %d)", hb_printer_t().print (v), line); if (plevel) --*plevel; @@ -278,17 +327,21 @@ const char *message, ...) HB_PRINTF_FUNC(6, 7) {} - inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; } + ret_t ret (ret_t v, + const char *func HB_UNUSED = nullptr, + unsigned int line HB_UNUSED = 0) { return v; } }; /* For disabled tracing; optimize out everything. * https://github.com/harfbuzz/harfbuzz/pull/605 */ template struct hb_no_trace_t { - inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; } + ret_t ret (ret_t v, + const char *func HB_UNUSED = "", + unsigned int line HB_UNUSED = 0) { return v; } }; -#define return_trace(RET) return trace.ret (RET, __LINE__) +#define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__) /* @@ -348,30 +401,6 @@ #define TRACE_APPLY(this) hb_no_trace_t trace #endif -#ifndef HB_DEBUG_CLOSURE -#define HB_DEBUG_CLOSURE (HB_DEBUG+0) -#endif -#if HB_DEBUG_CLOSURE -#define TRACE_CLOSURE(this) \ - hb_auto_trace_t trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - " ") -#else -#define TRACE_CLOSURE(this) hb_no_trace_t trace HB_UNUSED -#endif - -#ifndef HB_DEBUG_COLLECT_GLYPHS -#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0) -#endif -#if HB_DEBUG_COLLECT_GLYPHS -#define TRACE_COLLECT_GLYPHS(this) \ - hb_auto_trace_t trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - " ") -#else -#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t trace HB_UNUSED -#endif - #ifndef HB_DEBUG_SANITIZE #define HB_DEBUG_SANITIZE (HB_DEBUG+0) #endif @@ -423,8 +452,6 @@ #ifndef HB_DEBUG_DISPATCH #define HB_DEBUG_DISPATCH ( \ HB_DEBUG_APPLY + \ - HB_DEBUG_CLOSURE + \ - HB_DEBUG_COLLECT_GLYPHS + \ HB_DEBUG_SANITIZE + \ HB_DEBUG_SERIALIZE + \ HB_DEBUG_SUBSET + \ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-deprecated.h 2019-02-28 12:03:48.930503125 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-deprecated.h 2019-02-28 12:03:48.830503127 -0800 @@ -36,10 +36,23 @@ #include "hb-font.h" #include "hb-set.h" + +/** + * SECTION:hb-deprecated + * @title: hb-deprecated + * @short_description: Deprecated API + * @include: hb.h + * + * These API have been deprecated in favor of newer API, or because they + * were deemed unnecessary. + **/ + + HB_BEGIN_DECLS #ifndef HB_DISABLE_DEPRECATED + #define HB_SCRIPT_CANADIAN_ABORIGINAL HB_SCRIPT_CANADIAN_SYLLABICS #define HB_BUFFER_FLAGS_DEFAULT HB_BUFFER_FLAG_DEFAULT @@ -50,14 +63,162 @@ hb_codepoint_t *glyph, void *user_data); -HB_EXTERN void +HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func or hb_font_funcs_set_variation_glyph_func) void hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_func_t func, void *user_data, hb_destroy_func_t destroy); -HB_EXTERN void +HB_EXTERN HB_DEPRECATED void hb_set_invert (hb_set_t *set); +/** + * hb_unicode_eastasian_width_func_t: + * + * Deprecated: 2.0.0 + */ +typedef unsigned int (*hb_unicode_eastasian_width_func_t) (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode, + void *user_data); + +/** + * hb_unicode_funcs_set_eastasian_width_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + * Deprecated: 2.0.0 + **/ +HB_EXTERN HB_DEPRECATED void +hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_eastasian_width_func_t func, + void *user_data, hb_destroy_func_t destroy); + +/** + * hb_unicode_eastasian_width: + * + * Since: 0.9.2 + * Deprecated: 2.0.0 + **/ +HB_EXTERN HB_DEPRECATED unsigned int +hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + + +/** + * hb_unicode_decompose_compatibility_func_t: + * @ufuncs: a Unicode function structure + * @u: codepoint to decompose + * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into + * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func() + * + * Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed. + * The complete length of the decomposition will be returned. + * + * If @u has no compatibility decomposition, zero should be returned. + * + * The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any + * compatibility decomposition plus an terminating value of 0. Consequently, @decompose must be allocated by the caller to be at least this length. Implementations + * of this function type must ensure that they do not write past the provided array. + * + * Return value: number of codepoints in the full compatibility decomposition of @u, or 0 if no decomposition available. + * + * Deprecated: 2.0.0 + */ +typedef unsigned int (*hb_unicode_decompose_compatibility_func_t) (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t u, + hb_codepoint_t *decomposed, + void *user_data); + +/** + * HB_UNICODE_MAX_DECOMPOSITION_LEN: + * + * See Unicode 6.1 for details on the maximum decomposition length. + * + * Deprecated: 2.0.0 + */ +#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */ + +/** + * hb_unicode_funcs_set_decompose_compatibility_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + * Deprecated: 2.0.0 + **/ +HB_EXTERN HB_DEPRECATED void +hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_decompose_compatibility_func_t func, + void *user_data, hb_destroy_func_t destroy); + +HB_EXTERN HB_DEPRECATED unsigned int +hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t u, + hb_codepoint_t *decomposed); + + +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; + +/** + * hb_font_funcs_set_glyph_h_kerning_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + * Deprecated: 2.0.0 + **/ +HB_EXTERN 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); + +/** + * hb_font_funcs_set_glyph_v_kerning_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + * Deprecated: 2.0.0 + **/ +HB_EXTERN 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); + +HB_EXTERN hb_position_t +hb_font_get_glyph_h_kerning (hb_font_t *font, + hb_codepoint_t left_glyph, hb_codepoint_t right_glyph); +HB_EXTERN hb_position_t +hb_font_get_glyph_v_kerning (hb_font_t *font, + hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); + +HB_EXTERN 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); + + #endif HB_END_DECLS --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-dsalgs.hh 2019-02-28 12:03:49.274503120 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-dsalgs.hh 2019-02-28 12:03:49.150503122 -0800 @@ -27,9 +27,339 @@ #ifndef HB_DSALGS_HH #define HB_DSALGS_HH -#include "hb-private.hh" +#include "hb.hh" +#include "hb-null.hh" +/* Void! For when we need a expression-type of void. */ +typedef const struct _hb_void_t *hb_void_t; +#define HB_VOID ((const _hb_void_t *) nullptr) + + +/* + * Bithacks. + */ + +/* Return the number of 1 bits in v. */ +template +static inline HB_CONST_FUNC unsigned int +hb_popcount (T v) +{ +#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) + if (sizeof (T) <= sizeof (unsigned int)) + return __builtin_popcount (v); + + if (sizeof (T) <= sizeof (unsigned long)) + return __builtin_popcountl (v); + + if (sizeof (T) <= sizeof (unsigned long long)) + return __builtin_popcountll (v); +#endif + + if (sizeof (T) <= 4) + { + /* "HACKMEM 169" */ + uint32_t y; + y = (v >> 1) &033333333333; + y = v - y - ((y >>1) & 033333333333); + return (((y + (y >> 3)) & 030707070707) % 077); + } + + if (sizeof (T) == 8) + { + unsigned int shift = 32; + return hb_popcount ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift)); + } + + if (sizeof (T) == 16) + { + unsigned int shift = 64; + return hb_popcount ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift)); + } + + assert (0); + return 0; /* Shut up stupid compiler. */ +} + +/* Returns the number of bits needed to store number */ +template +static inline HB_CONST_FUNC unsigned int +hb_bit_storage (T v) +{ + if (unlikely (!v)) return 0; + +#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) + if (sizeof (T) <= sizeof (unsigned int)) + return sizeof (unsigned int) * 8 - __builtin_clz (v); + + if (sizeof (T) <= sizeof (unsigned long)) + return sizeof (unsigned long) * 8 - __builtin_clzl (v); + + if (sizeof (T) <= sizeof (unsigned long long)) + return sizeof (unsigned long long) * 8 - __builtin_clzll (v); +#endif + +#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__) + if (sizeof (T) <= sizeof (unsigned int)) + { + unsigned long where; + _BitScanReverse (&where, v); + return 1 + where; + } +# if defined(_WIN64) + if (sizeof (T) <= 8) + { + unsigned long where; + _BitScanReverse64 (&where, v); + return 1 + where; + } +# endif +#endif + + if (sizeof (T) <= 4) + { + /* "bithacks" */ + const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000}; + const unsigned int S[] = {1, 2, 4, 8, 16}; + unsigned int r = 0; + for (int i = 4; i >= 0; i--) + if (v & b[i]) + { + v >>= S[i]; + r |= S[i]; + } + return r + 1; + } + if (sizeof (T) <= 8) + { + /* "bithacks" */ + const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL}; + const unsigned int S[] = {1, 2, 4, 8, 16, 32}; + unsigned int r = 0; + for (int i = 5; i >= 0; i--) + if (v & b[i]) + { + v >>= S[i]; + r |= S[i]; + } + return r + 1; + } + if (sizeof (T) == 16) + { + unsigned int shift = 64; + return (v >> shift) ? hb_bit_storage ((uint64_t) (v >> shift)) + shift : + hb_bit_storage ((uint64_t) v); + } + + assert (0); + return 0; /* Shut up stupid compiler. */ +} + +/* Returns the number of zero bits in the least significant side of v */ +template +static inline HB_CONST_FUNC unsigned int +hb_ctz (T v) +{ + if (unlikely (!v)) return 0; + +#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) + if (sizeof (T) <= sizeof (unsigned int)) + return __builtin_ctz (v); + + if (sizeof (T) <= sizeof (unsigned long)) + return __builtin_ctzl (v); + + if (sizeof (T) <= sizeof (unsigned long long)) + return __builtin_ctzll (v); +#endif + +#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__) + if (sizeof (T) <= sizeof (unsigned int)) + { + unsigned long where; + _BitScanForward (&where, v); + return where; + } +# if defined(_WIN64) + if (sizeof (T) <= 8) + { + unsigned long where; + _BitScanForward64 (&where, v); + return where; + } +# endif +#endif + + if (sizeof (T) <= 4) + { + /* "bithacks" */ + unsigned int c = 32; + v &= - (int32_t) v; + if (v) c--; + if (v & 0x0000FFFF) c -= 16; + if (v & 0x00FF00FF) c -= 8; + if (v & 0x0F0F0F0F) c -= 4; + if (v & 0x33333333) c -= 2; + if (v & 0x55555555) c -= 1; + return c; + } + if (sizeof (T) <= 8) + { + /* "bithacks" */ + unsigned int c = 64; + v &= - (int64_t) (v); + if (v) c--; + if (v & 0x00000000FFFFFFFFULL) c -= 32; + if (v & 0x0000FFFF0000FFFFULL) c -= 16; + if (v & 0x00FF00FF00FF00FFULL) c -= 8; + if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4; + if (v & 0x3333333333333333ULL) c -= 2; + if (v & 0x5555555555555555ULL) c -= 1; + return c; + } + if (sizeof (T) == 16) + { + unsigned int shift = 64; + return (uint64_t) v ? hb_bit_storage ((uint64_t) v) : + hb_bit_storage ((uint64_t) (v >> shift)) + shift; + } + + assert (0); + return 0; /* Shut up stupid compiler. */ +} + + +/* + * Tiny stuff. + */ + +template +static inline T* hb_addressof (T& arg) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" + /* https://en.cppreference.com/w/cpp/memory/addressof */ + return reinterpret_cast( + &const_cast( + reinterpret_cast(arg))); +#pragma GCC diagnostic pop +} + +/* ASCII tag/character handling */ +static inline bool ISALPHA (unsigned char c) +{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } +static inline bool ISALNUM (unsigned char c) +{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); } +static inline bool ISSPACE (unsigned char c) +{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; } +static inline unsigned char TOUPPER (unsigned char c) +{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; } +static inline unsigned char TOLOWER (unsigned char c) +{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; } + +#undef MIN +template +static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; } + +#undef MAX +template +static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; } + +static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b) +{ return (a + (b - 1)) / b; } + + +#undef ARRAY_LENGTH +template +static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; } +/* A const version, but does not detect erratically being called on pointers. */ +#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0]))) + + +static inline int +hb_memcmp (const void *a, const void *b, unsigned int len) +{ + /* It's illegal to pass NULL to memcmp(), even if len is zero. + * So, wrap it. + * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */ + if (!len) return 0; + return memcmp (a, b, len); +} + +static inline bool +hb_unsigned_mul_overflows (unsigned int count, unsigned int size) +{ + return (size > 0) && (count >= ((unsigned int) -1) / size); +} + +static inline unsigned int +hb_ceil_to_4 (unsigned int v) +{ + return ((v - 1) | 3) + 1; +} + +template struct hb_is_signed; +/* https://github.com/harfbuzz/harfbuzz/issues/1535 */ +template <> struct hb_is_signed { enum { value = true }; }; +template <> struct hb_is_signed { enum { value = true }; }; +template <> struct hb_is_signed { enum { value = true }; }; +template <> struct hb_is_signed { enum { value = true }; }; +template <> struct hb_is_signed { enum { value = false }; }; +template <> struct hb_is_signed { enum { value = false }; }; +template <> struct hb_is_signed { enum { value = false }; }; +template <> struct hb_is_signed { enum { value = false }; }; + +template static inline bool +hb_in_range (T u, T lo, T hi) +{ + /* The sizeof() is here to force template instantiation. + * I'm sure there are better ways to do this but can't think of + * one right now. Declaring a variable won't work as HB_UNUSED + * is unusable on some platforms and unused types are less likely + * to generate a warning than unused variables. */ + static_assert (!hb_is_signed::value, ""); + + /* The casts below are important as if T is smaller than int, + * the subtract results will become a signed int! */ + return (T)(u - lo) <= (T)(hi - lo); +} +template static inline bool +hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2) +{ + return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2); +} +template static inline bool +hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) +{ + return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3); +} + + +/* + * Sort and search. + */ + +static inline void * +hb_bsearch (const void *key, const void *base, + size_t nmemb, size_t size, + int (*compar)(const void *_key, const void *_item)) +{ + int min = 0, max = (int) nmemb - 1; + while (min <= max) + { + int mid = (min + max) / 2; + const void *p = (const void *) (((const char *) base) + (mid * size)); + int c = compar (key, p); + if (c < 0) + max = mid - 1; + else if (c > 0) + min = mid + 1; + else + return (void *) p; + } + return nullptr; +} + static inline void * hb_bsearch_r (const void *key, const void *base, size_t nmemb, size_t size, @@ -39,7 +369,7 @@ int min = 0, max = (int) nmemb - 1; while (min <= max) { - int mid = (min + max) / 2; + int mid = ((unsigned int) min + (unsigned int) max) / 2; const void *p = (const void *) (((const char *) base) + (mid * size)); int c = compar (key, p, arg); if (c < 0) @@ -53,8 +383,12 @@ } - -/* From https://github.com/noporpoise/sort_r */ +/* From https://github.com/noporpoise/sort_r + * With following modifications: + * + * 10 November 2018: + * https://github.com/noporpoise/sort_r/issues/7 + */ /* Isaac Turner 29 April 2014 Public Domain */ @@ -110,7 +444,7 @@ /* Use median of first, middle and last items as pivot */ char *x, *y, *xend, ch; - char *pl, *pr; + char *pl, *pm, *pr; char *last = b+w*(nel-1), *tmp; char *l[3]; l[0] = b; @@ -132,13 +466,15 @@ pr = last; while(pl < pr) { - for(; pl < pr; pl += w) { + pm = pl+((pr-pl+1)>>1); + for(; pl < pm; pl += w) { if(sort_r_cmpswap(pl, pr, w, compar, arg)) { pr -= w; /* pivot now at pl */ break; } } - for(; pl < pr; pr -= w) { + pm = pl+((pr-pl)>>1); + for(; pm < pr; pr -= w) { if(sort_r_cmpswap(pl, pr, w, compar, arg)) { pl += w; /* pivot now at pr */ break; @@ -158,4 +494,139 @@ sort_r_simple(base, nel, width, compar, arg); } + +template static inline void +hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2) +{ + for (unsigned int i = 1; i < len; i++) + { + unsigned int j = i; + while (j && compar (&array[j - 1], &array[i]) > 0) + j--; + if (i == j) + continue; + /* Move item i to occupy place for item j, shift what's in between. */ + { + T t = array[i]; + memmove (&array[j + 1], &array[j], (i - j) * sizeof (T)); + array[j] = t; + } + if (array2) + { + T2 t = array2[i]; + memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2)); + array2[j] = t; + } + } +} + +template static inline void +hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *)) +{ + hb_stable_sort (array, len, compar, (int *) nullptr); +} + +static inline hb_bool_t +hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out) +{ + /* Pain because we don't know whether s is nul-terminated. */ + char buf[64]; + len = MIN (ARRAY_LENGTH (buf) - 1, len); + strncpy (buf, s, len); + buf[len] = '\0'; + + char *end; + errno = 0; + unsigned long v = strtoul (buf, &end, base); + if (errno) return false; + if (*end) return false; + *out = v; + return true; +} + + +struct HbOpOr +{ + static constexpr bool passthru_left = true; + static constexpr bool passthru_right = true; + template static void process (T &o, const T &a, const T &b) { o = a | b; } +}; +struct HbOpAnd +{ + static constexpr bool passthru_left = false; + static constexpr bool passthru_right = false; + template static void process (T &o, const T &a, const T &b) { o = a & b; } +}; +struct HbOpMinus +{ + static constexpr bool passthru_left = true; + static constexpr bool passthru_right = false; + template static void process (T &o, const T &a, const T &b) { o = a & ~b; } +}; +struct HbOpXor +{ + static constexpr bool passthru_left = true; + static constexpr bool passthru_right = true; + template static void process (T &o, const T &a, const T &b) { o = a ^ b; } +}; + + +/* Compiler-assisted vectorization. */ + +/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))), + * using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128). + * Define that to 0 to disable. */ +template +struct hb_vector_size_t +{ + elt_t& operator [] (unsigned int i) { return u.v[i]; } + const elt_t& operator [] (unsigned int i) const { return u.v[i]; } + + void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); } + + template + hb_vector_size_t process (const hb_vector_size_t &o) const + { + hb_vector_size_t r; +#if HB_VECTOR_SIZE + if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE) + for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++) + Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]); + else +#endif + for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++) + Op::process (r.u.v[i], u.v[i], o.u.v[i]); + return r; + } + hb_vector_size_t operator | (const hb_vector_size_t &o) const + { return process (o); } + hb_vector_size_t operator & (const hb_vector_size_t &o) const + { return process (o); } + hb_vector_size_t operator ^ (const hb_vector_size_t &o) const + { return process (o); } + hb_vector_size_t operator ~ () const + { + hb_vector_size_t r; +#if HB_VECTOR_SIZE && 0 + if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE) + for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++) + r.u.vec[i] = ~u.vec[i]; + else +#endif + for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++) + r.u.v[i] = ~u.v[i]; + return r; + } + + private: + static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, ""); + union { + elt_t v[byte_size / sizeof (elt_t)]; +#if HB_VECTOR_SIZE + hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)]; +#endif + } u; +}; + + #endif /* HB_DSALGS_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.cc 2019-02-28 12:03:49.586503115 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.cc 2019-02-28 12:03:49.490503116 -0800 @@ -26,23 +26,35 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-private.hh" - -#include "hb-face-private.hh" -#include "hb-blob-private.hh" -#include "hb-open-file-private.hh" -#include "hb-ot-head-table.hh" -#include "hb-ot-maxp-table.hh" +#include "hb.hh" +#include "hb-face.hh" +#include "hb-blob.hh" +#include "hb-open-file.hh" +#include "hb-ot-face.hh" +#include "hb-ot-cmap-table.hh" /** - * hb_face_count: Get number of faces on the blob - * @blob: + * SECTION:hb-face + * @title: hb-face + * @short_description: Font face objects + * @include: hb.h * + * Font face is objects represent a single face in a font family. + * More exactly, a font face represents a single face in a binary font file. + * Font faces are typically built from a binary blob and a face index. + * Font faces are used to create fonts. + **/ + + +/** + * hb_face_count: + * @blob: a blob. * + * Get number of faces in a blob. * - * Return value: Number of faces on the blob + * Return value: Number of faces in @blob * * Since: 1.7.7 **/ @@ -52,36 +64,33 @@ if (unlikely (!blob)) return 0; - hb_blob_t *sanitized = OT::Sanitizer ().sanitize (blob); + /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */ + /* Make API signature const after. */ + hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob (hb_blob_reference (blob)); const OT::OpenTypeFontFile& ot = *sanitized->as (); + unsigned int ret = ot.get_face_count (); + hb_blob_destroy (sanitized); - return ot.get_face_count (); + return ret; } /* * hb_face_t */ -const hb_face_t _hb_face_nil = { +DEFINE_NULL_INSTANCE (hb_face_t) = +{ HB_OBJECT_HEADER_STATIC, - true, /* immutable */ - nullptr, /* reference_table_func */ nullptr, /* user_data */ nullptr, /* destroy */ 0, /* index */ - 1000, /* upem */ - 0, /* num_glyphs */ + HB_ATOMIC_INT_INIT (1000), /* upem */ + HB_ATOMIC_INT_INIT (0), /* num_glyphs */ - { -#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - }, - - nullptr, /* shape_plans */ + /* Zero for the rest is fine. */ }; @@ -114,8 +123,10 @@ face->user_data = user_data; face->destroy = destroy; - face->upem = 0; - face->num_glyphs = (unsigned int) -1; + face->num_glyphs.set_relaxed (-1); + + face->data.init0 (face); + face->table.init0 (face); return face; } @@ -159,11 +170,12 @@ return hb_blob_reference (data->blob); const OT::OpenTypeFontFile &ot_file = *data->blob->as (); - const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); + unsigned int base_offset; + const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset); 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); + hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length); return blob; } @@ -188,7 +200,7 @@ if (unlikely (!blob)) blob = hb_blob_get_empty (); - hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer().sanitize (hb_blob_reference (blob)), index); + hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (hb_sanitize_context_t ().sanitize_blob (hb_blob_reference (blob)), index); if (unlikely (!closure)) return hb_face_get_empty (); @@ -212,9 +224,9 @@ * Since: 0.9.2 **/ hb_face_t * -hb_face_get_empty (void) +hb_face_get_empty () { - return const_cast (&_hb_face_nil); + return const_cast (&Null(hb_face_t)); } @@ -255,9 +267,8 @@ node = next; } -#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face); -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT + face->data.fini (); + face->table.fini (); if (face->destroy) face->destroy (face->user_data); @@ -301,7 +312,7 @@ * Since: 0.9.2 **/ void * -hb_face_get_user_data (hb_face_t *face, +hb_face_get_user_data (const hb_face_t *face, hb_user_data_key_t *key) { return hb_object_get_user_data (face, key); @@ -318,10 +329,10 @@ void hb_face_make_immutable (hb_face_t *face) { - if (unlikely (hb_object_is_inert (face))) + if (hb_object_is_immutable (face)) return; - face->immutable = true; + hb_object_make_immutable (face); } /** @@ -335,9 +346,9 @@ * Since: 0.9.2 **/ hb_bool_t -hb_face_is_immutable (hb_face_t *face) +hb_face_is_immutable (const hb_face_t *face) { - return face->immutable; + return hb_object_is_immutable (face); } @@ -353,8 +364,8 @@ * Since: 0.9.2 **/ hb_blob_t * -hb_face_reference_table (hb_face_t *face, - hb_tag_t tag) +hb_face_reference_table (const hb_face_t *face, + hb_tag_t tag) { return face->reference_table (tag); } @@ -388,7 +399,7 @@ hb_face_set_index (hb_face_t *face, unsigned int index) { - if (face->immutable) + if (hb_object_is_immutable (face)) return; face->index = index; @@ -405,7 +416,7 @@ * Since: 0.9.2 **/ unsigned int -hb_face_get_index (hb_face_t *face) +hb_face_get_index (const hb_face_t *face) { return face->index; } @@ -423,10 +434,10 @@ hb_face_set_upem (hb_face_t *face, unsigned int upem) { - if (face->immutable) + if (hb_object_is_immutable (face)) return; - face->upem = upem; + face->upem.set_relaxed (upem); } /** @@ -440,20 +451,11 @@ * Since: 0.9.2 **/ unsigned int -hb_face_get_upem (hb_face_t *face) +hb_face_get_upem (const 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 = head_blob->as (); - upem = head_table->get_upem (); - hb_blob_destroy (head_blob); -} - /** * hb_face_set_glyph_count: * @face: a face. @@ -467,10 +469,10 @@ hb_face_set_glyph_count (hb_face_t *face, unsigned int glyph_count) { - if (face->immutable) + if (hb_object_is_immutable (face)) return; - face->num_glyphs = glyph_count; + face->num_glyphs.set_relaxed (glyph_count); } /** @@ -484,23 +486,17 @@ * Since: 0.9.7 **/ unsigned int -hb_face_get_glyph_count (hb_face_t *face) +hb_face_get_glyph_count (const 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 = maxp_blob->as (); - num_glyphs = maxp_table->get_num_glyphs (); - hb_blob_destroy (maxp_blob); -} - /** * hb_face_get_table_tags: * @face: a face. + * @start_offset: index of first tag to return. + * @table_count: input length of @table_tags array, output number of items written. + * @table_tags: array to write tags into. * * Retrieves table tags for a face, if possible. * @@ -509,7 +505,7 @@ * Since: 1.6.0 **/ unsigned int -hb_face_get_table_tags (hb_face_t *face, +hb_face_get_table_tags (const hb_face_t *face, unsigned int start_offset, unsigned int *table_count, /* IN/OUT */ hb_tag_t *table_tags /* OUT */) @@ -528,3 +524,200 @@ return ot_face.get_table_tags (start_offset, table_count, table_tags); } + + +/* + * Character set. + */ + + +/** + * hb_face_collect_unicodes: + * @face: font face. + * @out: set to add Unicode characters covered by @face to. + * + * Since: 1.9.0 + */ +void +hb_face_collect_unicodes (hb_face_t *face, + hb_set_t *out) +{ + face->table.cmap->collect_unicodes (out); +} + +/** + * hb_face_collect_variation_selectors: + * @face: font face. + * @out: set to add Variation Selector characters covered by @face to. + * + * + * + * Since: 1.9.0 + */ +void +hb_face_collect_variation_selectors (hb_face_t *face, + hb_set_t *out) +{ + face->table.cmap->collect_variation_selectors (out); +} + +/** + * hb_face_collect_variation_unicodes: + * @face: font face. + * @out: set to add Unicode characters for @variation_selector covered by @face to. + * + * + * + * Since: 1.9.0 + */ +void +hb_face_collect_variation_unicodes (hb_face_t *face, + hb_codepoint_t variation_selector, + hb_set_t *out) +{ + face->table.cmap->collect_variation_unicodes (variation_selector, out); +} + + + +/* + * face-builder: A face that has add_table(). + */ + +struct hb_face_builder_data_t +{ + struct table_entry_t + { + int cmp (hb_tag_t t) const + { + if (t < tag) return -1; + if (t > tag) return -1; + return 0; + } + + hb_tag_t tag; + hb_blob_t *blob; + }; + + hb_vector_t tables; +}; + +static hb_face_builder_data_t * +_hb_face_builder_data_create () +{ + hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t)); + if (unlikely (!data)) + return nullptr; + + data->tables.init (); + + return data; +} + +static void +_hb_face_builder_data_destroy (void *user_data) +{ + hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data; + + for (unsigned int i = 0; i < data->tables.length; i++) + hb_blob_destroy (data->tables[i].blob); + + data->tables.fini (); + + free (data); +} + +static hb_blob_t * +_hb_face_builder_data_reference_blob (hb_face_builder_data_t *data) +{ + + unsigned int table_count = data->tables.length; + unsigned int face_length = table_count * 16 + 12; + + for (unsigned int i = 0; i < table_count; i++) + face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob)); + + char *buf = (char *) malloc (face_length); + if (unlikely (!buf)) + return nullptr; + + hb_serialize_context_t c (buf, face_length); + c.propagate_error (data->tables); + OT::OpenTypeFontFile *f = c.start_serialize (); + + bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2')); + hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag; + + bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ()); + + c.end_serialize (); + + if (unlikely (!ret)) + { + free (buf); + return nullptr; + } + + return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free); +} + +static hb_blob_t * +_hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) +{ + hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data; + + if (!tag) + return _hb_face_builder_data_reference_blob (data); + + hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag); + if (entry) + return hb_blob_reference (entry->blob); + + return nullptr; +} + + +/** + * hb_face_builder_create: + * + * Creates a #hb_face_t that can be used with hb_face_builder_add_table(). + * After tables are added to the face, it can be compiled to a binary + * font file by calling hb_face_reference_blob(). + * + * Return value: (transfer full): New face. + * + * Since: 1.9.0 + **/ +hb_face_t * +hb_face_builder_create () +{ + hb_face_builder_data_t *data = _hb_face_builder_data_create (); + if (unlikely (!data)) return hb_face_get_empty (); + + return hb_face_create_for_tables (_hb_face_builder_reference_table, + data, + _hb_face_builder_data_destroy); +} + +/** + * hb_face_builder_add_table: + * + * Add table for @tag with data provided by @blob to the face. @face must + * be created using hb_face_builder_create(). + * + * Since: 1.9.0 + **/ +hb_bool_t +hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob) +{ + if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy)) + return false; + + hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data; + hb_face_builder_data_t::table_entry_t *entry = data->tables.push (); + + entry->tag = tag; + entry->blob = hb_blob_reference (blob); + + return true; +} --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.h 2019-02-28 12:03:50.070503107 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.h 2019-02-28 12:03:49.966503108 -0800 @@ -33,6 +33,7 @@ #include "hb-common.h" #include "hb-blob.h" +#include "hb-set.h" HB_BEGIN_DECLS @@ -76,19 +77,19 @@ hb_bool_t replace); HB_EXTERN void * -hb_face_get_user_data (hb_face_t *face, +hb_face_get_user_data (const hb_face_t *face, hb_user_data_key_t *key); HB_EXTERN void hb_face_make_immutable (hb_face_t *face); HB_EXTERN hb_bool_t -hb_face_is_immutable (hb_face_t *face); +hb_face_is_immutable (const hb_face_t *face); HB_EXTERN hb_blob_t * -hb_face_reference_table (hb_face_t *face, - hb_tag_t tag); +hb_face_reference_table (const hb_face_t *face, + hb_tag_t tag); HB_EXTERN hb_blob_t * hb_face_reference_blob (hb_face_t *face); @@ -98,28 +99,60 @@ unsigned int index); HB_EXTERN unsigned int -hb_face_get_index (hb_face_t *face); +hb_face_get_index (const hb_face_t *face); HB_EXTERN void hb_face_set_upem (hb_face_t *face, unsigned int upem); HB_EXTERN unsigned int -hb_face_get_upem (hb_face_t *face); +hb_face_get_upem (const hb_face_t *face); HB_EXTERN void hb_face_set_glyph_count (hb_face_t *face, unsigned int glyph_count); HB_EXTERN unsigned int -hb_face_get_glyph_count (hb_face_t *face); +hb_face_get_glyph_count (const hb_face_t *face); HB_EXTERN unsigned int -hb_face_get_table_tags (hb_face_t *face, +hb_face_get_table_tags (const hb_face_t *face, unsigned int start_offset, unsigned int *table_count, /* IN/OUT */ hb_tag_t *table_tags /* OUT */); + +/* + * Character set. + */ + +HB_EXTERN void +hb_face_collect_unicodes (hb_face_t *face, + hb_set_t *out); + +HB_EXTERN void +hb_face_collect_variation_selectors (hb_face_t *face, + hb_set_t *out); + +HB_EXTERN void +hb_face_collect_variation_unicodes (hb_face_t *face, + hb_codepoint_t variation_selector, + hb_set_t *out); + + +/* + * Builder face. + */ + +HB_EXTERN hb_face_t * +hb_face_builder_create (void); + +HB_EXTERN hb_bool_t +hb_face_builder_add_table (hb_face_t *face, + hb_tag_t tag, + hb_blob_t *blob); + + HB_END_DECLS #endif /* HB_FACE_H */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-fallback-shape.cc 2019-02-28 12:03:50.430503101 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-fallback-shape.cc 2019-02-28 12:03:50.302503103 -0800 @@ -24,28 +24,23 @@ * Google Author(s): Behdad Esfahbod */ -#define HB_SHAPER fallback -#include "hb-shaper-impl-private.hh" - - -HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face) -HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font) +#include "hb-shaper-impl.hh" /* * shaper face data */ -struct hb_fallback_shaper_face_data_t {}; +struct hb_fallback_face_data_t {}; -hb_fallback_shaper_face_data_t * +hb_fallback_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; + return (hb_fallback_face_data_t *) HB_SHAPER_DATA_SUCCEEDED; } void -_hb_fallback_shaper_face_data_destroy (hb_fallback_shaper_face_data_t *data HB_UNUSED) +_hb_fallback_shaper_face_data_destroy (hb_fallback_face_data_t *data HB_UNUSED) { } @@ -54,38 +49,16 @@ * shaper font data */ -struct hb_fallback_shaper_font_data_t {}; +struct hb_fallback_font_data_t {}; -hb_fallback_shaper_font_data_t * +hb_fallback_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, - const int *coords HB_UNUSED, - unsigned int num_coords HB_UNUSED) -{ - return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; + return (hb_fallback_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; } void -_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shaper_shape_plan_data_t *data HB_UNUSED) +_hb_fallback_shaper_font_data_destroy (hb_fallback_font_data_t *data HB_UNUSED) { } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.cc 2019-02-28 12:03:50.766503095 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.cc 2019-02-28 12:03:50.670503097 -0800 @@ -26,9 +26,25 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-private.hh" +#include "hb.hh" -#include "hb-font-private.hh" +#include "hb-font.hh" +#include "hb-machinery.hh" + +#include "hb-ot.h" + + +/** + * SECTION:hb-font + * @title: hb-font + * @short_description: Font objects + * @include: hb.h + * + * Font objects represent a font face at a certain size and other + * parameters (pixels per EM, points per EM, variation settings.) + * Fonts are created from font faces, and are used as input to + * hb_shape() among other things. + **/ /* @@ -38,23 +54,23 @@ static hb_bool_t hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_font_extents_t *metrics, + hb_font_extents_t *extents, void *user_data HB_UNUSED) { - memset (metrics, 0, sizeof (*metrics)); + memset (extents, 0, sizeof (*extents)); return false; } static hb_bool_t -hb_font_get_font_h_extents_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_font_extents_t *metrics, - void *user_data HB_UNUSED) +hb_font_get_font_h_extents_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *extents, + void *user_data HB_UNUSED) { - hb_bool_t ret = font->parent->get_font_h_extents (metrics); + hb_bool_t ret = font->parent->get_font_h_extents (extents); if (ret) { - metrics->ascender = font->parent_scale_y_distance (metrics->ascender); - metrics->descender = font->parent_scale_y_distance (metrics->descender); - metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap); + extents->ascender = font->parent_scale_y_distance (extents->ascender); + extents->descender = font->parent_scale_y_distance (extents->descender); + extents->line_gap = font->parent_scale_y_distance (extents->line_gap); } return ret; } @@ -62,23 +78,23 @@ static hb_bool_t hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_font_extents_t *metrics, + hb_font_extents_t *extents, void *user_data HB_UNUSED) { - memset (metrics, 0, sizeof (*metrics)); + memset (extents, 0, sizeof (*extents)); return false; } static hb_bool_t -hb_font_get_font_v_extents_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_font_extents_t *metrics, - void *user_data HB_UNUSED) +hb_font_get_font_v_extents_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *extents, + void *user_data HB_UNUSED) { - hb_bool_t ret = font->parent->get_font_v_extents (metrics); + hb_bool_t ret = font->parent->get_font_v_extents (extents); if (ret) { - metrics->ascender = font->parent_scale_x_distance (metrics->ascender); - metrics->descender = font->parent_scale_x_distance (metrics->descender); - metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap); + extents->ascender = font->parent_scale_x_distance (extents->ascender); + extents->descender = font->parent_scale_x_distance (extents->descender); + extents->line_gap = font->parent_scale_x_distance (extents->line_gap); } return ret; } @@ -86,7 +102,7 @@ static hb_bool_t hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t unicode, + hb_codepoint_t unicode HB_UNUSED, hb_codepoint_t *glyph, void *user_data HB_UNUSED) { @@ -94,20 +110,53 @@ return false; } static hb_bool_t -hb_font_get_nominal_glyph_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t unicode, - hb_codepoint_t *glyph, - void *user_data HB_UNUSED) +hb_font_get_nominal_glyph_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) { + if (font->has_nominal_glyphs_func_set ()) + { + return font->get_nominal_glyphs (1, &unicode, 0, glyph, 0); + } return font->parent->get_nominal_glyph (unicode, glyph); } +#define hb_font_get_nominal_glyphs_nil hb_font_get_nominal_glyphs_default +static unsigned int +hb_font_get_nominal_glyphs_default (hb_font_t *font, + void *font_data HB_UNUSED, + unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + void *user_data HB_UNUSED) +{ + if (font->has_nominal_glyph_func_set ()) + { + for (unsigned int i = 0; i < count; i++) + { + if (!font->get_nominal_glyph (*first_unicode, first_glyph)) + return i; + + first_unicode = &StructAtOffsetUnaligned (first_unicode, unicode_stride); + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + } + return count; + } + + return font->parent->get_nominal_glyphs (count, + first_unicode, unicode_stride, + first_glyph, glyph_stride); +} + static hb_bool_t hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t unicode, - hb_codepoint_t variation_selector, + hb_codepoint_t unicode HB_UNUSED, + hb_codepoint_t variation_selector HB_UNUSED, hb_codepoint_t *glyph, void *user_data HB_UNUSED) { @@ -115,12 +164,12 @@ return false; } static hb_bool_t -hb_font_get_variation_glyph_parent (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) +hb_font_get_variation_glyph_default (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) { return font->parent->get_variation_glyph (unicode, variation_selector, glyph); } @@ -129,42 +178,118 @@ static hb_position_t hb_font_get_glyph_h_advance_nil (hb_font_t *font, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, void *user_data HB_UNUSED) { return font->x_scale; } static hb_position_t -hb_font_get_glyph_h_advance_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - void *user_data HB_UNUSED) +hb_font_get_glyph_h_advance_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) { + if (font->has_glyph_h_advances_func_set ()) + { + hb_position_t ret; + font->get_glyph_h_advances (1, &glyph, 0, &ret, 0); + return ret; + } return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); } static hb_position_t hb_font_get_glyph_v_advance_nil (hb_font_t *font, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, void *user_data HB_UNUSED) { /* TODO use font_extents.ascender+descender */ return font->y_scale; } static hb_position_t -hb_font_get_glyph_v_advance_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - void *user_data HB_UNUSED) +hb_font_get_glyph_v_advance_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) { + if (font->has_glyph_v_advances_func_set ()) + { + hb_position_t ret; + font->get_glyph_v_advances (1, &glyph, 0, &ret, 0); + return ret; + } return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); } +#define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default +static void +hb_font_get_glyph_h_advances_default (hb_font_t* font, + void* font_data HB_UNUSED, + unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + hb_position_t *first_advance, + unsigned int advance_stride, + void *user_data HB_UNUSED) +{ + if (font->has_glyph_h_advance_func_set ()) + { + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->get_glyph_h_advance (*first_glyph); + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } + return; + } + + font->parent->get_glyph_h_advances (count, + first_glyph, glyph_stride, + first_advance, advance_stride); + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->parent_scale_x_distance (*first_advance); + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } +} + +#define hb_font_get_glyph_v_advances_nil hb_font_get_glyph_v_advances_default +static void +hb_font_get_glyph_v_advances_default (hb_font_t* font, + void* font_data HB_UNUSED, + unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + hb_position_t *first_advance, + unsigned int advance_stride, + void *user_data HB_UNUSED) +{ + if (font->has_glyph_v_advance_func_set ()) + { + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->get_glyph_v_advance (*first_glyph); + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } + return; + } + + font->parent->get_glyph_v_advances (count, + first_glyph, glyph_stride, + first_advance, advance_stride); + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->parent_scale_y_distance (*first_advance); + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } +} + static hb_bool_t hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, hb_position_t *x, hb_position_t *y, void *user_data HB_UNUSED) @@ -173,12 +298,12 @@ return true; } static hb_bool_t -hb_font_get_glyph_h_origin_parent (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) +hb_font_get_glyph_h_origin_default (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) { hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y); if (ret) @@ -189,7 +314,7 @@ static hb_bool_t hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, hb_position_t *x, hb_position_t *y, void *user_data HB_UNUSED) @@ -198,12 +323,12 @@ return false; } static hb_bool_t -hb_font_get_glyph_v_origin_parent (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) +hb_font_get_glyph_v_origin_default (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) { hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y); if (ret) @@ -214,18 +339,18 @@ static hb_position_t hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t left_glyph, - hb_codepoint_t right_glyph, + hb_codepoint_t left_glyph HB_UNUSED, + hb_codepoint_t right_glyph HB_UNUSED, void *user_data HB_UNUSED) { return 0; } static hb_position_t -hb_font_get_glyph_h_kerning_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t left_glyph, - hb_codepoint_t right_glyph, - void *user_data HB_UNUSED) +hb_font_get_glyph_h_kerning_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t left_glyph, + hb_codepoint_t right_glyph, + void *user_data HB_UNUSED) { return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph)); } @@ -233,18 +358,18 @@ static hb_position_t hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t top_glyph, - hb_codepoint_t bottom_glyph, + hb_codepoint_t top_glyph HB_UNUSED, + hb_codepoint_t bottom_glyph HB_UNUSED, void *user_data HB_UNUSED) { return 0; } static hb_position_t -hb_font_get_glyph_v_kerning_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t top_glyph, - hb_codepoint_t bottom_glyph, - void *user_data HB_UNUSED) +hb_font_get_glyph_v_kerning_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t top_glyph, + hb_codepoint_t bottom_glyph, + void *user_data HB_UNUSED) { return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph)); } @@ -252,7 +377,7 @@ static hb_bool_t hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { @@ -260,11 +385,11 @@ return false; } static hb_bool_t -hb_font_get_glyph_extents_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - hb_glyph_extents_t *extents, - void *user_data HB_UNUSED) +hb_font_get_glyph_extents_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + void *user_data HB_UNUSED) { hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); if (ret) { @@ -277,8 +402,8 @@ static hb_bool_t hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t glyph, - unsigned int point_index, + hb_codepoint_t glyph HB_UNUSED, + unsigned int point_index HB_UNUSED, hb_position_t *x, hb_position_t *y, void *user_data HB_UNUSED) @@ -287,13 +412,13 @@ return false; } static hb_bool_t -hb_font_get_glyph_contour_point_parent (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) +hb_font_get_glyph_contour_point_default (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) { hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); if (ret) @@ -304,7 +429,7 @@ static hb_bool_t hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, char *name, unsigned int size, void *user_data HB_UNUSED) { @@ -312,11 +437,11 @@ return false; } static hb_bool_t -hb_font_get_glyph_name_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - char *name, unsigned int size, - void *user_data HB_UNUSED) +hb_font_get_glyph_name_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + char *name, unsigned int size, + void *user_data HB_UNUSED) { return font->parent->get_glyph_name (glyph, name, size); } @@ -324,7 +449,8 @@ static hb_bool_t hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - const char *name, int len, /* -1 means nul-terminated */ + const char *name HB_UNUSED, + int len HB_UNUSED, /* -1 means nul-terminated */ hb_codepoint_t *glyph, void *user_data HB_UNUSED) { @@ -332,20 +458,19 @@ return false; } static hb_bool_t -hb_font_get_glyph_from_name_parent (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) +hb_font_get_glyph_from_name_default (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) { return font->parent->get_glyph_from_name (name, len, glyph); } -static const hb_font_funcs_t _hb_font_funcs_nil = { +DEFINE_NULL_INSTANCE (hb_font_funcs_t) = +{ HB_OBJECT_HEADER_STATIC, - true, /* immutable */ - { #define HB_FONT_FUNC_IMPLEMENT(name) nullptr, HB_FONT_FUNCS_IMPLEMENT_CALLBACKS @@ -364,10 +489,9 @@ } } }; -static const hb_font_funcs_t _hb_font_funcs_parent = { - HB_OBJECT_HEADER_STATIC, - true, /* immutable */ +static const hb_font_funcs_t _hb_font_funcs_default = { + HB_OBJECT_HEADER_STATIC, { #define HB_FONT_FUNC_IMPLEMENT(name) nullptr, @@ -381,7 +505,7 @@ }, { { -#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent, +#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default, HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT } @@ -399,14 +523,14 @@ * Since: 0.9.2 **/ hb_font_funcs_t * -hb_font_funcs_create (void) +hb_font_funcs_create () { hb_font_funcs_t *ffuncs; if (!(ffuncs = hb_object_create ())) return hb_font_funcs_get_empty (); - ffuncs->get = _hb_font_funcs_parent.get; + ffuncs->get = _hb_font_funcs_default.get; return ffuncs; } @@ -421,9 +545,9 @@ * Since: 0.9.2 **/ hb_font_funcs_t * -hb_font_funcs_get_empty (void) +hb_font_funcs_get_empty () { - return const_cast (&_hb_font_funcs_parent); + return const_cast (&_hb_font_funcs_default); } /** @@ -517,10 +641,10 @@ void hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) { - if (unlikely (hb_object_is_inert (ffuncs))) + if (hb_object_is_immutable (ffuncs)) return; - ffuncs->immutable = true; + hb_object_make_immutable (ffuncs); } /** @@ -536,7 +660,7 @@ hb_bool_t hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs) { - return ffuncs->immutable; + return hb_object_is_immutable (ffuncs); } @@ -548,7 +672,7 @@ void *user_data, \ hb_destroy_func_t destroy) \ { \ - if (ffuncs->immutable) { \ + if (hb_object_is_immutable (ffuncs)) { \ if (destroy) \ destroy (user_data); \ return; \ @@ -562,9 +686,9 @@ ffuncs->user_data.name = user_data; \ ffuncs->destroy.name = destroy; \ } else { \ - ffuncs->get.f.name = hb_font_get_##name##_parent; \ - ffuncs->user_data.name = nullptr; \ - ffuncs->destroy.name = nullptr; \ + ffuncs->get.f.name = hb_font_get_##name##_default; \ + ffuncs->user_data.name = nullptr; \ + ffuncs->destroy.name = nullptr; \ } \ } @@ -572,11 +696,16 @@ #undef HB_FONT_FUNC_IMPLEMENT bool +hb_font_t::has_func_set (unsigned int i) +{ + return this->klass->get.array[i] != _hb_font_funcs_default.get.array[i]; +} + +bool hb_font_t::has_func (unsigned int i) { - if (parent && parent != hb_font_get_empty () && parent->has_func (i)) - return true; - return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i]; + return has_func_set (i) || + (parent && parent != &_hb_Null_hb_font_t && parent->has_func (i)); } /* Public getters */ @@ -718,6 +847,43 @@ } /** + * hb_font_get_glyph_h_advances: + * @font: a font. + * + * + * + * Since: 1.8.6 + **/ +void +hb_font_get_glyph_h_advances (hb_font_t* font, + unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride) +{ + font->get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); +} +/** + * hb_font_get_glyph_v_advances: + * @font: a font. + * + * + * + * Since: 1.8.6 + **/ +void +hb_font_get_glyph_v_advances (hb_font_t* font, + unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride) +{ + font->get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); +} + +/** * hb_font_get_glyph_h_origin: * @font: a font. * @glyph: @@ -770,6 +936,7 @@ * Return value: * * Since: 0.9.2 + * Deprecated: 2.0.0 **/ hb_position_t hb_font_get_glyph_h_kerning (hb_font_t *font, @@ -789,6 +956,7 @@ * Return value: * * Since: 0.9.2 + * Deprecated: 2.0.0 **/ hb_position_t hb_font_get_glyph_v_kerning (hb_font_t *font, @@ -888,7 +1056,7 @@ * hb_font_get_extents_for_direction: * @font: a font. * @direction: - * @extents: + * @extents: (out): * * * @@ -921,6 +1089,26 @@ { return font->get_glyph_advance_for_direction (glyph, direction, x, y); } +/** + * hb_font_get_glyph_advances_for_direction: + * @font: a font. + * @direction: + * + * + * + * Since: 1.8.6 + **/ +HB_EXTERN void +hb_font_get_glyph_advances_for_direction (hb_font_t* font, + hb_direction_t direction, + unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride) +{ + font->get_glyph_advances_for_direction (direction, count, first_glyph, glyph_stride, first_advance, advance_stride); +} /** * hb_font_get_glyph_origin_for_direction: @@ -997,6 +1185,7 @@ * * * Since: 0.9.2 + * Deprecated: 2.0.0 **/ void hb_font_get_glyph_kerning_for_direction (hb_font_t *font, @@ -1100,6 +1289,49 @@ * hb_font_t */ +DEFINE_NULL_INSTANCE (hb_font_t) = +{ + HB_OBJECT_HEADER_STATIC, + + nullptr, /* parent */ + const_cast (&_hb_Null_hb_face_t), + + 1000, /* x_scale */ + 1000, /* y_scale */ + + 0, /* x_ppem */ + 0, /* y_ppem */ + 0, /* ptem */ + + 0, /* num_coords */ + nullptr, /* coords */ + + const_cast (&_hb_Null_hb_font_funcs_t), + + /* Zero for the rest is fine. */ +}; + + +static hb_font_t * +_hb_font_create (hb_face_t *face) +{ + hb_font_t *font; + + if (unlikely (!face)) + face = hb_face_get_empty (); + if (!(font = hb_object_create ())) + return hb_font_get_empty (); + + hb_face_make_immutable (face); + font->parent = hb_font_get_empty (); + font->face = hb_face_reference (face); + font->klass = hb_font_funcs_get_empty (); + font->data.init0 (font); + font->x_scale = font->y_scale = hb_face_get_upem (face); + + return font; +} + /** * hb_font_create: (Xconstructor) * @face: a face. @@ -1113,19 +1345,10 @@ hb_font_t * hb_font_create (hb_face_t *face) { - hb_font_t *font; + hb_font_t *font = _hb_font_create (face); - if (unlikely (!face)) - face = hb_face_get_empty (); - if (!(font = hb_object_create ())) - return hb_font_get_empty (); - - hb_face_make_immutable (face); - font->parent = hb_font_get_empty (); - font->face = hb_face_reference (face); - font->klass = hb_font_funcs_get_empty (); - - font->x_scale = font->y_scale = hb_face_get_upem (face); + /* Install our in-house, very lightweight, funcs. */ + hb_ot_font_set_funcs (font); return font; } @@ -1146,9 +1369,9 @@ if (unlikely (!parent)) parent = hb_font_get_empty (); - hb_font_t *font = hb_font_create (parent->face); + hb_font_t *font = _hb_font_create (parent->face); - if (unlikely (hb_object_is_inert (font))) + if (unlikely (hb_object_is_immutable (font))) return font; font->parent = hb_font_reference (parent); @@ -1185,38 +1408,9 @@ * Since: 0.9.2 **/ hb_font_t * -hb_font_get_empty (void) +hb_font_get_empty () { - static const hb_font_t _hb_font_nil = { - HB_OBJECT_HEADER_STATIC, - - true, /* immutable */ - - nullptr, /* parent */ - const_cast (&_hb_face_nil), - - 1000, /* x_scale */ - 1000, /* y_scale */ - - 0, /* x_ppem */ - 0, /* y_ppem */ - 0, /* ptem */ - - 0, /* num_coords */ - nullptr, /* coords */ - - const_cast (&_hb_font_funcs_nil), /* klass */ - nullptr, /* user_data */ - nullptr, /* 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); + return const_cast (&Null(hb_font_t)); } /** @@ -1248,9 +1442,7 @@ { 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 + font->data.fini (); if (font->destroy) font->destroy (font->user_data); @@ -1317,13 +1509,13 @@ void hb_font_make_immutable (hb_font_t *font) { - if (unlikely (hb_object_is_inert (font))) + if (hb_object_is_immutable (font)) return; if (font->parent) hb_font_make_immutable (font->parent); - font->immutable = true; + hb_object_make_immutable (font); } /** @@ -1339,7 +1531,7 @@ hb_bool_t hb_font_is_immutable (hb_font_t *font) { - return font->immutable; + return hb_object_is_immutable (font); } /** @@ -1355,7 +1547,7 @@ hb_font_set_parent (hb_font_t *font, hb_font_t *parent) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; if (!parent) @@ -1397,7 +1589,7 @@ hb_font_set_face (hb_font_t *font, hb_face_t *face) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; if (unlikely (!face)) @@ -1444,7 +1636,8 @@ void *font_data, hb_destroy_func_t destroy) { - if (font->immutable) { + if (hb_object_is_immutable (font)) + { if (destroy) destroy (font_data); return; @@ -1479,7 +1672,8 @@ hb_destroy_func_t destroy) { /* Destroy user_data? */ - if (font->immutable) { + if (hb_object_is_immutable (font)) + { if (destroy) destroy (font_data); return; @@ -1508,7 +1702,7 @@ int x_scale, int y_scale) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; font->x_scale = x_scale; @@ -1549,7 +1743,7 @@ unsigned int x_ppem, unsigned int y_ppem) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; font->x_ppem = x_ppem; @@ -1578,16 +1772,18 @@ /** * hb_font_set_ptem: * @font: a font. - * @ptem: + * @ptem: font size in points. + * + * Sets "point size" of the font. Set to 0 to unset. * - * Sets "point size" of the font. + * There are 72 points in an inch. * * Since: 1.6.0 **/ void hb_font_set_ptem (hb_font_t *font, float ptem) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; font->ptem = ptem; @@ -1634,7 +1830,7 @@ const hb_variation_t *variations, unsigned int variations_length) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; if (!variations_length) @@ -1665,7 +1861,7 @@ const float *coords, unsigned int coords_length) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr; @@ -1686,7 +1882,7 @@ const int *coords, /* 2.14 normalized */ unsigned int coords_length) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr; @@ -1718,8 +1914,6 @@ } -#ifndef HB_DISABLE_DEPRECATED - /* * Deprecated get_glyph_func(): */ @@ -1806,9 +2000,9 @@ /** * hb_font_funcs_set_glyph_func: * @ffuncs: font functions. - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: + * @func: (closure user_data) (destroy destroy) (scope notified): callback function. + * @user_data: data to pass to @func. + * @destroy: function to call when @user_data is not needed anymore. * * Deprecated. Use hb_font_funcs_set_nominal_glyph_func() and * hb_font_funcs_set_variation_glyph_func() instead. @@ -1842,5 +2036,3 @@ trampoline, trampoline_destroy); } - -#endif /* HB_DISABLE_DEPRECATED */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.h 2019-02-28 12:03:51.122503089 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.h 2019-02-28 12:03:51.022503091 -0800 @@ -110,7 +110,7 @@ /* func types */ typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data, - hb_font_extents_t *metrics, + hb_font_extents_t *extents, void *user_data); typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t; typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t; @@ -125,6 +125,14 @@ hb_codepoint_t *glyph, void *user_data); +typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void *font_data, + unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + 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, @@ -132,6 +140,16 @@ 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 void (*hb_font_get_glyph_advances_func_t) (hb_font_t* font, void* font_data, + unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride, + void *user_data); +typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_h_advances_func_t; +typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_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, @@ -139,12 +157,6 @@ 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, @@ -217,6 +229,22 @@ void *user_data, hb_destroy_func_t destroy); /** + * hb_font_funcs_set_nominal_glyphs_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 2.0.0 + **/ +HB_EXTERN void +hb_font_funcs_set_nominal_glyphs_func (hb_font_funcs_t *ffuncs, + hb_font_get_nominal_glyphs_func_t func, + void *user_data, hb_destroy_func_t destroy); + +/** * hb_font_funcs_set_variation_glyph_func: * @ffuncs: font functions. * @func: (closure user_data) (destroy destroy) (scope notified): @@ -265,7 +293,7 @@ void *user_data, hb_destroy_func_t destroy); /** - * hb_font_funcs_set_glyph_h_origin_func: + * hb_font_funcs_set_glyph_h_advances_func: * @ffuncs: font functions. * @func: (closure user_data) (destroy destroy) (scope notified): * @user_data: @@ -273,15 +301,15 @@ * * * - * Since: 0.9.2 + * Since: 1.8.6 **/ HB_EXTERN 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); +hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_advances_func_t func, + void *user_data, hb_destroy_func_t destroy); /** - * hb_font_funcs_set_glyph_v_origin_func: + * hb_font_funcs_set_glyph_v_advances_func: * @ffuncs: font functions. * @func: (closure user_data) (destroy destroy) (scope notified): * @user_data: @@ -289,15 +317,15 @@ * * * - * Since: 0.9.2 + * Since: 1.8.6 **/ HB_EXTERN 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); +hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_advances_func_t func, + void *user_data, hb_destroy_func_t destroy); /** - * hb_font_funcs_set_glyph_h_kerning_func: + * hb_font_funcs_set_glyph_h_origin_func: * @ffuncs: font functions. * @func: (closure user_data) (destroy destroy) (scope notified): * @user_data: @@ -308,12 +336,12 @@ * Since: 0.9.2 **/ HB_EXTERN 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); +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); /** - * hb_font_funcs_set_glyph_v_kerning_func: + * hb_font_funcs_set_glyph_v_origin_func: * @ffuncs: font functions. * @func: (closure user_data) (destroy destroy) (scope notified): * @user_data: @@ -324,9 +352,9 @@ * Since: 0.9.2 **/ HB_EXTERN 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); +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); /** * hb_font_funcs_set_glyph_extents_func: @@ -417,6 +445,21 @@ hb_font_get_glyph_v_advance (hb_font_t *font, hb_codepoint_t glyph); +HB_EXTERN void +hb_font_get_glyph_h_advances (hb_font_t* font, + unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride); +HB_EXTERN void +hb_font_get_glyph_v_advances (hb_font_t* font, + unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride); + HB_EXTERN hb_bool_t hb_font_get_glyph_h_origin (hb_font_t *font, hb_codepoint_t glyph, @@ -426,13 +469,6 @@ hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y); -HB_EXTERN hb_position_t -hb_font_get_glyph_h_kerning (hb_font_t *font, - hb_codepoint_t left_glyph, hb_codepoint_t right_glyph); -HB_EXTERN hb_position_t -hb_font_get_glyph_v_kerning (hb_font_t *font, - hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); - HB_EXTERN hb_bool_t hb_font_get_glyph_extents (hb_font_t *font, hb_codepoint_t glyph, @@ -472,6 +508,14 @@ hb_direction_t direction, hb_position_t *x, hb_position_t *y); HB_EXTERN void +hb_font_get_glyph_advances_for_direction (hb_font_t* font, + hb_direction_t direction, + unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride); +HB_EXTERN void hb_font_get_glyph_origin_for_direction (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, @@ -487,12 +531,6 @@ hb_direction_t direction, hb_position_t *x, hb_position_t *y); -HB_EXTERN 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_EXTERN hb_bool_t hb_font_get_glyph_extents_for_origin (hb_font_t *font, hb_codepoint_t glyph, --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc 2019-02-28 12:03:51.502503083 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc 2019-02-28 12:03:51.394503085 -0800 @@ -27,47 +27,58 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-private.hh" -#include "hb-debug.hh" +#include "hb.hh" #include "hb-ft.h" -#include "hb-font-private.hh" +#include "hb-font.hh" +#include "hb-machinery.hh" +#include "hb-cache.hh" #include FT_ADVANCES_H #include FT_MULTIPLE_MASTERS_H #include FT_TRUETYPE_TABLES_H +/** + * SECTION:hb-ft + * @title: hb-ft + * @short_description: FreeType integration + * @include: hb-ft.h + * + * Functions for using HarfBuzz with the FreeType library to provide face and + * font data. + **/ + + /* TODO: * * In general, this file does a fine job of what it's supposed to do. * There are, however, things that need more work: * - * - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be buggy. - * Have not investigated. - * * - FreeType works in 26.6 mode. Clients can decide to use that mode, and everything * would work fine. However, we also abuse this API for performing in font-space, * but don't pass the correct flags to FreeType. We just abuse the no-hinting mode * for that, such that no rounding etc happens. As such, we don't set ppem, and * pass NO_HINTING as load_flags. Would be much better to use NO_SCALE, and scale - * ourselves, like we do in uniscribe, etc. + * ourselves. * * - We don't handle / allow for emboldening / obliqueing. * * - In the future, we should add constructors to create fonts in font space? - * - * - FT_Load_Glyph() is extremely costly. Do something about it? */ struct hb_ft_font_t { + mutable hb_mutex_t lock; FT_Face ft_face; int load_flags; bool symbol; /* Whether selected cmap is symbol cmap. */ bool unref; /* Whether to destroy ft_face when done. */ + + mutable hb_atomic_int_t cached_x_scale; + mutable hb_advance_cache_t advance_cache; }; static hb_ft_font_t * @@ -78,12 +89,16 @@ if (unlikely (!ft_font)) return nullptr; + ft_font->lock.init (); ft_font->ft_face = ft_face; ft_font->symbol = symbol; ft_font->unref = unref; ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; + ft_font->cached_x_scale.set (0); + ft_font->advance_cache.init (); + return ft_font; } @@ -98,9 +113,13 @@ { hb_ft_font_t *ft_font = (hb_ft_font_t *) data; + ft_font->advance_cache.fini (); + if (ft_font->unref) _hb_ft_face_destroy (ft_font->ft_face); + ft_font->lock.fini (); + free (ft_font); } @@ -116,7 +135,7 @@ void hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) { - if (font->immutable) + if (hb_object_is_immutable (font)) return; if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) @@ -168,6 +187,7 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode); if (unlikely (!g)) @@ -191,6 +211,32 @@ return true; } +static unsigned int +hb_ft_get_nominal_glyphs (hb_font_t *font HB_UNUSED, + void *font_data, + unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + void *user_data HB_UNUSED) +{ + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); + unsigned int done; + for (done = 0; + done < count && (*first_glyph = FT_Get_Char_Index (ft_font->ft_face, *first_unicode)); + done++) + { + first_unicode = &StructAtOffsetUnaligned (first_unicode, unicode_stride); + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + } + /* We don't need to do ft_font->symbol dance here, since HB calls the singular + * nominal_glyph() for what we don't handle here. */ + return done; +} + + static hb_bool_t hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED, void *font_data, @@ -200,6 +246,7 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector); if (unlikely (!g)) @@ -209,22 +256,45 @@ return true; } -static hb_position_t -hb_ft_get_glyph_h_advance (hb_font_t *font, - void *font_data, - hb_codepoint_t glyph, - void *user_data HB_UNUSED) +static void +hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data, + unsigned count, + const hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride, + void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; - FT_Fixed v; + hb_lock_t lock (ft_font->lock); + FT_Face ft_face = ft_font->ft_face; + int load_flags = ft_font->load_flags; + int mult = font->x_scale < 0 ? -1 : +1; - if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v))) - return 0; + if (font->x_scale != ft_font->cached_x_scale.get ()) + { + ft_font->advance_cache.clear (); + ft_font->cached_x_scale.set (font->x_scale); + } - if (font->x_scale < 0) - v = -v; + for (unsigned int i = 0; i < count; i++) + { + FT_Fixed v = 0; + hb_codepoint_t glyph = *first_glyph; - return (v + (1<<9)) >> 10; + unsigned int cv; + if (ft_font->advance_cache.get (glyph, &cv)) + v = cv; + else + { + FT_Get_Advance (ft_face, glyph, load_flags, &v); + ft_font->advance_cache.set (glyph, v); + } + + *first_advance = (v * mult + (1<<9)) >> 10; + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } } static hb_position_t @@ -234,6 +304,7 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Fixed v; if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v))) @@ -256,6 +327,7 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) @@ -274,23 +346,6 @@ return true; } -static hb_position_t -hb_ft_get_glyph_h_kerning (hb_font_t *font, - void *font_data, - hb_codepoint_t left_glyph, - hb_codepoint_t right_glyph, - void *user_data HB_UNUSED) -{ - const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; - FT_Vector kerningv; - - FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED; - if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv)) - return 0; - - return kerningv.x; -} - static hb_bool_t hb_ft_get_glyph_extents (hb_font_t *font, void *font_data, @@ -299,6 +354,7 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) @@ -331,6 +387,7 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) @@ -356,8 +413,10 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); + FT_Face ft_face = ft_font->ft_face; - hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size); + hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size); if (ret && (size && !*name)) ret = false; @@ -372,6 +431,7 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; if (len < 0) @@ -404,10 +464,11 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; - metrics->ascender = ft_face->size->metrics.ascender; - metrics->descender = ft_face->size->metrics.descender; - metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender); + metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale); + metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale); + metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender); if (font->y_scale < 0) { metrics->ascender = -metrics->ascender; @@ -417,41 +478,25 @@ return true; } -static hb_font_funcs_t *static_ft_funcs = nullptr; - -#ifdef HB_USE_ATEXIT -static -void free_static_ft_funcs (void) -{ -retry: - hb_font_funcs_t *ft_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs); - if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, ft_funcs, nullptr)) - goto retry; - - hb_font_funcs_destroy (ft_funcs); -} +#if HB_USE_ATEXIT +static void free_static_ft_funcs (); #endif -static void -_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref) +static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t { -retry: - hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs); - - if (unlikely (!funcs)) + static hb_font_funcs_t *create () { - funcs = hb_font_funcs_create (); + hb_font_funcs_t *funcs = hb_font_funcs_create (); hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr); //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr); hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr); + hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr); hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr); - hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, nullptr, nullptr); + hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr); hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr); //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr); hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr); - hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr); - //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr); hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr); hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr); hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr); @@ -459,20 +504,35 @@ hb_font_funcs_make_immutable (funcs); - if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, nullptr, funcs)) { - hb_font_funcs_destroy (funcs); - goto retry; - } +#if HB_USE_ATEXIT + atexit (free_static_ft_funcs); +#endif -#ifdef HB_USE_ATEXIT - atexit (free_static_ft_funcs); /* First person registers atexit() callback. */ + return funcs; + } +} static_ft_funcs; + +#if HB_USE_ATEXIT +static +void free_static_ft_funcs () +{ + static_ft_funcs.free_instance (); +} #endif - }; +static hb_font_funcs_t * +_hb_ft_get_font_funcs () +{ + return static_ft_funcs.get_unconst (); +} + +static void +_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref) +{ bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL; hb_font_set_funcs (font, - funcs, + _hb_ft_get_font_funcs (), _hb_ft_font_create (ft_face, symbol, unref), _hb_ft_font_destroy); } @@ -497,7 +557,8 @@ return nullptr; error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length); - if (error) { + if (error) + { free (buffer); return nullptr; } @@ -683,47 +744,47 @@ return hb_ft_font_create (ft_face, _hb_ft_face_destroy); } +#if HB_USE_ATEXIT +static void free_static_ft_library (); +#endif -/* Thread-safe, lock-free, FT_Library */ +static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t +{ + static FT_Library create () + { + FT_Library l; + if (FT_Init_FreeType (&l)) + return nullptr; -static FT_Library ft_library; +#if HB_USE_ATEXIT + atexit (free_static_ft_library); +#endif -#ifdef HB_USE_ATEXIT + return l; + } + static void destroy (FT_Library l) + { + FT_Done_FreeType (l); + } + static FT_Library get_null () + { + return nullptr; + } +} static_ft_library; + +#if HB_USE_ATEXIT static -void free_ft_library (void) +void free_static_ft_library () { -retry: - FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library); - if (!hb_atomic_ptr_cmpexch (&ft_library, library, nullptr)) - goto retry; - - FT_Done_FreeType (library); + static_ft_library.free_instance (); } #endif static FT_Library -get_ft_library (void) +get_ft_library () { -retry: - FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library); - - if (unlikely (!library)) - { - /* Not found; allocate one. */ - if (FT_Init_FreeType (&library)) - return nullptr; - - if (!hb_atomic_ptr_cmpexch (&ft_library, nullptr, library)) { - FT_Done_FreeType (library); - goto retry; - } - -#ifdef HB_USE_ATEXIT - atexit (free_ft_library); /* First person registers atexit() callback. */ -#endif - } - - return library; + return static_ft_library.get_unconst (); } static void --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map.cc 2019-02-28 12:03:51.866503077 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map.cc 2019-02-28 12:03:51.750503079 -0800 @@ -24,10 +24,19 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-map-private.hh" +#include "hb-map.hh" -/* Public API */ +/** + * SECTION:hb-map + * @title: hb-map + * @short_description: Object representing integer to integer mapping + * @include: hb.h + * + * Map objects are integer-to-integer hash-maps. Currently they are + * not used in the HarfBuzz public API, but are provided for client's + * use if desired. + **/ /** @@ -38,7 +47,7 @@ * Since: 1.7.7 **/ hb_map_t * -hb_map_create (void) +hb_map_create () { hb_map_t *map; @@ -58,7 +67,7 @@ * Since: 1.7.7 **/ hb_map_t * -hb_map_get_empty (void) +hb_map_get_empty () { return const_cast (&Null(hb_map_t)); } @@ -157,8 +166,6 @@ * * * - * Return value: - * * Since: 1.7.7 **/ void @@ -188,7 +195,7 @@ /** * hb_map_del: * @map: a map. - * @codepoint: + * @key: * * * @@ -204,7 +211,7 @@ /** * hb_map_has: * @map: a map. - * @codepoint: + * @key: * * * --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cmap-table.hh 2019-02-28 12:03:52.218503071 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cmap-table.hh 2019-02-28 12:03:52.118503073 -0800 @@ -27,9 +27,8 @@ #ifndef HB_OT_CMAP_TABLE_HH #define HB_OT_CMAP_TABLE_HH -#include "hb-open-type-private.hh" -#include "hb-set-private.hh" -#include "hb-subset-plan.hh" +#include "hb-open-type.hh" +#include "hb-set.hh" /* * cmap -- Character to Glyph Index Mapping @@ -37,13 +36,12 @@ */ #define HB_OT_TAG_cmap HB_TAG('c','m','a','p') - namespace OT { struct CmapSubtableFormat0 { - inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const + bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const { hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0; if (!gid) @@ -51,8 +49,14 @@ *glyph = gid; return true; } + void collect_unicodes (hb_set_t *out) const + { + for (unsigned int i = 0; i < 256; i++) + if (glyphIdArray[i]) + out->add (i); + } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -88,23 +92,23 @@ this->format.set (4); this->length.set (get_sub_table_size (segments)); - this->segCountX2.set (segments.len * 2); - this->entrySelector.set (MAX (1u, _hb_bit_storage (segments.len)) - 1); + this->segCountX2.set (segments.length * 2); + this->entrySelector.set (MAX (1u, hb_bit_storage (segments.length)) - 1); this->searchRange.set (2 * (1u << this->entrySelector)); - this->rangeShift.set (segments.len * 2 > this->searchRange - ? 2 * segments.len - this->searchRange + this->rangeShift.set (segments.length * 2 > this->searchRange + ? 2 * segments.length - this->searchRange : 0); - HBUINT16 *end_count = c->allocate_size (HBUINT16::static_size * segments.len); + HBUINT16 *end_count = c->allocate_size (HBUINT16::static_size * segments.length); c->allocate_size (HBUINT16::static_size); // 2 bytes of padding. - HBUINT16 *start_count = c->allocate_size (HBUINT16::static_size * segments.len); - HBINT16 *id_delta = c->allocate_size (HBUINT16::static_size * segments.len); - HBUINT16 *id_range_offset = c->allocate_size (HBUINT16::static_size * segments.len); + HBUINT16 *start_count = c->allocate_size (HBUINT16::static_size * segments.length); + HBINT16 *id_delta = c->allocate_size (HBUINT16::static_size * segments.length); + HBUINT16 *id_range_offset = c->allocate_size (HBUINT16::static_size * segments.length); if (id_range_offset == nullptr) return_trace (false); - for (unsigned int i = 0; i < segments.len; i++) + for (unsigned int i = 0; i < segments.length; i++) { end_count[i].set (segments[i].end_code); start_count[i].set (segments[i].start_code); @@ -150,10 +154,10 @@ return_trace (true); } - static inline size_t get_sub_table_size (const hb_vector_t &segments) + static size_t get_sub_table_size (const hb_vector_t &segments) { size_t segment_size = 0; - for (unsigned int i = 0; i < segments.len; i++) + for (unsigned int i = 0; i < segments.length; i++) { // Parallel array entries segment_size += @@ -172,8 +176,8 @@ + segment_size; } - static inline bool create_sub_table_plan (const hb_subset_plan_t *plan, - hb_vector_t *segments) + static bool create_sub_table_plan (const hb_subset_plan_t *plan, + hb_vector_t *segments) { segment_plan *segment = nullptr; hb_codepoint_t last_gid = 0; @@ -187,13 +191,11 @@ return false; } - if (cp > 0xFFFF) { - // We are now outside of unicode BMP, stop adding to this cmap. - break; - } + /* Stop adding to cmap if we are now outside of unicode BMP. */ + if (cp > 0xFFFF) break; - if (!segment - || cp != segment->end_code + 1u) + if (!segment || + cp != segment->end_code + 1u) { segment = segments->push (); segment->start_code.set (cp); @@ -224,29 +226,32 @@ struct accelerator_t { - inline void init (const CmapSubtableFormat4 *subtable) + accelerator_t () {} + accelerator_t (const CmapSubtableFormat4 *subtable) { init (subtable); } + ~accelerator_t () { fini (); } + + void init (const CmapSubtableFormat4 *subtable) { segCount = subtable->segCountX2 / 2; - endCount = subtable->values; + endCount = subtable->values.arrayZ; startCount = endCount + segCount + 1; idDelta = startCount + segCount; idRangeOffset = idDelta + segCount; glyphIdArray = idRangeOffset + segCount; glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2; } + void fini () {} - static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph) + bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const { - const accelerator_t *thiz = (const accelerator_t *) obj; - /* Custom two-array bsearch. */ - int min = 0, max = (int) thiz->segCount - 1; - const HBUINT16 *startCount = thiz->startCount; - const HBUINT16 *endCount = thiz->endCount; + int min = 0, max = (int) this->segCount - 1; + const HBUINT16 *startCount = this->startCount; + const HBUINT16 *endCount = this->endCount; unsigned int i; while (min <= max) { - int mid = (min + max) / 2; + int mid = ((unsigned int) min + (unsigned int) max) / 2; if (codepoint < startCount[mid]) max = mid - 1; else if (codepoint > endCount[mid]) @@ -261,33 +266,55 @@ found: hb_codepoint_t gid; - unsigned int rangeOffset = thiz->idRangeOffset[i]; + unsigned int rangeOffset = this->idRangeOffset[i]; if (rangeOffset == 0) - gid = codepoint + thiz->idDelta[i]; + gid = codepoint + this->idDelta[i]; else { /* Somebody has been smoking... */ - unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount; - if (unlikely (index >= thiz->glyphIdArrayLength)) + unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount; + if (unlikely (index >= this->glyphIdArrayLength)) return false; - gid = thiz->glyphIdArray[index]; + gid = this->glyphIdArray[index]; if (unlikely (!gid)) return false; - gid += thiz->idDelta[i]; + gid += this->idDelta[i]; } - - *glyph = gid & 0xFFFFu; + gid &= 0xFFFFu; + if (!gid) + return false; + *glyph = gid; return true; } - - static inline void get_all_codepoints_func (const void *obj, hb_set_t *out) + static bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph) + { + return ((const accelerator_t *) obj)->get_glyph (codepoint, glyph); + } + void collect_unicodes (hb_set_t *out) const { - const accelerator_t *thiz = (const accelerator_t *) obj; - for (unsigned int i = 0; i < thiz->segCount; i++) + unsigned int count = this->segCount; + if (count && this->startCount[count - 1] == 0xFFFFu) + count--; /* Skip sentinel segment. */ + for (unsigned int i = 0; i < count; i++) { - if (thiz->startCount[i] != 0xFFFFu - || thiz->endCount[i] != 0xFFFFu) // Skip the last segment (0xFFFF) - hb_set_add_range (out, thiz->startCount[i], thiz->endCount[i]); + unsigned int rangeOffset = this->idRangeOffset[i]; + if (rangeOffset == 0) + out->add_range (this->startCount[i], this->endCount[i]); + else + { + for (hb_codepoint_t codepoint = this->startCount[i]; + codepoint <= this->endCount[i]; + codepoint++) + { + unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount; + if (unlikely (index >= this->glyphIdArrayLength)) + break; + hb_codepoint_t gid = this->glyphIdArray[index]; + if (unlikely (!gid)) + continue; + out->add (codepoint); + } + } } } @@ -300,14 +327,18 @@ unsigned int glyphIdArrayLength; }; - inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const + bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const { - accelerator_t accel; - accel.init (this); + accelerator_t accel (this); return accel.get_glyph_func (&accel, codepoint, glyph); } + void collect_unicodes (hb_set_t *out) const + { + accelerator_t accel (this); + accel.collect_unicodes (out); + } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) @@ -340,7 +371,8 @@ HBUINT16 entrySelector; /* log2(searchRange/2) */ HBUINT16 rangeShift; /* 2 x segCount - searchRange */ - HBUINT16 values[VAR]; + UnsizedArrayOf + values; #if 0 HBUINT16 endCount[segCount]; /* End characterCode for each segment, * last=0xFFFFu. */ @@ -348,7 +380,8 @@ HBUINT16 startCount[segCount]; /* Start character code for each segment. */ HBINT16 idDelta[segCount]; /* Delta for all character codes in segment. */ HBUINT16 idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */ - HBUINT16 glyphIdArray[VAR]; /* Glyph index array (arbitrary length) */ + UnsizedArrayOf + glyphIdArray; /* Glyph index array (arbitrary length) */ #endif public: @@ -370,7 +403,7 @@ return 0; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -380,15 +413,16 @@ HBUINT32 startCharCode; /* First character code in this group. */ HBUINT32 endCharCode; /* Last character code in this group. */ HBUINT32 glyphID; /* Glyph index; interpretation depends on - * subtable format. */ + * subtable format. */ public: DEFINE_SIZE_STATIC (12); }; +DECLARE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup); template struct CmapSubtableTrimmed { - inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const + bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const { /* Rely on our implicit array bound-checking. */ hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode]; @@ -397,8 +431,16 @@ *glyph = gid; return true; } + void collect_unicodes (hb_set_t *out) const + { + hb_codepoint_t start = startCharCode; + unsigned int count = glyphIdArray.len; + for (unsigned int i = 0; i < count; i++) + if (glyphIdArray[i]) + out->add (start + i); + } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && glyphIdArray.sanitize (c)); @@ -424,37 +466,36 @@ { friend struct cmap; - inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const + bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const { - int i = groups.bsearch (codepoint); - if (i == -1) + hb_codepoint_t gid = T::group_get_glyph (groups.bsearch (codepoint), codepoint); + if (!gid) return false; - *glyph = T::group_get_glyph (groups[i], codepoint); + *glyph = gid; return true; } - inline void get_all_codepoints (hb_set_t *out) const + void collect_unicodes (hb_set_t *out) const { for (unsigned int i = 0; i < this->groups.len; i++) { - hb_set_add_range (out, - this->groups[i].startCharCode, - this->groups[i].endCharCode); + out->add_range (this->groups[i].startCharCode, + MIN ((hb_codepoint_t) this->groups[i].endCharCode, + (hb_codepoint_t) HB_UNICODE_MAX)); } } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && groups.sanitize (c)); } - inline bool serialize (hb_serialize_context_t *c, - const hb_vector_t &group_data) + bool serialize (hb_serialize_context_t *c, + const hb_vector_t &group_data) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - Supplier supplier (group_data.arrayZ, group_data.len); - if (unlikely (!groups.serialize (c, supplier, group_data.len))) return_trace (false); + if (unlikely (!groups.serialize (c, group_data.as_array ()))) return_trace (false); return true; } @@ -471,9 +512,10 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented { - static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group, - hb_codepoint_t u) - { return group.glyphID + (u - group.startCharCode); } + static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group, + hb_codepoint_t u) + { return likely (group.startCharCode <= group.endCharCode) ? + group.glyphID + (u - group.startCharCode) : 0; } bool serialize (hb_serialize_context_t *c, @@ -488,13 +530,13 @@ return CmapSubtableLongSegmented::serialize (c, groups); } - static inline size_t get_sub_table_size (const hb_vector_t &groups) + static size_t get_sub_table_size (const hb_vector_t &groups) { - return 16 + 12 * groups.len; + return 16 + 12 * groups.length; } - static inline bool create_sub_table_plan (const hb_subset_plan_t *plan, - hb_vector_t *groups) + static bool create_sub_table_plan (const hb_subset_plan_t *plan, + hb_vector_t *groups) { CmapSubtableLongGroup *group = nullptr; @@ -513,14 +555,12 @@ group->startCharCode.set (cp); group->endCharCode.set (cp); group->glyphID.set (new_gid); - } else - { - group->endCharCode.set (cp); } + else group->endCharCode.set (cp); } DEBUG_MSG(SUBSET, nullptr, "cmap"); - for (unsigned int i = 0; i < groups->len; i++) { + for (unsigned int i = 0; i < groups->length; i++) { CmapSubtableLongGroup& group = (*groups)[i]; DEBUG_MSG(SUBSET, nullptr, " %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode)); } @@ -529,9 +569,9 @@ } private: - static inline bool _is_gid_consecutive (CmapSubtableLongGroup *group, - hb_codepoint_t cp, - hb_codepoint_t new_gid) + static bool _is_gid_consecutive (CmapSubtableLongGroup *group, + hb_codepoint_t cp, + hb_codepoint_t new_gid) { return (cp - 1 == group->endCharCode) && new_gid == group->glyphID + (cp - group->startCharCode); @@ -541,8 +581,8 @@ struct CmapSubtableFormat13 : CmapSubtableLongSegmented { - static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group, - hb_codepoint_t u HB_UNUSED) + static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group, + hb_codepoint_t u HB_UNUSED) { return group.glyphID; } }; @@ -555,36 +595,52 @@ struct UnicodeValueRange { - inline int cmp (const hb_codepoint_t &codepoint) const + int cmp (const hb_codepoint_t &codepoint) const { if (codepoint < startUnicodeValue) return -1; if (codepoint > startUnicodeValue + additionalCount) return +1; return 0; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } HBUINT24 startUnicodeValue; /* First value in this range. */ - HBUINT8 additionalCount; /* Number of additional values in this + HBUINT8 additionalCount; /* Number of additional values in this * range. */ public: DEFINE_SIZE_STATIC (4); }; -typedef SortedArrayOf DefaultUVS; +struct DefaultUVS : SortedArrayOf +{ + void collect_unicodes (hb_set_t *out) const + { + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + { + hb_codepoint_t first = arrayZ[i].startUnicodeValue; + hb_codepoint_t last = MIN ((hb_codepoint_t) (first + arrayZ[i].additionalCount), + (hb_codepoint_t) HB_UNICODE_MAX); + out->add_range (first, last); + } + } + + public: + DEFINE_SIZE_ARRAY (4, *this); +}; struct UVSMapping { - inline int cmp (const hb_codepoint_t &codepoint) const + int cmp (const hb_codepoint_t &codepoint) const { return unicodeValue.cmp (codepoint); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -596,35 +652,48 @@ DEFINE_SIZE_STATIC (5); }; -typedef SortedArrayOf NonDefaultUVS; +struct NonDefaultUVS : SortedArrayOf +{ + void collect_unicodes (hb_set_t *out) const + { + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + out->add (arrayZ[i].glyphID); + } + + public: + DEFINE_SIZE_ARRAY (4, *this); +}; struct VariationSelectorRecord { - inline glyph_variant_t get_glyph (hb_codepoint_t codepoint, - hb_codepoint_t *glyph, - const void *base) const - { - int i; - const DefaultUVS &defaults = base+defaultUVS; - i = defaults.bsearch (codepoint); - if (i != -1) + glyph_variant_t get_glyph (hb_codepoint_t codepoint, + hb_codepoint_t *glyph, + const void *base) const + { + if ((base+defaultUVS).bfind (codepoint)) return GLYPH_VARIANT_USE_DEFAULT; - const NonDefaultUVS &nonDefaults = base+nonDefaultUVS; - i = nonDefaults.bsearch (codepoint); - if (i != -1) + const UVSMapping &nonDefault = (base+nonDefaultUVS).bsearch (codepoint); + if (nonDefault.glyphID) { - *glyph = nonDefaults[i].glyphID; + *glyph = nonDefault.glyphID; return GLYPH_VARIANT_FOUND; } return GLYPH_VARIANT_NOT_FOUND; } - inline int cmp (const hb_codepoint_t &variation_selector) const + void collect_unicodes (hb_set_t *out, const void *base) const + { + (base+defaultUVS).collect_unicodes (out); + (base+nonDefaultUVS).collect_unicodes (out); + } + + int cmp (const hb_codepoint_t &variation_selector) const { return varSelector.cmp (variation_selector); } - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -634,23 +703,35 @@ HBUINT24 varSelector; /* Variation selector. */ LOffsetTo - defaultUVS; /* Offset to Default UVS Table. May be 0. */ + defaultUVS; /* Offset to Default UVS Table. May be 0. */ LOffsetTo - nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */ + nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */ public: DEFINE_SIZE_STATIC (11); }; struct CmapSubtableFormat14 { - inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint, - hb_codepoint_t variation_selector, - hb_codepoint_t *glyph) const + glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph) const + { + return record.bsearch (variation_selector).get_glyph (codepoint, glyph, this); + } + + void collect_variation_selectors (hb_set_t *out) const + { + unsigned int count = record.len; + for (unsigned int i = 0; i < count; i++) + out->add (record.arrayZ[i].varSelector); + } + void collect_variation_unicodes (hb_codepoint_t variation_selector, + hb_set_t *out) const { - return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this); + record.bsearch (variation_selector).collect_unicodes (out, this); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -671,8 +752,8 @@ { /* Note: We intentionally do NOT implement subtable formats 2 and 8. */ - inline bool get_glyph (hb_codepoint_t codepoint, - hb_codepoint_t *glyph) const + bool get_glyph (hb_codepoint_t codepoint, + hb_codepoint_t *glyph) const { switch (u.format) { case 0: return u.format0 .get_glyph (codepoint, glyph); @@ -685,8 +766,21 @@ default: return false; } } + void collect_unicodes (hb_set_t *out) const + { + switch (u.format) { + case 0: u.format0 .collect_unicodes (out); return; + case 4: u.format4 .collect_unicodes (out); return; + case 6: u.format6 .collect_unicodes (out); return; + case 10: u.format10.collect_unicodes (out); return; + case 12: u.format12.collect_unicodes (out); return; + case 13: u.format13.collect_unicodes (out); return; + case 14: + default: return; + } + } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return_trace (false); @@ -720,7 +814,7 @@ struct EncodingRecord { - inline int cmp (const EncodingRecord &other) const + int cmp (const EncodingRecord &other) const { int ret; ret = platformID.cmp (other.platformID); @@ -730,7 +824,7 @@ return 0; } - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -747,22 +841,11 @@ struct cmap { - static const hb_tag_t tableTag = HB_OT_TAG_cmap; - - struct subset_plan { - subset_plan(void) - { - format4_segments.init(); - format12_groups.init(); - } + static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap; - ~subset_plan(void) - { - format4_segments.fini(); - format12_groups.fini(); - } - - inline size_t final_size() const + struct subset_plan + { + size_t final_size () const { return 4 // header + 8 * 3 // 3 EncodingRecord @@ -770,67 +853,57 @@ + CmapSubtableFormat12::get_sub_table_size (this->format12_groups); } - // Format 4 hb_vector_t format4_segments; - // Format 12 hb_vector_t format12_groups; }; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - likely (version == 0) && - encodingRecord.sanitize (c, this)); - } - - inline bool _create_plan (const hb_subset_plan_t *plan, - subset_plan *cmap_plan) const + bool _create_plan (const hb_subset_plan_t *plan, + subset_plan *cmap_plan) const { - if (unlikely( !CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments))) + if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments))) return false; return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups); } - inline bool _subset (const hb_subset_plan_t *plan, - const subset_plan &cmap_subset_plan, - size_t dest_sz, - void *dest) const + bool _subset (const hb_subset_plan_t *plan, + const subset_plan &cmap_subset_plan, + size_t dest_sz, + void *dest) const { hb_serialize_context_t c (dest, dest_sz); - OT::cmap *cmap = c.start_serialize (); - if (unlikely (!c.extend_min (*cmap))) + cmap *table = c.start_serialize (); + if (unlikely (!c.extend_min (*table))) { return false; } - cmap->version.set (0); + table->version.set (0); - if (unlikely (!cmap->encodingRecord.serialize (&c, /* numTables */ 3))) + if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ 3))) return false; // TODO(grieger): Convert the below to a for loop // Format 4, Plat 0 Encoding Record - EncodingRecord &format4_plat0_rec = cmap->encodingRecord[0]; + EncodingRecord &format4_plat0_rec = table->encodingRecord[0]; format4_plat0_rec.platformID.set (0); // Unicode format4_plat0_rec.encodingID.set (3); // Format 4, Plat 3 Encoding Record - EncodingRecord &format4_plat3_rec = cmap->encodingRecord[1]; + EncodingRecord &format4_plat3_rec = table->encodingRecord[1]; format4_plat3_rec.platformID.set (3); // Windows format4_plat3_rec.encodingID.set (1); // Unicode BMP // Format 12 Encoding Record - EncodingRecord &format12_rec = cmap->encodingRecord[2]; + EncodingRecord &format12_rec = table->encodingRecord[2]; format12_rec.platformID.set (3); // Windows format12_rec.encodingID.set (10); // Unicode UCS-4 // Write out format 4 sub table { - CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, cmap); + CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, table); format4_plat3_rec.subtable.set (format4_plat0_rec.subtable); subtable.u.format.set (4); @@ -841,7 +914,7 @@ // Write out format 12 sub table. { - CmapSubtable &subtable = format12_rec.subtable.serialize (&c, cmap); + CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table); subtable.u.format.set (12); CmapSubtableFormat12 &format12 = subtable.u.format12; @@ -854,7 +927,7 @@ return true; } - inline bool subset (hb_subset_plan_t *plan) const + bool subset (hb_subset_plan_t *plan) const { subset_plan cmap_subset_plan; @@ -865,7 +938,7 @@ } // We now know how big our blob needs to be - size_t dest_sz = cmap_subset_plan.final_size(); + size_t dest_sz = cmap_subset_plan.final_size (); void *dest = malloc (dest_sz); if (unlikely (!dest)) { DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for cmap subset output", (unsigned long) dest_sz); @@ -880,7 +953,7 @@ } // all done, write the blob into dest - hb_blob_t *cmap_prime = hb_blob_create ((const char *)dest, + hb_blob_t *cmap_prime = hb_blob_create ((const char *) dest, dest_sz, HB_MEMORY_MODE_READONLY, dest, @@ -890,137 +963,149 @@ return result; } - struct accelerator_t + const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const { - inline void init (hb_face_t *face) + if (symbol) *symbol = false; + + const CmapSubtable *subtable; + + /* 32-bit subtables. */ + if ((subtable = this->find_subtable (3, 10))) return subtable; + if ((subtable = this->find_subtable (0, 6))) return subtable; + if ((subtable = this->find_subtable (0, 4))) return subtable; + + /* 16-bit subtables. */ + if ((subtable = this->find_subtable (3, 1))) return subtable; + if ((subtable = this->find_subtable (0, 3))) return subtable; + if ((subtable = this->find_subtable (0, 2))) return subtable; + if ((subtable = this->find_subtable (0, 1))) return subtable; + if ((subtable = this->find_subtable (0, 0))) return subtable; + + /* Symbol subtable. */ + if ((subtable = this->find_subtable (3, 0))) { - this->blob = OT::Sanitizer().sanitize (face->reference_table (HB_OT_TAG_cmap)); - const OT::cmap *cmap = this->blob->as (); - const OT::CmapSubtable *subtable = nullptr; - const OT::CmapSubtableFormat14 *subtable_uvs = nullptr; - - bool symbol = false; - /* 32-bit subtables. */ - if (!subtable) subtable = cmap->find_subtable (3, 10); - if (!subtable) subtable = cmap->find_subtable (0, 6); - if (!subtable) subtable = cmap->find_subtable (0, 4); - /* 16-bit subtables. */ - if (!subtable) subtable = cmap->find_subtable (3, 1); - if (!subtable) subtable = cmap->find_subtable (0, 3); - if (!subtable) subtable = cmap->find_subtable (0, 2); - if (!subtable) subtable = cmap->find_subtable (0, 1); - if (!subtable) subtable = cmap->find_subtable (0, 0); - if (!subtable) - { - subtable = cmap->find_subtable (3, 0); - if (subtable) symbol = true; - } - /* Meh. */ - if (!subtable) subtable = &Null(OT::CmapSubtable); + if (symbol) *symbol = true; + return subtable; + } - /* UVS subtable. */ - if (!subtable_uvs) + /* Meh. */ + return &Null (CmapSubtable); + } + + struct accelerator_t + { + void init (hb_face_t *face) + { + this->table = hb_sanitize_context_t ().reference_table (face); + bool symbol; + this->subtable = table->find_best_subtable (&symbol); + this->subtable_uvs = &Null (CmapSubtableFormat14); { - const OT::CmapSubtable *st = cmap->find_subtable (0, 5); + const CmapSubtable *st = table->find_subtable (0, 5); if (st && st->u.format == 14) subtable_uvs = &st->u.format14; } - /* Meh. */ - if (!subtable_uvs) subtable_uvs = &Null(OT::CmapSubtableFormat14); - - this->uvs_table = subtable_uvs; this->get_glyph_data = subtable; if (unlikely (symbol)) { - this->get_glyph_func = get_glyph_from_symbol; - this->get_all_codepoints_func = null_get_all_codepoints_func; + this->get_glyph_funcZ = get_glyph_from_symbol; } else { switch (subtable->u.format) { /* Accelerate format 4 and format 12. */ default: - this->get_glyph_func = get_glyph_from; - this->get_all_codepoints_func = null_get_all_codepoints_func; + this->get_glyph_funcZ = get_glyph_from; break; case 12: - this->get_glyph_func = get_glyph_from; - this->get_all_codepoints_func = get_all_codepoints_from; + this->get_glyph_funcZ = get_glyph_from; break; case 4: { this->format4_accel.init (&subtable->u.format4); this->get_glyph_data = &this->format4_accel; - this->get_glyph_func = this->format4_accel.get_glyph_func; - this->get_all_codepoints_func = this->format4_accel.get_all_codepoints_func; + this->get_glyph_funcZ = this->format4_accel.get_glyph_func; } break; } } } - inline void fini (void) - { - hb_blob_destroy (this->blob); - } + void fini () { this->table.destroy (); } - inline bool get_nominal_glyph (hb_codepoint_t unicode, + bool get_nominal_glyph (hb_codepoint_t unicode, hb_codepoint_t *glyph) const { - return this->get_glyph_func (this->get_glyph_data, unicode, glyph); + if (unlikely (!this->get_glyph_funcZ)) return false; + return this->get_glyph_funcZ (this->get_glyph_data, unicode, glyph); + } + unsigned int get_nominal_glyphs (unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride) const + { + if (unlikely (!this->get_glyph_funcZ)) return 0; + + hb_cmap_get_glyph_func_t get_glyph_funcZ = this->get_glyph_funcZ; + const void *get_glyph_data = this->get_glyph_data; + + unsigned int done; + for (done = 0; + done < count && get_glyph_funcZ (get_glyph_data, *first_unicode, first_glyph); + done++) + { + first_unicode = &StructAtOffsetUnaligned (first_unicode, unicode_stride); + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + } + return done; } - inline bool get_variation_glyph (hb_codepoint_t unicode, - hb_codepoint_t variation_selector, - hb_codepoint_t *glyph) const + bool get_variation_glyph (hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph) const { - switch (this->uvs_table->get_glyph_variant (unicode, - variation_selector, - glyph)) + switch (this->subtable_uvs->get_glyph_variant (unicode, + variation_selector, + glyph)) { - case OT::GLYPH_VARIANT_NOT_FOUND: return false; - case OT::GLYPH_VARIANT_FOUND: return true; - case OT::GLYPH_VARIANT_USE_DEFAULT: break; + case GLYPH_VARIANT_NOT_FOUND: return false; + case GLYPH_VARIANT_FOUND: return true; + case GLYPH_VARIANT_USE_DEFAULT: break; } return get_nominal_glyph (unicode, glyph); } - inline void get_all_codepoints (hb_set_t *out) const + void collect_unicodes (hb_set_t *out) const + { + subtable->collect_unicodes (out); + } + void collect_variation_selectors (hb_set_t *out) const { - this->get_all_codepoints_func (get_glyph_data, out); + subtable_uvs->collect_variation_selectors (out); + } + void collect_variation_unicodes (hb_codepoint_t variation_selector, + hb_set_t *out) const + { + subtable_uvs->collect_variation_unicodes (variation_selector, out); } protected: typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph); - typedef void (*hb_cmap_get_all_codepoints_func_t) (const void *obj, - hb_set_t *out); - - static inline void null_get_all_codepoints_func (const void *obj, hb_set_t *out) - { - // NOOP - } template - static inline bool get_glyph_from (const void *obj, - hb_codepoint_t codepoint, - hb_codepoint_t *glyph) + static bool get_glyph_from (const void *obj, + hb_codepoint_t codepoint, + hb_codepoint_t *glyph) { const Type *typed_obj = (const Type *) obj; return typed_obj->get_glyph (codepoint, glyph); } template - static inline void get_all_codepoints_from (const void *obj, - hb_set_t *out) - { - const Type *typed_obj = (const Type *) obj; - typed_obj->get_all_codepoints (out); - } - - template - static inline bool get_glyph_from_symbol (const void *obj, + static bool get_glyph_from_symbol (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph) { @@ -1042,33 +1127,41 @@ } private: - hb_cmap_get_glyph_func_t get_glyph_func; + hb_nonnull_ptr_t subtable; + hb_nonnull_ptr_t subtable_uvs; + + hb_cmap_get_glyph_func_t get_glyph_funcZ; const void *get_glyph_data; - hb_cmap_get_all_codepoints_func_t get_all_codepoints_func; - OT::CmapSubtableFormat4::accelerator_t format4_accel; + CmapSubtableFormat4::accelerator_t format4_accel; - const OT::CmapSubtableFormat14 *uvs_table; - hb_blob_t *blob; + hb_blob_ptr_t table; }; protected: - inline const CmapSubtable *find_subtable (unsigned int platform_id, - unsigned int encoding_id) const + const CmapSubtable *find_subtable (unsigned int platform_id, + unsigned int encoding_id) const { EncodingRecord key; key.platformID.set (platform_id); key.encodingID.set (encoding_id); - /* Note: We can use bsearch, but since it has no performance - * implications, we use lsearch and as such accept fonts with - * unsorted subtable list. */ - int result = encodingRecord./*bsearch*/lsearch (key); - if (result == -1 || !encodingRecord[result].subtable) + const EncodingRecord &result = encodingRecord.bsearch (key); + if (!result.subtable) return nullptr; - return &(this+encodingRecord[result].subtable); + return &(this+result.subtable); + } + + public: + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + likely (version == 0) && + encodingRecord.sanitize (c, this)); } protected: @@ -1079,6 +1172,7 @@ DEFINE_SIZE_ARRAY (4, encodingRecord); }; +struct cmap_accelerator_t : cmap::accelerator_t {}; } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cbdt-table.hh 2019-02-28 12:03:52.626503065 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cbdt-table.hh 2019-02-28 12:03:52.490503067 -0800 @@ -27,7 +27,7 @@ #ifndef HB_OT_COLOR_CBDT_TABLE_HH #define HB_OT_COLOR_CBDT_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" /* * CBLC -- Color Bitmap Location @@ -45,18 +45,18 @@ struct SmallGlyphMetrics { - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } - inline void get_extents (hb_glyph_extents_t *extents) const + void get_extents (hb_glyph_extents_t *extents) const { extents->x_bearing = bearingX; extents->y_bearing = bearingY; extents->width = width; - extents->height = -height; + extents->height = - (hb_position_t) height; } HBUINT8 height; @@ -79,7 +79,7 @@ struct SBitLineMetrics { - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -108,7 +108,7 @@ struct IndexSubtableHeader { - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -124,11 +124,11 @@ template struct IndexSubtableFormat1Or3 { - inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const + bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1)); + offsetArrayZ.sanitize (c, glyph_count + 1)); } bool get_image_data (unsigned int idx, @@ -144,7 +144,8 @@ } IndexSubtableHeader header; - Offset offsetArrayZ[VAR]; + UnsizedArrayOf > + offsetArrayZ; public: DEFINE_SIZE_ARRAY(8, offsetArrayZ); }; @@ -154,7 +155,7 @@ struct IndexSubtable { - inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const + bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const { TRACE_SANITIZE (this); if (!u.header.sanitize (c)) return_trace (false); @@ -165,7 +166,7 @@ } } - inline bool get_extents (hb_glyph_extents_t *extents) const + bool get_extents (hb_glyph_extents_t *extents HB_UNUSED) const { switch (u.header.indexFormat) { case 2: case 5: /* TODO */ @@ -200,29 +201,28 @@ struct IndexSubtableRecord { - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && firstGlyphIndex <= lastGlyphIndex && - offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1)); + offsetToSubtable.sanitize (c, base, lastGlyphIndex - firstGlyphIndex + 1)); } - inline bool get_extents (hb_glyph_extents_t *extents) const + bool get_extents (hb_glyph_extents_t *extents, + const void *base) const { - return (this+offsetToSubtable).get_extents (extents); + return (base+offsetToSubtable).get_extents (extents); } - bool get_image_data (unsigned int gid, + bool get_image_data (unsigned int gid, + const void *base, unsigned int *offset, unsigned int *length, unsigned int *format) const { - if (gid < firstGlyphIndex || gid > lastGlyphIndex) - { - return false; - } - return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex, + if (gid < firstGlyphIndex || gid > lastGlyphIndex) return false; + return (base+offsetToSubtable).get_image_data (gid - firstGlyphIndex, offset, length, format); } @@ -237,15 +237,10 @@ { friend struct CBDT; - inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const + bool sanitize (hb_sanitize_context_t *c, unsigned int count) const { TRACE_SANITIZE (this); - if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count))) - return_trace (false); - for (unsigned int i = 0; i < count; i++) - if (unlikely (!indexSubtablesZ[i].sanitize (c, this))) - return_trace (false); - return_trace (true); + return_trace (indexSubtablesZ.sanitize (c, count, this)); } public: @@ -255,17 +250,14 @@ { unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex; unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex; - if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) { + if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) return &indexSubtablesZ[i]; - } } return nullptr; } protected: - IndexSubtableRecord indexSubtablesZ[VAR]; - public: - DEFINE_SIZE_ARRAY(0, indexSubtablesZ); + UnsizedArrayOf indexSubtablesZ; }; struct BitmapSizeTable @@ -273,23 +265,25 @@ friend struct CBLC; friend struct CBDT; - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) && - c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) && horizontal.sanitize (c) && vertical.sanitize (c)); } - const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const + const IndexSubtableRecord *find_table (hb_codepoint_t glyph, + const void *base, + const void **out_base) const { + *out_base = &(base+indexSubtableArrayOffset); return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables); } protected: - LOffsetTo + LNNOffsetTo indexSubtableArrayOffset; HBUINT32 indexTablesSize; HBUINT32 numberOfIndexSubtables; @@ -338,9 +332,9 @@ { friend struct CBDT; - static const hb_tag_t tableTag = HB_OT_TAG_CBLC; + static constexpr hb_tag_t tableTag = HB_OT_TAG_CBLC; - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -349,25 +343,30 @@ } protected: - const IndexSubtableRecord *find_table (hb_codepoint_t glyph, - unsigned int *x_ppem, unsigned int *y_ppem) const + const BitmapSizeTable &choose_strike (hb_font_t *font) const { - /* TODO: Make it possible to select strike. */ + unsigned count = sizeTables.len; + if (unlikely (!count)) + return Null(BitmapSizeTable); + + unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem); + if (!requested_ppem) + requested_ppem = 1<<30; /* Choose largest strike. */ + unsigned int best_i = 0; + unsigned int best_ppem = MAX (sizeTables[0].ppemX, sizeTables[0].ppemY); - unsigned int count = sizeTables.len; - for (uint32_t i = 0; i < count; ++i) + for (unsigned int i = 1; i < count; i++) { - unsigned int startGlyphIndex = sizeTables.arrayZ[i].startGlyphIndex; - unsigned int endGlyphIndex = sizeTables.arrayZ[i].endGlyphIndex; - if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) + unsigned int ppem = MAX (sizeTables[i].ppemX, sizeTables[i].ppemY); + if ((requested_ppem <= ppem && ppem < best_ppem) || + (requested_ppem > best_ppem && ppem > best_ppem)) { - *x_ppem = sizeTables[i].ppemX; - *y_ppem = sizeTables[i].ppemY; - return sizeTables[i].find_table (glyph, this); + best_i = i; + best_ppem = ppem; } } - return nullptr; + return sizeTables[best_i]; } protected: @@ -379,60 +378,42 @@ struct CBDT { - static const hb_tag_t tableTag = HB_OT_TAG_CBDT; - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - likely (version.major == 2 || version.major == 3)); - } + static constexpr hb_tag_t tableTag = HB_OT_TAG_CBDT; struct accelerator_t { - inline void init (hb_face_t *face) + void init (hb_face_t *face) { - upem = hb_face_get_upem (face); - - cblc_blob = Sanitizer().sanitize (face->reference_table (HB_OT_TAG_CBLC)); - cbdt_blob = Sanitizer().sanitize (face->reference_table (HB_OT_TAG_CBDT)); - cbdt_len = hb_blob_get_length (cbdt_blob); - - if (hb_blob_get_length (cblc_blob) == 0) { - cblc = nullptr; - cbdt = nullptr; - return; /* Not a bitmap font. */ - } - cblc = cblc_blob->as (); - cbdt = cbdt_blob->as (); + cblc = hb_sanitize_context_t().reference_table (face); + cbdt = hb_sanitize_context_t().reference_table (face); + upem = hb_face_get_upem (face); } - inline void fini (void) + void fini () { - hb_blob_destroy (this->cblc_blob); - hb_blob_destroy (this->cbdt_blob); + this->cblc.destroy (); + this->cbdt.destroy (); } - inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const + bool get_extents (hb_font_t *font, hb_codepoint_t glyph, + hb_glyph_extents_t *extents) const { - unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */ - - if (!cblc) - return false; // Not a color bitmap font. - - const IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem); - if (!subtable_record || !x_ppem || !y_ppem) + const void *base; + const BitmapSizeTable &strike = this->cblc->choose_strike (font); + const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base); + if (!subtable_record || !strike.ppemX || !strike.ppemY) return false; - if (subtable_record->get_extents (extents)) + if (subtable_record->get_extents (extents, base)) return true; unsigned int image_offset = 0, image_length = 0, image_format = 0; - if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format)) + if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format)) return false; { + unsigned int cbdt_len = cbdt.get_length (); if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length)) return false; @@ -441,98 +422,114 @@ case 17: { if (unlikely (image_length < GlyphBitmapDataFormat17::min_size)) return false; - const GlyphBitmapDataFormat17& glyphFormat17 = StructAtOffset (this->cbdt, image_offset); glyphFormat17.glyphMetrics.get_extents (extents); + break; + } + case 18: { + if (unlikely (image_length < GlyphBitmapDataFormat18::min_size)) + return false; + const GlyphBitmapDataFormat18& glyphFormat18 = + StructAtOffset (this->cbdt, image_offset); + glyphFormat18.glyphMetrics.get_extents (extents); + break; } - break; default: // TODO: Support other image formats. return false; } } - /* Convert to the font units. */ - extents->x_bearing *= upem / (float) x_ppem; - extents->y_bearing *= upem / (float) y_ppem; - extents->width *= upem / (float) x_ppem; - extents->height *= upem / (float) y_ppem; + /* Convert to font units. */ + double x_scale = upem / (double) strike.ppemX; + double y_scale = upem / (double) strike.ppemY; + extents->x_bearing = round (extents->x_bearing * x_scale); + extents->y_bearing = round (extents->y_bearing * y_scale); + extents->width = round (extents->width * x_scale); + extents->height = round (extents->height * y_scale); return true; } - inline void dump (void (*callback) (const uint8_t* data, unsigned int length, - unsigned int group, unsigned int gid)) const + hb_blob_t* reference_png (hb_font_t *font, + hb_codepoint_t glyph) const { - if (!cblc) - return; // Not a color bitmap font. + const void *base; + const BitmapSizeTable &strike = this->cblc->choose_strike (font); + const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base); + if (!subtable_record || !strike.ppemX || !strike.ppemY) + return hb_blob_get_empty (); + + unsigned int image_offset = 0, image_length = 0, image_format = 0; + if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format)) + return hb_blob_get_empty (); - for (unsigned int i = 0; i < cblc->sizeTables.len; ++i) { - const BitmapSizeTable &sizeTable = cblc->sizeTables[i]; - const IndexSubtableArray &subtable_array = cblc+sizeTable.indexSubtableArrayOffset; - for (unsigned int j = 0; j < sizeTable.numberOfIndexSubtables; ++j) + unsigned int cbdt_len = cbdt.get_length (); + if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length)) + return hb_blob_get_empty (); + + switch (image_format) { - const IndexSubtableRecord &subtable_record = subtable_array.indexSubtablesZ[j]; - for (unsigned int gid = subtable_record.firstGlyphIndex; - gid <= subtable_record.lastGlyphIndex; ++gid) - { - unsigned int image_offset = 0, image_length = 0, image_format = 0; - - if (!subtable_record.get_image_data (gid, - &image_offset, &image_length, &image_format)) - continue; - - switch (image_format) - { - case 17: { - const GlyphBitmapDataFormat17& glyphFormat17 = - StructAtOffset (this->cbdt, image_offset); - callback ((const uint8_t *) &glyphFormat17.data.arrayZ, - glyphFormat17.data.len, i, gid); - } - break; - case 18: { - const GlyphBitmapDataFormat18& glyphFormat18 = - StructAtOffset (this->cbdt, image_offset); - callback ((const uint8_t *) &glyphFormat18.data.arrayZ, - glyphFormat18.data.len, i, gid); - } - break; - case 19: { - const GlyphBitmapDataFormat19& glyphFormat19 = - StructAtOffset (this->cbdt, image_offset); - callback ((const uint8_t *) &glyphFormat19.data.arrayZ, - glyphFormat19.data.len, i, gid); - } - break; - default: - continue; - } + case 17: { + if (unlikely (image_length < GlyphBitmapDataFormat17::min_size)) + return hb_blob_get_empty (); + const GlyphBitmapDataFormat17& glyphFormat17 = + StructAtOffset (this->cbdt, image_offset); + return hb_blob_create_sub_blob (cbdt.get_blob (), + image_offset + GlyphBitmapDataFormat17::min_size, + glyphFormat17.data.len); + } + case 18: { + if (unlikely (image_length < GlyphBitmapDataFormat18::min_size)) + return hb_blob_get_empty (); + const GlyphBitmapDataFormat18& glyphFormat18 = + StructAtOffset (this->cbdt, image_offset); + return hb_blob_create_sub_blob (cbdt.get_blob (), + image_offset + GlyphBitmapDataFormat18::min_size, + glyphFormat18.data.len); + } + case 19: { + if (unlikely (image_length < GlyphBitmapDataFormat19::min_size)) + return hb_blob_get_empty (); + const GlyphBitmapDataFormat19& glyphFormat19 = + StructAtOffset (this->cbdt, image_offset); + return hb_blob_create_sub_blob (cbdt.get_blob (), + image_offset + GlyphBitmapDataFormat19::min_size, + glyphFormat19.data.len); } } } + + return hb_blob_get_empty (); } + bool has_data () const { return cbdt.get_length (); } + private: - hb_blob_t *cblc_blob; - hb_blob_t *cbdt_blob; - const CBLC *cblc; - const CBDT *cbdt; + hb_blob_ptr_t cblc; + hb_blob_ptr_t cbdt; - unsigned int cbdt_len; unsigned int upem; }; + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + likely (version.major == 2 || version.major == 3)); + } protected: - FixedVersion<> version; - HBUINT8 dataZ[VAR]; + FixedVersion<> version; + UnsizedArrayOf dataZ; public: DEFINE_SIZE_ARRAY(4, dataZ); }; +struct CBDT_accelerator_t : CBDT::accelerator_t {}; + } /* namespace OT */ #endif /* HB_OT_COLOR_CBDT_TABLE_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-colr-table.hh 2019-02-28 12:03:52.970503059 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-colr-table.hh 2019-02-28 12:03:52.874503060 -0800 @@ -25,7 +25,7 @@ #ifndef HB_OT_COLOR_COLR_TABLE_HH #define HB_OT_COLOR_COLR_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" /* * COLR -- Color @@ -39,101 +39,97 @@ struct LayerRecord { - friend struct COLR; - - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } - protected: - GlyphID glyphid; /* Glyph ID of layer glyph */ - HBUINT16 colorIdx; /* Index value to use with a selected color palette */ + public: + GlyphID glyphId; /* Glyph ID of layer glyph */ + Index colorIdx; /* Index value to use with a + * selected color palette. + * An index value of 0xFFFF + * is a special case indicating + * that the text foreground + * color (defined by a + * higher-level client) should + * be used and shall not be + * treated as actual index + * into CPAL ColorRecord array. */ public: DEFINE_SIZE_STATIC (4); }; struct BaseGlyphRecord { - friend struct COLR; + int cmp (hb_codepoint_t g) const + { return g < glyphId ? -1 : g > glyphId ? 1 : 0; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this))); } - inline int cmp (hb_codepoint_t g) const { - return g < glyphid ? -1 : g > glyphid ? 1 : 0; - } - - protected: - GlyphID glyphid; /* Glyph ID of reference glyph */ - HBUINT16 firstLayerIdx; /* Index to the layer record */ - HBUINT16 numLayers; /* Number of color layers associated with this glyph */ + public: + GlyphID glyphId; /* Glyph ID of reference glyph */ + HBUINT16 firstLayerIdx; /* Index (from beginning of + * the Layer Records) to the + * layer record. There will be + * numLayers consecutive entries + * for this base glyph. */ + HBUINT16 numLayers; /* Number of color layers + * associated with this glyph */ public: DEFINE_SIZE_STATIC (6); }; -static int compare_bgr (const void *pa, const void *pb) -{ - const hb_codepoint_t *a = (const hb_codepoint_t *) pa; - const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb; - return b->cmp (*a); -} - struct COLR { - static const hb_tag_t tableTag = HB_OT_TAG_COLR; + static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) && - (this+layersZ).sanitize (c, numLayers))); - } + bool has_data () const { return numBaseGlyphs; } - inline bool get_base_glyph_record (hb_codepoint_t glyph_id, - unsigned int *first_layer /* OUT */, - unsigned int *num_layers /* OUT */) const + unsigned int get_glyph_layers (hb_codepoint_t glyph, + unsigned int start_offset, + unsigned int *count, /* IN/OUT. May be NULL. */ + hb_ot_color_layer_t *layers /* OUT. May be NULL. */) const { - const BaseGlyphRecord* record; - record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs, - sizeof (BaseGlyphRecord), compare_bgr); - if (unlikely (!record)) - return false; - - *first_layer = record->firstLayerIdx; - *num_layers = record->numLayers; - return true; - } + const BaseGlyphRecord &record = (this+baseGlyphsZ).bsearch (numBaseGlyphs, glyph); - inline bool get_layer_record (unsigned int record, - hb_codepoint_t *glyph_id /* OUT */, - unsigned int *palette_index /* OUT */) const - { - if (unlikely (record >= numLayers)) + hb_array_t all_layers ((this+layersZ).arrayZ, numLayers); + hb_array_t glyph_layers = all_layers.sub_array (record.firstLayerIdx, + record.numLayers); + if (count) { - *glyph_id = 0; - *palette_index = 0xFFFF; - return false; + hb_array_t segment_layers = glyph_layers.sub_array (start_offset, *count); + *count = segment_layers.length; + for (unsigned int i = 0; i < segment_layers.length; i++) + { + layers[i].glyph = segment_layers.arrayZ[i].glyphId; + layers[i].color_index = segment_layers.arrayZ[i].colorIdx; + } } - const LayerRecord &layer = (this+layersZ)[record]; - *glyph_id = layer.glyphid; - *palette_index = layer.colorIdx; - return true; + return glyph_layers.length; + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) && + (this+layersZ).sanitize (c, numLayers))); } protected: - HBUINT16 version; /* Table version number */ - HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records */ - LOffsetTo > + HBUINT16 version; /* Table version number (starts at 0). */ + HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */ + LNNOffsetTo > baseGlyphsZ; /* Offset to Base Glyph records. */ - LOffsetTo > - layersZ; /* Offset to Layer Records */ - HBUINT16 numLayers; /* Number of Layer Records */ + LNNOffsetTo > + layersZ; /* Offset to Layer Records. */ + HBUINT16 numLayers; /* Number of Layer Records. */ public: DEFINE_SIZE_STATIC (14); }; --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cpal-table.hh 2019-02-28 12:03:53.298503054 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cpal-table.hh 2019-02-28 12:03:53.198503055 -0800 @@ -28,54 +28,9 @@ #ifndef HB_OT_COLOR_CPAL_TABLE_HH #define HB_OT_COLOR_CPAL_TABLE_HH -#include "hb-open-type-private.hh" - - -/* - * Following parts to be moved to a public header. - */ - -/** - * hb_ot_color_t: - * ARGB data type for holding color values. - * - * Since: REPLACEME - */ -typedef uint32_t hb_ot_color_t; - - -/** - * hb_ot_color_palette_flags_t: - * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special to note about a color palette. - * @HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND: flag indicating that the color palette is suitable for rendering text on light background. - * @HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND: flag indicating that the color palette is suitable for rendering text on dark background. - * - * Since: REPLACEME - */ -typedef enum { /*< flags >*/ - HB_OT_COLOR_PALETTE_FLAG_DEFAULT = 0x00000000u, - HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND = 0x00000001u, - HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND = 0x00000002u, -} hb_ot_color_palette_flags_t; - -// HB_EXTERN unsigned int -// hb_ot_color_get_palette_count (hb_face_t *face); - -// HB_EXTERN unsigned int -// hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette); - -// HB_EXTERN hb_ot_color_palette_flags_t -// hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette); - -// HB_EXTERN unsigned int -// hb_ot_color_get_palette_colors (hb_face_t *face, -// unsigned int palette, /* default=0 */ -// unsigned int start_offset, -// unsigned int *color_count /* IN/OUT */, -// hb_ot_color_t *colors /* OUT */); - - - +#include "hb-open-type.hh" +#include "hb-ot-color.h" +#include "hb-ot-name.h" /* @@ -92,43 +47,57 @@ { friend struct CPAL; - inline bool - sanitize (hb_sanitize_context_t *c, const void *base, unsigned int palettes) const + private: + hb_ot_color_palette_flags_t get_palette_flags (const void *base, + unsigned int palette_index, + unsigned int palette_count) const { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - (base+paletteFlagsZ).sanitize (c, palettes) && - (base+paletteLabelZ).sanitize (c, palettes) && - (base+paletteEntryLabelZ).sanitize (c, palettes)); + if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; + return (hb_ot_color_palette_flags_t) (uint32_t) + (base+paletteFlagsZ).as_array (palette_count)[palette_index]; } - private: - inline hb_ot_color_palette_flags_t - get_palette_flags (const void *base, unsigned int palette) const + hb_ot_name_id_t get_palette_name_id (const void *base, + unsigned int palette_index, + unsigned int palette_count) const + { + if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID; + return (base+paletteLabelsZ).as_array (palette_count)[palette_index]; + } + + hb_ot_name_id_t get_color_name_id (const void *base, + unsigned int color_index, + unsigned int color_count) const { - // range checked at the CPAL caller - return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette]; + if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID; + return (base+colorLabelsZ).as_array (color_count)[color_index]; } - inline unsigned int - get_palette_name_id (const void *base, unsigned int palette) const + public: + bool sanitize (hb_sanitize_context_t *c, + const void *base, + unsigned int palette_count, + unsigned int color_count) const { - // range checked at the CPAL caller - return (base+paletteLabelZ)[palette]; + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + (!paletteFlagsZ || (base+paletteFlagsZ).sanitize (c, palette_count)) && + (!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) && + (!colorLabelsZ || (base+colorLabelsZ).sanitize (c, color_count))); } protected: - LOffsetTo > + LNNOffsetTo > paletteFlagsZ; /* Offset from the beginning of CPAL table to * the Palette Type Array. Set to 0 if no array * is provided. */ - LOffsetTo > - paletteLabelZ; /* Offset from the beginning of CPAL table to - * the Palette Labels Array. Set to 0 if no + LNNOffsetTo > + paletteLabelsZ; /* Offset from the beginning of CPAL table to + * the palette labels array. Set to 0 if no * array is provided. */ - LOffsetTo > - paletteEntryLabelZ; /* Offset from the beginning of CPAL table to - * the Palette Entry Label Array. Set to 0 + LNNOffsetTo > + colorLabelsZ; /* Offset from the beginning of CPAL table to + * the color labels array. Set to 0 * if no array is provided. */ public: DEFINE_SIZE_STATIC (12); @@ -138,76 +107,76 @@ struct CPAL { - static const hb_tag_t tableTag = HB_OT_TAG_CPAL; + static constexpr hb_tag_t tableTag = HB_OT_TAG_CPAL; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!(c->check_struct (this) && // it checks colorRecordIndices also - // see #get_size - (this+colorRecordsZ).sanitize (c, numColorRecords)))) - return_trace (false); + bool has_data () const { return numPalettes; } - // Check for indices sanity so no need for doing it runtime - for (unsigned int i = 0; i < numPalettes; ++i) - if (unlikely (colorRecordIndicesZ[i] + numPaletteEntries > numColorRecords)) - return_trace (false); + unsigned int get_size () const + { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); } - // If version is zero, we are done here; otherwise we need to check tail also - if (version == 0) - return_trace (true); + unsigned int get_palette_count () const { return numPalettes; } + unsigned int get_color_count () const { return numColors; } - const CPALV1Tail &v1 = StructAfter (*this); - return_trace (likely (v1.sanitize (c, this, numPalettes))); - } + hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const + { return v1 ().get_palette_flags (this, palette_index, numPalettes); } - inline unsigned int get_size (void) const - { - return min_size + numPalettes * sizeof (HBUINT16); - } + hb_ot_name_id_t get_palette_name_id (unsigned int palette_index) const + { return v1 ().get_palette_name_id (this, palette_index, numPalettes); } - inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const - { - if (unlikely (version == 0 || palette >= numPalettes)) - return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; + hb_ot_name_id_t get_color_name_id (unsigned int color_index) const + { return v1 ().get_color_name_id (this, color_index, numColors); } - const CPALV1Tail& cpal1 = StructAfter (*this); - return cpal1.get_palette_flags (this, palette); - } - - inline unsigned int get_palette_name_id (unsigned int palette) const + unsigned int get_palette_colors (unsigned int palette_index, + unsigned int start_offset, + unsigned int *color_count, /* IN/OUT. May be NULL. */ + hb_color_t *colors /* OUT. May be NULL. */) const { - if (unlikely (version == 0 || palette >= numPalettes)) - return 0xFFFF; - - const CPALV1Tail& cpal1 = StructAfter (*this); - return cpal1.get_palette_name_id (this, palette); + if (unlikely (palette_index >= numPalettes)) + { + if (color_count) *color_count = 0; + return 0; + } + unsigned int start_index = colorRecordIndicesZ[palette_index]; + hb_array_t all_colors ((this+colorRecordsZ).arrayZ, numColorRecords); + hb_array_t palette_colors = all_colors.sub_array (start_index, + numColors); + if (color_count) + { + hb_array_t segment_colors = palette_colors.sub_array (start_offset, *color_count); + /* Always return numColors colors per palette even if it has out-of-bounds start index. */ + unsigned int count = MIN (MAX (numColors - start_offset, 0), *color_count); + *color_count = count; + for (unsigned int i = 0; i < count; i++) + colors[i] = segment_colors[i]; /* Bound-checked read. */ + } + return numColors; } - inline unsigned int get_palette_count () const + private: + const CPALV1Tail& v1 () const { - return numPalettes; + if (version == 0) return Null(CPALV1Tail); + return StructAfter (*this); } - inline hb_ot_color_t - get_color_record_argb (unsigned int color_index, unsigned int palette) const + public: + bool sanitize (hb_sanitize_context_t *c) const { - if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes)) - return 0; - - // No need for more range check as it is already done on #sanitize - const UnsizedArrayOf& color_records = this+colorRecordsZ; - return color_records[colorRecordIndicesZ[palette] + color_index]; + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + (this+colorRecordsZ).sanitize (c, numColorRecords) && + colorRecordIndicesZ.sanitize (c, numPalettes) && + (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors))); } protected: HBUINT16 version; /* Table version number */ /* Version 0 */ - HBUINT16 numPaletteEntries; /* Number of palette entries in each palette. */ + HBUINT16 numColors; /* Number of colors in each palette. */ HBUINT16 numPalettes; /* Number of palettes in the table. */ HBUINT16 numColorRecords; /* Total number of color records, combined for * all palettes. */ - LOffsetTo > + LNNOffsetTo > colorRecordsZ; /* Offset from the beginning of CPAL table to * the first ColorRecord. */ UnsizedArrayOf --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-sbix-table.hh 2019-02-28 12:03:53.618503048 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-sbix-table.hh 2019-02-28 12:03:53.518503050 -0800 @@ -25,7 +25,7 @@ #ifndef HB_OT_COLOR_SBIX_TABLE_HH #define HB_OT_COLOR_SBIX_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" /* * sbix -- Standard Bitmap Graphics @@ -62,19 +62,65 @@ struct SBIXStrike { - friend struct sbix; - - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - imageOffsetsZ.sanitize_shallow (c, c->num_glyphs + 1)); + imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1)); } - protected: + hb_blob_t *get_glyph_blob (unsigned int glyph_id, + hb_blob_t *sbix_blob, + hb_tag_t file_type, + int *x_offset, + int *y_offset, + unsigned int num_glyphs, + unsigned int *strike_ppem) const + { + if (unlikely (!ppem)) return hb_blob_get_empty (); /* To get Null() object out of the way. */ + + unsigned int retry_count = 8; + unsigned int sbix_len = sbix_blob->length; + unsigned int strike_offset = (const char *) this - (const char *) sbix_blob->data; + assert (strike_offset < sbix_len); + + retry: + if (unlikely (glyph_id >= num_glyphs || + imageOffsetsZ[glyph_id + 1] <= imageOffsetsZ[glyph_id] || + imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] <= SBIXGlyph::min_size || + (unsigned int) imageOffsetsZ[glyph_id + 1] > sbix_len - strike_offset)) + return hb_blob_get_empty (); + + unsigned int glyph_offset = strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size; + unsigned int glyph_length = imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] - SBIXGlyph::min_size; + + const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]); + + if (glyph->graphicType == HB_TAG ('d','u','p','e')) + { + if (glyph_length >= 2) + { + glyph_id = *((HBUINT16 *) &glyph->data); + if (retry_count--) + goto retry; + } + return hb_blob_get_empty (); + } + + if (unlikely (file_type != glyph->graphicType)) + return hb_blob_get_empty (); + + if (strike_ppem) *strike_ppem = ppem; + if (x_offset) *x_offset = glyph->xOffset; + if (y_offset) *y_offset = glyph->yOffset; + return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length); + } + + public: HBUINT16 ppem; /* The PPEM size for which this strike was designed. */ HBUINT16 resolution; /* The device pixel density (in PPI) for which this * strike was designed. (E.g., 96 PPI, 192 PPI.) */ + protected: UnsizedArrayOf > imageOffsetsZ; /* Offset from the beginning of the strike data header * to bitmap data for an individual glyph ID. */ @@ -84,70 +130,157 @@ struct sbix { - static const hb_tag_t tableTag = HB_OT_TAG_sbix; + static constexpr hb_tag_t tableTag = HB_OT_TAG_sbix; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && strikes.sanitize (c, this))); - } + bool has_data () const { return version; } + + const SBIXStrike &get_strike (unsigned int i) const { return this+strikes[i]; } struct accelerator_t { - inline void init (hb_face_t *face) + void init (hb_face_t *face) { - num_glyphs = hb_face_get_glyph_count (face); + table = hb_sanitize_context_t().reference_table (face); + num_glyphs = face->get_num_glyphs (); + } + void fini () { table.destroy (); } - OT::Sanitizer sanitizer; - sanitizer.set_num_glyphs (num_glyphs); - sbix_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_sbix)); - sbix_len = hb_blob_get_length (sbix_blob); - sbix_table = sbix_blob->as (); + bool has_data () const { return table->has_data (); } + bool get_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents) const + { + /* We only support PNG right now, and following function checks type. */ + return get_png_extents (font, glyph, extents); } - inline void fini (void) + hb_blob_t *reference_png (hb_font_t *font, + hb_codepoint_t glyph_id, + int *x_offset, + int *y_offset, + unsigned int *available_ppem) const { - hb_blob_destroy (sbix_blob); + return choose_strike (font).get_glyph_blob (glyph_id, table.get_blob (), + HB_TAG ('p','n','g',' '), + x_offset, y_offset, + num_glyphs, available_ppem); } - inline void dump (void (*callback) (const uint8_t* data, unsigned int length, - unsigned int group, unsigned int gid)) const + private: + + const SBIXStrike &choose_strike (hb_font_t *font) const { - for (unsigned group = 0; group < sbix_table->strikes.len; ++group) + unsigned count = table->strikes.len; + if (unlikely (!count)) + return Null(SBIXStrike); + + unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem); + if (!requested_ppem) + requested_ppem = 1<<30; /* Choose largest strike. */ + /* TODO Add DPI sensitivity as well? */ + unsigned int best_i = 0; + unsigned int best_ppem = table->get_strike (0).ppem; + + for (unsigned int i = 1; i < count; i++) { - const SBIXStrike &strike = sbix_table->strikes[group](sbix_table); - for (unsigned int glyph = 0; glyph < num_glyphs; ++glyph) - if (strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] > 0) - { - const SBIXGlyph &sbixGlyph = strike.imageOffsetsZ[glyph]((const void *) &strike); - callback ((const uint8_t*) &sbixGlyph.data, - strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] - 8, - group, glyph); - } + unsigned int ppem = (table->get_strike (i)).ppem; + if ((requested_ppem <= ppem && ppem < best_ppem) || + (requested_ppem > best_ppem && ppem > best_ppem)) + { + best_i = i; + best_ppem = ppem; + } } + + return table->get_strike (best_i); + } + + struct PNGHeader + { + HBUINT8 signature[8]; + struct + { + struct + { + HBUINT32 length; + Tag type; + } header; + HBUINT32 width; + HBUINT32 height; + HBUINT8 bitDepth; + HBUINT8 colorType; + HBUINT8 compressionMethod; + HBUINT8 filterMethod; + HBUINT8 interlaceMethod; + } IHDR; + + public: + DEFINE_SIZE_STATIC (29); + }; + + bool get_png_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents) const + { + /* Following code is safe to call even without data. + * But faster to short-circuit. */ + if (!has_data ()) + return false; + + int x_offset = 0, y_offset = 0; + unsigned int strike_ppem = 0; + hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem); + + const PNGHeader &png = *blob->as(); + + extents->x_bearing = x_offset; + extents->y_bearing = y_offset; + extents->width = png.IHDR.width; + extents->height = png.IHDR.height; + + /* Convert to font units. */ + if (strike_ppem) + { + double scale = font->face->get_upem () / (double) strike_ppem; + extents->x_bearing = round (extents->x_bearing * scale); + extents->y_bearing = round (extents->y_bearing * scale); + extents->width = round (extents->width * scale); + extents->height = round (extents->height * scale); + } + + hb_blob_destroy (blob); + + return strike_ppem; } private: - hb_blob_t *sbix_blob; - const sbix *sbix_table; + hb_blob_ptr_t table; - unsigned int sbix_len; unsigned int num_glyphs; - }; + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + version >= 1 && + strikes.sanitize (c, this))); + } + protected: HBUINT16 version; /* Table version number — set to 1 */ HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines. * Bits 2 to 15: reserved (set to 0). */ - LArrayOf > + LOffsetLArrayOf strikes; /* Offsets from the beginning of the 'sbix' * table to data for each individual bitmap strike. */ public: DEFINE_SIZE_ARRAY (8, strikes); }; +struct sbix_accelerator_t : sbix::accelerator_t {}; + } /* namespace OT */ #endif /* HB_OT_COLOR_SBIX_TABLE_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-svg-table.hh 2019-02-28 12:03:53.950503043 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-svg-table.hh 2019-02-28 12:03:53.854503044 -0800 @@ -25,7 +25,7 @@ #ifndef HB_OT_COLOR_SVG_TABLE_HH #define HB_OT_COLOR_SVG_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" /* * SVG -- SVG (Scalable Vector Graphics) @@ -40,13 +40,21 @@ struct SVGDocumentIndexEntry { - friend struct SVG; + int cmp (hb_codepoint_t g) const + { return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; } - inline bool sanitize (hb_sanitize_context_t *c, const void* base) const + hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const + { + return hb_blob_create_sub_blob (svg_blob, + index_offset + (unsigned int) svgDoc, + svgDocLength); + } + + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - (base+svgDoc).sanitize (c, svgDocLength)); + svgDoc.sanitize (c, base, svgDocLength)); } protected: @@ -54,91 +62,62 @@ * this index entry. */ HBUINT16 endGlyphID; /* The last glyph ID in the range described by * this index entry. Must be >= startGlyphID. */ - LOffsetTo > + LNNOffsetTo > svgDoc; /* Offset from the beginning of the SVG Document Index * to an SVG document. Must be non-zero. */ - HBUINT32 svgDocLength; /* Length of the SVG document. + HBUINT32 svgDocLength; /* Length of the SVG document. * Must be non-zero. */ public: DEFINE_SIZE_STATIC (12); }; -struct SVGDocumentIndex -{ - friend struct SVG; - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - entries.sanitize (c, this)); - } - - protected: - ArrayOf - entries; /* Array of SVG Document Index Entries. */ - public: - DEFINE_SIZE_ARRAY (2, entries); -}; - struct SVG { - static const hb_tag_t tableTag = HB_OT_TAG_SVG; + static constexpr hb_tag_t tableTag = HB_OT_TAG_SVG; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - (this+svgDocIndex).sanitize (c))); - } + bool has_data () const { return svgDocEntries; } struct accelerator_t { - inline void init (hb_face_t *face) - { - OT::Sanitizer sanitizer; - svg_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_SVG)); - svg_len = hb_blob_get_length (svg_blob); - svg = svg_blob->as (); - - } + void init (hb_face_t *face) + { table = hb_sanitize_context_t().reference_table (face); } + void fini () { table.destroy (); } - inline void fini (void) + hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const { - hb_blob_destroy (svg_blob); + return table->get_glyph_entry (glyph_id).reference_blob (table.get_blob (), + table->svgDocEntries); } - inline void - dump (void (*callback) (const uint8_t* data, unsigned int length, - unsigned int start_glyph, unsigned int end_glyph)) const - { - const SVGDocumentIndex &index = svg+svg->svgDocIndex; - const ArrayOf &entries = index.entries; - for (unsigned int i = 0; i < entries.len; ++i) - { - const SVGDocumentIndexEntry &entry = entries[i]; - callback ((const uint8_t*) &entry.svgDoc (&index), entry.svgDocLength, - entry.startGlyphID, entry.endGlyphID); - } - } + bool has_data () const { return table->has_data (); } private: - hb_blob_t *svg_blob; - const SVG *svg; - - unsigned int svg_len; + hb_blob_ptr_t table; }; + const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const + { return (this+svgDocEntries).bsearch (glyph_id); } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + (this+svgDocEntries).sanitize_shallow (c))); + } + protected: HBUINT16 version; /* Table version (starting at 0). */ - LOffsetTo - svgDocIndex; /* Offset (relative to the start of the SVG table) to the + LOffsetTo > + svgDocEntries; /* Offset (relative to the start of the SVG table) to the * SVG Documents Index. Must be non-zero. */ + /* Array of SVG Document Index Entries. */ HBUINT32 reserved; /* Set to 0. */ public: DEFINE_SIZE_STATIC (10); }; +struct SVG_accelerator_t : SVG::accelerator_t {}; + } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc 2019-02-28 12:03:54.278503037 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc 2019-02-28 12:03:54.182503039 -0800 @@ -24,67 +24,38 @@ * Google Author(s): Behdad Esfahbod, Roozbeh Pournader */ -#include "hb-private.hh" +#include "hb.hh" #include "hb-ot.h" -#include "hb-font-private.hh" +#include "hb-font.hh" +#include "hb-machinery.hh" +#include "hb-ot-face.hh" #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" +#include "hb-ot-cff1-table.hh" +#include "hb-ot-cff2-table.hh" #include "hb-ot-hmtx-table.hh" #include "hb-ot-kern-table.hh" +#include "hb-ot-os2-table.hh" #include "hb-ot-post-table.hh" - +#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise. +#include "hb-ot-vorg-table.hh" #include "hb-ot-color-cbdt-table.hh" +#include "hb-ot-color-sbix-table.hh" -struct hb_ot_font_t -{ - OT::cmap::accelerator_t cmap; - OT::hmtx::accelerator_t h_metrics; - OT::vmtx::accelerator_t v_metrics; - OT::hb_lazy_loader_t glyf; - OT::hb_lazy_loader_t cbdt; - OT::hb_lazy_loader_t post; - OT::hb_lazy_loader_t kern; -}; - - -static hb_ot_font_t * -_hb_ot_font_create (hb_face_t *face) -{ - hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t)); - - if (unlikely (!ot_font)) - return nullptr; - - ot_font->cmap.init (face); - ot_font->h_metrics.init (face); - ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */ - ot_font->glyf.init (face); - ot_font->cbdt.init (face); - ot_font->post.init (face); - ot_font->kern.init (face); - - return ot_font; -} - -static void -_hb_ot_font_destroy (void *data) -{ - hb_ot_font_t *ot_font = (hb_ot_font_t *) data; - - ot_font->cmap.fini (); - ot_font->h_metrics.fini (); - ot_font->v_metrics.fini (); - ot_font->glyf.fini (); - ot_font->cbdt.fini (); - ot_font->post.fini (); - ot_font->kern.fini (); - - free (ot_font); -} +/** + * SECTION:hb-ot-font + * @title: hb-ot-font + * @short_description: OpenType font implementation + * @include: hb-ot.h + * + * Functions for using OpenType fonts with hb_shape(). Not that fonts returned + * by hb_font_create() default to using these functions, so most clients would + * never need to call these functions directly. + **/ static hb_bool_t @@ -93,10 +64,25 @@ hb_codepoint_t unicode, hb_codepoint_t *glyph, void *user_data HB_UNUSED) +{ + const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + return ot_face->cmap->get_nominal_glyph (unicode, glyph); +} +static unsigned int +hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED, + void *font_data, + unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + void *user_data HB_UNUSED) { - const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return ot_font->cmap.get_nominal_glyph (unicode, glyph); + const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + return ot_face->cmap->get_nominal_glyphs (count, + first_unicode, unicode_stride, + first_glyph, glyph_stride); } static hb_bool_t @@ -107,39 +93,83 @@ hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph); + const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph); } -static hb_position_t -hb_ot_get_glyph_h_advance (hb_font_t *font, - void *font_data, - hb_codepoint_t glyph, - void *user_data HB_UNUSED) +static void +hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, + unsigned count, + const hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride, + void *user_data HB_UNUSED) { - const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font)); + const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; + + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font)); + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } } -static hb_position_t -hb_ot_get_glyph_v_advance (hb_font_t *font, - void *font_data, - hb_codepoint_t glyph, - void *user_data HB_UNUSED) +static void +hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, + unsigned count, + const hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride, + void *user_data HB_UNUSED) { - const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font)); + const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; + + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font)); + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } } -static hb_position_t -hb_ot_get_glyph_h_kerning (hb_font_t *font, - void *font_data, - hb_codepoint_t left_glyph, - hb_codepoint_t right_glyph, - void *user_data HB_UNUSED) +static hb_bool_t +hb_ot_get_glyph_v_origin (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) { - const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph)); + const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + + *x = font->get_glyph_h_advance (glyph) / 2; + + const OT::VORG &VORG = *ot_face->VORG; + if (VORG.has_data ()) + { + *y = font->em_scale_y (VORG.get_y_origin (glyph)); + return true; + } + + hb_glyph_extents_t extents = {0}; + if (ot_face->glyf->get_extents (glyph, &extents)) + { + const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; + hb_position_t tsb = vmtx.get_side_bearing (glyph); + *y = font->em_scale_y (extents.y_bearing + tsb); + return true; + } + + hb_font_extents_t font_extents; + font->get_h_extents_with_fallback (&font_extents); + *y = font_extents.ascender; + + return true; } static hb_bool_t @@ -149,10 +179,16 @@ hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { - const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - bool ret = ot_font->glyf->get_extents (glyph, extents); + const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + bool ret = ot_face->sbix->get_extents (font, glyph, extents); + if (!ret) + ret = ot_face->glyf->get_extents (glyph, extents); if (!ret) - ret = ot_font->cbdt->get_extents (glyph, extents); + ret = ot_face->cff1->get_extents (glyph, extents); + if (!ret) + ret = ot_face->cff2->get_extents (font, glyph, extents); + if (!ret) + ret = ot_face->CBDT->get_extents (font, glyph, extents); // TODO Hook up side-bearings variations. extents->x_bearing = font->em_scale_x (extents->x_bearing); extents->y_bearing = font->em_scale_y (extents->y_bearing); @@ -168,8 +204,8 @@ char *name, unsigned int size, void *user_data HB_UNUSED) { - const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return ot_font->post->get_glyph_name (glyph, name, size); + const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + return ot_face->post->get_glyph_name (glyph, name, size); } static hb_bool_t @@ -179,8 +215,8 @@ hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return ot_font->post->get_glyph_from_name (name, len, glyph); + const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + return ot_face->post->get_glyph_from_name (name, len, glyph); } static hb_bool_t @@ -189,12 +225,13 @@ hb_font_extents_t *metrics, void *user_data HB_UNUSED) { - const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender); - metrics->descender = font->em_scale_y (ot_font->h_metrics.descender); - metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap); + const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; + metrics->ascender = font->em_scale_y (hmtx.ascender); + metrics->descender = font->em_scale_y (hmtx.descender); + metrics->line_gap = font->em_scale_y (hmtx.line_gap); // TODO Hook up variations. - return ot_font->h_metrics.has_font_extents; + return hmtx.has_font_extents; } static hb_bool_t @@ -203,49 +240,34 @@ hb_font_extents_t *metrics, void *user_data HB_UNUSED) { - const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender); - metrics->descender = font->em_scale_x (ot_font->v_metrics.descender); - metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap); + const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; + metrics->ascender = font->em_scale_x (vmtx.ascender); + metrics->descender = font->em_scale_x (vmtx.descender); + metrics->line_gap = font->em_scale_x (vmtx.line_gap); // TODO Hook up variations. - return ot_font->v_metrics.has_font_extents; + return vmtx.has_font_extents; } -static hb_font_funcs_t *static_ot_funcs = nullptr; - -#ifdef HB_USE_ATEXIT -static -void free_static_ot_funcs (void) -{ -retry: - hb_font_funcs_t *ot_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs); - if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, ot_funcs, nullptr)) - goto retry; - - hb_font_funcs_destroy (ot_funcs); -} +#if HB_USE_ATEXIT +static void free_static_ot_funcs (); #endif -static hb_font_funcs_t * -_hb_ot_get_font_funcs (void) +static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t { -retry: - hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs); - - if (unlikely (!funcs)) + static hb_font_funcs_t *create () { - funcs = hb_font_funcs_create (); + hb_font_funcs_t *funcs = hb_font_funcs_create (); hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr); hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr); hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr); + hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr); hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr); - hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr); - hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr); + hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr); + hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr); //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr); - //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr); - hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr); - //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, nullptr, nullptr); + hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr); hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr); //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr); hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr); @@ -253,17 +275,26 @@ hb_font_funcs_make_immutable (funcs); - if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, nullptr, funcs)) { - hb_font_funcs_destroy (funcs); - goto retry; - } +#if HB_USE_ATEXIT + atexit (free_static_ot_funcs); +#endif + + return funcs; + } +} static_ot_funcs; -#ifdef HB_USE_ATEXIT - atexit (free_static_ot_funcs); /* First person registers atexit() callback. */ +#if HB_USE_ATEXIT +static +void free_static_ot_funcs () +{ + static_ot_funcs.free_instance (); +} #endif - }; - return funcs; +static hb_font_funcs_t * +_hb_ot_get_font_funcs () +{ + return static_ot_funcs.get_unconst (); } @@ -275,12 +306,8 @@ void hb_ot_font_set_funcs (hb_font_t *font) { - hb_ot_font_t *ot_font = _hb_ot_font_create (font->face); - if (unlikely (!ot_font)) - return; - hb_font_set_funcs (font, _hb_ot_get_font_funcs (), - ot_font, - _hb_ot_font_destroy); + &font->face->table, + nullptr); } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-glyf-table.hh 2019-02-28 12:03:54.670503031 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-glyf-table.hh 2019-02-28 12:03:54.542503033 -0800 @@ -27,11 +27,9 @@ #ifndef HB_OT_GLYF_TABLE_HH #define HB_OT_GLYF_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" #include "hb-ot-head-table.hh" #include "hb-subset-glyf.hh" -#include "hb-subset-plan.hh" -#include "hb-subset-private.hh" namespace OT { @@ -47,17 +45,20 @@ { friend struct glyf; - static const hb_tag_t tableTag = HB_OT_TAG_loca; + static constexpr hb_tag_t tableTag = HB_OT_TAG_loca; - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const { TRACE_SANITIZE (this); return_trace (true); } protected: - HBUINT8 dataZ[VAR]; /* Location data. */ - DEFINE_SIZE_ARRAY (0, dataZ); + UnsizedArrayOf dataZ; /* Location data. */ + public: + DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always + * check the size externally, allow Null() object of it by + * defining it MIN() instead. */ }; @@ -70,9 +71,9 @@ struct glyf { - static const hb_tag_t tableTag = HB_OT_TAG_glyf; + static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf; - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const { TRACE_SANITIZE (this); /* We don't check for anything specific here. The users of the @@ -80,7 +81,7 @@ return_trace (true); } - inline bool subset (hb_subset_plan_t *plan) const + bool subset (hb_subset_plan_t *plan) const { hb_blob_t *glyf_prime = nullptr; hb_blob_t *loca_prime = nullptr; @@ -103,14 +104,14 @@ static bool _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca) { - hb_blob_t *head_blob = OT::Sanitizer().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_head)); + hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table (plan->source); hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob); hb_blob_destroy (head_blob); if (unlikely (!head_prime_blob)) return false; - OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr); + head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr); head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1); bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob); @@ -150,28 +151,23 @@ }; HBUINT16 flags; - HBUINT16 glyphIndex; + GlyphID glyphIndex; - inline unsigned int get_size (void) const + unsigned int get_size () const { unsigned int size = min_size; - if (flags & ARG_1_AND_2_ARE_WORDS) { - // arg1 and 2 are int16 - size += 4; - } else { - // arg1 and 2 are int8 - size += 2; - } - if (flags & WE_HAVE_A_SCALE) { - // One x 16 bit (scale) - size += 2; - } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { - // Two x 16 bit (xscale, yscale) - size += 4; - } else if (flags & WE_HAVE_A_TWO_BY_TWO) { - // Four x 16 bit (xscale, scale01, scale10, yscale) - size += 8; - } + // arg1 and 2 are int16 + if (flags & ARG_1_AND_2_ARE_WORDS) size += 4; + // arg1 and 2 are int8 + else size += 2; + + // One x 16 bit (scale) + if (flags & WE_HAVE_A_SCALE) size += 2; + // Two x 16 bit (xscale, yscale) + else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4; + // Four x 16 bit (xscale, scale01, scale10, yscale) + else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8; + return size; } @@ -181,7 +177,7 @@ const char *glyph_end; const CompositeGlyphHeader *current; - inline bool move_to_next () + bool move_to_next () { if (current->flags & CompositeGlyphHeader::MORE_COMPONENTS) { @@ -195,17 +191,17 @@ return false; } - inline bool in_range (const CompositeGlyphHeader *composite) const + bool in_range (const CompositeGlyphHeader *composite) const { return (const char *) composite >= glyph_start && ((const char *) composite + CompositeGlyphHeader::min_size) <= glyph_end - && ((const char *) composite + composite->get_size()) <= glyph_end; + && ((const char *) composite + composite->get_size ()) <= glyph_end; } }; - static inline bool get_iterator (const char * glyph_data, - unsigned int length, - CompositeGlyphHeader::Iterator *iterator /* OUT */) + static bool get_iterator (const char * glyph_data, + unsigned int length, + CompositeGlyphHeader::Iterator *iterator /* OUT */) { if (length < GlyphHeader::static_size) return false; /* Empty glyph; zero extents. */ @@ -232,34 +228,26 @@ struct accelerator_t { - inline void init (hb_face_t *face) + void init (hb_face_t *face) { memset (this, 0, sizeof (accelerator_t)); - hb_blob_t *head_blob = Sanitizer().sanitize (face->reference_table (HB_OT_TAG_head)); - const head *head_table = head_blob->as (); - if (head_table == &Null(head) || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0) - { - /* head table is not present, or in an unknown format. Leave num_glyphs=0, that takes care of disabling us. */ - hb_blob_destroy (head_blob); + const OT::head &head = *face->table.head; + if (head.indexToLocFormat > 1 || head.glyphDataFormat != 0) + /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ return; - } - short_offset = 0 == head_table->indexToLocFormat; - hb_blob_destroy (head_blob); + short_offset = 0 == head.indexToLocFormat; - loca_blob = Sanitizer().sanitize (face->reference_table (HB_OT_TAG_loca)); - loca_table = loca_blob->as (); - glyf_blob = Sanitizer().sanitize (face->reference_table (HB_OT_TAG_glyf)); - glyf_table = glyf_blob->as (); + loca_table = hb_sanitize_context_t ().reference_table (face); + glyf_table = hb_sanitize_context_t ().reference_table (face); - num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1; - glyf_len = hb_blob_get_length (glyf_blob); + num_glyphs = MAX (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1; } - inline void fini (void) + void fini () { - hb_blob_destroy (loca_blob); - hb_blob_destroy (glyf_blob); + loca_table.destroy (); + glyf_table.destroy (); } /* @@ -267,35 +255,37 @@ * If true is returned a pointer to the composite glyph will be written into * composite. */ - inline bool get_composite (hb_codepoint_t glyph, - CompositeGlyphHeader::Iterator *composite /* OUT */) const + bool get_composite (hb_codepoint_t glyph, + CompositeGlyphHeader::Iterator *composite /* OUT */) const { - if (this->glyf_table == &Null(glyf) || !num_glyphs) + if (unlikely (!num_glyphs)) return false; unsigned int start_offset, end_offset; if (!get_offsets (glyph, &start_offset, &end_offset)) return false; /* glyph not found */ - return CompositeGlyphHeader::get_iterator ((const char*) this->glyf_table + start_offset, + return CompositeGlyphHeader::get_iterator ((const char *) this->glyf_table + start_offset, end_offset - start_offset, composite); } enum simple_glyph_flag_t { + FLAG_ON_CURVE = 0x01, FLAG_X_SHORT = 0x02, FLAG_Y_SHORT = 0x04, FLAG_REPEAT = 0x08, FLAG_X_SAME = 0x10, - FLAG_Y_SAME = 0x20 + FLAG_Y_SAME = 0x20, + FLAG_RESERVED1 = 0x40, + FLAG_RESERVED2 = 0x80 }; /* based on FontTools _g_l_y_f.py::trim */ - inline bool remove_padding(unsigned int start_offset, - unsigned int *end_offset) const + bool remove_padding (unsigned int start_offset, + unsigned int *end_offset) const { - if (*end_offset - start_offset < GlyphHeader::static_size) - return true; + if (*end_offset - start_offset < GlyphHeader::static_size) return true; const char *glyph = ((const char *) glyf_table) + start_offset; const char * const glyph_end = glyph + (*end_offset - start_offset); @@ -312,8 +302,8 @@ glyph += GlyphHeader::static_size + 2 * num_contours; if (unlikely (glyph + 2 >= glyph_end)) return false; - uint16_t nCoordinates = (uint16_t) StructAtOffset(glyph - 2, 0) + 1; - uint16_t nInstructions = (uint16_t) StructAtOffset(glyph, 0); + uint16_t nCoordinates = (uint16_t) StructAtOffset (glyph - 2, 0) + 1; + uint16_t nInstructions = (uint16_t) StructAtOffset (glyph, 0); glyph += 2 + nInstructions; if (unlikely (glyph + 2 >= glyph_end)) return false; @@ -339,15 +329,11 @@ unsigned int xBytes, yBytes; xBytes = yBytes = 0; - if (flag & FLAG_X_SHORT) - xBytes = 1; - else if ((flag & FLAG_X_SAME) == 0) - xBytes = 2; - - if (flag & FLAG_Y_SHORT) - yBytes = 1; - else if ((flag & FLAG_Y_SAME) == 0) - yBytes = 2; + if (flag & FLAG_X_SHORT) xBytes = 1; + else if ((flag & FLAG_X_SAME) == 0) xBytes = 2; + + if (flag & FLAG_Y_SHORT) yBytes = 1; + else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2; coordBytes += (xBytes + yBytes) * repeat; coordsWithFlags += repeat; @@ -368,37 +354,37 @@ return true; } - inline bool get_offsets (hb_codepoint_t glyph, - unsigned int *start_offset /* OUT */, - unsigned int *end_offset /* OUT */) const + bool get_offsets (hb_codepoint_t glyph, + unsigned int *start_offset /* OUT */, + unsigned int *end_offset /* OUT */) const { if (unlikely (glyph >= num_glyphs)) return false; if (short_offset) { - const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ; + const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ; *start_offset = 2 * offsets[glyph]; *end_offset = 2 * offsets[glyph + 1]; } else { - const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ; + const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ; *start_offset = offsets[glyph]; *end_offset = offsets[glyph + 1]; } - if (*start_offset > *end_offset || *end_offset > glyf_len) + if (*start_offset > *end_offset || *end_offset > glyf_table.get_length ()) return false; return true; } - inline bool get_instruction_offsets(unsigned int start_offset, - unsigned int end_offset, - unsigned int *instruction_start /* OUT */, - unsigned int *instruction_end /* OUT */) const + bool get_instruction_offsets (unsigned int start_offset, + unsigned int end_offset, + unsigned int *instruction_start /* OUT */, + unsigned int *instruction_end /* OUT */) const { if (end_offset - start_offset < GlyphHeader::static_size) { @@ -417,10 +403,10 @@ const CompositeGlyphHeader *last; do { last = composite_it.current; - } while (composite_it.move_to_next()); + } while (composite_it.move_to_next ()); - if ( (uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS) - *instruction_start = ((char *) last - (char *) glyf_table->dataZ) + last->get_size(); + if ((uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS) + *instruction_start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size (); else *instruction_start = end_offset; *instruction_end = end_offset; @@ -454,8 +440,7 @@ return true; } - inline bool get_extents (hb_codepoint_t glyph, - hb_glyph_extents_t *extents) const + bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const { unsigned int start_offset, end_offset; if (!get_offsets (glyph, &start_offset, &end_offset)) @@ -477,19 +462,20 @@ private: bool short_offset; unsigned int num_glyphs; - const loca *loca_table; - const glyf *glyf_table; - hb_blob_t *loca_blob; - hb_blob_t *glyf_blob; - unsigned int glyf_len; + hb_blob_ptr_t loca_table; + hb_blob_ptr_t glyf_table; }; protected: - HBUINT8 dataZ[VAR]; /* Glyphs data. */ - - DEFINE_SIZE_ARRAY (0, dataZ); + UnsizedArrayOf dataZ; /* Glyphs data. */ + public: + DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always + * check the size externally, allow Null() object of it by + * defining it MIN() instead. */ }; +struct glyf_accelerator_t : glyf::accelerator_t {}; + } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-head-table.hh 2019-02-28 12:03:55.078503024 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-head-table.hh 2019-02-28 12:03:54.942503026 -0800 @@ -29,7 +29,7 @@ #ifndef HB_OT_HEAD_TABLE_HH #define HB_OT_HEAD_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" /* * head -- Font Header @@ -45,16 +45,29 @@ { friend struct OffsetTable; - static const hb_tag_t tableTag = HB_OT_TAG_head; + static constexpr hb_tag_t tableTag = HB_OT_TAG_head; - inline unsigned int get_upem (void) const + unsigned int get_upem () 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) const + enum mac_style_flag_t { + BOLD = 1u<<0, + ITALIC = 1u<<1, + UNDERLINE = 1u<<2, + OUTLINE = 1u<<3, + SHADOW = 1u<<4, + CONDENSED = 1u<<5 + }; + + bool is_bold () const { return macStyle & BOLD; } + bool is_italic () const { return macStyle & ITALIC; } + bool is_condensed () const { return macStyle & CONDENSED; } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -141,8 +154,8 @@ * -1: Only strongly right to left; * -2: Like -1 but also contains neutrals. */ public: - HBINT16 indexToLocFormat; /* 0 for short offsets, 1 for long. */ - HBINT16 glyphDataFormat; /* 0 for current format. */ + HBUINT16 indexToLocFormat; /* 0 for short offsets, 1 for long. */ + HBUINT16 glyphDataFormat; /* 0 for current format. */ DEFINE_SIZE_STATIC (54); }; --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hhea-table.hh 2019-02-28 12:03:55.450503018 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hhea-table.hh 2019-02-28 12:03:55.346503020 -0800 @@ -27,7 +27,7 @@ #ifndef HB_OT_HHEA_TABLE_HH #define HB_OT_HHEA_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" /* * hhea -- Horizontal Header @@ -45,7 +45,7 @@ template struct _hea { - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && likely (version.major == 1)); @@ -86,10 +86,10 @@ }; struct hhea : _hea { - static const hb_tag_t tableTag = HB_OT_TAG_hhea; + static constexpr hb_tag_t tableTag = HB_OT_TAG_hhea; }; struct vhea : _hea { - static const hb_tag_t tableTag = HB_OT_TAG_vhea; + static constexpr hb_tag_t tableTag = HB_OT_TAG_vhea; }; --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hmtx-table.hh 2019-02-28 12:03:55.778503013 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hmtx-table.hh 2019-02-28 12:03:55.678503014 -0800 @@ -27,11 +27,10 @@ #ifndef HB_OT_HMTX_TABLE_HH #define HB_OT_HMTX_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" #include "hb-ot-hhea-table.hh" #include "hb-ot-os2-table.hh" #include "hb-ot-var-hvar-table.hh" -#include "hb-subset-plan.hh" /* * hmtx -- Horizontal Metrics @@ -49,7 +48,7 @@ struct LongMetric { UFWORD advance; /* Advance width/height. */ - FWORD lsb; /* Leading (left/top) side bearing. */ + FWORD sb; /* Leading (left/top) side bearing. */ public: DEFINE_SIZE_STATIC (4); }; @@ -57,7 +56,7 @@ template struct hmtxvmtx { - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const { TRACE_SANITIZE (this); /* We don't check for anything specific here. The users of the @@ -66,11 +65,11 @@ } - inline bool subset_update_header (hb_subset_plan_t *plan, + bool subset_update_header (hb_subset_plan_t *plan, unsigned int num_hmetrics) const { - hb_blob_t *src_blob = OT::Sanitizer ().sanitize (plan->source->reference_table (H::tableTag)); - hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail(src_blob); + hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table (plan->source, H::tableTag); + hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob); hb_blob_destroy (src_blob); if (unlikely (!dest_blob)) { @@ -87,7 +86,7 @@ return result; } - inline bool subset (hb_subset_plan_t *plan) const + bool subset (hb_subset_plan_t *plan) const { typename T::accelerator_t _mtx; _mtx.init (plan->source); @@ -95,33 +94,33 @@ /* All the trailing glyphs with the same advance can use one LongMetric * and just keep LSB */ hb_vector_t &gids = plan->glyphs; - unsigned int num_advances = gids.len; + unsigned int num_advances = gids.length; unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]); - while (num_advances > 1 - && last_advance == _mtx.get_advance (gids[num_advances - 2])) + while (num_advances > 1 && + last_advance == _mtx.get_advance (gids[num_advances - 2])) { num_advances--; } /* alloc the new table */ size_t dest_sz = num_advances * 4 - + (gids.len - num_advances) * 2; + + (gids.length - num_advances) * 2; void *dest = (void *) malloc (dest_sz); if (unlikely (!dest)) { return false; } DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances); - DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.len - num_advances, (unsigned int) dest_sz); + DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.length - num_advances, (unsigned int) dest_sz); - const char *source_table = hb_blob_get_data (_mtx.blob, nullptr); + const char *source_table = hb_blob_get_data (_mtx.table.get_blob (), nullptr); // Copy everything over LongMetric * old_metrics = (LongMetric *) source_table; FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances); char * dest_pos = (char *) dest; bool failed = false; - for (unsigned int i = 0; i < gids.len; i++) + for (unsigned int i = 0; i < gids.length; i++) { /* the last metric or the one for gids[i] */ LongMetric *src_metric = old_metrics + MIN ((hb_codepoint_t) _mtx.num_advances - 1, gids[i]); @@ -135,8 +134,8 @@ } else { - /* dest just lsb */ - *((FWORD *) dest_pos) = src_metric->lsb; + /* dest just sb */ + *((FWORD *) dest_pos) = src_metric->sb; } } else @@ -148,18 +147,18 @@ failed = true; break; } - FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances); + FWORD src_sb = *(lsbs + gids[i] - _mtx.num_advances); if (i < num_advances) { /* dest needs a full LongMetric */ LongMetric *metric = (LongMetric *)dest_pos; metric->advance = src_metric->advance; - metric->lsb = src_lsb; + metric->sb = src_sb; } else { - /* dest just needs an lsb */ - *((FWORD *) dest_pos) = src_lsb; + /* dest just needs an sb */ + *((FWORD *) dest_pos) = src_sb; } } dest_pos += (i < num_advances ? 4 : 2); @@ -187,34 +186,27 @@ { friend struct hmtxvmtx; - inline void init (hb_face_t *face, + void init (hb_face_t *face, unsigned int default_advance_ = 0) { default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face); bool got_font_extents = false; - if (T::os2Tag) + if (T::os2Tag != HB_TAG_NONE && face->table.OS2->is_typo_metrics ()) { - hb_blob_t *os2_blob = Sanitizer ().sanitize (face->reference_table (T::os2Tag)); - const os2 *os2_table = os2_blob->as (); -#define USE_TYPO_METRICS (1u<<7) - if (0 != (os2_table->fsSelection & USE_TYPO_METRICS)) - { - ascender = os2_table->sTypoAscender; - descender = os2_table->sTypoDescender; - line_gap = os2_table->sTypoLineGap; - got_font_extents = (ascender | descender) != 0; - } - hb_blob_destroy (os2_blob); + ascender = abs (face->table.OS2->sTypoAscender); + descender = -abs (face->table.OS2->sTypoDescender); + line_gap = face->table.OS2->sTypoLineGap; + got_font_extents = (ascender | descender) != 0; } - hb_blob_t *_hea_blob = Sanitizer ().sanitize (face->reference_table (H::tableTag)); + hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table (face); const H *_hea_table = _hea_blob->as (); num_advances = _hea_table->numberOfLongMetrics; if (!got_font_extents) { - ascender = _hea_table->ascender; - descender = _hea_table->descender; + ascender = abs (_hea_table->ascender); + descender = -abs (_hea_table->descender); line_gap = _hea_table->lineGap; got_font_extents = (ascender | descender) != 0; } @@ -222,10 +214,10 @@ has_font_extents = got_font_extents; - blob = Sanitizer ().sanitize (face->reference_table (T::tableTag)); + table = hb_sanitize_context_t().reference_table (face, T::tableTag); /* Cap num_metrics() and num_advances() based on table length. */ - unsigned int len = hb_blob_get_length (blob); + unsigned int len = table.get_length (); if (unlikely (num_advances * 4 > len)) num_advances = len / 4; num_metrics = num_advances + (len - 4 * num_advances) / 2; @@ -235,22 +227,33 @@ if (unlikely (!num_advances)) { num_metrics = num_advances = 0; - hb_blob_destroy (blob); - blob = hb_blob_get_empty (); + table.destroy (); + table = hb_blob_get_empty (); } - table = blob->as (); - var_blob = Sanitizer ().sanitize (face->reference_table (T::variationsTag)); - var_table = var_blob->as (); + var_table = hb_sanitize_context_t().reference_table (face, T::variationsTag); + } + + void fini () + { + table.destroy (); + var_table.destroy (); } - inline void fini (void) + /* TODO Add variations version. */ + unsigned int get_side_bearing (hb_codepoint_t glyph) const { - hb_blob_destroy (blob); - hb_blob_destroy (var_blob); + if (glyph < num_advances) + return table->longMetricZ[glyph].sb; + + if (unlikely (glyph >= num_metrics)) + return 0; + + const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances]; + return bearings[glyph - num_advances]; } - inline unsigned int get_advance (hb_codepoint_t glyph) const + unsigned int get_advance (hb_codepoint_t glyph) const { if (unlikely (glyph >= num_metrics)) { @@ -263,14 +266,14 @@ return default_advance; } - return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance; + return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance; } - inline unsigned int get_advance (hb_codepoint_t glyph, - hb_font_t *font) const + unsigned int get_advance (hb_codepoint_t glyph, + hb_font_t *font) const { unsigned int advance = get_advance (glyph); - if (likely(glyph < num_metrics)) + if (likely (glyph < num_metrics)) { advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?! } @@ -279,9 +282,9 @@ public: bool has_font_extents; - unsigned short ascender; - unsigned short descender; - unsigned short line_gap; + int ascender; + int descender; + int line_gap; protected: unsigned int num_metrics; @@ -289,14 +292,12 @@ unsigned int default_advance; private: - const hmtxvmtx *table; - hb_blob_t *blob; - const HVARVVAR *var_table; - hb_blob_t *var_blob; + hb_blob_ptr_t table; + hb_blob_ptr_t var_table; }; protected: - LongMetric longMetric[VAR]; /* Paired advance width and leading + UnsizedArrayOflongMetricZ;/* Paired advance width and leading * bearing values for each glyph. The * value numOfHMetrics comes from * the 'hhea' table. If the font is @@ -304,7 +305,7 @@ * be in the array, but that entry is * required. The last entry applies to * all subsequent glyphs. */ -/*FWORD leadingBearingX[VAR];*/ /* Here the advance is assumed +/*UnsizedArrayOf leadingBearingX;*//* Here the advance is assumed * to be the same as the advance * for the last entry above. The * number of entries in this array is @@ -318,20 +319,23 @@ * font to vary the side bearing * values for each glyph. */ public: - DEFINE_SIZE_ARRAY (0, longMetric); + DEFINE_SIZE_ARRAY (0, longMetricZ); }; struct hmtx : hmtxvmtx { - static const hb_tag_t tableTag = HB_OT_TAG_hmtx; - static const hb_tag_t variationsTag = HB_OT_TAG_HVAR; - static const hb_tag_t os2Tag = HB_OT_TAG_os2; + static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx; + static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR; + static constexpr hb_tag_t os2Tag = HB_OT_TAG_OS2; }; struct vmtx : hmtxvmtx { - static const hb_tag_t tableTag = HB_OT_TAG_vmtx; - static const hb_tag_t variationsTag = HB_OT_TAG_VVAR; - static const hb_tag_t os2Tag = HB_TAG_NONE; + static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx; + static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR; + static constexpr hb_tag_t os2Tag = HB_TAG_NONE; }; +struct hmtx_accelerator_t : hmtx::accelerator_t {}; +struct vmtx_accelerator_t : vmtx::accelerator_t {}; + } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-kern-table.hh 2019-02-28 12:03:56.118503007 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-kern-table.hh 2019-02-28 12:03:56.018503009 -0800 @@ -27,7 +27,8 @@ #ifndef HB_OT_KERN_TABLE_HH #define HB_OT_KERN_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-aat-layout-kerx-table.hh" + /* * kern -- Kerning @@ -40,354 +41,297 @@ namespace OT { -struct hb_glyph_pair_t -{ - hb_codepoint_t left; - hb_codepoint_t right; -}; - -struct KernPair -{ - inline int get_kerning (void) const - { return value; } - - inline int cmp (const hb_glyph_pair_t &o) const - { - int ret = left.cmp (o.left); - if (ret) return ret; - return right.cmp (o.right); - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); - } - - protected: - GlyphID left; - GlyphID right; - FWORD value; - public: - DEFINE_SIZE_STATIC (6); -}; - -struct KernSubTableFormat0 +template +struct KernSubTableFormat3 { - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const { - hb_glyph_pair_t pair = {left, right}; - int i = pairs.bsearch (pair); - if (i == -1) + hb_array_t kernValue = kernValueZ.as_array (kernValueCount); + hb_array_t leftClass = StructAfter > (kernValue).as_array (glyphCount); + hb_array_t rightClass = StructAfter > (leftClass).as_array (glyphCount); + hb_array_t kernIndex = StructAfter > (rightClass).as_array (leftClassCount * rightClassCount); + + unsigned int leftC = leftClass[left]; + unsigned int rightC = rightClass[right]; + if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount)) return 0; - return pairs[i].get_kerning (); + unsigned int i = leftC * rightClassCount + rightC; + return kernValue[kernIndex[i]]; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool apply (AAT::hb_aat_apply_context_t *c) const { - TRACE_SANITIZE (this); - return_trace (pairs.sanitize (c)); - } + TRACE_APPLY (this); - protected: - BinSearchArrayOf pairs; /* Array of kerning pairs. */ - public: - DEFINE_SIZE_ARRAY (8, pairs); -}; + if (!c->plan->requested_kerning) + return false; -struct KernClassTable -{ - inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (firstGlyph.sanitize (c) && classes.sanitize (c)); - } + if (header.coverage & header.Backwards) + return false; - protected: - HBUINT16 firstGlyph; /* First glyph in class range. */ - ArrayOf classes; /* Glyph classes. */ - public: - DEFINE_SIZE_ARRAY (4, classes); -}; + hb_kern_machine_t machine (*this, header.coverage & header.CrossStream); + machine.kern (c->font, c->buffer, c->plan->kern_mask); -struct KernSubTableFormat2 -{ - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const - { - unsigned int l = (this+leftClassTable).get_class (left); - unsigned int r = (this+rightClassTable).get_class (right); - unsigned int offset = l * rowWidth + r * sizeof (FWORD); - const FWORD *arr = &(this+array); - if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end)) - return 0; - const FWORD *v = &StructAtOffset (arr, offset); - if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end)) - return 0; - return *v; + return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (rowWidth.sanitize (c) && - leftClassTable.sanitize (c, this) && - rightClassTable.sanitize (c, this) && - array.sanitize (c, this)); + return_trace (c->check_struct (this) && + c->check_range (kernValueZ, + kernValueCount * sizeof (FWORD) + + glyphCount * 2 + + leftClassCount * rightClassCount)); } protected: - HBUINT16 rowWidth; /* The width, in bytes, of a row in the table. */ - OffsetTo - leftClassTable; /* Offset from beginning of this subtable to - * left-hand class table. */ - OffsetTo - rightClassTable;/* Offset from beginning of this subtable to - * right-hand class table. */ - OffsetTo - array; /* Offset from beginning of this subtable to - * the start of the kerning array. */ + KernSubTableHeader header; + HBUINT16 glyphCount; /* The number of glyphs in this font. */ + HBUINT8 kernValueCount; /* The number of kerning values. */ + HBUINT8 leftClassCount; /* The number of left-hand classes. */ + HBUINT8 rightClassCount;/* The number of right-hand classes. */ + HBUINT8 flags; /* Set to zero (reserved for future use). */ + UnsizedArrayOf kernValueZ; /* The kerning values. + * Length kernValueCount. */ +#if 0 + UnsizedArrayOfleftClass; /* The left-hand classes. + * Length glyphCount. */ + UnsizedArrayOfrightClass; /* The right-hand classes. + * Length glyphCount. */ + UnsizedArrayOfkernIndex; /* The indices into the kernValue array. + * Length leftClassCount * rightClassCount */ +#endif public: - DEFINE_SIZE_MIN (8); + DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ); }; +template struct KernSubTable { - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const + unsigned int get_size () const { return u.header.length; } + unsigned int get_type () const { return u.header.format; } + + int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const { - switch (format) { + switch (get_type ()) { + /* This method hooks up to hb_font_t's get_h_kerning. Only support Format0. */ case 0: return u.format0.get_kerning (left, right); - case 2: return u.format2.get_kerning (left, right, end); default:return 0; } } - inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const + template + typename context_t::return_t dispatch (context_t *c) const { - TRACE_SANITIZE (this); - switch (format) { - case 0: return_trace (u.format0.sanitize (c)); - case 2: return_trace (u.format2.sanitize (c)); - default:return_trace (true); + unsigned int subtable_type = get_type (); + TRACE_DISPATCH (this, subtable_type); + switch (subtable_type) { + case 0: return_trace (c->dispatch (u.format0)); + case 1: return_trace (u.header.apple ? c->dispatch (u.format1) : c->default_return_value ()); + case 2: return_trace (c->dispatch (u.format2)); + case 3: return_trace (u.header.apple ? c->dispatch (u.format3) : c->default_return_value ()); + default: return_trace (c->default_return_value ()); } } - protected: + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!u.header.sanitize (c) || + u.header.length < u.header.min_size || + !c->check_range (this, u.header.length))) return_trace (false); + + return_trace (dispatch (c)); + } + + public: union { - KernSubTableFormat0 format0; - KernSubTableFormat2 format2; + KernSubTableHeader header; + AAT::KerxSubTableFormat0 format0; + AAT::KerxSubTableFormat1 format1; + AAT::KerxSubTableFormat2 format2; + KernSubTableFormat3 format3; } u; public: - DEFINE_SIZE_MIN (0); + DEFINE_SIZE_MIN (KernSubTableHeader::static_size); }; -template -struct KernSubTableWrapper +struct KernOTSubTableHeader { - /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ - inline const T* thiz (void) const { return static_cast (this); } + static constexpr bool apple = false; + typedef AAT::ObsoleteTypes Types; - inline bool is_horizontal (void) const - { return (thiz()->coverage & T::COVERAGE_CHECK_FLAGS) == T::COVERAGE_CHECK_HORIZONTAL; } + unsigned int tuple_count () const { return 0; } + bool is_horizontal () const { return (coverage & Horizontal); } - inline bool is_override (void) const - { return bool (thiz()->coverage & T::COVERAGE_OVERRIDE_FLAG); } - - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const - { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); } - - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const - { return is_horizontal () ? get_kerning (left, right, end) : 0; } + enum Coverage + { + Horizontal = 0x01u, + Minimum = 0x02u, + CrossStream = 0x04u, + Override = 0x08u, - inline unsigned int get_size (void) const { return thiz()->length; } + /* Not supported: */ + Backwards = 0x00u, + Variation = 0x00u, + }; - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (thiz()) && - thiz()->length >= T::min_size && - c->check_array (thiz(), 1, thiz()->length) && - thiz()->subtable.sanitize (c, thiz()->format)); + return_trace (c->check_struct (this)); } + + public: + HBUINT16 versionZ; /* Unused. */ + HBUINT16 length; /* Length of the subtable (including this header). */ + HBUINT8 format; /* Subtable format. */ + HBUINT8 coverage; /* Coverage bits. */ + public: + DEFINE_SIZE_STATIC (6); }; -template -struct KernTable +struct KernOT : AAT::KerxTable { - /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ - inline const T* thiz (void) const { return static_cast (this); } + friend struct AAT::KerxTable; - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const - { - int v = 0; - const typename T::SubTableWrapper *st = CastP (thiz()->data); - unsigned int count = thiz()->nTables; - for (unsigned int i = 0; i < count; i++) - { - if (st->is_override ()) - v = 0; - v += st->get_h_kerning (left, right, table_length + (const char *) this); - st = &StructAfter (*st); - } - return v; - } + static constexpr hb_tag_t tableTag = HB_OT_TAG_kern; + static constexpr unsigned minVersion = 0u; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (thiz()) || - thiz()->version != T::VERSION)) - return_trace (false); - - const typename T::SubTableWrapper *st = CastP (thiz()->data); - unsigned int count = thiz()->nTables; - for (unsigned int i = 0; i < count; i++) - { - if (unlikely (!st->sanitize (c))) - return_trace (false); - st = &StructAfter (*st); - } + typedef KernOTSubTableHeader SubTableHeader; + typedef SubTableHeader::Types Types; + typedef KernSubTable SubTable; - return_trace (true); - } + protected: + HBUINT16 version; /* Version--0x0000u */ + HBUINT16 tableCount; /* Number of subtables in the kerning table. */ + SubTable firstSubTable; /* Subtables. */ + public: + DEFINE_SIZE_MIN (4); }; -struct KernOT : KernTable + +struct KernAATSubTableHeader { - friend struct KernTable; + static constexpr bool apple = true; + typedef AAT::ObsoleteTypes Types; - static const uint16_t VERSION = 0x0000u; + unsigned int tuple_count () const { return 0; } + bool is_horizontal () const { return !(coverage & Vertical); } - struct SubTableWrapper : KernSubTableWrapper + enum Coverage { - friend struct KernSubTableWrapper; + Vertical = 0x80u, + CrossStream = 0x40u, + Variation = 0x20u, - enum coverage_flags_t { - COVERAGE_DIRECTION_FLAG = 0x01u, - COVERAGE_MINIMUM_FLAG = 0x02u, - COVERAGE_CROSSSTREAM_FLAG = 0x04u, - COVERAGE_OVERRIDE_FLAG = 0x08u, - - COVERAGE_VARIATION_FLAG = 0x00u, /* Not supported. */ - - COVERAGE_CHECK_FLAGS = 0x07u, - COVERAGE_CHECK_HORIZONTAL = 0x01u - }; - - protected: - HBUINT16 versionZ; /* Unused. */ - HBUINT16 length; /* Length of the subtable (including this header). */ - HBUINT8 format; /* Subtable format. */ - HBUINT8 coverage; /* Coverage bits. */ - KernSubTable subtable; /* Subtable data. */ - public: - DEFINE_SIZE_MIN (6); + /* Not supported: */ + Backwards = 0x00u, }; - protected: - HBUINT16 version; /* Version--0x0000u */ - HBUINT16 nTables; /* Number of subtables in the kerning table. */ - HBUINT8 data[VAR]; + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + HBUINT32 length; /* Length of the subtable (including this header). */ + HBUINT8 coverage; /* Coverage bits. */ + HBUINT8 format; /* Subtable format. */ + HBUINT16 tupleIndex; /* The tuple index (used for variations fonts). + * This value specifies which tuple this subtable covers. + * Note: We don't implement. */ public: - DEFINE_SIZE_ARRAY (4, data); + DEFINE_SIZE_STATIC (8); }; -struct KernAAT : KernTable +struct KernAAT : AAT::KerxTable { - friend struct KernTable; - - static const uint32_t VERSION = 0x00010000u; + friend struct AAT::KerxTable; - struct SubTableWrapper : KernSubTableWrapper - { - friend struct KernSubTableWrapper; + static constexpr hb_tag_t tableTag = HB_OT_TAG_kern; + static constexpr unsigned minVersion = 0x00010000u; - enum coverage_flags_t { - COVERAGE_DIRECTION_FLAG = 0x80u, - COVERAGE_CROSSSTREAM_FLAG = 0x40u, - COVERAGE_VARIATION_FLAG = 0x20u, - - COVERAGE_OVERRIDE_FLAG = 0x00u, /* Not supported. */ - - COVERAGE_CHECK_FLAGS = 0xE0u, - COVERAGE_CHECK_HORIZONTAL = 0x00u - }; - - protected: - HBUINT32 length; /* Length of the subtable (including this header). */ - HBUINT8 coverage; /* Coverage bits. */ - HBUINT8 format; /* Subtable format. */ - HBUINT16 tupleIndex; /* The tuple index (used for variations fonts). - * This value specifies which tuple this subtable covers. */ - KernSubTable subtable; /* Subtable data. */ - public: - DEFINE_SIZE_MIN (8); - }; + typedef KernAATSubTableHeader SubTableHeader; + typedef SubTableHeader::Types Types; + typedef KernSubTable SubTable; protected: - HBUINT32 version; /* Version--0x00010000u */ - HBUINT32 nTables; /* Number of subtables in the kerning table. */ - HBUINT8 data[VAR]; + HBUINT32 version; /* Version--0x00010000u */ + HBUINT32 tableCount; /* Number of subtables in the kerning table. */ + SubTable firstSubTable; /* Subtables. */ public: - DEFINE_SIZE_ARRAY (8, data); + DEFINE_SIZE_MIN (8); }; struct kern { - static const hb_tag_t tableTag = HB_OT_TAG_kern; + static constexpr hb_tag_t tableTag = HB_OT_TAG_kern; - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const + bool has_data () const { return u.version32; } + unsigned int get_type () const { return u.major; } + + bool has_state_machine () const { - switch (u.major) { - case 0: return u.ot.get_h_kerning (left, right, table_length); - case 1: return u.aat.get_h_kerning (left, right, table_length); - default:return 0; + switch (get_type ()) { + case 0: return u.ot.has_state_machine (); + case 1: return u.aat.has_state_machine (); + default:return false; } } - inline bool sanitize (hb_sanitize_context_t *c) const + bool has_cross_stream () const { - TRACE_SANITIZE (this); - if (!u.major.sanitize (c)) return_trace (false); - switch (u.major) { - case 0: return_trace (u.ot.sanitize (c)); - case 1: return_trace (u.aat.sanitize (c)); - default:return_trace (true); + switch (get_type ()) { + case 0: return u.ot.has_cross_stream (); + case 1: return u.aat.has_cross_stream (); + default:return false; } } - struct accelerator_t + int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const { - inline void init (hb_face_t *face) - { - blob = Sanitizer().sanitize (face->reference_table (HB_OT_TAG_kern)); - table = blob->as (); - table_length = blob->length; - } - inline void fini (void) - { - hb_blob_destroy (blob); + switch (get_type ()) { + case 0: return u.ot.get_h_kerning (left, right); + case 1: return u.aat.get_h_kerning (left, right); + default:return 0; } + } - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const - { return table->get_h_kerning (left, right, table_length); } + bool apply (AAT::hb_aat_apply_context_t *c) const + { return dispatch (c); } - private: - hb_blob_t *blob; - const kern *table; - unsigned int table_length; - }; + template + typename context_t::return_t dispatch (context_t *c) const + { + unsigned int subtable_type = get_type (); + TRACE_DISPATCH (this, subtable_type); + switch (subtable_type) { + case 0: return_trace (c->dispatch (u.ot)); + case 1: return_trace (c->dispatch (u.aat)); + default: return_trace (c->default_return_value ()); + } + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.version32.sanitize (c)) return_trace (false); + return_trace (dispatch (c)); + } protected: union { + HBUINT32 version32; HBUINT16 major; KernOT ot; KernAAT aat; } u; public: - DEFINE_SIZE_UNION (2, major); + DEFINE_SIZE_UNION (4, version32); }; } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-base-table.hh 2019-02-28 12:03:56.454503002 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-base-table.hh 2019-02-28 12:03:56.354503003 -0800 @@ -1,6 +1,7 @@ /* * Copyright © 2016 Elie Roux * Copyright © 2018 Google, Inc. + * Copyright © 2018 Ebrahim Byagowi * * This is part of HarfBuzz, a text shaping library. * @@ -28,12 +29,13 @@ #ifndef HB_OT_LAYOUT_BASE_TABLE_HH #define HB_OT_LAYOUT_BASE_TABLE_HH -#include "hb-open-type-private.hh" -#include "hb-ot-layout-common-private.hh" +#include "hb-open-type.hh" +#include "hb-ot-layout-common.hh" -namespace OT { +/* To be removed */ +typedef hb_tag_t hb_ot_layout_baseline_t; -#define NOT_INDEXED ((unsigned int) -1) +namespace OT { /* * BASE -- Baseline @@ -42,30 +44,30 @@ struct BaseCoordFormat1 { - inline int get_coord (void) const { return coordinate; } + hb_position_t get_coord () const { return coordinate; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); + return_trace (likely (c->check_struct (this))); } protected: HBUINT16 format; /* Format identifier--format = 1 */ - HBINT16 coordinate; /* X or Y value, in design units */ + FWORD coordinate; /* X or Y value, in design units */ public: DEFINE_SIZE_STATIC (4); }; struct BaseCoordFormat2 { - inline int get_coord (void) const + hb_position_t get_coord () const { /* TODO */ return coordinate; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -73,7 +75,7 @@ protected: HBUINT16 format; /* Format identifier--format = 2 */ - HBINT16 coordinate; /* X or Y value, in design units */ + FWORD coordinate; /* X or Y value, in design units */ GlyphID referenceGlyph; /* Glyph ID of control glyph */ HBUINT16 coordPoint; /* Index of contour point on the * reference glyph */ @@ -83,44 +85,53 @@ struct BaseCoordFormat3 { - inline int get_coord (void) const + hb_position_t get_coord (hb_font_t *font, + const VariationStore &var_store, + hb_direction_t direction) const { - /* TODO */ - return coordinate; + const Device &device = this+deviceTable; + return coordinate + (HB_DIRECTION_IS_VERTICAL (direction) ? + device.get_y_delta (font, var_store) : + device.get_x_delta (font, var_store)); } - inline bool sanitize (hb_sanitize_context_t *c) const + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && deviceTable.sanitize (c, this)); + return_trace (likely (c->check_struct (this) && + deviceTable.sanitize (c, this))); } protected: - HBUINT16 format; /* Format identifier--format = 3 */ - HBINT16 coordinate; /* X or Y value, in design units */ - OffsetTo deviceTable; /* Offset to Device table for X or - * Y value, from beginning of - * BaseCoord table (may be NULL). */ + HBUINT16 format; /* Format identifier--format = 3 */ + FWORD coordinate; /* X or Y value, in design units */ + OffsetTo + deviceTable; /* Offset to Device table for X or + * Y value, from beginning of + * BaseCoord table (may be NULL). */ public: DEFINE_SIZE_STATIC (6); }; struct BaseCoord { - inline int get_coord (void) const + hb_position_t get_coord (hb_font_t *font, + const VariationStore &var_store, + hb_direction_t direction) const { switch (u.format) { case 1: return u.format1.get_coord (); case 2: return u.format2.get_coord (); - case 3: return u.format3.get_coord (); + case 3: return u.format3.get_coord (font, var_store, direction); default:return 0; } } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (!u.format.sanitize (c)) return_trace (false); + if (unlikely (!u.format.sanitize (c))) return_trace (false); switch (u.format) { case 1: return_trace (u.format1.sanitize (c)); case 2: return_trace (u.format2.sanitize (c)); @@ -142,32 +153,40 @@ struct FeatMinMaxRecord { - inline int get_min_value (void) const - { return (this+minCoord).get_coord(); } - - inline int get_max_value (void) const - { return (this+maxCoord).get_coord(); } + static int cmp (const void *key_, const void *entry_) + { + hb_tag_t key = * (hb_tag_t *) key_; + const FeatMinMaxRecord &entry = * (const FeatMinMaxRecord *) entry_; + return key < (unsigned int) entry.tag ? -1 : + key > (unsigned int) entry.tag ? 1 : + 0; + } - inline const Tag &get_tag () const - { return tag; } + void get_min_max (const BaseCoord **min, const BaseCoord **max) const + { + if (likely (min)) *min = &(this+minCoord); + if (likely (max)) *max = &(this+maxCoord); + } - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - minCoord.sanitize (c, base) && - maxCoord.sanitize (c, base)); + return_trace (likely (c->check_struct (this) && + minCoord.sanitize (c, this) && + maxCoord.sanitize (c, this))); } protected: - Tag tag; /* 4-byte feature identification tag--must - * match feature tag in FeatureList */ - OffsetTo minCoord; /* Offset to BaseCoord table that defines - * the minimum extent value, from beginning - * of MinMax table (may be NULL) */ - OffsetTo maxCoord; /* Offset to BaseCoord table that defines - * the maximum extent value, from beginning - * of MinMax table (may be NULL) */ + Tag tag; /* 4-byte feature identification tag--must + * match feature tag in FeatureList */ + OffsetTo + minCoord; /* Offset to BaseCoord table that defines + * the minimum extent value, from beginning + * of MinMax table (may be NULL) */ + OffsetTo + maxCoord; /* Offset to BaseCoord table that defines + * the maximum extent value, from beginning + * of MinMax table (may be NULL) */ public: DEFINE_SIZE_STATIC (8); @@ -175,356 +194,269 @@ struct MinMax { - inline unsigned int get_feature_tag_index (Tag featureTableTag) const - { - /* TODO bsearch */ - unsigned int count = featMinMaxRecords.len; - for (unsigned int i = 0; i < count; i++) + void get_min_max (hb_tag_t feature_tag, + const BaseCoord **min, + const BaseCoord **max) const + { + /* TODO Replace hb_bsearch() with .bsearch(). */ + const FeatMinMaxRecord *minMaxCoord = (const FeatMinMaxRecord *) + hb_bsearch (&feature_tag, featMinMaxRecords.arrayZ, + featMinMaxRecords.len, + FeatMinMaxRecord::static_size, + FeatMinMaxRecord::cmp); + if (minMaxCoord) + minMaxCoord->get_min_max (min, max); + else { - Tag tag = featMinMaxRecords[i].get_tag(); - int cmp = tag.cmp(featureTableTag); - if (cmp == 0) return i; - if (cmp > 0) return NOT_INDEXED; + if (likely (min)) *min = &(this+minCoord); + if (likely (max)) *max = &(this+maxCoord); } - return NOT_INDEXED; - } - - inline int get_min_value (unsigned int featureTableTagIndex) const - { - if (featureTableTagIndex == NOT_INDEXED) - return (this+minCoord).get_coord(); - return featMinMaxRecords[featureTableTagIndex].get_min_value(); - } - - inline int get_max_value (unsigned int featureTableTagIndex) const - { - if (featureTableTagIndex == NOT_INDEXED) - return (this+maxCoord).get_coord(); - return featMinMaxRecords[featureTableTagIndex].get_max_value(); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - minCoord.sanitize (c, this) && - maxCoord.sanitize (c, this) && - featMinMaxRecords.sanitize (c, this)); + return_trace (likely (c->check_struct (this) && + minCoord.sanitize (c, this) && + maxCoord.sanitize (c, this) && + featMinMaxRecords.sanitize (c, this))); } protected: - OffsetTo minCoord; /* Offset to BaseCoord table that defines - * minimum extent value, from the beginning - * of MinMax table (may be NULL) */ - OffsetTo maxCoord; /* Offset to BaseCoord table that defines - * maximum extent value, from the beginning - * of MinMax table (may be NULL) */ - ArrayOf - featMinMaxRecords; /* Array of FeatMinMaxRecords, in alphabetical - * order by featureTableTag */ + OffsetTo + minCoord; /* Offset to BaseCoord table that defines + * minimum extent value, from the beginning + * of MinMax table (may be NULL) */ + OffsetTo + maxCoord; /* Offset to BaseCoord table that defines + * maximum extent value, from the beginning + * of MinMax table (may be NULL) */ + SortedArrayOf + featMinMaxRecords; + /* Array of FeatMinMaxRecords, in alphabetical + * order by featureTableTag */ public: DEFINE_SIZE_ARRAY (6, featMinMaxRecords); }; -/* TODO... */ -struct BaseLangSysRecord -{ - inline const Tag& get_tag(void) const - { return baseLangSysTag; } - - inline unsigned int get_feature_tag_index (Tag featureTableTag) const - { return (this+minMax).get_feature_tag_index(featureTableTag); } - - inline int get_min_value (unsigned int featureTableTagIndex) const - { return (this+minMax).get_min_value(featureTableTagIndex); } - - inline int get_max_value (unsigned int featureTableTagIndex) const - { return (this+minMax).get_max_value(featureTableTagIndex); } - - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - minMax.sanitize (c, base)); - } - - protected: - Tag baseLangSysTag; - OffsetTo minMax; - public: - DEFINE_SIZE_STATIC (6); - -}; - struct BaseValues { - inline unsigned int get_default_base_tag_index (void) const - { return defaultIndex; } - - inline int get_base_coord (unsigned int baselineTagIndex) const + const BaseCoord &get_base_coord (int baseline_tag_index) const { - return (this+baseCoords[baselineTagIndex]).get_coord(); + if (baseline_tag_index == -1) baseline_tag_index = defaultIndex; + return this+baseCoords[baseline_tag_index]; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - defaultIndex <= baseCoordCount && - baseCoords.sanitize (c, this)); + return_trace (likely (c->check_struct (this) && + baseCoords.sanitize (c, this))); } protected: - Index defaultIndex; - HBUINT16 baseCoordCount; - OffsetArrayOf baseCoords; + Index defaultIndex; /* Index number of default baseline for this + * script — equals index position of baseline tag + * in baselineTags array of the BaseTagList */ + OffsetArrayOf + baseCoords; /* Number of BaseCoord tables defined — should equal + * baseTagCount in the BaseTagList + * + * Array of offsets to BaseCoord tables, from beginning of + * BaseValues table — order matches baselineTags array in + * the BaseTagList */ public: - DEFINE_SIZE_ARRAY (6, baseCoords); - + DEFINE_SIZE_ARRAY (4, baseCoords); }; -struct BaseScript { - - inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const - { - Tag tag; - int cmp; - for (unsigned int i = 0; i < baseLangSysCount; i++) { - tag = baseLangSysRecords[i].get_tag(); - // taking advantage of alphabetical order - cmp = tag.cmp(baseLangSysTag); - if (cmp == 0) return i; - if (cmp > 0) return NOT_INDEXED; - } - return NOT_INDEXED; - } - - inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const - { - if (baseLangSysIndex == NOT_INDEXED) { - if (unlikely(defaultMinMax)) return NOT_INDEXED; - return (this+defaultMinMax).get_feature_tag_index(featureTableTag); - } - if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED; - return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag); - } - - inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - if (baseLangSysIndex == NOT_INDEXED) - return (this+defaultMinMax).get_min_value(featureTableTagIndex); - return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex); - } - - inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const +struct BaseLangSysRecord +{ + static int cmp (const void *key_, const void *entry_) { - if (baseLangSysIndex == NOT_INDEXED) - return (this+defaultMinMax).get_min_value(featureTableTagIndex); - return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex); + hb_tag_t key = * (hb_tag_t *) key_; + const BaseLangSysRecord &entry = * (const BaseLangSysRecord *) entry_; + return key < (unsigned int) entry.baseLangSysTag ? -1 : + key > (unsigned int) entry.baseLangSysTag ? 1 : + 0; } - inline unsigned int get_default_base_tag_index (void) const - { return (this+baseValues).get_default_base_tag_index(); } + const MinMax &get_min_max () const + { return this+minMax; } - inline int get_base_coord (unsigned int baselineTagIndex) const - { return (this+baseValues).get_base_coord(baselineTagIndex); } - - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - baseValues.sanitize (c, this) && - defaultMinMax.sanitize (c, this) && - baseLangSysRecords.sanitize (c, this)); + return_trace (likely (c->check_struct (this) && + minMax.sanitize (c, this))); } protected: - OffsetTo baseValues; - OffsetTo defaultMinMax; - HBUINT16 baseLangSysCount; - ArrayOf baseLangSysRecords; - + Tag baseLangSysTag; /* 4-byte language system identification tag */ + OffsetTo + minMax; /* Offset to MinMax table, from beginning + * of BaseScript table */ public: - DEFINE_SIZE_ARRAY (8, baseLangSysRecords); + DEFINE_SIZE_STATIC (6); }; +struct BaseScript +{ + const MinMax &get_min_max (hb_tag_t language_tag) const + { + /* TODO Replace hb_bsearch() with .bsearch(). */ + const BaseLangSysRecord* record = (const BaseLangSysRecord *) + hb_bsearch (&language_tag, baseLangSysRecords.arrayZ, + baseLangSysRecords.len, + BaseLangSysRecord::static_size, + BaseLangSysRecord::cmp); + return record ? record->get_min_max () : this+defaultMinMax; + } -struct BaseScriptRecord { - - inline const Tag& get_tag (void) const - { return baseScriptTag; } - - inline unsigned int get_default_base_tag_index(void) const - { return (this+baseScript).get_default_base_tag_index(); } - - inline int get_base_coord(unsigned int baselineTagIndex) const - { return (this+baseScript).get_base_coord(baselineTagIndex); } - - inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const - { return (this+baseScript).get_lang_tag_index(baseLangSysTag); } - - inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const - { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); } - - inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); } + const BaseCoord &get_base_coord (int baseline_tag_index) const + { return (this+baseValues).get_base_coord (baseline_tag_index); } - inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); } + bool is_empty () const { return !baseValues; } - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - baseScript != Null(OffsetTo) && - baseScript.sanitize (c, base)); + return_trace (likely (c->check_struct (this) && + baseValues.sanitize (c, this) && + defaultMinMax.sanitize (c, this) && + baseLangSysRecords.sanitize (c, this))); } protected: - Tag baseScriptTag; - OffsetTo baseScript; + OffsetTo + baseValues; /* Offset to BaseValues table, from beginning + * of BaseScript table (may be NULL) */ + OffsetTo + defaultMinMax; /* Offset to MinMax table, from beginning of + * BaseScript table (may be NULL) */ + SortedArrayOf + baseLangSysRecords; + /* Number of BaseLangSysRecords + * defined — may be zero (0) */ public: - DEFINE_SIZE_STATIC (6); + DEFINE_SIZE_ARRAY (6, baseLangSysRecords); }; -struct BaseScriptList { - - inline unsigned int get_base_script_index (Tag baseScriptTag) const - { - for (unsigned int i = 0; i < baseScriptCount; i++) - if (baseScriptRecords[i].get_tag() == baseScriptTag) - return i; - return NOT_INDEXED; - } - - inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const - { - if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED; - return baseScriptRecords[baseScriptIndex].get_default_base_tag_index(); - } - - inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const - { - return baseScriptRecords[baseScriptIndex].get_base_coord(baselineTagIndex); - } - - inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const - { - if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED; - return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag); - } - - inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const - { - if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED; - return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag); - } - - inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const +struct BaseScriptList; +struct BaseScriptRecord +{ + static int cmp (const void *key_, const void *entry_) { - return baseScriptRecords[baseScriptIndex].get_max_value(baseLangSysIndex, featureTableTagIndex); + hb_tag_t key = * (hb_tag_t *) key_; + const BaseScriptRecord &entry = * (const BaseScriptRecord *) entry_; + return key < (unsigned int) entry.baseScriptTag ? -1 : + key > (unsigned int) entry.baseScriptTag ? 1 : + 0; } - inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return baseScriptRecords[baseScriptIndex].get_min_value(baseLangSysIndex, featureTableTagIndex); - } + const BaseScript &get_base_script (const BaseScriptList *list) const + { return list+baseScript; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - baseScriptRecords.sanitize (c, this)); + return_trace (likely (c->check_struct (this) && + baseScript.sanitize (c, base))); } protected: - HBUINT16 baseScriptCount; - ArrayOf baseScriptRecords; + Tag baseScriptTag; /* 4-byte script identification tag */ + OffsetTo + baseScript; /* Offset to BaseScript table, from beginning + * of BaseScriptList */ public: - DEFINE_SIZE_ARRAY (4, baseScriptRecords); - + DEFINE_SIZE_STATIC (6); }; -struct BaseTagList +struct BaseScriptList { + const BaseScriptRecord *find_record (hb_tag_t script) const + { + /* TODO Replace hb_bsearch() with .bsearch(). */ + return (const BaseScriptRecord *) hb_bsearch (&script, baseScriptRecords.arrayZ, + baseScriptRecords.len, + BaseScriptRecord::static_size, + BaseScriptRecord::cmp); + } - inline unsigned int get_tag_index(Tag baselineTag) const + /* TODO: Or client should handle fallback? */ + const BaseScript &get_base_script (hb_tag_t script) const { - for (unsigned int i = 0; i < baseTagCount; i++) - if (baselineTags[i] == baselineTag) - return i; - return NOT_INDEXED; + const BaseScriptRecord *record = find_record (script); + if (!record) record = find_record ((hb_script_t) HB_TAG ('D','F','L','T')); + + return record ? record->get_base_script (this) : Null (BaseScript); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); + return_trace (c->check_struct (this) && + baseScriptRecords.sanitize (c, this)); } protected: - HBUINT16 baseTagCount; - SortedArrayOf baselineTags; + SortedArrayOf + baseScriptRecords; public: - DEFINE_SIZE_ARRAY (4, baselineTags); + DEFINE_SIZE_ARRAY (2, baseScriptRecords); }; struct Axis { - - inline unsigned int get_base_tag_index(Tag baselineTag) const + bool get_baseline (hb_ot_layout_baseline_t baseline, + hb_tag_t script_tag, + hb_tag_t language_tag, + const BaseCoord **coord) const { - if (unlikely(baseTagList == Null(OffsetTo))) return NOT_INDEXED; - return (this+baseTagList).get_tag_index(baselineTag); - } + const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); + if (base_script.is_empty ()) return false; - inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const - { - if (unlikely(baseScriptList == Null(OffsetTo))) return NOT_INDEXED; - return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex); - } - - inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const - { - return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex); - } + if (likely (coord)) *coord = &base_script.get_base_coord ((this+baseTagList).bsearch (baseline)); - inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const - { - if (unlikely(baseScriptList == Null(OffsetTo))) return NOT_INDEXED; - return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag); + return true; } - inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const + bool get_min_max (hb_tag_t script_tag, + hb_tag_t language_tag, + hb_tag_t feature_tag, + const BaseCoord **min_coord, + const BaseCoord **max_coord) const { - if (unlikely(baseScriptList == Null(OffsetTo))) return NOT_INDEXED; - return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); - } + const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); + if (base_script.is_empty ()) return false; - inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+baseScriptList).get_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); - } + base_script.get_min_max (language_tag).get_min_max (feature_tag, min_coord, max_coord); - inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+baseScriptList).get_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + return true; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - baseTagList.sanitize (c, this) && - baseScriptList.sanitize (c, this)); + return_trace (likely (c->check_struct (this) && + (this+baseTagList).sanitize (c) && + (this+baseScriptList).sanitize (c))); } protected: - OffsetTo baseTagList; - OffsetTo baseScriptList; + OffsetTo > + baseTagList; /* Offset to BaseTagList table, from beginning + * of Axis table (may be NULL) + * Array of 4-byte baseline identification tags — must + * be in alphabetical order */ + OffsetTo + baseScriptList; /* Offset to BaseScriptList table, from beginning + * of Axis table + * Array of BaseScriptRecords, in alphabetical order + * by baseScriptTag */ public: DEFINE_SIZE_STATIC (4); @@ -532,119 +464,72 @@ struct BASE { - static const hb_tag_t tableTag = HB_OT_TAG_BASE; - - inline bool has_vert_axis(void) - { return vertAxis != Null(OffsetTo); } + static constexpr hb_tag_t tableTag = HB_OT_TAG_BASE; - inline bool has_horiz_axis(void) - { return horizAxis != Null(OffsetTo); } + const Axis &get_axis (hb_direction_t direction) const + { return HB_DIRECTION_IS_VERTICAL (direction) ? this+vAxis : this+hAxis; } - // horizontal axis base coords: + const VariationStore &get_var_store () const + { return version.to_int () < 0x00010001u ? Null (VariationStore) : this+varStore; } - inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const + bool get_baseline (hb_font_t *font, + hb_ot_layout_baseline_t baseline, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_position_t *base) const { - if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+horizAxis).get_base_tag_index(baselineTag); - } + const BaseCoord *base_coord; + if (!get_axis (direction).get_baseline (baseline, script_tag, language_tag, &base_coord)) + return false; - inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const - { - if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex); + if (likely (base && base_coord)) *base = base_coord->get_coord (font, + get_var_store (), + direction); + return true; } - inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const + /* TODO: Expose this separately sometime? */ + bool get_min_max (hb_font_t *font, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_tag_t feature_tag, + hb_position_t *min, + hb_position_t *max) { - return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex); - } - - // vertical axis base coords: - - inline unsigned int get_vert_base_tag_index(Tag baselineTag) const - { - if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+vertAxis).get_base_tag_index(baselineTag); - } - - inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const - { - if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex); - } - - inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const - { - return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex); - } - - // horizontal axis min/max coords: - - inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const - { - if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag); - } - - inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const - { - if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag); - } + const BaseCoord *min_coord, *max_coord; + if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag, + &min_coord, &max_coord)) + return false; - inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); - } - - inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); - } - - // vertical axis min/max coords: - - inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const - { - if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag); - } - - inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const - { - if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; - return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag); - } - - inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + const VariationStore &var_store = get_var_store (); + if (likely (min && min_coord)) *min = min_coord->get_coord (font, var_store, direction); + if (likely (max && max_coord)) *max = max_coord->get_coord (font, var_store, direction); + return true; } - inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const - { - return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); - } - - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - likely (version.major == 1) && - horizAxis.sanitize (c, this) && - vertAxis.sanitize (c, this) && - (version.to_int () < 0x00010001u || varStore.sanitize (c, this))); + return_trace (likely (c->check_struct (this) && + likely (version.major == 1) && + hAxis.sanitize (c, this) && + vAxis.sanitize (c, this) && + (version.to_int () < 0x00010001u || varStore.sanitize (c, this)))); } protected: - FixedVersion<> version; - OffsetTo horizAxis; - OffsetTo vertAxis; + FixedVersion<>version; /* Version of the BASE table */ + OffsetTohAxis; /* Offset to horizontal Axis table, from beginning + * of BASE table (may be NULL) */ + OffsetTovAxis; /* Offset to vertical Axis table, from beginning + * of BASE table (may be NULL) */ LOffsetTo - varStore; /* Offset to the table of Item Variation - * Store--from beginning of BASE - * header (may be NULL). Introduced - * in version 0x00010001. */ + varStore; /* Offset to the table of Item Variation + * Store--from beginning of BASE + * header (may be NULL). Introduced + * in version 0x00010001. */ public: DEFINE_SIZE_MIN (8); }; --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gdef-table.hh 2019-02-28 12:03:56.782502996 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gdef-table.hh 2019-02-28 12:03:56.682502998 -0800 @@ -29,9 +29,9 @@ #ifndef HB_OT_LAYOUT_GDEF_TABLE_HH #define HB_OT_LAYOUT_GDEF_TABLE_HH -#include "hb-ot-layout-common-private.hh" +#include "hb-ot-layout-common.hh" -#include "hb-font-private.hh" +#include "hb-font.hh" namespace OT { @@ -46,10 +46,10 @@ struct AttachList { - inline unsigned int get_attach_points (hb_codepoint_t glyph_id, - unsigned int start_offset, - unsigned int *point_count /* IN/OUT */, - unsigned int *point_array /* OUT */) const + unsigned int get_attach_points (hb_codepoint_t glyph_id, + unsigned int start_offset, + unsigned int *point_count /* IN/OUT */, + unsigned int *point_array /* OUT */) const { unsigned int index = (this+coverage).get_coverage (glyph_id); if (index == NOT_COVERED) @@ -61,9 +61,10 @@ const AttachPoint &points = this+attachPoint[index]; - if (point_count) { - const HBUINT16 *array = points.sub_array (start_offset, point_count); - unsigned int count = *point_count; + if (point_count) + { + hb_array_t array = points.sub_array (start_offset, point_count); + unsigned int count = array.length; for (unsigned int i = 0; i < count; i++) point_array[i] = array[i]; } @@ -71,7 +72,7 @@ return points.len; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this)); @@ -97,12 +98,12 @@ friend struct CaretValue; private: - inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const + hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const { return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -120,16 +121,14 @@ friend struct CaretValue; private: - inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const + hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const { hb_position_t x, y; - if (font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y)) - return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y; - else - return 0; + font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y); + return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -146,14 +145,15 @@ { friend struct CaretValue; - inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VariationStore &var_store) const + hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, + const VariationStore &var_store) const { return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) : font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && deviceTable.sanitize (c, this)); @@ -172,7 +172,7 @@ struct CaretValue { - inline hb_position_t get_caret_value (hb_font_t *font, + hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, const VariationStore &var_store) const @@ -185,7 +185,7 @@ } } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return_trace (false); @@ -210,17 +210,18 @@ struct LigGlyph { - inline unsigned int get_lig_carets (hb_font_t *font, - hb_direction_t direction, - hb_codepoint_t glyph_id, - const VariationStore &var_store, - unsigned int start_offset, - unsigned int *caret_count /* IN/OUT */, - hb_position_t *caret_array /* OUT */) const - { - if (caret_count) { - const OffsetTo *array = carets.sub_array (start_offset, caret_count); - unsigned int count = *caret_count; + unsigned int get_lig_carets (hb_font_t *font, + hb_direction_t direction, + hb_codepoint_t glyph_id, + const VariationStore &var_store, + unsigned int start_offset, + unsigned int *caret_count /* IN/OUT */, + hb_position_t *caret_array /* OUT */) const + { + if (caret_count) + { + hb_array_t > array = carets.sub_array (start_offset, caret_count); + unsigned int count = array.length; for (unsigned int i = 0; i < count; i++) caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store); } @@ -228,7 +229,7 @@ return carets.len; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (carets.sanitize (c, this)); @@ -245,13 +246,13 @@ struct LigCaretList { - inline unsigned int get_lig_carets (hb_font_t *font, - hb_direction_t direction, - hb_codepoint_t glyph_id, - const VariationStore &var_store, - unsigned int start_offset, - unsigned int *caret_count /* IN/OUT */, - hb_position_t *caret_array /* OUT */) const + unsigned int get_lig_carets (hb_font_t *font, + hb_direction_t direction, + hb_codepoint_t glyph_id, + const VariationStore &var_store, + unsigned int start_offset, + unsigned int *caret_count /* IN/OUT */, + hb_position_t *caret_array /* OUT */) const { unsigned int index = (this+coverage).get_coverage (glyph_id); if (index == NOT_COVERED) @@ -264,7 +265,7 @@ return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this)); @@ -284,10 +285,10 @@ struct MarkGlyphSetsFormat1 { - inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const + bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this)); @@ -304,7 +305,7 @@ struct MarkGlyphSets { - inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const + bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const { switch (u.format) { case 1: return u.format1.covers (set_index, glyph_id); @@ -312,7 +313,7 @@ } } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return_trace (false); @@ -337,9 +338,10 @@ * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef */ + struct GDEF { - static const hb_tag_t tableTag = HB_OT_TAG_GDEF; + static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF; enum GlyphClasses { UnclassifiedGlyph = 0, @@ -349,59 +351,47 @@ ComponentGlyph = 4 }; - inline bool has_glyph_classes (void) const { return glyphClassDef != 0; } - inline unsigned int get_glyph_class (hb_codepoint_t glyph) const + bool has_data () const { return version.to_int (); } + bool has_glyph_classes () const { return glyphClassDef != 0; } + unsigned int get_glyph_class (hb_codepoint_t glyph) const { return (this+glyphClassDef).get_class (glyph); } - inline void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const + void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const { (this+glyphClassDef).add_class (glyphs, klass); } - inline bool has_mark_attachment_types (void) const { return markAttachClassDef != 0; } - inline unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const + bool has_mark_attachment_types () const { return markAttachClassDef != 0; } + unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const { return (this+markAttachClassDef).get_class (glyph); } - inline bool has_attach_points (void) const { return attachList != 0; } - inline unsigned int get_attach_points (hb_codepoint_t glyph_id, - unsigned int start_offset, - unsigned int *point_count /* IN/OUT */, - unsigned int *point_array /* OUT */) const + bool has_attach_points () const { return attachList != 0; } + unsigned int get_attach_points (hb_codepoint_t glyph_id, + unsigned int start_offset, + unsigned int *point_count /* IN/OUT */, + unsigned int *point_array /* OUT */) const { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); } - inline bool has_lig_carets (void) const { return ligCaretList != 0; } - inline unsigned int get_lig_carets (hb_font_t *font, - hb_direction_t direction, - hb_codepoint_t glyph_id, - unsigned int start_offset, - unsigned int *caret_count /* IN/OUT */, - hb_position_t *caret_array /* OUT */) const + bool has_lig_carets () const { return ligCaretList != 0; } + unsigned int get_lig_carets (hb_font_t *font, + hb_direction_t direction, + hb_codepoint_t glyph_id, + unsigned int start_offset, + unsigned int *caret_count /* IN/OUT */, + hb_position_t *caret_array /* OUT */) const { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, get_var_store(), start_offset, caret_count, caret_array); } - inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; } - inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const + bool has_mark_sets () const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; } + bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); } - inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; } - inline const VariationStore &get_var_store (void) const + bool has_var_store () const { return version.to_int () >= 0x00010003u && varStore != 0; } + const VariationStore &get_var_store () const { return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (version.sanitize (c) && - likely (version.major == 1) && - glyphClassDef.sanitize (c, this) && - attachList.sanitize (c, this) && - ligCaretList.sanitize (c, this) && - markAttachClassDef.sanitize (c, this) && - (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) && - (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); - } - /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing - * glyph class and other bits, and high 8-bit gthe mark attachment type (if any). + * glyph class and other bits, and high 8-bit the mark attachment type (if any). * Not to be confused with lookup_props which is very similar. */ - inline unsigned int get_glyph_props (hb_codepoint_t glyph) const + unsigned int get_glyph_props (hb_codepoint_t glyph) const { unsigned int klass = get_glyph_class (glyph); @@ -419,6 +409,65 @@ } } + HB_INTERNAL bool is_blacklisted (hb_blob_t *blob, + hb_face_t *face) const; + + struct accelerator_t + { + void init (hb_face_t *face) + { + this->table = hb_sanitize_context_t().reference_table (face); + if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face))) + { + hb_blob_destroy (this->table.get_blob ()); + this->table = hb_blob_get_empty (); + } + } + + void fini () { this->table.destroy (); } + + hb_blob_ptr_t table; + }; + + unsigned int get_size () const + { + return min_size + + (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) + + (version.to_int () >= 0x00010003u ? varStore.static_size : 0); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + struct GDEF *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + + out->glyphClassDef.serialize_subset (c, this+glyphClassDef, out); + out->attachList.set (0);//TODO(subset) serialize_subset (c, this+attachList, out); + out->ligCaretList.set (0);//TODO(subset) serialize_subset (c, this+ligCaretList, out); + out->markAttachClassDef.serialize_subset (c, this+markAttachClassDef, out); + + if (version.to_int () >= 0x00010002u) + out->markGlyphSetsDef.set (0);// TODO(subset) serialize_subset (c, this+markGlyphSetsDef, out); + + if (version.to_int () >= 0x00010003u) + out->varStore.set (0);// TODO(subset) serialize_subset (c, this+varStore, out); + + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + glyphClassDef.sanitize (c, this) && + attachList.sanitize (c, this) && + ligCaretList.sanitize (c, this) && + markAttachClassDef.sanitize (c, this) && + (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) && + (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); + } protected: FixedVersion<>version; /* Version of the GDEF table--currently @@ -453,6 +502,7 @@ DEFINE_SIZE_MIN (12); }; +struct GDEF_accelerator_t : GDEF::accelerator_t {}; } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gpos-table.hh 2019-02-28 12:03:57.122502991 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gpos-table.hh 2019-02-28 12:03:57.022502992 -0800 @@ -29,7 +29,7 @@ #ifndef HB_OT_LAYOUT_GPOS_TABLE_HH #define HB_OT_LAYOUT_GPOS_TABLE_HH -#include "hb-ot-layout-gsubgpos-private.hh" +#include "hb-ot-layout-gsubgpos.hh" namespace OT { @@ -53,7 +53,7 @@ typedef HBUINT16 Value; -typedef Value ValueRecord[VAR]; +typedef UnsizedArrayOf ValueRecord; struct ValueFormat : HBUINT16 { @@ -84,79 +84,79 @@ HBINT16 yAdvance; /* Vertical adjustment for advance--in * design units (only used for vertical * writing) */ - Offset xPlaDevice; /* Offset to Device table for + OffsetTo xPlaDevice; /* Offset to Device table for * horizontal placement--measured from * beginning of PosTable (may be NULL) */ - Offset yPlaDevice; /* Offset to Device table for vertical + OffsetTo yPlaDevice; /* Offset to Device table for vertical * placement--measured from beginning * of PosTable (may be NULL) */ - Offset xAdvDevice; /* Offset to Device table for + OffsetTo xAdvDevice; /* Offset to Device table for * horizontal advance--measured from * beginning of PosTable (may be NULL) */ - Offset yAdvDevice; /* Offset to Device table for vertical + OffsetTo yAdvDevice; /* Offset to Device table for vertical * advance--measured from beginning of * PosTable (may be NULL) */ #endif - inline unsigned int get_len (void) const - { return _hb_popcount ((unsigned int) *this); } - inline unsigned int get_size (void) const - { return get_len () * Value::static_size; } + unsigned int get_len () const { return hb_popcount ((unsigned int) *this); } + unsigned int get_size () const { return get_len () * Value::static_size; } - void apply_value (hb_ot_apply_context_t *c, + bool apply_value (hb_ot_apply_context_t *c, const void *base, const Value *values, hb_glyph_position_t &glyph_pos) const { + bool ret = false; unsigned int format = *this; - if (!format) return; + if (!format) return ret; hb_font_t *font = c->font; - hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction); + bool horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction); - if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++)); - if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++)); + if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret)); + if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret)); if (format & xAdvance) { - if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values)); + if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret)); values++; } /* y_advance values grow downward but font-space grows upward, hence negation */ if (format & yAdvance) { - if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values)); + if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret)); values++; } - if (!has_device ()) return; + if (!has_device ()) return ret; bool use_x_device = font->x_ppem || font->num_coords; bool use_y_device = font->y_ppem || font->num_coords; - if (!use_x_device && !use_y_device) return; + if (!use_x_device && !use_y_device) return ret; const VariationStore &store = c->var_store; /* pixel -> fractional pixel */ if (format & xPlaDevice) { - if (use_x_device) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font, store); + if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store); values++; } if (format & yPlaDevice) { - if (use_y_device) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font, store); + if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store); values++; } if (format & xAdvDevice) { - if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store); + if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store); values++; } if (format & yAdvDevice) { /* y_advance values grow downward but font-space grows upward, hence negation */ - if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store); + if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store); values++; } + return ret; } private: - inline bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const + bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const { unsigned int format = *this; @@ -173,33 +173,40 @@ return true; } - static inline OffsetTo& get_device (Value* value) - { return *CastP > (value); } - static inline const OffsetTo& get_device (const Value* value) + static OffsetTo& get_device (Value* value) { return *CastP > (value); } + static const OffsetTo& get_device (const Value* value, bool *worked=nullptr) + { + if (worked) *worked |= bool (*value); + return *CastP > (value); + } - static inline const HBINT16& get_short (const Value* value) - { return *CastP (value); } + static const HBINT16& get_short (const Value* value, bool *worked=nullptr) + { + if (worked) *worked |= bool (*value); + return *CastP (value); + } public: - inline bool has_device (void) const { + bool has_device () const + { unsigned int format = *this; return (format & devices) != 0; } - inline bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const + bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const { TRACE_SANITIZE (this); return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values))); } - inline bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const + bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const { TRACE_SANITIZE (this); unsigned int len = get_len (); - if (!c->check_array (values, get_size (), count)) return_trace (false); + if (!c->check_range (values, count, get_size ())) return_trace (false); if (!has_device ()) return_trace (true); @@ -213,7 +220,7 @@ } /* Just sanitize referenced Device tables. Doesn't check the values themselves. */ - inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const + bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const { TRACE_SANITIZE (this); @@ -232,15 +239,15 @@ struct AnchorFormat1 { - inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, - float *x, float *y) const + void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, + float *x, float *y) const { hb_font_t *font = c->font; *x = font->em_fscale_x (xCoordinate); *y = font->em_fscale_y (yCoordinate); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -256,22 +263,22 @@ struct AnchorFormat2 { - inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id, - float *x, float *y) const + void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id, + float *x, float *y) const { hb_font_t *font = c->font; unsigned int x_ppem = font->x_ppem; unsigned int y_ppem = font->y_ppem; hb_position_t cx = 0, cy = 0; - hb_bool_t ret; + bool ret; ret = (x_ppem || y_ppem) && - font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); + font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate); *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -288,8 +295,8 @@ struct AnchorFormat3 { - inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, - float *x, float *y) const + void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, + float *x, float *y) const { hb_font_t *font = c->font; *x = font->em_fscale_x (xCoordinate); @@ -301,7 +308,7 @@ *y += (this+yDeviceTable).get_y_delta (font, c->var_store); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); @@ -325,8 +332,8 @@ struct Anchor { - inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id, - float *x, float *y) const + void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id, + float *x, float *y) const { *x = *y = 0; switch (u.format) { @@ -337,7 +344,7 @@ } } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return_trace (false); @@ -363,20 +370,22 @@ struct AnchorMatrix { - inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const { + const Anchor& get_anchor (unsigned int row, unsigned int col, + unsigned int cols, bool *found) const + { *found = false; if (unlikely (row >= rows || col >= cols)) return Null(Anchor); *found = !matrixZ[row * cols + col].is_null (); return this+matrixZ[row * cols + col]; } - inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const + bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const { TRACE_SANITIZE (this); if (!c->check_struct (this)) return_trace (false); - if (unlikely (_hb_unsigned_int_mul_overflows (rows, cols))) return_trace (false); + if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false); unsigned int count = rows * cols; - if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false); + if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false); for (unsigned int i = 0; i < count; i++) if (!matrixZ[i].sanitize (c, this)) return_trace (false); return_trace (true); @@ -384,8 +393,8 @@ HBUINT16 rows; /* Number of rows */ protected: - OffsetTo - matrixZ[VAR]; /* Matrix of offsets to Anchor tables-- + UnsizedArrayOf > + matrixZ; /* Matrix of offsets to Anchor tables-- * from beginning of AnchorMatrix table */ public: DEFINE_SIZE_ARRAY (2, matrixZ); @@ -396,7 +405,7 @@ { friend struct MarkArray; - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && markAnchor.sanitize (c, base)); @@ -413,10 +422,10 @@ struct MarkArray : ArrayOf /* Array of MarkRecords--in Coverage order */ { - inline bool apply (hb_ot_apply_context_t *c, - unsigned int mark_index, unsigned int glyph_index, - const AnchorMatrix &anchors, unsigned int class_count, - unsigned int glyph_pos) const + bool apply (hb_ot_apply_context_t *c, + unsigned int mark_index, unsigned int glyph_index, + const AnchorMatrix &anchors, unsigned int class_count, + unsigned int glyph_pos) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; @@ -447,7 +456,7 @@ return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (ArrayOf::sanitize (c, this)); @@ -459,18 +468,15 @@ struct SinglePosFormat1 { - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const - { - TRACE_COLLECT_GLYPHS (this); - if (unlikely (!(this+coverage).add_coverage (c->input))) return; - } + bool intersects (const hb_set_t *glyphs) const + { return (this+coverage).intersects (glyphs); } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + void collect_glyphs (hb_collect_glyphs_context_t *c) const + { if (unlikely (!(this+coverage).add_coverage (c->input))) return; } + + const Coverage &get_coverage () const { return this+coverage; } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; @@ -483,7 +489,14 @@ return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -507,18 +520,15 @@ struct SinglePosFormat2 { - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const - { - TRACE_COLLECT_GLYPHS (this); - if (unlikely (!(this+coverage).add_coverage (c->input))) return; - } + bool intersects (const hb_set_t *glyphs) const + { return (this+coverage).intersects (glyphs); } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + void collect_glyphs (hb_collect_glyphs_context_t *c) const + { if (unlikely (!(this+coverage).add_coverage (c->input))) return; } + + const Coverage &get_coverage () const { return this+coverage; } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; @@ -535,7 +545,14 @@ return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -560,7 +577,7 @@ struct SinglePos { template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -598,19 +615,36 @@ { friend struct PairPosFormat1; - inline void collect_glyphs (hb_collect_glyphs_context_t *c, + bool intersects (const hb_set_t *glyphs, + const ValueFormat *valueFormats) const + { + unsigned int len1 = valueFormats[0].get_len (); + unsigned int len2 = valueFormats[1].get_len (); + unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); + + const PairValueRecord *record = &firstPairValueRecord; + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + { + if (glyphs->has (record->secondGlyph)) + return true; + record = &StructAtOffset (record, record_size); + } + return false; + } + + void collect_glyphs (hb_collect_glyphs_context_t *c, const ValueFormat *valueFormats) const { - TRACE_COLLECT_GLYPHS (this); unsigned int len1 = valueFormats[0].get_len (); unsigned int len2 = valueFormats[1].get_len (); unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); - const PairValueRecord *record = CastP (arrayZ); + const PairValueRecord *record = &firstPairValueRecord; c->input->add_array (&record->secondGlyph, len, record_size); } - inline bool apply (hb_ot_apply_context_t *c, + bool apply (hb_ot_apply_context_t *c, const ValueFormat *valueFormats, unsigned int pos) const { @@ -620,7 +654,6 @@ unsigned int len2 = valueFormats[1].get_len (); unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); - const PairValueRecord *record_array = CastP (arrayZ); unsigned int count = len; /* Hand-coded bsearch. */ @@ -630,8 +663,8 @@ int min = 0, max = (int) count - 1; while (min <= max) { - int mid = (min + max) / 2; - const PairValueRecord *record = &StructAtOffset (record_array, record_size * mid); + int mid = ((unsigned int) min + (unsigned int) max) / 2; + const PairValueRecord *record = &StructAtOffset (&firstPairValueRecord, record_size * mid); hb_codepoint_t mid_x = record->secondGlyph; if (x < mid_x) max = mid - 1; @@ -639,9 +672,10 @@ min = mid + 1; else { - buffer->unsafe_to_break (buffer->idx, pos + 1); - valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); - valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); + /* Note the intentional use of "|" instead of short-circuit "||". */ + if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) | + valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos])) + buffer->unsafe_to_break (buffer->idx, pos + 1); if (len2) pos++; buffer->idx = pos; @@ -652,50 +686,65 @@ return_trace (false); } - struct sanitize_closure_t { + struct sanitize_closure_t + { const void *base; const ValueFormat *valueFormats; unsigned int len1; /* valueFormats[0].get_len() */ unsigned int stride; /* 1 + len1 + len2 */ }; - inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const + bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const { TRACE_SANITIZE (this); if (!(c->check_struct (this) - && c->check_array (arrayZ, HBUINT16::static_size * closure->stride, len))) return_trace (false); + && c->check_range (&firstPairValueRecord, + len, + HBUINT16::static_size, + closure->stride))) return_trace (false); unsigned int count = len; - const PairValueRecord *record = CastP (arrayZ); + const PairValueRecord *record = &firstPairValueRecord; return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) && closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride)); } protected: - HBUINT16 len; /* Number of PairValueRecords */ - HBUINT16 arrayZ[VAR]; /* Array of PairValueRecords--ordered - * by GlyphID of the second glyph */ + HBUINT16 len; /* Number of PairValueRecords */ + PairValueRecord firstPairValueRecord; + /* Array of PairValueRecords--ordered + * by GlyphID of the second glyph */ public: - DEFINE_SIZE_ARRAY (2, arrayZ); + DEFINE_SIZE_MIN (2); }; struct PairPosFormat1 { - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { + unsigned int count = pairSet.len; + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ + if (glyphs->has (iter.get_glyph ()) && + (this+pairSet[iter.get_coverage ()]).intersects (glyphs, valueFormat)) + return true; + } + return false; + } + + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; unsigned int count = pairSet.len; for (unsigned int i = 0; i < count; i++) (this+pairSet[i]).collect_glyphs (c, valueFormat); } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + const Coverage &get_coverage () const { return this+coverage; } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; @@ -709,7 +758,14 @@ return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -717,7 +773,8 @@ unsigned int len1 = valueFormat[0].get_len (); unsigned int len2 = valueFormat[1].get_len (); - PairSet::sanitize_closure_t closure = { + PairSet::sanitize_closure_t closure = + { this, valueFormat, len1, @@ -747,19 +804,21 @@ struct PairPosFormat2 { - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + bool intersects (const hb_set_t *glyphs) const { - TRACE_COLLECT_GLYPHS (this); - if (unlikely (!(this+coverage).add_coverage (c->input))) return; - if (unlikely (!(this+classDef2).add_coverage (c->input))) return; + return (this+coverage).intersects (glyphs) && + (this+classDef2).intersects (glyphs); } - inline const Coverage &get_coverage (void) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - return this+coverage; + if (unlikely (!(this+coverage).add_coverage (c->input))) return; + if (unlikely (!(this+classDef2).add_coverage (c->input))) return; } - inline bool apply (hb_ot_apply_context_t *c) const + const Coverage &get_coverage () const { return this+coverage; } + + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; @@ -778,10 +837,11 @@ unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false); - buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1); const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; - valueFormat1.apply_value (c, this, v, buffer->cur_pos()); - valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); + /* Note the intentional use of "|" instead of short-circuit "||". */ + if (valueFormat1.apply_value (c, this, v, buffer->cur_pos()) | + valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx])) + buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1); buffer->idx = skippy_iter.idx; if (len2) @@ -790,7 +850,14 @@ return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (!(c->check_struct (this) @@ -803,7 +870,9 @@ unsigned int stride = len1 + len2; unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size (); unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count; - return_trace (c->check_array (values, record_size, count) && + return_trace (c->check_range ((const void *) values, + count, + record_size) && valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)); } @@ -841,7 +910,7 @@ struct PairPos { template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -865,7 +934,7 @@ { friend struct CursivePosFormat1; - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base)); @@ -889,39 +958,36 @@ struct CursivePosFormat1 { - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const - { - TRACE_COLLECT_GLYPHS (this); - if (unlikely (!(this+coverage).add_coverage (c->input))) return; - } + bool intersects (const hb_set_t *glyphs) const + { return (this+coverage).intersects (glyphs); } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + void collect_glyphs (hb_collect_glyphs_context_t *c) const + { if (unlikely (!(this+coverage).add_coverage (c->input))) return; } - inline bool apply (hb_ot_apply_context_t *c) const + const Coverage &get_coverage () const { return this+coverage; } + + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)]; - if (!this_record.exitAnchor) return_trace (false); + if (!this_record.entryAnchor) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, 1); - if (!skippy_iter.next ()) return_trace (false); + if (!skippy_iter.prev ()) return_trace (false); - const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)]; - if (!next_record.entryAnchor) return_trace (false); + const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)]; + if (!prev_record.exitAnchor) return_trace (false); - unsigned int i = buffer->idx; - unsigned int j = skippy_iter.idx; + unsigned int i = skippy_iter.idx; + unsigned int j = buffer->idx; buffer->unsafe_to_break (i, j); float entry_x, entry_y, exit_x, exit_y; - (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y); - (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y); + (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y); + (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y); hb_glyph_position_t *pos = buffer->pos; @@ -968,7 +1034,7 @@ * parent. * * Optimize things for the case of RightToLeft, as that's most common in - * Arabinc. */ + * Arabic. */ unsigned int child = i; unsigned int parent = j; hb_position_t x_offset = entry_x - exit_x; @@ -997,11 +1063,18 @@ else pos[child].x_offset = x_offset; - buffer->idx = j; + buffer->idx++; return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this)); @@ -1022,7 +1095,7 @@ struct CursivePos { template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -1047,19 +1120,19 @@ struct MarkBasePosFormat1 { - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { return (this+markCoverage).intersects (glyphs) && + (this+baseCoverage).intersects (glyphs); } + + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+markCoverage).add_coverage (c->input))) return; if (unlikely (!(this+baseCoverage).add_coverage (c->input))) return; } - inline const Coverage &get_coverage (void) const - { - return this+markCoverage; - } + const Coverage &get_coverage () const { return this+markCoverage; } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; @@ -1088,7 +1161,7 @@ )) break; skippy_iter.reject (); - } while (1); + } while (true); /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */ //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); } @@ -1099,7 +1172,14 @@ return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -1131,7 +1211,7 @@ struct MarkBasePos { template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -1161,19 +1241,19 @@ struct MarkLigPosFormat1 { - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { return (this+markCoverage).intersects (glyphs) && + (this+ligatureCoverage).intersects (glyphs); } + + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+markCoverage).add_coverage (c->input))) return; if (unlikely (!(this+ligatureCoverage).add_coverage (c->input))) return; } - inline const Coverage &get_coverage (void) const - { - return this+markCoverage; - } + const Coverage &get_coverage () const { return this+markCoverage; } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; @@ -1216,7 +1296,14 @@ return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -1249,7 +1336,7 @@ struct MarkLigPos { template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -1274,19 +1361,19 @@ struct MarkMarkPosFormat1 { - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { return (this+mark1Coverage).intersects (glyphs) && + (this+mark2Coverage).intersects (glyphs); } + + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+mark1Coverage).add_coverage (c->input))) return; if (unlikely (!(this+mark2Coverage).add_coverage (c->input))) return; } - inline const Coverage &get_coverage (void) const - { - return this+mark1Coverage; - } + const Coverage &get_coverage () const { return this+mark1Coverage; } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; @@ -1330,7 +1417,14 @@ return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -1364,7 +1458,7 @@ struct MarkMarkPos { template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -1388,7 +1482,7 @@ struct ExtensionPos : Extension { - typedef struct PosLookupSubTable LookupSubTable; + typedef struct PosLookupSubTable SubTable; }; @@ -1400,6 +1494,7 @@ struct PosLookupSubTable { + friend struct Lookup; friend struct PosLookup; enum Type { @@ -1415,10 +1510,9 @@ }; template - inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const + typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const { TRACE_DISPATCH (this, lookup_type); - if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ()); switch (lookup_type) { case Single: return_trace (u.single.dispatch (c)); case Pair: return_trace (u.pair.dispatch (c)); @@ -1435,7 +1529,6 @@ protected: union { - HBUINT16 sub_format; SinglePos single; PairPos pair; CursivePos cursive; @@ -1447,34 +1540,39 @@ ExtensionPos extension; } u; public: - DEFINE_SIZE_UNION (2, sub_format); + DEFINE_SIZE_MIN (0); }; struct PosLookup : Lookup { - inline const PosLookupSubTable& get_subtable (unsigned int i) const - { return Lookup::get_subtable (i); } + typedef struct PosLookupSubTable SubTable; + + const SubTable& get_subtable (unsigned int i) const + { return Lookup::get_subtable (i); } - inline bool is_reverse (void) const + bool is_reverse () const { return false; } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); return_trace (dispatch (c)); } - inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const + bool intersects (const hb_set_t *glyphs) const { - TRACE_COLLECT_GLYPHS (this); - return_trace (dispatch (c)); + hb_intersects_context_t c (glyphs); + return dispatch (&c); } + hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const + { return dispatch (c); } + template - inline void add_coverage (set_t *glyphs) const + void add_coverage (set_t *glyphs) const { hb_add_coverage_context_t c (glyphs); dispatch (&c); @@ -1483,21 +1581,18 @@ static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index); template - static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); + static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); template - inline typename context_t::return_t dispatch (context_t *c) const - { return Lookup::dispatch (c); } + typename context_t::return_t dispatch (context_t *c) const + { return Lookup::dispatch (c); } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!Lookup::sanitize (c))) return_trace (false); - return_trace (dispatch (c)); - } -}; + bool subset (hb_subset_context_t *c) const + { return Lookup::subset (c); } -typedef OffsetListOf PosLookupList; + bool sanitize (hb_sanitize_context_t *c) const + { return Lookup::sanitize (c); } +}; /* * GPOS -- Glyph Positioning @@ -1506,22 +1601,25 @@ struct GPOS : GSUBGPOS { - static const hb_tag_t tableTag = HB_OT_TAG_GPOS; + static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS; - inline const PosLookup& get_lookup (unsigned int i) const + const PosLookup& get_lookup (unsigned int i) const { return CastR (GSUBGPOS::get_lookup (i)); } static inline void position_start (hb_font_t *font, hb_buffer_t *buffer); static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer); static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer); - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false); - const OffsetTo &list = CastR > (lookupList); - return_trace (list.sanitize (c, this)); - } + bool subset (hb_subset_context_t *c) const + { return GSUBGPOS::subset (c); } + + bool sanitize (hb_sanitize_context_t *c) const + { return GSUBGPOS::sanitize (c); } + + HB_INTERNAL bool is_blacklisted (hb_blob_t *blob, + hb_face_t *face) const; + + typedef GSUBGPOS::accelerator_t accelerator_t; }; @@ -1551,7 +1649,10 @@ pos[j].attach_type() = type; } static void -propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) +propagate_attachment_offsets (hb_glyph_position_t *pos, + unsigned int len, + unsigned int i, + hb_direction_t direction) { /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate * offset of glyph they are attached to. */ @@ -1559,11 +1660,14 @@ if (likely (!chain)) return; + pos[i].attach_chain() = 0; + unsigned int j = (int) i + chain; - pos[i].attach_chain() = 0; + if (unlikely (j >= len)) + return; - propagate_attachment_offsets (pos, j, direction); + propagate_attachment_offsets (pos, len, j, direction); assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE)); @@ -1602,7 +1706,7 @@ } void -GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) +GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED) { //_hb_buffer_assert_gsubgpos_vars (buffer); } @@ -1619,24 +1723,25 @@ /* Handle attachments */ if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT) for (unsigned int i = 0; i < len; i++) - propagate_attachment_offsets (pos, i, direction); + propagate_attachment_offsets (pos, len, i, direction); } +struct GPOS_accelerator_t : GPOS::accelerator_t {}; + + /* Out-of-class implementation for methods recursing */ template /*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) { - const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos); - const PosLookup &l = gpos.get_lookup (lookup_index); + const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index); return l.dispatch (c); } /*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index) { - const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos); - const PosLookup &l = gpos.get_lookup (lookup_index); + const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index); unsigned int saved_lookup_props = c->lookup_props; unsigned int saved_lookup_index = c->lookup_index; c->set_lookup_index (lookup_index); @@ -1648,10 +1753,6 @@ } -#undef attach_chain -#undef attach_type - - } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsub-table.hh 2019-02-28 12:03:57.502502984 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsub-table.hh 2019-02-28 12:03:57.374502986 -0800 @@ -29,34 +29,37 @@ #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH #define HB_OT_LAYOUT_GSUB_TABLE_HH -#include "hb-ot-layout-gsubgpos-private.hh" +#include "hb-ot-layout-gsubgpos.hh" namespace OT { +static inline void SingleSubst_serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitutes); + struct SingleSubstFormat1 { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { return (this+coverage).intersects (glyphs); } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); - Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { /* TODO Switch to range-based API to work around malicious fonts. * https://github.com/harfbuzz/harfbuzz/issues/363 */ hb_codepoint_t glyph_id = iter.get_glyph (); if (c->glyphs->has (glyph_id)) - c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu); + c->out->add ((glyph_id + deltaGlyphID) & 0xFFFFu); } } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; - Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { /* TODO Switch to range-based API to work around malicious fonts. * https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -65,18 +68,15 @@ } } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + const Coverage &get_coverage () const { return this+coverage; } - inline bool would_apply (hb_would_apply_context_t *c) const + bool would_apply (hb_would_apply_context_t *c) const { TRACE_WOULD_APPLY (this); return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); hb_codepoint_t glyph_id = c->buffer->cur().codepoint; @@ -91,19 +91,37 @@ return_trace (true); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - unsigned int num_glyphs, - int delta) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + int delta) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); - deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */ + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false); + deltaGlyphID.set (delta); /* TODO(serialize) overflow? */ return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset; + const hb_map_t &glyph_map = *c->plan->glyph_map; + hb_vector_t from; + hb_vector_t to; + hb_codepoint_t delta = deltaGlyphID; + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) + { + if (!glyphset.has (iter.get_glyph ())) continue; + from.push ()->set (glyph_map[iter.get_glyph ()]); + to.push ()->set (glyph_map[(iter.get_glyph () + delta) & 0xFFFF]); + } + c->serializer->propagate_error (from, to); + SingleSubst_serialize (c->serializer, from, to); + return_trace (from.length); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c)); @@ -122,27 +140,26 @@ struct SingleSubstFormat2 { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { return (this+coverage).intersects (glyphs); } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); - Coverage::Iter iter; unsigned int count = substitute.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) - c->glyphs->add (substitute[iter.get_coverage ()]); + c->out->add (substitute[iter.get_coverage ()]); } } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; - Coverage::Iter iter; unsigned int count = substitute.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -150,45 +167,57 @@ } } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + const Coverage &get_coverage () const { return this+coverage; } - inline bool would_apply (hb_would_apply_context_t *c) const + bool would_apply (hb_would_apply_context_t *c) const { TRACE_WOULD_APPLY (this); return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); - hb_codepoint_t glyph_id = c->buffer->cur().codepoint; - unsigned int index = (this+coverage).get_coverage (glyph_id); + unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); if (unlikely (index >= substitute.len)) return_trace (false); - glyph_id = substitute[index]; - c->replace_glyph (glyph_id); + c->replace_glyph (substitute[index]); return_trace (true); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - Supplier &substitutes, - unsigned int num_glyphs) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitutes) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return_trace (false); - if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); + if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false); + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false); return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset; + const hb_map_t &glyph_map = *c->plan->glyph_map; + hb_vector_t from; + hb_vector_t to; + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) + { + if (!glyphset.has (iter.get_glyph ())) continue; + from.push ()->set (glyph_map[iter.get_glyph ()]); + to.push ()->set (glyph_map[substitute[iter.get_coverage ()]]); + } + c->serializer->propagate_error (from, to); + SingleSubst_serialize (c->serializer, from, to); + return_trace (from.length); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && substitute.sanitize (c)); @@ -208,35 +237,35 @@ struct SingleSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - Supplier &substitutes, - unsigned int num_glyphs) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitutes) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); unsigned int format = 2; int delta = 0; - if (num_glyphs) { + if (glyphs.length) + { format = 1; /* TODO(serialize) check for wrap-around */ delta = substitutes[0] - glyphs[0]; - for (unsigned int i = 1; i < num_glyphs; i++) - if (delta != substitutes[i] - glyphs[i]) { + for (unsigned int i = 1; i < glyphs.length; i++) + if (delta != (int) (substitutes[i] - glyphs[i])) { format = 2; break; } } u.format.set (format); switch (u.format) { - case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs, delta)); - case 2: return_trace (u.format2.serialize (c, glyphs, substitutes, num_glyphs)); + case 1: return_trace (u.format1.serialize (c, glyphs, delta)); + case 2: return_trace (u.format2.serialize (c, glyphs, substitutes)); default:return_trace (false); } } template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -255,24 +284,25 @@ } u; }; +static inline void +SingleSubst_serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitutes) +{ c->start_embed ()->serialize (c, glyphs, substitutes); } struct Sequence { - inline void closure (hb_closure_context_t *c) const + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); unsigned int count = substitute.len; for (unsigned int i = 0; i < count; i++) - c->glyphs->add (substitute[i]); + c->out->add (substitute[i]); } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const - { - TRACE_COLLECT_GLYPHS (this); - c->output->add_array (substitute.arrayZ, substitute.len); - } + void collect_glyphs (hb_collect_glyphs_context_t *c) const + { c->output->add_array (substitute.arrayZ, substitute.len); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); unsigned int count = substitute.len; @@ -304,17 +334,14 @@ return_trace (true); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - unsigned int num_glyphs) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return_trace (false); - return_trace (true); + return_trace (substitute.serialize (c, glyphs)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (substitute.sanitize (c)); @@ -329,12 +356,13 @@ struct MultipleSubstFormat1 { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { return (this+coverage).intersects (glyphs); } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); - Coverage::Iter iter; unsigned int count = sequence.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -343,27 +371,23 @@ } } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; unsigned int count = sequence.len; for (unsigned int i = 0; i < count; i++) - (this+sequence[i]).collect_glyphs (c); + (this+sequence[i]).collect_glyphs (c); } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + const Coverage &get_coverage () const { return this+coverage; } - inline bool would_apply (hb_would_apply_context_t *c) const + bool would_apply (hb_would_apply_context_t *c) const { TRACE_WOULD_APPLY (this); return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); @@ -373,25 +397,33 @@ return_trace ((this+sequence[index]).apply (c)); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - Supplier &substitute_len_list, - unsigned int num_glyphs, - Supplier &substitute_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitute_len_list, + hb_array_t substitute_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!sequence.serialize (c, num_glyphs))) return_trace (false); - for (unsigned int i = 0; i < num_glyphs; i++) - if (unlikely (!sequence[i].serialize (c, this).serialize (c, - substitute_glyphs_list, - substitute_len_list[i]))) return_trace (false); - substitute_len_list += num_glyphs; - if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); - return_trace (true); + if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false); + for (unsigned int i = 0; i < glyphs.length; i++) + { + unsigned int substitute_len = substitute_len_list[i]; + if (unlikely (!sequence[i].serialize (c, this) + .serialize (c, substitute_glyphs_list.sub_array (0, substitute_len)))) + return_trace (false); + substitute_glyphs_list += substitute_len; + } + return_trace (coverage.serialize (c, this).serialize (c, glyphs)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this)); @@ -411,24 +443,23 @@ struct MultipleSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - Supplier &substitute_len_list, - unsigned int num_glyphs, - Supplier &substitute_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitute_len_list, + hb_array_t substitute_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); unsigned int format = 1; u.format.set (format); switch (u.format) { - case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list)); + case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list)); default:return_trace (false); } } template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -445,103 +476,138 @@ } u; }; +struct AlternateSet +{ + void closure (hb_closure_context_t *c) const + { + unsigned int count = alternates.len; + for (unsigned int i = 0; i < count; i++) + c->out->add (alternates[i]); + } + + void collect_glyphs (hb_collect_glyphs_context_t *c) const + { c->output->add_array (alternates.arrayZ, alternates.len); } + + bool apply (hb_ot_apply_context_t *c) const + { + TRACE_APPLY (this); + unsigned int count = alternates.len; -typedef ArrayOf AlternateSet; /* Array of alternate GlyphIDs--in + if (unlikely (!count)) return_trace (false); + + hb_mask_t glyph_mask = c->buffer->cur().mask; + hb_mask_t lookup_mask = c->lookup_mask; + + /* Note: This breaks badly if two features enabled this lookup together. */ + unsigned int shift = hb_ctz (lookup_mask); + unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift); + + /* If alt_index is MAX, randomize feature if it is the rand feature. */ + if (alt_index == HB_OT_MAP_MAX_VALUE && c->random) + alt_index = c->random_number () % count + 1; + + if (unlikely (alt_index > count || alt_index == 0)) return_trace (false); + + c->replace_glyph (alternates[alt_index - 1]); + + return_trace (true); + } + + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs) + { + TRACE_SERIALIZE (this); + return_trace (alternates.serialize (c, glyphs)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (alternates.sanitize (c)); + } + + protected: + ArrayOf + alternates; /* Array of alternate GlyphIDs--in * arbitrary order */ + public: + DEFINE_SIZE_ARRAY (2, alternates); +}; struct AlternateSubstFormat1 { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { return (this+coverage).intersects (glyphs); } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); - Coverage::Iter iter; unsigned int count = alternateSet.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ - if (c->glyphs->has (iter.get_glyph ())) { - const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; - unsigned int count = alt_set.len; - for (unsigned int i = 0; i < count; i++) - c->glyphs->add (alt_set[i]); - } + if (c->glyphs->has (iter.get_glyph ())) + (this+alternateSet[iter.get_coverage ()]).closure (c); } } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; - Coverage::Iter iter; unsigned int count = alternateSet.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ - const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; - c->output->add_array (alt_set.arrayZ, alt_set.len); + (this+alternateSet[iter.get_coverage ()]).collect_glyphs (c); } } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + const Coverage &get_coverage () const { return this+coverage; } - inline bool would_apply (hb_would_apply_context_t *c) const + bool would_apply (hb_would_apply_context_t *c) const { TRACE_WOULD_APPLY (this); return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); - hb_codepoint_t glyph_id = c->buffer->cur().codepoint; - unsigned int index = (this+coverage).get_coverage (glyph_id); + unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - const AlternateSet &alt_set = this+alternateSet[index]; - - if (unlikely (!alt_set.len)) return_trace (false); - - hb_mask_t glyph_mask = c->buffer->cur().mask; - hb_mask_t lookup_mask = c->lookup_mask; - - /* Note: This breaks badly if two features enabled this lookup together. */ - unsigned int shift = _hb_ctz (lookup_mask); - unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift); - - if (unlikely (alt_index > alt_set.len || alt_index == 0)) return_trace (false); - - glyph_id = alt_set[alt_index - 1]; - - c->replace_glyph (glyph_id); - - return_trace (true); + return_trace ((this+alternateSet[index]).apply (c)); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - Supplier &alternate_len_list, - unsigned int num_glyphs, - Supplier &alternate_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t alternate_len_list, + hb_array_t alternate_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!alternateSet.serialize (c, num_glyphs))) return_trace (false); - for (unsigned int i = 0; i < num_glyphs; i++) - if (unlikely (!alternateSet[i].serialize (c, this).serialize (c, - alternate_glyphs_list, - alternate_len_list[i]))) return_trace (false); - alternate_len_list += num_glyphs; - if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); - return_trace (true); + if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false); + for (unsigned int i = 0; i < glyphs.length; i++) + { + unsigned int alternate_len = alternate_len_list[i]; + if (unlikely (!alternateSet[i].serialize (c, this) + .serialize (c, alternate_glyphs_list.sub_array (0, alternate_len)))) + return_trace (false); + alternate_glyphs_list += alternate_len; + } + return_trace (coverage.serialize (c, this).serialize (c, glyphs)); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this)); @@ -561,24 +627,23 @@ struct AlternateSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - Supplier &alternate_len_list, - unsigned int num_glyphs, - Supplier &alternate_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t alternate_len_list, + hb_array_t alternate_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); unsigned int format = 1; u.format.set (format); switch (u.format) { - case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list)); + case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list)); default:return_trace (false); } } template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -598,27 +663,34 @@ struct Ligature { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const { - TRACE_CLOSURE (this); - unsigned int count = component.len; + unsigned int count = component.lenP1; + for (unsigned int i = 1; i < count; i++) + if (!glyphs->has (component[i])) + return false; + return true; + } + + void closure (hb_closure_context_t *c) const + { + unsigned int count = component.lenP1; for (unsigned int i = 1; i < count; i++) if (!c->glyphs->has (component[i])) return; - c->glyphs->add (ligGlyph); + c->out->add (ligGlyph); } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); - c->input->add_array (component.arrayZ, component.len ? component.len - 1 : 0); + c->input->add_array (component.arrayZ, component.lenP1 ? component.lenP1 - 1 : 0); c->output->add (ligGlyph); } - inline bool would_apply (hb_would_apply_context_t *c) const + bool would_apply (hb_would_apply_context_t *c) const { TRACE_WOULD_APPLY (this); - if (c->len != component.len) + if (c->len != component.lenP1) return_trace (false); for (unsigned int i = 1; i < c->len; i++) @@ -628,10 +700,10 @@ return_trace (true); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); - unsigned int count = component.len; + unsigned int count = component.lenP1; if (unlikely (!count)) return_trace (false); @@ -643,7 +715,6 @@ return_trace (true); } - bool is_mark_ligature = false; unsigned int total_component_count = 0; unsigned int match_length = 0; @@ -655,7 +726,6 @@ nullptr, &match_length, match_positions, - &is_mark_ligature, &total_component_count))) return_trace (false); @@ -664,26 +734,24 @@ match_positions, match_length, ligGlyph, - is_mark_ligature, total_component_count); return_trace (true); } - inline bool serialize (hb_serialize_context_t *c, - GlyphID ligature, - Supplier &components, /* Starting from second */ - unsigned int num_components /* Including first component */) + bool serialize (hb_serialize_context_t *c, + GlyphID ligature, + hb_array_t components /* Starting from second */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); ligGlyph = ligature; - if (unlikely (!component.serialize (c, components, num_components))) return_trace (false); + if (unlikely (!component.serialize (c, components))) return_trace (false); return_trace (true); } public: - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (ligGlyph.sanitize (c) && component.sanitize (c)); @@ -701,23 +769,30 @@ struct LigatureSet { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { + unsigned int num_ligs = ligature.len; + for (unsigned int i = 0; i < num_ligs; i++) + if ((this+ligature[i]).intersects (glyphs)) + return true; + return false; + } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); unsigned int num_ligs = ligature.len; for (unsigned int i = 0; i < num_ligs; i++) (this+ligature[i]).closure (c); } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); unsigned int num_ligs = ligature.len; for (unsigned int i = 0; i < num_ligs; i++) (this+ligature[i]).collect_glyphs (c); } - inline bool would_apply (hb_would_apply_context_t *c) const + bool would_apply (hb_would_apply_context_t *c) const { TRACE_WOULD_APPLY (this); unsigned int num_ligs = ligature.len; @@ -730,7 +805,7 @@ return_trace (false); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); unsigned int num_ligs = ligature.len; @@ -743,26 +818,28 @@ return_trace (false); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &ligatures, - Supplier &component_count_list, - unsigned int num_ligatures, - Supplier &component_list /* Starting from second for each ligature */) + bool serialize (hb_serialize_context_t *c, + hb_array_t ligatures, + hb_array_t component_count_list, + hb_array_t &component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!ligature.serialize (c, num_ligatures))) return_trace (false); - for (unsigned int i = 0; i < num_ligatures; i++) - if (unlikely (!ligature[i].serialize (c, this).serialize (c, - ligatures[i], - component_list, - component_count_list[i]))) return_trace (false); - ligatures += num_ligatures; - component_count_list += num_ligatures; + if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false); + for (unsigned int i = 0; i < ligatures.length; i++) + { + unsigned int component_count = MAX (component_count_list[i] - 1, 0); + if (unlikely (!ligature[i].serialize (c, this) + .serialize (c, + ligatures[i], + component_list.sub_array (0, component_count)))) + return_trace (false); + component_list += component_count; + } return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (ligature.sanitize (c, this)); @@ -778,12 +855,24 @@ struct LigatureSubstFormat1 { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const { - TRACE_CLOSURE (this); - Coverage::Iter iter; unsigned int count = ligatureSet.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ + if (glyphs->has (iter.get_glyph ()) && + (this+ligatureSet[iter.get_coverage ()]).intersects (glyphs)) + return true; + } + return false; + } + + void closure (hb_closure_context_t *c) const + { + unsigned int count = ligatureSet.len; + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -792,13 +881,11 @@ } } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; - Coverage::Iter iter; unsigned int count = ligatureSet.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -806,12 +893,9 @@ } } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + const Coverage &get_coverage () const { return this+coverage; } - inline bool would_apply (hb_would_apply_context_t *c) const + bool would_apply (hb_would_apply_context_t *c) const { TRACE_WOULD_APPLY (this); unsigned int index = (this+coverage).get_coverage (c->glyphs[0]); @@ -821,41 +905,49 @@ return_trace (lig_set.would_apply (c)); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); - hb_codepoint_t glyph_id = c->buffer->cur().codepoint; - unsigned int index = (this+coverage).get_coverage (glyph_id); + unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); const LigatureSet &lig_set = this+ligatureSet[index]; return_trace (lig_set.apply (c)); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &first_glyphs, - Supplier &ligature_per_first_glyph_count_list, - unsigned int num_first_glyphs, - Supplier &ligatures_list, - Supplier &component_count_list, - Supplier &component_list /* Starting from second for each ligature */) + bool serialize (hb_serialize_context_t *c, + hb_array_t first_glyphs, + hb_array_t ligature_per_first_glyph_count_list, + hb_array_t ligatures_list, + hb_array_t component_count_list, + hb_array_t component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return_trace (false); - for (unsigned int i = 0; i < num_first_glyphs; i++) - if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c, - ligatures_list, - component_count_list, - ligature_per_first_glyph_count_list[i], - component_list))) return_trace (false); - ligature_per_first_glyph_count_list += num_first_glyphs; - if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return_trace (false); - return_trace (true); + if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false); + for (unsigned int i = 0; i < first_glyphs.length; i++) + { + unsigned int ligature_count = ligature_per_first_glyph_count_list[i]; + if (unlikely (!ligatureSet[i].serialize (c, this) + .serialize (c, + ligatures_list.sub_array (0, ligature_count), + component_count_list.sub_array (0, ligature_count), + component_list))) return_trace (false); + ligatures_list += ligature_count; + component_count_list += ligature_count; + } + return_trace (coverage.serialize (c, this).serialize (c, first_glyphs)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); @@ -875,13 +967,12 @@ struct LigatureSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier &first_glyphs, - Supplier &ligature_per_first_glyph_count_list, - unsigned int num_first_glyphs, - Supplier &ligatures_list, - Supplier &component_count_list, - Supplier &component_list /* Starting from second for each ligature */) + bool serialize (hb_serialize_context_t *c, + hb_array_t first_glyphs, + hb_array_t ligature_per_first_glyph_count_list, + hb_array_t ligatures_list, + hb_array_t component_count_list, + hb_array_t component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); @@ -891,7 +982,6 @@ case 1: return_trace (u.format1.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, - num_first_glyphs, ligatures_list, component_count_list, component_list)); @@ -900,7 +990,7 @@ } template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -924,17 +1014,38 @@ struct ExtensionSubst : Extension { - typedef struct SubstLookupSubTable LookupSubTable; + typedef struct SubstLookupSubTable SubTable; - inline bool is_reverse (void) const; + bool is_reverse () const; }; struct ReverseChainSingleSubstFormat1 { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { + if (!(this+coverage).intersects (glyphs)) + return false; + + const OffsetArrayOf &lookahead = StructAfter > (backtrack); + + unsigned int count; + + count = backtrack.len; + for (unsigned int i = 0; i < count; i++) + if (!(this+backtrack[i]).intersects (glyphs)) + return false; + + count = lookahead.len; + for (unsigned int i = 0; i < count; i++) + if (!(this+lookahead[i]).intersects (glyphs)) + return false; + + return true; + } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); const OffsetArrayOf &lookahead = StructAfter > (backtrack); unsigned int count; @@ -950,20 +1061,18 @@ return; const ArrayOf &substitute = StructAfter > (lookahead); - Coverage::Iter iter; count = substitute.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) - c->glyphs->add (substitute[iter.get_coverage ()]); + c->out->add (substitute[iter.get_coverage ()]); } } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; unsigned int count; @@ -982,18 +1091,15 @@ c->output->add_array (substitute.arrayZ, substitute.len); } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + const Coverage &get_coverage () const { return this+coverage; } - inline bool would_apply (hb_would_apply_context_t *c) const + bool would_apply (hb_would_apply_context_t *c) const { TRACE_WOULD_APPLY (this); return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL)) @@ -1026,7 +1132,14 @@ return_trace (false); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) @@ -1045,7 +1158,7 @@ * beginning of table */ OffsetArrayOf backtrack; /* Array of coverage tables - * in backtracking sequence, in glyph + * in backtracking sequence, in glyph * sequence order */ OffsetArrayOf lookaheadX; /* Array of coverage tables @@ -1061,7 +1174,7 @@ struct ReverseChainSingleSubst { template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -1086,6 +1199,7 @@ struct SubstLookupSubTable { + friend struct Lookup; friend struct SubstLookup; enum Type { @@ -1100,10 +1214,9 @@ }; template - inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const + typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const { TRACE_DISPATCH (this, lookup_type); - if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ()); switch (lookup_type) { case Single: return_trace (u.single.dispatch (c)); case Multiple: return_trace (u.multiple.dispatch (c)); @@ -1119,7 +1232,6 @@ protected: union { - HBUINT16 sub_format; SingleSubst single; MultipleSubst multiple; AlternateSubst alternate; @@ -1130,58 +1242,69 @@ ReverseChainSingleSubst reverseChainContextSingle; } u; public: - DEFINE_SIZE_UNION (2, sub_format); + DEFINE_SIZE_MIN (0); }; struct SubstLookup : Lookup { - inline const SubstLookupSubTable& get_subtable (unsigned int i) const - { return Lookup::get_subtable (i); } + typedef SubstLookupSubTable SubTable; + + const SubTable& get_subtable (unsigned int i) const + { return Lookup::get_subtable (i); } - inline static bool lookup_type_is_reverse (unsigned int lookup_type) - { return lookup_type == SubstLookupSubTable::ReverseChainSingle; } + static bool lookup_type_is_reverse (unsigned int lookup_type) + { return lookup_type == SubTable::ReverseChainSingle; } - inline bool is_reverse (void) const + bool is_reverse () const { unsigned int type = get_type (); - if (unlikely (type == SubstLookupSubTable::Extension)) + if (unlikely (type == SubTable::Extension)) return CastR (get_subtable(0)).is_reverse (); return lookup_type_is_reverse (type); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); return_trace (dispatch (c)); } - inline hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const + bool intersects (const hb_set_t *glyphs) const + { + hb_intersects_context_t c (glyphs); + return dispatch (&c); + } + + hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const { - TRACE_CLOSURE (this); if (!c->should_visit_lookup (this_index)) - return_trace (HB_VOID); + return hb_closure_context_t::default_return_value (); c->set_recurse_func (dispatch_closure_recurse_func); - return_trace (dispatch (c)); + + hb_closure_context_t::return_t ret = dispatch (c); + + c->flush (); + + return ret; } - inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const + hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); c->set_recurse_func (dispatch_recurse_func); - return_trace (dispatch (c)); + return dispatch (c); } template - inline void add_coverage (set_t *glyphs) const + void add_coverage (set_t *glyphs) const { hb_add_coverage_context_t c (glyphs); dispatch (&c); } - inline bool would_apply (hb_would_apply_context_t *c, - const hb_ot_layout_lookup_accelerator_t *accel) const + bool would_apply (hb_would_apply_context_t *c, + const hb_ot_layout_lookup_accelerator_t *accel) const { TRACE_WOULD_APPLY (this); if (unlikely (!c->len)) return_trace (false); @@ -1191,111 +1314,95 @@ static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index); - inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c, - unsigned int i) - { return get_subtables ()[i].serialize (c, this); } - - inline bool serialize_single (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier &glyphs, - Supplier &substitutes, - unsigned int num_glyphs) + SubTable& serialize_subtable (hb_serialize_context_t *c, + unsigned int i) + { return get_subtables ()[i].serialize (c, this); } + + bool serialize_single (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_array_t glyphs, + hb_array_t substitutes) { TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return_trace (false); - return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs)); + if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false); + return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes)); } - inline bool serialize_multiple (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier &glyphs, - Supplier &substitute_len_list, - unsigned int num_glyphs, - Supplier &substitute_glyphs_list) + bool serialize_multiple (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_array_t glyphs, + hb_array_t substitute_len_list, + hb_array_t substitute_glyphs_list) { TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return_trace (false); + if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false); return_trace (serialize_subtable (c, 0).u.multiple.serialize (c, glyphs, substitute_len_list, - num_glyphs, substitute_glyphs_list)); } - inline bool serialize_alternate (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier &glyphs, - Supplier &alternate_len_list, - unsigned int num_glyphs, - Supplier &alternate_glyphs_list) + bool serialize_alternate (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_array_t glyphs, + hb_array_t alternate_len_list, + hb_array_t alternate_glyphs_list) { TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return_trace (false); + if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false); return_trace (serialize_subtable (c, 0).u.alternate.serialize (c, glyphs, alternate_len_list, - num_glyphs, alternate_glyphs_list)); } - inline bool serialize_ligature (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier &first_glyphs, - Supplier &ligature_per_first_glyph_count_list, - unsigned int num_first_glyphs, - Supplier &ligatures_list, - Supplier &component_count_list, - Supplier &component_list /* Starting from second for each ligature */) + bool serialize_ligature (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_array_t first_glyphs, + hb_array_t ligature_per_first_glyph_count_list, + hb_array_t ligatures_list, + hb_array_t component_count_list, + hb_array_t component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return_trace (false); + if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false); return_trace (serialize_subtable (c, 0).u.ligature.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, - num_first_glyphs, ligatures_list, component_count_list, component_list)); } template - static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); + static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); - static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index) + static hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index) { if (!c->should_visit_lookup (lookup_index)) return HB_VOID; - return dispatch_recurse_func (c, lookup_index); + + hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index); + + /* While in theory we should flush here, it will cause timeouts because a recursive + * lookup can keep growing the glyph set. Skip, and outer loop will retry up to + * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */ + //c->flush (); + + return ret; } template - inline typename context_t::return_t dispatch (context_t *c) const - { return Lookup::dispatch (c); } + typename context_t::return_t dispatch (context_t *c) const + { return Lookup::dispatch (c); } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!Lookup::sanitize (c))) return_trace (false); - if (unlikely (!dispatch (c))) return_trace (false); + bool subset (hb_subset_context_t *c) const + { return Lookup::subset (c); } - if (unlikely (get_type () == SubstLookupSubTable::Extension)) - { - /* The spec says all subtables of an Extension lookup should - * have the same type, which shall not be the Extension type - * itself (but we already checked for that). - * This is specially important if one has a reverse type! */ - unsigned int type = get_subtable (0).u.extension.get_type (); - unsigned int count = get_subtable_count (); - for (unsigned int i = 1; i < count; i++) - if (get_subtable (i).u.extension.get_type () != type) - return_trace (false); - } - return_trace (true); - } + bool sanitize (hb_sanitize_context_t *c) const + { return Lookup::sanitize (c); } }; -typedef OffsetListOf SubstLookupList; - /* * GSUB -- Glyph Substitution * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub @@ -1303,61 +1410,47 @@ struct GSUB : GSUBGPOS { - static const hb_tag_t tableTag = HB_OT_TAG_GSUB; + static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB; - inline const SubstLookup& get_lookup (unsigned int i) const + const SubstLookup& get_lookup (unsigned int i) const { return CastR (GSUBGPOS::get_lookup (i)); } - static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer); + bool subset (hb_subset_context_t *c) const + { return GSUBGPOS::subset (c); } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false); - const OffsetTo &list = CastR > (lookupList); - return_trace (list.sanitize (c, this)); - } -}; + bool sanitize (hb_sanitize_context_t *c) const + { return GSUBGPOS::sanitize (c); } + HB_INTERNAL bool is_blacklisted (hb_blob_t *blob, + hb_face_t *face) const; -void -GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer) -{ - _hb_buffer_assert_gsubgpos_vars (buffer); + typedef GSUBGPOS::accelerator_t accelerator_t; +}; - const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef; - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - { - _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint)); - _hb_glyph_info_clear_lig_props (&buffer->info[i]); - buffer->info[i].syllable() = 0; - } -} + +struct GSUB_accelerator_t : GSUB::accelerator_t {}; /* Out-of-class implementation for methods recursing */ -/*static*/ inline bool ExtensionSubst::is_reverse (void) const +/*static*/ inline bool ExtensionSubst::is_reverse () const { unsigned int type = get_type (); - if (unlikely (type == SubstLookupSubTable::Extension)) - return CastR (get_subtable()).is_reverse (); + if (unlikely (type == SubTable::Extension)) + return CastR (get_subtable()).is_reverse (); return SubstLookup::lookup_type_is_reverse (type); } template /*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) { - const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); - const SubstLookup &l = gsub.get_lookup (lookup_index); + const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index); return l.dispatch (c); } /*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index) { - const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); - const SubstLookup &l = gsub.get_lookup (lookup_index); + const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index); unsigned int saved_lookup_props = c->lookup_props; unsigned int saved_lookup_index = c->lookup_index; c->set_lookup_index (lookup_index); @@ -1368,7 +1461,6 @@ return ret; } - } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-jstf-table.hh 2019-02-28 12:03:57.890502978 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-jstf-table.hh 2019-02-28 12:03:57.790502979 -0800 @@ -27,7 +27,7 @@ #ifndef HB_OT_LAYOUT_JSTF_TABLE_HH #define HB_OT_LAYOUT_JSTF_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" #include "hb-ot-layout-gpos-table.hh" @@ -54,7 +54,7 @@ struct JstfPriority { - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -123,8 +123,8 @@ struct JstfLangSys : OffsetListOf { - inline bool sanitize (hb_sanitize_context_t *c, - const Record::sanitize_closure_t * = nullptr) const + bool sanitize (hb_sanitize_context_t *c, + const Record_sanitize_closure_t * = nullptr) const { TRACE_SANITIZE (this); return_trace (OffsetListOf::sanitize (c)); @@ -145,27 +145,27 @@ struct JstfScript { - inline unsigned int get_lang_sys_count (void) const + unsigned int get_lang_sys_count () const { return langSys.len; } - inline const Tag& get_lang_sys_tag (unsigned int i) const + 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 + 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 JstfLangSys& get_lang_sys (unsigned int i) const + const JstfLangSys& 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 + 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 JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } + bool has_default_lang_sys () const { return defaultLangSys != 0; } + const JstfLangSys& get_default_lang_sys () const { return this+defaultLangSys; } - inline bool sanitize (hb_sanitize_context_t *c, - const Record::sanitize_closure_t * = nullptr) const + bool sanitize (hb_sanitize_context_t *c, + const Record_sanitize_closure_t * = nullptr) const { TRACE_SANITIZE (this); return_trace (extenderGlyphs.sanitize (c, this) && @@ -195,22 +195,22 @@ struct JSTF { - static const hb_tag_t tableTag = HB_OT_TAG_JSTF; + static constexpr hb_tag_t tableTag = HB_OT_TAG_JSTF; - inline unsigned int get_script_count (void) const + unsigned int get_script_count () const { return scriptList.len; } - inline const Tag& get_script_tag (unsigned int i) const + const Tag& get_script_tag (unsigned int i) const { return scriptList.get_tag (i); } - inline unsigned int get_script_tags (unsigned int start_offset, - unsigned int *script_count /* IN/OUT */, - hb_tag_t *script_tags /* OUT */) const + unsigned int get_script_tags (unsigned int start_offset, + unsigned int *script_count /* IN/OUT */, + hb_tag_t *script_tags /* OUT */) const { return scriptList.get_tags (start_offset, script_count, script_tags); } - inline const JstfScript& get_script (unsigned int i) const + const JstfScript& get_script (unsigned int i) const { return this+scriptList[i].offset; } - inline bool find_script_index (hb_tag_t tag, unsigned int *index) const + bool find_script_index (hb_tag_t tag, unsigned int *index) const { return scriptList.find_index (tag, index); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.cc 2019-02-28 12:03:58.250502972 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.cc 2019-02-28 12:03:58.122502974 -0800 @@ -28,232 +28,201 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-open-type-private.hh" -#include "hb-ot-layout-private.hh" -#include "hb-ot-map-private.hh" +#include "hb-open-type.hh" +#include "hb-ot-layout.hh" +#include "hb-ot-face.hh" +#include "hb-ot-map.hh" +#include "hb-map.hh" +#include "hb-ot-kern-table.hh" +#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise. #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" - -// Just so we compile them; unused otherwise: -#include "hb-ot-layout-base-table.hh" -#include "hb-ot-layout-jstf-table.hh" -#include "hb-ot-color-colr-table.hh" -#include "hb-ot-color-cpal-table.hh" -#include "hb-ot-color-sbix-table.hh" -#include "hb-ot-color-svg-table.hh" +#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise. +#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise. #include "hb-ot-name-table.hh" -#include "hb-map-private.hh" - +#include "hb-ot-os2-table.hh" -hb_ot_layout_t * -_hb_ot_layout_create (hb_face_t *face) -{ - hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t)); - if (unlikely (!layout)) - return nullptr; - - layout->gdef_blob = OT::Sanitizer().sanitize (face->reference_table (HB_OT_TAG_GDEF)); - layout->gdef = layout->gdef_blob->as (); - - layout->gsub_blob = OT::Sanitizer().sanitize (face->reference_table (HB_OT_TAG_GSUB)); - layout->gsub = layout->gsub_blob->as (); - - layout->gpos_blob = OT::Sanitizer().sanitize (face->reference_table (HB_OT_TAG_GPOS)); - layout->gpos = layout->gpos_blob->as (); - - layout->math.init (face); - layout->fvar.init (face); - layout->avar.init (face); - - { - /* - * The ugly business of blacklisting individual fonts' tables happen here! - * See this thread for why we finally had to bend in and do this: - * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html - */ - unsigned int gdef_len = layout->gdef_blob->length; - unsigned int gsub_len = layout->gsub_blob->length; - unsigned int gpos_len = layout->gpos_blob->length; - if (0 - /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */ - || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len) - /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */ - || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len) - /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */ - || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len) - /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */ - || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len) - /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */ - || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len) - /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */ - || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len) - ) - { - /* In certain versions of Times New Roman Italic and Bold Italic, - * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong - * glyph class 3 (mark) in GDEF. Nuke the GDEF to avoid zero-width - * double-quote. See: - * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html - */ - if (3 == layout->gdef->get_glyph_class (5)) - layout->gdef = &Null(OT::GDEF); - } - else if (0 - /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */ - || (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len) - /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */ - || (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len) - /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */ - || (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len) - /* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */ - || (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len) - /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - || (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len) - /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - || (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len) - /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */ - || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len) - /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */ - || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len) - /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - || (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len) - /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - || (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len) - /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */ - || (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len) - /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */ - || (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len) - /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */ - || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len) - /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */ - || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len) - /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */ - || (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len) - /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */ - || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len) - /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */ - || (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len) - /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */ - /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */ - || (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len) - /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */ - /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */ - || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len) - /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */ - || (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len) - /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/ - || (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len) - /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */ - || (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len) - /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */ - || (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len) - /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */ - || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len) - /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */ - || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len) - /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */ - || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len) - /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */ - || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len) - /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf - * "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */ - || (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len) - ) - { - /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks - * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya, - * and the version of Cantarell shipped by Ubuntu 16.04. - * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing. - * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 - * https://bugzilla.mozilla.org/show_bug.cgi?id=1279693 - * https://bugzilla.mozilla.org/show_bug.cgi?id=1279875 - */ - layout->gdef = &Null(OT::GDEF); - } - } +#include "hb-aat-layout-lcar-table.hh" +#include "hb-aat-layout-morx-table.hh" - layout->gsub_lookup_count = layout->gsub->get_lookup_count (); - layout->gpos_lookup_count = layout->gpos->get_lookup_count (); - layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t)); - layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t)); +/** + * SECTION:hb-ot-layout + * @title: hb-ot-layout + * @short_description: OpenType Layout + * @include: hb-ot.h + * + * Functions for querying OpenType Layout features in the font face. + **/ - if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) || - (layout->gpos_lookup_count && !layout->gpos_accels))) - { - _hb_ot_layout_destroy (layout); - return nullptr; - } - for (unsigned int i = 0; i < layout->gsub_lookup_count; i++) - layout->gsub_accels[i].init (layout->gsub->get_lookup (i)); - for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) - layout->gpos_accels[i].init (layout->gpos->get_lookup (i)); +/* + * kern + */ - return layout; +bool +hb_ot_layout_has_kerning (hb_face_t *face) +{ + return face->table.kern->has_data (); } -void -_hb_ot_layout_destroy (hb_ot_layout_t *layout) +bool +hb_ot_layout_has_machine_kerning (hb_face_t *face) { - if (layout->gsub_accels) - for (unsigned int i = 0; i < layout->gsub_lookup_count; i++) - layout->gsub_accels[i].fini (); - if (layout->gpos_accels) - for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) - layout->gpos_accels[i].fini (); + return face->table.kern->has_state_machine (); +} - free (layout->gsub_accels); - free (layout->gpos_accels); +bool +hb_ot_layout_has_cross_kerning (hb_face_t *face) +{ + return face->table.kern->has_cross_stream (); +} - hb_blob_destroy (layout->gdef_blob); - hb_blob_destroy (layout->gsub_blob); - hb_blob_destroy (layout->gpos_blob); +void +hb_ot_layout_kern (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) +{ + hb_blob_t *blob = font->face->table.kern.get_blob (); + const AAT::kern& kern = *blob->as (); - layout->math.fini (); - layout->fvar.fini (); - layout->avar.fini (); + AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); - free (layout); + kern.apply (&c); } -// static inline const OT::BASE& -// _get_base (hb_face_t *face) -// { -// if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::BASE); -// hb_ot_layout_t * layout = hb_ot_layout_from_face (face); -// return *(layout->base.get ()); -// } -static inline const OT::GDEF& -_get_gdef (hb_face_t *face) -{ - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF); - return *hb_ot_layout_from_face (face)->gdef; -} -static inline const OT::GSUB& -_get_gsub (hb_face_t *face) -{ - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GSUB); - return *hb_ot_layout_from_face (face)->gsub; +/* + * GDEF + */ + +bool +OT::GDEF::is_blacklisted (hb_blob_t *blob, + hb_face_t *face) const +{ + /* The ugly business of blacklisting individual fonts' tables happen here! + * See this thread for why we finally had to bend in and do this: + * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html + * + * In certain versions of Times New Roman Italic and Bold Italic, + * ASCII double quotation mark U+0022 has wrong glyph class 3 (mark) + * in GDEF. Many versions of Tahoma have bad GDEF tables that + * incorrectly classify some spacing marks such as certain IPA + * symbols as glyph class 3. So do older versions of Microsoft + * Himalaya, and the version of Cantarell shipped by Ubuntu 16.04. + * + * Nuke the GDEF tables of to avoid unwanted width-zeroing. + * + * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 + * https://bugzilla.mozilla.org/show_bug.cgi?id=1279693 + * https://bugzilla.mozilla.org/show_bug.cgi?id=1279875 + */ +#define ENCODE(x,y,z) (((uint64_t) (x) << 48) | ((uint64_t) (y) << 24) | (uint64_t) (z)) + switch ENCODE(blob->length, + face->table.GSUB->table.get_length (), + face->table.GPOS->table.get_length ()) + { + /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */ + case ENCODE (442, 2874, 42038): + /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */ + case ENCODE (430, 2874, 40662): + /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */ + case ENCODE (442, 2874, 39116): + /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */ + case ENCODE (430, 2874, 39374): + /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */ + case ENCODE (490, 3046, 41638): + /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */ + case ENCODE (478, 3046, 41902): + /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */ + case ENCODE (898, 12554, 46470): + /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */ + case ENCODE (910, 12566, 47732): + /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */ + case ENCODE (928, 23298, 59332): + /* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */ + case ENCODE (940, 23310, 60732): + /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + case ENCODE (964, 23836, 60072): + /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + case ENCODE (976, 23832, 61456): + /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */ + case ENCODE (994, 24474, 60336): + /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */ + case ENCODE (1006, 24470, 61740): + /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + case ENCODE (1006, 24576, 61346): + /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + case ENCODE (1018, 24572, 62828): + /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */ + case ENCODE (1006, 24576, 61352): + /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */ + case ENCODE (1018, 24572, 62834): + /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */ + case ENCODE (832, 7324, 47162): + /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */ + case ENCODE (844, 7302, 45474): + /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */ + case ENCODE (180, 13054, 7254): + /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */ + case ENCODE (192, 12638, 7254): + /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */ + case ENCODE (192, 12690, 7254): + /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */ + /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */ + case ENCODE (188, 248, 3852): + /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */ + /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */ + case ENCODE (188, 264, 3426): + /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */ + case ENCODE (1058, 47032, 11818): + /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/ + case ENCODE (1046, 47030, 12600): + /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */ + case ENCODE (1058, 71796, 16770): + /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */ + case ENCODE (1046, 71790, 17862): + /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */ + case ENCODE (1046, 71788, 17112): + /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */ + case ENCODE (1058, 71794, 17514): + /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */ + case ENCODE (1330, 109904, 57938): + /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */ + case ENCODE (1330, 109904, 58972): + /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf + * "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */ + case ENCODE (1004, 59092, 14836): + return true; +#undef ENCODE + } + return false; } -static inline const OT::GPOS& -_get_gpos (hb_face_t *face) + +static void +_hb_ot_layout_set_glyph_props (hb_font_t *font, + hb_buffer_t *buffer) { - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GPOS); - return *hb_ot_layout_from_face (face)->gpos; + _hb_buffer_assert_gsubgpos_vars (buffer); + + const OT::GDEF &gdef = *font->face->table.GDEF->table; + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + { + _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint)); + _hb_glyph_info_clear_lig_props (&buffer->info[i]); + buffer->info[i].syllable() = 0; + } } -/* - * GDEF - */ +/* Public API */ hb_bool_t hb_ot_layout_has_glyph_classes (hb_face_t *face) { - return _get_gdef (face).has_glyph_classes (); + return face->table.GDEF->table->has_glyph_classes (); } /** @@ -265,7 +234,7 @@ hb_ot_layout_get_glyph_class (hb_face_t *face, hb_codepoint_t glyph) { - return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph); + return (hb_ot_layout_glyph_class_t) face->table.GDEF->table->get_glyph_class (glyph); } /** @@ -278,7 +247,7 @@ hb_ot_layout_glyph_class_t klass, hb_set_t *glyphs /* OUT */) { - return _get_gdef (face).get_glyphs_in_class (klass, glyphs); + return face->table.GDEF->table->get_glyphs_in_class (klass, glyphs); } unsigned int @@ -288,7 +257,10 @@ unsigned int *point_count /* IN/OUT */, unsigned int *point_array /* OUT */) { - return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array); + return face->table.GDEF->table->get_attach_points (glyph, + start_offset, + point_count, + point_array); } unsigned int @@ -299,7 +271,15 @@ unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) { - return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array); + unsigned int result_caret_count = 0; + unsigned int result = font->face->table.GDEF->table->get_lig_carets (font, direction, glyph, start_offset, &result_caret_count, caret_array); + if (result) + { + if (caret_count) *caret_count = result_caret_count; + } + else + result = font->face->table.lcar->get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array); + return result; } @@ -307,13 +287,45 @@ * GSUB/GPOS */ +bool +OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED, + hb_face_t *face) const +{ + /* Mac OS X prefers morx over GSUB. It also ships with various Indic fonts, + * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken + * GSUB/GPOS tables. Some have GSUB with zero scripts, those are ignored by + * our morx/GSUB preference code. But if GSUB has non-zero scripts, we tend + * to prefer it over morx because we want to be consistent with other OpenType + * shapers. + * + * To work around broken Indic Mac system fonts, we ignore GSUB table if + * OS/2 VendorId is 'MUTF' and font has morx table as well. + * + * https://github.com/harfbuzz/harfbuzz/issues/1410 + * https://github.com/harfbuzz/harfbuzz/issues/1348 + * https://github.com/harfbuzz/harfbuzz/issues/1391 + */ + if (unlikely (face->table.OS2->achVendID == HB_TAG ('M','U','T','F') && + face->table.morx->has_data ())) + return true; + + return false; +} + +bool +OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED, + hb_face_t *face HB_UNUSED) const +{ + return false; +} + static const OT::GSUBGPOS& get_gsubgpos_table (hb_face_t *face, hb_tag_t table_tag) { switch (table_tag) { - case HB_OT_TAG_GSUB: return _get_gsub (face); - case HB_OT_TAG_GPOS: return _get_gpos (face); + case HB_OT_TAG_GSUB: return *face->table.GSUB->table; + case HB_OT_TAG_GPOS: return *face->table.GPOS->table; default: return Null(OT::GSUBGPOS); } } @@ -324,7 +336,7 @@ hb_tag_t table_tag, unsigned int start_offset, unsigned int *script_count /* IN/OUT */, - hb_tag_t *script_tags /* OUT */) + hb_tag_t *script_tags /* OUT */) { const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); @@ -370,17 +382,36 @@ unsigned int *script_index, hb_tag_t *chosen_script) { + const hb_tag_t *t; + for (t = script_tags; *t; t++); + return hb_ot_layout_table_select_script (face, table_tag, t - script_tags, script_tags, script_index, chosen_script); +} + +/** + * hb_ot_layout_table_select_script: + * + * Since: 2.0.0 + **/ +hb_bool_t +hb_ot_layout_table_select_script (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_count, + const hb_tag_t *script_tags, + unsigned int *script_index /* OUT */, + hb_tag_t *chosen_script /* OUT */) +{ static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX), ""); const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + unsigned int i; - while (*script_tags) + for (i = 0; i < script_count; i++) { - if (g.find_script_index (*script_tags, script_index)) { + if (g.find_script_index (script_tags[i], script_index)) + { if (chosen_script) - *chosen_script = *script_tags; + *chosen_script = script_tags[i]; return true; } - script_tags++; } /* try finding 'DFLT' */ @@ -416,14 +447,14 @@ hb_tag_t table_tag, unsigned int start_offset, unsigned int *feature_count /* IN/OUT */, - hb_tag_t *feature_tags /* OUT */) + hb_tag_t *feature_tags /* OUT */) { const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); return g.get_feature_tags (start_offset, feature_count, feature_tags); } -hb_bool_t +bool hb_ot_layout_table_find_feature (hb_face_t *face, hb_tag_t table_tag, hb_tag_t feature_tag, @@ -452,7 +483,7 @@ unsigned int script_index, unsigned int start_offset, unsigned int *language_count /* IN/OUT */, - hb_tag_t *language_tags /* OUT */) + hb_tag_t *language_tags /* OUT */) { const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); @@ -466,13 +497,38 @@ hb_tag_t language_tag, unsigned int *language_index) { + return hb_ot_layout_script_select_language (face, + table_tag, + script_index, + 1, + &language_tag, + language_index); +} + +/** + * hb_ot_layout_script_select_language: + * + * Since: 2.0.0 + **/ +hb_bool_t +hb_ot_layout_script_select_language (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int language_count, + const hb_tag_t *language_tags, + unsigned int *language_index /* OUT */) +{ static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX), ""); const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); + unsigned int i; - if (s.find_lang_sys_index (language_tag, language_index)) - return true; + for (i = 0; i < language_count; i++) + { + if (s.find_lang_sys_index (language_tags[i], language_index)) + return true; + } - /* try with 'dflt'; MS site has had typos and many fonts use it now :( */ + /* try finding 'dflt' */ if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index)) return false; @@ -524,7 +580,7 @@ unsigned int script_index, unsigned int language_index, unsigned int start_offset, - unsigned int *feature_count /* IN/OUT */, + unsigned int *feature_count /* IN/OUT */, unsigned int *feature_indexes /* OUT */) { const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); @@ -540,7 +596,7 @@ unsigned int language_index, unsigned int start_offset, unsigned int *feature_count /* IN/OUT */, - hb_tag_t *feature_tags /* OUT */) + hb_tag_t *feature_tags /* OUT */) { const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index); @@ -594,7 +650,7 @@ hb_tag_t table_tag, unsigned int feature_index, unsigned int start_offset, - unsigned int *lookup_count /* IN/OUT */, + unsigned int *lookup_count /* IN/OUT */, unsigned int *lookup_indexes /* OUT */) { return hb_ot_layout_feature_with_variations_get_lookups (face, @@ -615,207 +671,202 @@ hb_ot_layout_table_get_lookup_count (hb_face_t *face, hb_tag_t table_tag) { - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return 0; - switch (table_tag) + return get_gsubgpos_table (face, table_tag).get_lookup_count (); +} + + +struct hb_collect_features_context_t +{ + hb_collect_features_context_t (hb_face_t *face, + hb_tag_t table_tag, + hb_set_t *feature_indexes_) + : g (get_gsubgpos_table (face, table_tag)), + feature_indexes (feature_indexes_), + script_count(0),langsys_count(0) {} + + bool visited (const OT::Script &s) { - case HB_OT_TAG_GSUB: - { - return hb_ot_layout_from_face (face)->gsub_lookup_count; - } - case HB_OT_TAG_GPOS: - { - return hb_ot_layout_from_face (face)->gpos_lookup_count; - } + /* We might have Null() object here. Don't want to involve + * that in the memoize. So, detect empty objects and return. */ + if (unlikely (!s.has_default_lang_sys () && + !s.get_lang_sys_count ())) + return true; + + if (script_count++ > HB_MAX_SCRIPTS) + return true; + + return visited (s, visited_script); } - return 0; -} + bool visited (const OT::LangSys &l) + { + /* We might have Null() object here. Don't want to involve + * that in the memoize. So, detect empty objects and return. */ + if (unlikely (!l.has_required_feature () && + !l.get_feature_count ())) + return true; -static void -_hb_ot_layout_collect_lookups_lookups (hb_face_t *face, - hb_tag_t table_tag, - unsigned int feature_index, - hb_set_t *lookup_indexes /* OUT */) -{ - unsigned int lookup_indices[32]; - unsigned int offset, len; - - offset = 0; - do { - len = ARRAY_LENGTH (lookup_indices); - hb_ot_layout_feature_get_lookups (face, - table_tag, - feature_index, - offset, &len, - lookup_indices); + if (langsys_count++ > HB_MAX_LANGSYS) + return true; - for (unsigned int i = 0; i < len; i++) - lookup_indexes->add (lookup_indices[i]); + return visited (l, visited_langsys); + } - offset += len; - } while (len == ARRAY_LENGTH (lookup_indices)); -} + private: + template + bool visited (const T &p, hb_set_t &visited_set) + { + hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) &p - (uintptr_t) &g); + if (visited_set.has (delta)) + return true; + + visited_set.add (delta); + return false; + } + + public: + const OT::GSUBGPOS &g; + hb_set_t *feature_indexes; + + private: + hb_set_t visited_script; + hb_set_t visited_langsys; + unsigned int script_count; + unsigned int langsys_count; +}; static void -_hb_ot_layout_collect_lookups_features (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index, - unsigned int language_index, - const hb_tag_t *features, - hb_set_t *lookup_indexes /* OUT */) +langsys_collect_features (hb_collect_features_context_t *c, + const OT::LangSys &l, + const hb_tag_t *features) { + if (c->visited (l)) return; + if (!features) { - unsigned int required_feature_index; - if (hb_ot_layout_language_get_required_feature (face, - table_tag, - script_index, - language_index, - &required_feature_index, - nullptr)) - _hb_ot_layout_collect_lookups_lookups (face, - table_tag, - required_feature_index, - lookup_indexes); - - /* All features */ - unsigned int feature_indices[32]; - unsigned int offset, len; - - offset = 0; - do { - len = ARRAY_LENGTH (feature_indices); - hb_ot_layout_language_get_feature_indexes (face, - table_tag, - script_index, - language_index, - offset, &len, - feature_indices); - - for (unsigned int i = 0; i < len; i++) - _hb_ot_layout_collect_lookups_lookups (face, - table_tag, - feature_indices[i], - lookup_indexes); + /* All features. */ + if (l.has_required_feature ()) + c->feature_indexes->add (l.get_required_feature_index ()); - offset += len; - } while (len == ARRAY_LENGTH (feature_indices)); + l.add_feature_indexes_to (c->feature_indexes); } else { + /* Ugh. Any faster way? */ for (; *features; features++) { - unsigned int feature_index; - if (hb_ot_layout_language_find_feature (face, - table_tag, - script_index, - language_index, - *features, - &feature_index)) - _hb_ot_layout_collect_lookups_lookups (face, - table_tag, - feature_index, - lookup_indexes); + hb_tag_t feature_tag = *features; + unsigned int num_features = l.get_feature_count (); + for (unsigned int i = 0; i < num_features; i++) + { + unsigned int feature_index = l.get_feature_index (i); + + if (feature_tag == c->g.get_feature_tag (feature_index)) + { + c->feature_indexes->add (feature_index); + break; + } + } } } } static void -_hb_ot_layout_collect_lookups_languages (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index, - const hb_tag_t *languages, - const hb_tag_t *features, - hb_set_t *lookup_indexes /* OUT */) -{ - _hb_ot_layout_collect_lookups_features (face, - table_tag, - script_index, - HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, - features, - lookup_indexes); +script_collect_features (hb_collect_features_context_t *c, + const OT::Script &s, + const hb_tag_t *languages, + const hb_tag_t *features) +{ + if (c->visited (s)) return; if (!languages) { - /* All languages */ - unsigned int count = hb_ot_layout_script_get_language_tags (face, - table_tag, - script_index, - 0, nullptr, nullptr); + /* All languages. */ + if (s.has_default_lang_sys ()) + langsys_collect_features (c, + s.get_default_lang_sys (), + features); + + unsigned int count = s.get_lang_sys_count (); for (unsigned int language_index = 0; language_index < count; language_index++) - _hb_ot_layout_collect_lookups_features (face, - table_tag, - script_index, - language_index, - features, - lookup_indexes); + langsys_collect_features (c, + s.get_lang_sys (language_index), + features); } else { for (; *languages; languages++) { unsigned int language_index; - if (hb_ot_layout_script_find_language (face, - table_tag, - script_index, - *languages, - &language_index)) - _hb_ot_layout_collect_lookups_features (face, - table_tag, - script_index, - language_index, - features, - lookup_indexes); + if (s.find_lang_sys_index (*languages, &language_index)) + langsys_collect_features (c, + s.get_lang_sys (language_index), + features); } } } /** - * hb_ot_layout_collect_lookups: + * hb_ot_layout_collect_features: * - * Since: 0.9.8 + * Since: 1.8.5 **/ void -hb_ot_layout_collect_lookups (hb_face_t *face, - hb_tag_t table_tag, - const hb_tag_t *scripts, - const hb_tag_t *languages, - const hb_tag_t *features, - hb_set_t *lookup_indexes /* OUT */) +hb_ot_layout_collect_features (hb_face_t *face, + hb_tag_t table_tag, + const hb_tag_t *scripts, + const hb_tag_t *languages, + const hb_tag_t *features, + hb_set_t *feature_indexes /* OUT */) { + hb_collect_features_context_t c (face, table_tag, feature_indexes); if (!scripts) { - /* All scripts */ - unsigned int count = hb_ot_layout_table_get_script_tags (face, - table_tag, - 0, nullptr, nullptr); + /* All scripts. */ + unsigned int count = c.g.get_script_count (); for (unsigned int script_index = 0; script_index < count; script_index++) - _hb_ot_layout_collect_lookups_languages (face, - table_tag, - script_index, - languages, - features, - lookup_indexes); + script_collect_features (&c, + c.g.get_script (script_index), + languages, + features); } else { for (; *scripts; scripts++) { unsigned int script_index; - if (hb_ot_layout_table_find_script (face, - table_tag, - *scripts, - &script_index)) - _hb_ot_layout_collect_lookups_languages (face, - table_tag, - script_index, - languages, - features, - lookup_indexes); + if (c.g.find_script_index (*scripts, &script_index)) + script_collect_features (&c, + c.g.get_script (script_index), + languages, + features); } } } /** + * hb_ot_layout_collect_lookups: + * + * Since: 0.9.8 + **/ +void +hb_ot_layout_collect_lookups (hb_face_t *face, + hb_tag_t table_tag, + const hb_tag_t *scripts, + const hb_tag_t *languages, + const hb_tag_t *features, + hb_set_t *lookup_indexes /* OUT */) +{ + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + hb_set_t feature_indexes; + hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes); + + for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID; + hb_set_next (&feature_indexes, &feature_index);) + g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes); +} + +/** * hb_ot_layout_lookup_collect_glyphs: * * Since: 0.9.7 @@ -824,13 +875,11 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, hb_tag_t table_tag, unsigned int lookup_index, - hb_set_t *glyphs_before, /* OUT. May be nullptr */ - hb_set_t *glyphs_input, /* OUT. May be nullptr */ - hb_set_t *glyphs_after, /* OUT. May be nullptr */ - hb_set_t *glyphs_output /* OUT. May be nullptr */) + hb_set_t *glyphs_before, /* OUT. May be NULL */ + hb_set_t *glyphs_input, /* OUT. May be NULL */ + hb_set_t *glyphs_after, /* OUT. May be NULL */ + hb_set_t *glyphs_output /* OUT. May be NULL */) { - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return; - OT::hb_collect_glyphs_context_t c (face, glyphs_before, glyphs_input, @@ -841,13 +890,13 @@ { case HB_OT_TAG_GSUB: { - const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); + const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index); l.collect_glyphs (&c); return; } case HB_OT_TAG_GPOS: { - const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index); + const OT::PosLookup& l = face->table.GPOS->table->get_lookup (lookup_index); l.collect_glyphs (&c); return; } @@ -894,7 +943,7 @@ hb_bool_t hb_ot_layout_has_substitution (hb_face_t *face) { - return &_get_gsub (face) != &Null(OT::GSUB); + return face->table.GSUB->table->has_data (); } /** @@ -909,29 +958,82 @@ unsigned int glyphs_length, hb_bool_t zero_context) { - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false; - return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context); + return hb_ot_layout_lookup_would_substitute_fast (face, + lookup_index, + glyphs, glyphs_length, + zero_context); } -hb_bool_t +bool hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face, unsigned int lookup_index, const hb_codepoint_t *glyphs, unsigned int glyphs_length, - hb_bool_t zero_context) + bool zero_context) { - if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false; + if (unlikely (lookup_index >= face->table.GSUB->lookup_count)) return false; OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context); - const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); + const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index); - return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]); + return l.would_apply (&c, &face->table.GSUB->accels[lookup_index]); +} + +void +hb_ot_layout_substitute_start (hb_font_t *font, + hb_buffer_t *buffer) +{ +_hb_ot_layout_set_glyph_props (font, buffer); } void -hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer) +hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer, + bool (*filter) (const hb_glyph_info_t *info)) { - OT::GSUB::substitute_start (font, buffer); + /* Merge clusters and delete filtered glyphs. + * NOTE! We can't use out-buffer as we have positioning data. */ + unsigned int j = 0; + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + hb_glyph_position_t *pos = buffer->pos; + for (unsigned int i = 0; i < count; i++) + { + if (filter (&info[i])) + { + /* Merge clusters. + * Same logic as buffer->delete_glyph(), but for in-place removal. */ + + unsigned int cluster = info[i].cluster; + if (i + 1 < count && cluster == info[i + 1].cluster) + continue; /* Cluster survives; do nothing. */ + + if (j) + { + /* Merge cluster backward. */ + if (cluster < info[j - 1].cluster) + { + unsigned int mask = info[i].mask; + unsigned int old_cluster = info[j - 1].cluster; + for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) + buffer->set_cluster (info[k - 1], cluster, mask); + } + continue; + } + + if (i + 1 < count) + buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */ + + continue; + } + + if (j != i) + { + info[j] = info[i]; + pos[j] = pos[i]; + } + j++; + } + buffer->len = j; } /** @@ -944,10 +1046,10 @@ unsigned int lookup_index, hb_set_t *glyphs) { - hb_auto_t done_lookups; + hb_map_t done_lookups; OT::hb_closure_context_t c (face, glyphs, &done_lookups); - const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index); + const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index); l.closure (&c, lookup_index); } @@ -965,10 +1067,11 @@ const hb_set_t *lookups, hb_set_t *glyphs) { - hb_auto_t done_lookups; + hb_map_t done_lookups; OT::hb_closure_context_t c (face, glyphs, &done_lookups); - const OT::GSUB& gsub = _get_gsub (face); + const OT::GSUB& gsub = *face->table.GSUB->table; + unsigned int iteration_count = 0; unsigned int glyphs_length; do { @@ -983,7 +1086,8 @@ for (unsigned int i = 0; i < gsub.get_lookup_count (); i++) gsub.get_lookup (i).closure (&c, i); } - } while (glyphs_length != glyphs->get_population ()); + } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES && + glyphs_length != glyphs->get_population ()); } /* @@ -993,7 +1097,7 @@ hb_bool_t hb_ot_layout_has_positioning (hb_face_t *face) { - return &_get_gpos (face) != &Null(OT::GPOS); + return face->table.GPOS->table->has_data (); } void @@ -1020,14 +1124,14 @@ * Since: 0.9.10 **/ hb_bool_t -hb_ot_layout_get_size_params (hb_face_t *face, - unsigned int *design_size, /* OUT. May be nullptr */ - unsigned int *subfamily_id, /* OUT. May be nullptr */ - unsigned int *subfamily_name_id, /* OUT. May be nullptr */ - unsigned int *range_start, /* OUT. May be nullptr */ - unsigned int *range_end /* OUT. May be nullptr */) +hb_ot_layout_get_size_params (hb_face_t *face, + unsigned int *design_size, /* OUT. May be NULL */ + unsigned int *subfamily_id, /* OUT. May be NULL */ + hb_ot_name_id_t *subfamily_name_id, /* OUT. May be NULL */ + unsigned int *range_start, /* OUT. May be NULL */ + unsigned int *range_end /* OUT. May be NULL */) { - const OT::GPOS &gpos = _get_gpos (face); + const OT::GPOS &gpos = *face->table.GPOS->table; const hb_tag_t tag = HB_TAG ('s','i','z','e'); unsigned int num_features = gpos.get_feature_count (); @@ -1040,30 +1144,152 @@ if (params.designSize) { -#define PARAM(a, A) if (a) *a = params.A - PARAM (design_size, designSize); - PARAM (subfamily_id, subfamilyID); - PARAM (subfamily_name_id, subfamilyNameID); - PARAM (range_start, rangeStart); - PARAM (range_end, rangeEnd); -#undef PARAM + if (design_size) *design_size = params.designSize; + if (subfamily_id) *subfamily_id = params.subfamilyID; + if (subfamily_name_id) *subfamily_name_id = params.subfamilyNameID; + if (range_start) *range_start = params.rangeStart; + if (range_end) *range_end = params.rangeEnd; return true; } } } -#define PARAM(a, A) if (a) *a = 0 - PARAM (design_size, designSize); - PARAM (subfamily_id, subfamilyID); - PARAM (subfamily_name_id, subfamilyNameID); - PARAM (range_start, rangeStart); - PARAM (range_end, rangeEnd); -#undef PARAM + if (design_size) *design_size = 0; + if (subfamily_id) *subfamily_id = 0; + if (subfamily_name_id) *subfamily_name_id = HB_OT_NAME_ID_INVALID; + if (range_start) *range_start = 0; + if (range_end) *range_end = 0; return false; } +/** + * hb_ot_layout_feature_get_name_ids: + * @face: #hb_face_t to work upon + * @table_tag: table tag to query, "GSUB" or "GPOS". + * @feature_index: index of feature to query. + * @label_id: (out) (allow-none): The ‘name’ table name ID that specifies a string + * for a user-interface label for this feature. (May be NULL.) + * @tooltip_id: (out) (allow-none): The ‘name’ table name ID that specifies a string + * that an application can use for tooltip text for this + * feature. (May be NULL.) + * @sample_id: (out) (allow-none): The ‘name’ table name ID that specifies sample text + * that illustrates the effect of this feature. (May be NULL.) + * @num_named_parameters: (out) (allow-none): Number of named parameters. (May be zero.) + * @first_param_id: (out) (allow-none): The first ‘name’ table name ID used to specify + * strings for user-interface labels for the feature + * parameters. (Must be zero if numParameters is zero.) + * + * Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or + * "Character Variant" ('cvXX') features. + * + * Return value: true if data found, false otherwise + * + * Since: 2.0.0 + **/ +hb_bool_t +hb_ot_layout_feature_get_name_ids (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + hb_ot_name_id_t *label_id, /* OUT. May be NULL */ + hb_ot_name_id_t *tooltip_id, /* OUT. May be NULL */ + hb_ot_name_id_t *sample_id, /* OUT. May be NULL */ + unsigned int *num_named_parameters, /* OUT. May be NULL */ + hb_ot_name_id_t *first_param_id /* OUT. May be NULL */) +{ + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + hb_tag_t feature_tag = g.get_feature_tag (feature_index); + const OT::Feature &f = g.get_feature (feature_index); + + const OT::FeatureParams &feature_params = f.get_feature_params (); + if (&feature_params != &Null (OT::FeatureParams)) + { + const OT::FeatureParamsStylisticSet& ss_params = + feature_params.get_stylistic_set_params (feature_tag); + if (&ss_params != &Null (OT::FeatureParamsStylisticSet)) /* ssXX */ + { + if (label_id) *label_id = ss_params.uiNameID; + // ssXX features don't have the rest + if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID; + if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID; + if (num_named_parameters) *num_named_parameters = 0; + if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID; + return true; + } + const OT::FeatureParamsCharacterVariants& cv_params = + feature_params.get_character_variants_params (feature_tag); + if (&cv_params != &Null (OT::FeatureParamsCharacterVariants)) /* cvXX */ + { + if (label_id) *label_id = cv_params.featUILableNameID; + if (tooltip_id) *tooltip_id = cv_params.featUITooltipTextNameID; + if (sample_id) *sample_id = cv_params.sampleTextNameID; + if (num_named_parameters) *num_named_parameters = cv_params.numNamedParameters; + if (first_param_id) *first_param_id = cv_params.firstParamUILabelNameID; + return true; + } + } + + if (label_id) *label_id = HB_OT_NAME_ID_INVALID; + if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID; + if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID; + if (num_named_parameters) *num_named_parameters = 0; + if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID; + return false; +} + +/** + * hb_ot_layout_feature_get_characters: + * @face: #hb_face_t to work upon + * @table_tag: table tag to query, "GSUB" or "GPOS". + * @feature_index: index of feature to query. + * @start_offset: In case the resulting char_count was equal to its input value, there + * is a chance there were more characters on the tag so this API can be + * called with an offset till resulting char_count gets to a number + * lower than input buffer (or consider using just a bigger buffer for + * one shot copying). + * @char_count: (inout) (allow-none): The count of characters for which this feature + * provides glyph variants. (May be zero.) + * @characters: (out caller-allocates) (array length=char_count): A buffer pointer. The Unicode codepoints + * of the characters for which this feature provides glyph variants. + * + * Fetches characters listed by designer under feature parameters for "Character + * Variant" ("cvXX") features. + * + * Return value: Number of total sample characters in the cvXX feature. + * + * Since: 2.0.0 + **/ +unsigned int +hb_ot_layout_feature_get_characters (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + unsigned int start_offset, + unsigned int *char_count, /* IN/OUT. May be NULL */ + hb_codepoint_t *characters /* OUT. May be NULL */) +{ + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + hb_tag_t feature_tag = g.get_feature_tag (feature_index); + const OT::Feature &f = g.get_feature (feature_index); + + const OT::FeatureParams &feature_params = f.get_feature_params (); + + const OT::FeatureParamsCharacterVariants& cv_params = + feature_params.get_character_variants_params(feature_tag); + + unsigned int len = 0; + if (char_count && characters && start_offset < cv_params.characters.len) + { + len = MIN (cv_params.characters.len - start_offset, *char_count); + for (unsigned int i = 0; i < len; ++i) + characters[i] = cv_params.characters[start_offset + i]; + } + if (char_count) *char_count = len; + return cv_params.characters.len; +} + /* * Parts of different types are implemented here such that they have direct @@ -1073,86 +1299,36 @@ struct GSUBProxy { - static const unsigned int table_index = 0; - static const bool inplace = false; + static constexpr unsigned table_index = 0u; + static constexpr bool inplace = false; typedef OT::SubstLookup Lookup; GSUBProxy (hb_face_t *face) : - table (*hb_ot_layout_from_face (face)->gsub), - accels (hb_ot_layout_from_face (face)->gsub_accels) {} + table (*face->table.GSUB->table), + accels (face->table.GSUB->accels) {} const OT::GSUB &table; - const hb_ot_layout_lookup_accelerator_t *accels; + const OT::hb_ot_layout_lookup_accelerator_t *accels; }; struct GPOSProxy { - static const unsigned int table_index = 1; - static const bool inplace = true; + static constexpr unsigned table_index = 1u; + static constexpr bool inplace = true; typedef OT::PosLookup Lookup; GPOSProxy (hb_face_t *face) : - table (*hb_ot_layout_from_face (face)->gpos), - accels (hb_ot_layout_from_face (face)->gpos_accels) {} + table (*face->table.GPOS->table), + accels (face->table.GPOS->accels) {} const OT::GPOS &table; - const hb_ot_layout_lookup_accelerator_t *accels; + const OT::hb_ot_layout_lookup_accelerator_t *accels; }; -struct hb_get_subtables_context_t : - OT::hb_dispatch_context_t -{ - template - static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c) - { - const Type *typed_obj = (const Type *) obj; - return typed_obj->apply (c); - } - - typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c); - - struct hb_applicable_t - { - inline void init (const void *obj_, hb_apply_func_t apply_func_) - { - obj = obj_; - apply_func = apply_func_; - } - - inline bool apply (OT::hb_ot_apply_context_t *c) const { return apply_func (obj, c); } - - private: - const void *obj; - hb_apply_func_t apply_func; - }; - - typedef hb_auto_t > array_t; - - /* Dispatch interface. */ - inline const char *get_name (void) { return "GET_SUBTABLES"; } - template - inline return_t dispatch (const T &obj) - { - hb_applicable_t *entry = array.push(); - entry->init (&obj, apply_to); - return HB_VOID; - } - static return_t default_return_value (void) { return HB_VOID; } - bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; } - - hb_get_subtables_context_t (array_t &array_) : - array (array_), - debug_depth (0) {} - - array_t &array; - unsigned int debug_depth; -}; - static inline bool apply_forward (OT::hb_ot_apply_context_t *c, - const hb_ot_layout_lookup_accelerator_t &accel, - const hb_get_subtables_context_t::array_t &subtables) + const OT::hb_ot_layout_lookup_accelerator_t &accel) { bool ret = false; hb_buffer_t *buffer = c->buffer; @@ -1163,12 +1339,7 @@ (buffer->cur().mask & c->lookup_mask) && c->check_glyph_property (&buffer->cur(), c->lookup_props)) { - for (unsigned int i = 0; i < subtables.len; i++) - if (subtables[i].apply (c)) - { - applied = true; - break; - } + applied = accel.apply (c); } if (applied) @@ -1181,8 +1352,7 @@ static inline bool apply_backward (OT::hb_ot_apply_context_t *c, - const hb_ot_layout_lookup_accelerator_t &accel, - const hb_get_subtables_context_t::array_t &subtables) + const OT::hb_ot_layout_lookup_accelerator_t &accel) { bool ret = false; hb_buffer_t *buffer = c->buffer; @@ -1191,14 +1361,8 @@ if (accel.may_have (buffer->cur().codepoint) && (buffer->cur().mask & c->lookup_mask) && c->check_glyph_property (&buffer->cur(), c->lookup_props)) - { - for (unsigned int i = 0; i < subtables.len; i++) - if (subtables[i].apply (c)) - { - ret = true; - break; - } - } + ret |= accel.apply (c); + /* The reverse lookup doesn't "advance" cursor (for good reason). */ buffer->idx--; @@ -1211,7 +1375,7 @@ static inline void apply_string (OT::hb_ot_apply_context_t *c, const typename Proxy::Lookup &lookup, - const hb_ot_layout_lookup_accelerator_t &accel) + const OT::hb_ot_layout_lookup_accelerator_t &accel) { hb_buffer_t *buffer = c->buffer; @@ -1220,19 +1384,15 @@ c->set_lookup_props (lookup.get_props ()); - hb_get_subtables_context_t::array_t subtables; - hb_get_subtables_context_t c_get_subtables (subtables); - lookup.dispatch (&c_get_subtables); - if (likely (!lookup.is_reverse ())) { /* in/out forward substitution/positioning */ - if (Proxy::table_index == 0) + if (Proxy::table_index == 0u) buffer->clear_output (); buffer->idx = 0; bool ret; - ret = apply_forward (c, accel, subtables); + ret = apply_forward (c, accel); if (ret) { if (!Proxy::inplace) @@ -1244,11 +1404,11 @@ else { /* in-place backward substitution/positioning */ - if (Proxy::table_index == 0) + if (Proxy::table_index == 0u) buffer->remove_output (); buffer->idx = buffer->len - 1; - apply_backward (c, accel, subtables); + apply_backward (c, accel); } } @@ -1263,7 +1423,7 @@ OT::hb_ot_apply_context_t c (table_index, font, buffer); c.set_recurse_func (Proxy::Lookup::apply_recurse_func); - for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) { + for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) { const stage_map_t *stage = &stages[table_index][stage_index]; for (; i < stage->last_lookup; i++) { @@ -1273,6 +1433,11 @@ c.set_lookup_mask (lookups[table_index][i].mask); c.set_auto_zwj (lookups[table_index][i].auto_zwj); c.set_auto_zwnj (lookups[table_index][i].auto_zwnj); + if (lookups[table_index][i].random) + { + c.set_random (true); + buffer->unsafe_to_break_all (); + } apply_string (&c, proxy.table.get_lookup (lookup_index), proxy.accels[lookup_index]); @@ -1302,31 +1467,65 @@ void hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c, const OT::SubstLookup &lookup, - const hb_ot_layout_lookup_accelerator_t &accel) + const OT::hb_ot_layout_lookup_accelerator_t &accel) { apply_string (c, lookup, accel); } +#if 0 +static const OT::BASE& _get_base (hb_face_t *face) +{ + return *face->table.BASE; +} + +hb_bool_t +hb_ot_layout_get_baseline (hb_font_t *font, + hb_ot_layout_baseline_t baseline, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_position_t *coord /* OUT. May be NULL. */) +{ + const OT::BASE &base = _get_base (font->face); + bool result = base.get_baseline (font, baseline, direction, script_tag, + language_tag, coord); + + /* TODO: Simulate https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags#ideographic-em-box */ + if (!result && coord) *coord = 0; + if (coord) *coord = font->em_scale_dir (*coord, direction); + return result; +} +/* To be moved to public header */ /* - * OT::BASE + * BASE + */ + +/** + * hb_ot_layout_baseline_t: + * + * https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags + * + * Since: DONTREPLACEME */ +typedef enum { + HB_OT_LAYOUT_BASELINE_HANG = HB_TAG('h','a','n','g'), + HB_OT_LAYOUT_BASELINE_ICFB = HB_TAG('i','c','f','b'), + HB_OT_LAYOUT_BASELINE_ICFT = HB_TAG('i','c','f','t'), + HB_OT_LAYOUT_BASELINE_IDEO = HB_TAG('i','d','e','o'), + HB_OT_LAYOUT_BASELINE_IDTB = HB_TAG('i','d','t','b'), + HB_OT_LAYOUT_BASELINE_MATH = HB_TAG('m','a','t','h'), + HB_OT_LAYOUT_BASELINE_ROMN = HB_TAG('r','o','m','n') +} hb_ot_layout_baseline_t; + +HB_EXTERN hb_bool_t +hb_ot_layout_get_baseline (hb_font_t *font, + hb_ot_layout_baseline_t baseline, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_position_t *coord /* OUT. May be NULL. */); -// /** -// * hb_ot_base_has_data: -// * @face: #hb_face_t to test -// * -// * This function allows to verify the presence of an OpenType BASE table on the -// * face. -// * -// * Return value: true if face has a BASE table, false otherwise -// * -// * Since: XXX -// **/ -// hb_bool_t -// hb_ot_base_has_data (hb_face_t *face) -// { -// return &_get_base (face) != &Null(OT::BASE); -// } +#endif --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.h 2019-02-28 12:03:58.638502966 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.h 2019-02-28 12:03:58.522502967 -0800 @@ -33,7 +33,7 @@ #include "hb.h" -#include "hb-ot-tag.h" +#include "hb-ot-name.h" HB_BEGIN_DECLS @@ -46,6 +46,47 @@ /* + * Script & Language tags. + */ + +#define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T') +#define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't') + +/** + * HB_OT_MAX_TAGS_PER_SCRIPT: + * + * Since: 2.0.0 + **/ +#define HB_OT_MAX_TAGS_PER_SCRIPT 3u +/** + * HB_OT_MAX_TAGS_PER_LANGUAGE: + * + * Since: 2.0.0 + **/ +#define HB_OT_MAX_TAGS_PER_LANGUAGE 3u + +HB_EXTERN void +hb_ot_tags_from_script_and_language (hb_script_t script, + hb_language_t language, + unsigned int *script_count /* IN/OUT */, + hb_tag_t *script_tags /* OUT */, + unsigned int *language_count /* IN/OUT */, + hb_tag_t *language_tags /* OUT */); + +HB_EXTERN hb_script_t +hb_ot_tag_to_script (hb_tag_t tag); + +HB_EXTERN hb_language_t +hb_ot_tag_to_language (hb_tag_t tag); + +HB_EXTERN void +hb_ot_tags_to_script_and_language (hb_tag_t script_tag, + hb_tag_t language_tag, + hb_script_t *script /* OUT */, + hb_language_t *language /* OUT */); + + +/* * GDEF */ @@ -111,13 +152,13 @@ hb_tag_t script_tag, unsigned int *script_index); -/* Like find_script, but takes zero-terminated array of scripts to test */ HB_EXTERN hb_bool_t -hb_ot_layout_table_choose_script (hb_face_t *face, +hb_ot_layout_table_select_script (hb_face_t *face, hb_tag_t table_tag, + unsigned int script_count, const hb_tag_t *script_tags, - unsigned int *script_index, - hb_tag_t *chosen_script); + unsigned int *script_index /* OUT */, + hb_tag_t *chosen_script /* OUT */); HB_EXTERN unsigned int hb_ot_layout_table_get_feature_tags (hb_face_t *face, @@ -135,11 +176,12 @@ hb_tag_t *language_tags /* OUT */); HB_EXTERN hb_bool_t -hb_ot_layout_script_find_language (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index, - hb_tag_t language_tag, - unsigned int *language_index); +hb_ot_layout_script_select_language (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int language_count, + const hb_tag_t *language_tags, + unsigned int *language_index /* OUT */); HB_EXTERN hb_bool_t hb_ot_layout_language_get_required_feature_index (hb_face_t *face, @@ -194,6 +236,13 @@ hb_ot_layout_table_get_lookup_count (hb_face_t *face, hb_tag_t table_tag); +HB_EXTERN void +hb_ot_layout_collect_features (hb_face_t *face, + hb_tag_t table_tag, + const hb_tag_t *scripts, + const hb_tag_t *languages, + const hb_tag_t *features, + hb_set_t *feature_indexes /* OUT */); HB_EXTERN void hb_ot_layout_collect_lookups (hb_face_t *face, @@ -207,10 +256,10 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, hb_tag_t table_tag, unsigned int lookup_index, - hb_set_t *glyphs_before, /* OUT. May be NULL */ - hb_set_t *glyphs_input, /* OUT. May be NULL */ - hb_set_t *glyphs_after, /* OUT. May be NULL */ - hb_set_t *glyphs_output /* OUT. May be NULL */); + hb_set_t *glyphs_before, /* OUT. May be NULL */ + hb_set_t *glyphs_input, /* OUT. May be NULL */ + hb_set_t *glyphs_after, /* OUT. May be NULL */ + hb_set_t *glyphs_output /* OUT. May be NULL */); #ifdef HB_NOT_IMPLEMENTED typedef struct @@ -315,29 +364,32 @@ /* Optical 'size' feature info. Returns true if found. * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */ HB_EXTERN hb_bool_t -hb_ot_layout_get_size_params (hb_face_t *face, - unsigned int *design_size, /* OUT. May be NULL */ - unsigned int *subfamily_id, /* OUT. May be NULL */ - unsigned int *subfamily_name_id, /* OUT. May be NULL */ - unsigned int *range_start, /* OUT. May be NULL */ - unsigned int *range_end /* OUT. May be NULL */); +hb_ot_layout_get_size_params (hb_face_t *face, + unsigned int *design_size, /* OUT. May be NULL */ + unsigned int *subfamily_id, /* OUT. May be NULL */ + hb_ot_name_id_t *subfamily_name_id, /* OUT. May be NULL */ + unsigned int *range_start, /* OUT. May be NULL */ + unsigned int *range_end /* OUT. May be NULL */); -/* - * BASE - */ -#if 0 - -#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g') -#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b') -#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t') -#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o') -#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b') -#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h') -#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n') +HB_EXTERN hb_bool_t +hb_ot_layout_feature_get_name_ids (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + hb_ot_name_id_t *label_id /* OUT. May be NULL */, + hb_ot_name_id_t *tooltip_id /* OUT. May be NULL */, + hb_ot_name_id_t *sample_id /* OUT. May be NULL */, + unsigned int *num_named_parameters /* OUT. May be NULL */, + hb_ot_name_id_t *first_param_id /* OUT. May be NULL */); -#endif +HB_EXTERN unsigned int +hb_ot_layout_feature_get_characters (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + unsigned int start_offset, + unsigned int *char_count /* IN/OUT. May be NULL */, + hb_codepoint_t *characters /* OUT. May be NULL */); HB_END_DECLS --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map.cc 2019-02-28 12:03:58.994502960 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map.cc 2019-02-28 12:03:58.870502962 -0800 @@ -26,14 +26,14 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-ot-map-private.hh" - -#include "hb-ot-layout-private.hh" +#include "hb-ot-map.hh" +#include "hb-ot-shape.hh" +#include "hb-ot-layout.hh" void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const { - for (unsigned int i = 0; i < lookups[table_index].len; i++) + for (unsigned int i = 0; i < lookups[table_index].length; i++) hb_set_add (lookups_out, lookups[table_index][i].index); } @@ -54,33 +54,35 @@ /* Fetch script/language indices for GSUB/GPOS. We need these later to skip * features not available in either table and not waste precious bits for them. */ - hb_tag_t script_tags[3] = {HB_TAG_NONE, HB_TAG_NONE, HB_TAG_NONE}; - hb_tag_t language_tag; + unsigned int script_count = HB_OT_MAX_TAGS_PER_SCRIPT; + unsigned int language_count = HB_OT_MAX_TAGS_PER_LANGUAGE; + hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT]; + hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE]; - hb_ot_tags_from_script (props.script, &script_tags[0], &script_tags[1]); - language_tag = hb_ot_tag_from_language (props.language); + hb_ot_tags_from_script_and_language (props.script, props.language, &script_count, script_tags, &language_count, language_tags); for (unsigned int table_index = 0; table_index < 2; table_index++) { hb_tag_t table_tag = table_tags[table_index]; - found_script[table_index] = (bool) hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]); - hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]); + found_script[table_index] = (bool) hb_ot_layout_table_select_script (face, table_tag, script_count, script_tags, &script_index[table_index], &chosen_script[table_index]); + hb_ot_layout_script_select_language (face, table_tag, script_index[table_index], language_count, language_tags, &language_index[table_index]); } } -hb_ot_map_builder_t::~hb_ot_map_builder_t (void) +hb_ot_map_builder_t::~hb_ot_map_builder_t () { feature_infos.fini (); for (unsigned int table_index = 0; table_index < 2; table_index++) stages[table_index].fini (); } -void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, - hb_ot_map_feature_flags_t flags) +void hb_ot_map_builder_t::add_feature (hb_tag_t tag, + hb_ot_map_feature_flags_t flags, + unsigned int value) { - feature_info_t *info = feature_infos.push(); if (unlikely (!tag)) return; + feature_info_t *info = feature_infos.push(); info->tag = tag; - info->seq = feature_infos.len; + info->seq = feature_infos.length; info->max_value = value; info->flags = flags; info->default_value = (flags & F_GLOBAL) ? value : 0; @@ -95,7 +97,8 @@ unsigned int variations_index, hb_mask_t mask, bool auto_zwnj, - bool auto_zwj) + bool auto_zwj, + bool random) { unsigned int lookup_indices[32]; unsigned int offset, len; @@ -122,6 +125,7 @@ lookup->index = lookup_indices[i]; lookup->auto_zwnj = auto_zwnj; lookup->auto_zwj = auto_zwj; + lookup->random = random; } offset += len; @@ -139,13 +143,12 @@ } void -hb_ot_map_builder_t::compile (hb_ot_map_t &m, - const int *coords, - unsigned int num_coords) +hb_ot_map_builder_t::compile (hb_ot_map_t &m, + const hb_ot_shape_plan_key_t &key) { static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), ""); unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1; - unsigned int global_bit_shift = _hb_popcount (HB_GLYPH_FLAG_DEFINED); + unsigned int global_bit_shift = hb_popcount (HB_GLYPH_FLAG_DEFINED); m.global_mask = global_bit_mask; @@ -171,10 +174,11 @@ } /* Sort features and merge duplicates */ + if (feature_infos.length) { feature_infos.qsort (); unsigned int j = 0; - for (unsigned int i = 1; i < feature_infos.len; i++) + for (unsigned int i = 1; i < feature_infos.length; i++) if (feature_infos[i].tag != feature_infos[j].tag) feature_infos[++j] = feature_infos[i]; else { @@ -198,7 +202,7 @@ /* Allocate bits now */ unsigned int next_bit = global_bit_shift + 1; - for (unsigned int i = 0; i < feature_infos.len; i++) + for (unsigned int i = 0; i < feature_infos.length; i++) { const feature_info_t *info = &feature_infos[i]; @@ -208,8 +212,8 @@ /* Uses the global bit */ bits_needed = 0; else - /* Limit to 8 bits per feature. */ - bits_needed = MIN(8u, _hb_bit_storage (info->max_value)); + /* Limit bits per feature. */ + bits_needed = MIN(HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value)); if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t)) continue; /* Feature disabled, or not enough bits. */ @@ -252,6 +256,7 @@ map->stage[1] = info->stage[1]; map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ); map->auto_zwj = !(info->flags & F_MANUAL_ZWJ); + map->random = !!(info->flags & F_RANDOM); if ((info->flags & F_GLOBAL) && info->max_value == 1) { /* Uses the global bit */ map->shift = global_bit_shift; @@ -276,13 +281,6 @@ { /* Collect lookup indices for features */ - unsigned int variations_index; - hb_ot_layout_table_find_feature_variations (face, - table_tags[table_index], - coords, - num_coords, - &variations_index); - unsigned int stage_index = 0; unsigned int last_num_lookups = 0; for (unsigned stage = 0; stage < current_stage[table_index]; stage++) @@ -291,25 +289,26 @@ required_feature_stage[table_index] == stage) add_lookups (m, table_index, required_feature_index[table_index], - variations_index, + key.variations_index[table_index], global_bit_mask); - for (unsigned i = 0; i < m.features.len; i++) + for (unsigned i = 0; i < m.features.length; i++) if (m.features[i].stage[table_index] == stage) add_lookups (m, table_index, m.features[i].index[table_index], - variations_index, + key.variations_index[table_index], m.features[i].mask, m.features[i].auto_zwnj, - m.features[i].auto_zwj); + m.features[i].auto_zwj, + m.features[i].random); /* Sort lookups and merge duplicates */ - if (last_num_lookups < m.lookups[table_index].len) + if (last_num_lookups < m.lookups[table_index].length) { - m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].len); + m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].length); unsigned int j = last_num_lookups; - for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++) + for (unsigned int i = j + 1; i < m.lookups[table_index].length; i++) if (m.lookups[table_index][i].index != m.lookups[table_index][j].index) m.lookups[table_index][++j] = m.lookups[table_index][i]; else @@ -321,9 +320,9 @@ m.lookups[table_index].shrink (j + 1); } - last_num_lookups = m.lookups[table_index].len; + last_num_lookups = m.lookups[table_index].length; - if (stage_index < stages[table_index].len && stages[table_index][stage_index].index == stage) { + if (stage_index < stages[table_index].length && stages[table_index][stage_index].index == stage) { hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push (); stage_map->last_lookup = last_num_lookups; stage_map->pause_func = stages[table_index][stage_index].pause_func; --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-maxp-table.hh 2019-02-28 12:03:59.326502954 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-maxp-table.hh 2019-02-28 12:03:59.226502956 -0800 @@ -27,8 +27,7 @@ #ifndef HB_OT_MAXP_TABLE_HH #define HB_OT_MAXP_TABLE_HH -#include "hb-open-type-private.hh" -#include "hb-subset-plan.hh" +#include "hb-open-type.hh" namespace OT { @@ -42,7 +41,7 @@ struct maxpV1Tail { - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -72,19 +71,16 @@ struct maxp { - static const hb_tag_t tableTag = HB_OT_TAG_maxp; + static constexpr hb_tag_t tableTag = HB_OT_TAG_maxp; - inline unsigned int get_num_glyphs (void) const - { - return numGlyphs; - } + unsigned int get_num_glyphs () const { return numGlyphs; } - inline void set_num_glyphs (unsigned int count) + void set_num_glyphs (unsigned int count) { numGlyphs.set (count); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) @@ -93,23 +89,23 @@ if (version.major == 1) { const maxpV1Tail &v1 = StructAfter (*this); - return v1.sanitize (c); + return_trace (v1.sanitize (c)); } return_trace (likely (version.major == 0 && version.minor == 0x5000u)); } - inline bool subset (hb_subset_plan_t *plan) const + bool subset (hb_subset_plan_t *plan) const { - hb_blob_t *maxp_blob = OT::Sanitizer().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_maxp)); + hb_blob_t *maxp_blob = hb_sanitize_context_t().reference_table (plan->source); hb_blob_t *maxp_prime_blob = hb_blob_copy_writable_or_fail (maxp_blob); hb_blob_destroy (maxp_blob); if (unlikely (!maxp_prime_blob)) { return false; } - OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr); + maxp *maxp_prime = (maxp *) hb_blob_get_data (maxp_prime_blob, nullptr); - maxp_prime->set_num_glyphs (plan->glyphs.len); + maxp_prime->set_num_glyphs (plan->glyphs.length); if (plan->drop_hints) drop_hint_fields (plan, maxp_prime); @@ -118,7 +114,7 @@ return result; } - static inline void drop_hint_fields (hb_subset_plan_t *plan, OT::maxp *maxp_prime) + static void drop_hint_fields (hb_subset_plan_t *plan HB_UNUSED, maxp *maxp_prime) { if (maxp_prime->version.major == 1) { @@ -137,7 +133,7 @@ FixedVersion<>version; /* Version of the maxp table (0.5 or 1.0), * 0x00005000u or 0x00010000u. */ HBUINT16 numGlyphs; /* The number of glyphs in the font. */ -/*maxpV1Tail v1Tail[VAR]; */ +/*maxpV1Tail v1Tail[VAR]; */ public: DEFINE_SIZE_STATIC (6); }; --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-table.hh 2019-02-28 12:03:59.674502948 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-table.hh 2019-02-28 12:03:59.558502950 -0800 @@ -27,38 +27,73 @@ #ifndef HB_OT_NAME_TABLE_HH #define HB_OT_NAME_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" +#include "hb-ot-name-language.hh" +#include "hb-aat-layout.hh" namespace OT { +#define entry_score var.u16[0] +#define entry_index var.u16[1] + + /* * name -- Naming * https://docs.microsoft.com/en-us/typography/opentype/spec/name */ #define HB_OT_TAG_name HB_TAG('n','a','m','e') +#define UNSUPPORTED 42 struct NameRecord { - static int cmp (const void *pa, const void *pb) + hb_language_t language (hb_face_t *face) const { - const NameRecord *a = (const NameRecord *) pa; - const NameRecord *b = (const NameRecord *) pb; - int ret; - ret = b->platformID.cmp (a->platformID); - if (ret) return ret; - ret = b->encodingID.cmp (a->encodingID); - if (ret) return ret; - ret = b->languageID.cmp (a->languageID); - if (ret) return ret; - ret = b->nameID.cmp (a->nameID); - if (ret) return ret; - return 0; + unsigned int p = platformID; + unsigned int l = languageID; + + if (p == 3) + return _hb_ot_name_language_for_ms_code (l); + + if (p == 1) + return _hb_ot_name_language_for_mac_code (l); + + if (p == 0) + return _hb_aat_language_get (face, l); + + return HB_LANGUAGE_INVALID; } - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + uint16_t score () const + { + /* Same order as in cmap::find_best_subtable(). */ + unsigned int p = platformID; + unsigned int e = encodingID; + + /* 32-bit. */ + if (p == 3 && e == 10) return 0; + if (p == 0 && e == 6) return 1; + if (p == 0 && e == 4) return 2; + + /* 16-bit. */ + if (p == 3 && e == 1) return 3; + if (p == 0 && e == 3) return 4; + if (p == 0 && e == 2) return 5; + if (p == 0 && e == 1) return 6; + if (p == 0 && e == 0) return 7; + + /* Symbol. */ + if (p == 3 && e == 0) return 8; + + /* We treat all Mac Latin names as ASCII only. */ + if (p == 1 && e == 0) return 10; /* 10 is magic number :| */ + + return UNSUPPORTED; + } + + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); /* We can check from base all the way up to the end of string... */ @@ -75,62 +110,168 @@ DEFINE_SIZE_STATIC (12); }; -struct name +static int +_hb_ot_name_entry_cmp_key (const void *pa, const void *pb) { - static const hb_tag_t tableTag = HB_OT_TAG_name; + const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa; + const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb; - inline unsigned int get_name (unsigned int platform_id, - unsigned int encoding_id, - unsigned int language_id, - unsigned int name_id, - void *buffer, - unsigned int buffer_length) const - { - NameRecord key; - key.platformID.set (platform_id); - key.encodingID.set (encoding_id); - key.languageID.set (language_id); - key.nameID.set (name_id); - NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), NameRecord::cmp); - - if (!match) - return 0; - - unsigned int length = MIN (buffer_length, (unsigned int) match->length); - memcpy (buffer, (char *) this + stringOffset + match->offset, length); - return length; - } + /* Compare by name_id, then language. */ + + if (a->name_id != b->name_id) + return a->name_id < b->name_id ? -1 : +1; - inline unsigned int get_size (void) const - { return min_size + count * nameRecord[0].min_size; } + if (a->language == b->language) return 0; + if (!a->language) return -1; + if (!b->language) return +1; + return strcmp (hb_language_to_string (a->language), + hb_language_to_string (b->language)); +} - inline bool sanitize_records (hb_sanitize_context_t *c) const { +static int +_hb_ot_name_entry_cmp (const void *pa, const void *pb) +{ + /* Compare by name_id, then language, then score, then index. */ + + int v = _hb_ot_name_entry_cmp_key (pa, pb); + if (v) + return v; + + const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa; + const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb; + + if (a->entry_score != b->entry_score) + return a->entry_score < b->entry_score ? -1 : +1; + + if (a->entry_index != b->entry_index) + return a->entry_index < b->entry_index ? -1 : +1; + + return 0; +} + +struct name +{ + static constexpr hb_tag_t tableTag = HB_OT_TAG_name; + + unsigned int get_size () const + { return min_size + count * nameRecordZ.item_size; } + + bool sanitize_records (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - char *string_pool = (char *) this + stringOffset; + const void *string_pool = (this+stringOffset).arrayZ; unsigned int _count = count; + /* Move to run-time?! */ for (unsigned int i = 0; i < _count; i++) - if (!nameRecord[i].sanitize (c, string_pool)) return_trace (false); + if (!nameRecordZ[i].sanitize (c, string_pool)) return_trace (false); return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && likely (format == 0 || format == 1) && - c->check_array (nameRecord, nameRecord[0].static_size, count) && - sanitize_records (c)); + c->check_array (nameRecordZ.arrayZ, count) && + c->check_range (this, stringOffset)); } + struct accelerator_t + { + void init (hb_face_t *face) + { + this->table = hb_sanitize_context_t().reference_table (face); + assert (this->table.get_length () >= this->table->stringOffset); + this->pool = (const char *) (const void *) (this->table+this->table->stringOffset); + this->pool_len = this->table.get_length () - this->table->stringOffset; + const hb_array_t all_names (this->table->nameRecordZ.arrayZ, + this->table->count); + + this->names.init (); + this->names.alloc (all_names.length); + + for (unsigned int i = 0; i < all_names.length; i++) + { + hb_ot_name_entry_t *entry = this->names.push (); + + entry->name_id = all_names[i].nameID; + entry->language = all_names[i].language (face); + entry->entry_score = all_names[i].score (); + entry->entry_index = i; + } + + this->names.qsort (_hb_ot_name_entry_cmp); + /* Walk and pick best only for each name_id,language pair, + * while dropping unsupported encodings. */ + unsigned int j = 0; + for (unsigned int i = 0; i < this->names.length; i++) + { + if (this->names[i].entry_score == UNSUPPORTED || + this->names[i].language == HB_LANGUAGE_INVALID) + continue; + if (i && + this->names[i - 1].name_id == this->names[i].name_id && + this->names[i - 1].language == this->names[i].language) + continue; + this->names[j++] = this->names[i]; + } + this->names.resize (j); + } + + void fini () + { + this->names.fini (); + this->table.destroy (); + } + + int get_index (hb_ot_name_id_t name_id, + hb_language_t language, + unsigned int *width=nullptr) const + { + const hb_ot_name_entry_t key = {name_id, {0}, language}; + const hb_ot_name_entry_t *entry = (const hb_ot_name_entry_t *) + hb_bsearch (&key, + (const hb_ot_name_entry_t *) this->names, + this->names.length, + sizeof (key), + _hb_ot_name_entry_cmp_key); + if (!entry) + return -1; + + if (width) + *width = entry->entry_score < 10 ? 2 : 1; + + return entry->entry_index; + } + + hb_bytes_t get_name (unsigned int idx) const + { + const hb_array_t all_names (table->nameRecordZ.arrayZ, table->count); + const NameRecord &record = all_names[idx]; + const hb_bytes_t string_pool (pool, pool_len); + return string_pool.sub_array (record.offset, record.length); + } + + private: + const char *pool; + unsigned int pool_len; + public: + hb_blob_ptr_t table; + hb_vector_t names; + }; + /* We only implement format 0 for now. */ HBUINT16 format; /* Format selector (=0/1). */ HBUINT16 count; /* Number of name records. */ - Offset16 stringOffset; /* Offset to start of string storage (from start of table). */ - NameRecord nameRecord[VAR]; /* The name records where count is the number of records. */ + NNOffsetTo > + stringOffset; /* Offset to start of string storage (from start of table). */ + UnsizedArrayOf + nameRecordZ; /* The name records where count is the number of records. */ public: - DEFINE_SIZE_ARRAY (6, nameRecord); + DEFINE_SIZE_ARRAY (6, nameRecordZ); }; +struct name_accelerator_t : name::accelerator_t {}; } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-table.hh 2019-02-28 12:04:00.050502942 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-table.hh 2019-02-28 12:03:59.946502944 -0800 @@ -1,5 +1,6 @@ /* * Copyright © 2011,2012 Google, Inc. + * Copyright © 2018 Ebrahim Byagowi * * This is part of HarfBuzz, a text shaping library. * @@ -27,36 +28,131 @@ #ifndef HB_OT_OS2_TABLE_HH #define HB_OT_OS2_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" #include "hb-ot-os2-unicode-ranges.hh" -#include "hb-subset-plan.hh" -namespace OT { +#include "hb-set.hh" /* * OS/2 and Windows Metrics * https://docs.microsoft.com/en-us/typography/opentype/spec/os2 */ -#define HB_OT_TAG_os2 HB_TAG('O','S','/','2') +#define HB_OT_TAG_OS2 HB_TAG('O','S','/','2') + + +namespace OT { -struct os2 +struct OS2V1Tail { - static const hb_tag_t tableTag = HB_OT_TAG_os2; + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + HBUINT32 ulCodePageRange1; + HBUINT32 ulCodePageRange2; + public: + DEFINE_SIZE_STATIC (8); +}; - inline bool sanitize (hb_sanitize_context_t *c) const +struct OS2V2Tail +{ + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } - inline bool subset (hb_subset_plan_t *plan) const + public: + HBINT16 sxHeight; + HBINT16 sCapHeight; + HBUINT16 usDefaultChar; + HBUINT16 usBreakChar; + HBUINT16 usMaxContext; + public: + DEFINE_SIZE_STATIC (10); +}; + +struct OS2V5Tail +{ + bool sanitize (hb_sanitize_context_t *c) const { - hb_blob_t *os2_blob = OT::Sanitizer().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_os2)); + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + HBUINT16 usLowerOpticalPointSize; + HBUINT16 usUpperOpticalPointSize; + public: + DEFINE_SIZE_STATIC (4); +}; + +struct OS2 +{ + static constexpr hb_tag_t tableTag = HB_OT_TAG_OS2; + + bool has_data () const { return this != &Null (OS2); } + + const OS2V1Tail &v1 () const { return version >= 1 ? v1X : Null (OS2V1Tail); } + const OS2V2Tail &v2 () const { return version >= 2 ? v2X : Null (OS2V2Tail); } + const OS2V5Tail &v5 () const { return version >= 5 ? v5X : Null (OS2V5Tail); } + + enum selection_flag_t { + ITALIC = 1u<<0, + UNDERSCORE = 1u<<1, + NEGATIVE = 1u<<2, + OUTLINED = 1u<<3, + STRIKEOUT = 1u<<4, + BOLD = 1u<<5, + REGULAR = 1u<<6, + USE_TYPO_METRICS = 1u<<7, + WWS = 1u<<8, + OBLIQUE = 1u<<9 + }; + + bool is_italic () const { return fsSelection & ITALIC; } + bool is_oblique () const { return fsSelection & OBLIQUE; } + bool is_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; } + + enum width_class_t { + FWIDTH_ULTRA_CONDENSED = 1, /* 50% */ + FWIDTH_EXTRA_CONDENSED = 2, /* 62.5% */ + FWIDTH_CONDENSED = 3, /* 75% */ + FWIDTH_SEMI_CONDENSED = 4, /* 87.5% */ + FWIDTH_NORMAL = 5, /* 100% */ + FWIDTH_SEMI_EXPANDED = 6, /* 112.5% */ + FWIDTH_EXPANDED = 7, /* 125% */ + FWIDTH_EXTRA_EXPANDED = 8, /* 150% */ + FWIDTH_ULTRA_EXPANDED = 9 /* 200% */ + }; + + float get_width () const + { + switch (usWidthClass) { + case FWIDTH_ULTRA_CONDENSED:return 50.f; + case FWIDTH_EXTRA_CONDENSED:return 62.5f; + case FWIDTH_CONDENSED: return 75.f; + case FWIDTH_SEMI_CONDENSED: return 87.5f; + default: + case FWIDTH_NORMAL: return 100.f; + case FWIDTH_SEMI_EXPANDED: return 112.5f; + case FWIDTH_EXPANDED: return 125.f; + case FWIDTH_EXTRA_EXPANDED: return 150.f; + case FWIDTH_ULTRA_EXPANDED: return 200.f; + } + } + + bool subset (hb_subset_plan_t *plan) const + { + hb_blob_t *os2_blob = hb_sanitize_context_t ().reference_table (plan->source); hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1); // TODO(grieger): move to hb_blob_copy_writable_or_fail hb_blob_destroy (os2_blob); - OT::os2 *os2_prime = (OT::os2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr); + OS2 *os2_prime = (OS2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr); if (unlikely (!os2_prime)) { hb_blob_destroy (os2_prime_blob); return false; @@ -68,21 +164,21 @@ os2_prime->usLastCharIndex.set (max_cp); _update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange); - bool result = plan->add_table (HB_OT_TAG_os2, os2_prime_blob); + bool result = plan->add_table (HB_OT_TAG_OS2, os2_prime_blob); hb_blob_destroy (os2_prime_blob); return result; } - inline void _update_unicode_ranges (const hb_set_t *codepoints, - HBUINT32 ulUnicodeRange[4]) const + void _update_unicode_ranges (const hb_set_t *codepoints, + HBUINT32 ulUnicodeRange[4]) const { for (unsigned int i = 0; i < 4; i++) ulUnicodeRange[i].set (0); hb_codepoint_t cp = HB_SET_VALUE_INVALID; while (codepoints->next (&cp)) { - unsigned int bit = hb_get_unicode_range_bit (cp); + unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp); if (bit < 128) { unsigned int block = bit / 32; @@ -100,7 +196,7 @@ } } - static inline void find_min_and_max_codepoint (const hb_set_t *codepoints, + static void find_min_and_max_codepoint (const hb_set_t *codepoints, uint16_t *min_cp, /* OUT */ uint16_t *max_cp /* OUT */) { @@ -119,17 +215,21 @@ }; // https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681 - inline font_page_t get_font_page () const + font_page_t get_font_page () const + { return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); } + + bool sanitize (hb_sanitize_context_t *c) const { - if (version != 0) - return (font_page_t) 0; - return (font_page_t) (fsSelection & 0xFF00); + TRACE_SANITIZE (this); + if (unlikely (!c->check_struct (this))) return_trace (false); + if (unlikely (version >= 1 && !v1X.sanitize (c))) return_trace (false); + if (unlikely (version >= 2 && !v2X.sanitize (c))) return_trace (false); + if (unlikely (version >= 5 && !v5X.sanitize (c))) return_trace (false); + return_trace (true); } public: HBUINT16 version; - - /* Version 0 */ HBINT16 xAvgCharWidth; HBUINT16 usWeightClass; HBUINT16 usWidthClass; @@ -156,24 +256,11 @@ HBINT16 sTypoLineGap; HBUINT16 usWinAscent; HBUINT16 usWinDescent; - - /* Version 1 */ - //HBUINT32 ulCodePageRange1; - //HBUINT32 ulCodePageRange2; - - /* Version 2 */ - //HBINT16 sxHeight; - //HBINT16 sCapHeight; - //HBUINT16 usDefaultChar; - //HBUINT16 usBreakChar; - //HBUINT16 usMaxContext; - - /* Version 5 */ - //HBUINT16 usLowerOpticalPointSize; - //HBUINT16 usUpperOpticalPointSize; - + OS2V1Tail v1X; + OS2V2Tail v2X; + OS2V5Tail v5X; public: - DEFINE_SIZE_STATIC (78); + DEFINE_SIZE_MIN (78); }; } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-unicode-ranges.hh 2019-02-28 12:04:00.378502937 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-unicode-ranges.hh 2019-02-28 12:04:00.282502938 -0800 @@ -27,19 +27,33 @@ #ifndef HB_OT_OS2_UNICODE_RANGES_HH #define HB_OT_OS2_UNICODE_RANGES_HH -#include "hb-private.hh" -#include "hb-dsalgs.hh" +#include "hb.hh" namespace OT { -struct Range { +struct OS2Range +{ + static int + cmp (const void *_key, const void *_item) + { + hb_codepoint_t cp = *((hb_codepoint_t *) _key); + const OS2Range *range = (OS2Range *) _item; + + if (cp < range->start) + return -1; + else if (cp <= range->end) + return 0; + else + return +1; + } + hb_codepoint_t start; hb_codepoint_t end; unsigned int bit; }; -/* Note: The contents of this array was generated using src/gen-unicode-ranges.py. */ -static Range os2UnicodeRangesSorted[] = +/* Note: The contents of this array was generated using gen-os2-unicode-ranges.py. */ +static const OS2Range _hb_os2_unicode_ranges[] = { { 0x0, 0x7F, 0}, // Basic Latin { 0x80, 0xFF, 1}, // Latin-1 Supplement @@ -212,31 +226,17 @@ {0x100000, 0x10FFFD, 90}, // Private Use (plane 16) }; -static int -_compare_range (const void *_key, const void *_item, void *_arg) -{ - hb_codepoint_t cp = *((hb_codepoint_t *) _key); - const Range *range = (Range *) _item; - - if (cp < range->start) - return -1; - else if (cp <= range->end) - return 0; - else - return 1; -} - /** - * hb_get_unicode_range_bit: - * Returns the bit to be set in os/2 ulUnicodeRange for a given codepoint. + * _hb_ot_os2_get_unicode_range_bit: + * Returns the bit to be set in os/2 ulUnicodeOS2Range for a given codepoint. **/ static unsigned int -hb_get_unicode_range_bit (hb_codepoint_t cp) +_hb_ot_os2_get_unicode_range_bit (hb_codepoint_t cp) { - Range *range = (Range*) hb_bsearch_r (&cp, os2UnicodeRangesSorted, - sizeof (os2UnicodeRangesSorted) / sizeof(Range), - sizeof(Range), - _compare_range, nullptr); + OS2Range *range = (OS2Range*) hb_bsearch (&cp, _hb_os2_unicode_ranges, + ARRAY_LENGTH (_hb_os2_unicode_ranges), + sizeof (OS2Range), + OS2Range::cmp); if (range != nullptr) return range->bit; return -1; --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-macroman.hh 2019-02-28 12:04:00.686502932 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-macroman.hh 2019-02-28 12:04:00.590502933 -0800 @@ -27,7 +27,7 @@ #ifndef HB_OT_POST_MACROMAN_HH #if 0 /* Make checks happy. */ #define HB_OT_POST_MACROMAN_HH -#include "hb-private.hh" +#include "hb.hh" #endif --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-table.hh 2019-02-28 12:04:01.010502926 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-table.hh 2019-02-28 12:04:00.910502928 -0800 @@ -27,9 +27,7 @@ #ifndef HB_OT_POST_TABLE_HH #define HB_OT_POST_TABLE_HH -#include "hb-open-type-private.hh" -#include "hb-dsalgs.hh" -#include "hb-subset-plan.hh" +#include "hb-open-type.hh" #define HB_STRING_ARRAY_NAME format1_names #define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh" @@ -51,47 +49,39 @@ struct postV2Tail { - inline bool sanitize (hb_sanitize_context_t *c) const + friend struct post; + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (glyphNameIndex.sanitize (c)); } - ArrayOfglyphNameIndex; /* This is not an offset, but is the + protected: + ArrayOf glyphNameIndex; /* This is not an offset, but is the * ordinal number of the glyph in 'post' * string tables. */ - HBUINT8 namesX[VAR]; /* Glyph names with length bytes [variable] +/*UnsizedArrayOf + namesX;*/ /* Glyph names with length bytes [variable] * (a Pascal string). */ - DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX); + public: + DEFINE_SIZE_ARRAY (2, glyphNameIndex); }; struct post { - static const hb_tag_t tableTag = HB_OT_TAG_post; - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) - return_trace (false); - if (version.to_int () == 0x00020000) - { - const postV2Tail &v2 = StructAfter (*this); - return_trace (v2.sanitize (c)); - } - return_trace (true); - } + static constexpr hb_tag_t tableTag = HB_OT_TAG_post; - inline bool subset (hb_subset_plan_t *plan) const + bool subset (hb_subset_plan_t *plan) const { unsigned int post_prime_length; - hb_blob_t *post_blob = OT::Sanitizer().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_post)); - hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::static_size); + hb_blob_t *post_blob = hb_sanitize_context_t ().reference_table(plan->source); + hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::min_size); post *post_prime = (post *) hb_blob_get_data_writable (post_prime_blob, &post_prime_length); hb_blob_destroy (post_blob); - if (unlikely (!post_prime || post_prime_length != post::static_size)) + if (unlikely (!post_prime || post_prime_length != post::min_size)) { hb_blob_destroy (post_prime_blob); DEBUG_MSG(SUBSET, nullptr, "Invalid source post table with length %d.", post_prime_length); @@ -107,63 +97,58 @@ struct accelerator_t { - inline void init (hb_face_t *face) + void init (hb_face_t *face) { index_to_offset.init (); - blob = Sanitizer().sanitize (face->reference_table (HB_OT_TAG_post)); - const post *table = blob->as (); - unsigned int table_length = blob->length; + table = hb_sanitize_context_t ().reference_table (face); + unsigned int table_length = table.get_length (); version = table->version.to_int (); - if (version != 0x00020000) - return; + if (version != 0x00020000) return; - const postV2Tail &v2 = StructAfter (*table); + const postV2Tail &v2 = table->v2X; glyphNameIndex = &v2.glyphNameIndex; pool = &StructAfter (v2.glyphNameIndex); - const uint8_t *end = (uint8_t *) table + table_length; - for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data) + const uint8_t *end = (const uint8_t *) (const void *) table + table_length; + for (const uint8_t *data = pool; + index_to_offset.length < 65535 && data < end && data + *data < end; + data += 1 + *data) index_to_offset.push (data - pool); } - inline void fini (void) + void fini () { index_to_offset.fini (); - free (gids_sorted_by_name); + free (gids_sorted_by_name.get ()); + table.destroy (); } - inline bool get_glyph_name (hb_codepoint_t glyph, - char *buf, unsigned int buf_len) const + bool get_glyph_name (hb_codepoint_t glyph, + char *buf, unsigned int buf_len) const { hb_bytes_t s = find_glyph_name (glyph); - if (!s.len) - return false; - if (!buf_len) - return true; - if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */ - return false; - strncpy (buf, s.bytes, s.len); - buf[s.len] = '\0'; + if (!s.length) return false; + if (!buf_len) return true; + unsigned int len = MIN (buf_len - 1, s.length); + strncpy (buf, s.arrayZ, len); + buf[len] = '\0'; return true; } - inline bool get_glyph_from_name (const char *name, int len, - hb_codepoint_t *glyph) const + bool get_glyph_from_name (const char *name, int len, + hb_codepoint_t *glyph) const { unsigned int count = get_glyph_count (); - if (unlikely (!count)) - return false; + if (unlikely (!count)) return false; - if (len < 0) - len = strlen (name); + if (len < 0) len = strlen (name); - if (unlikely (!len)) - return false; + if (unlikely (!len)) return false; retry: - uint16_t *gids = (uint16_t *) hb_atomic_ptr_get (&gids_sorted_by_name); + uint16_t *gids = gids_sorted_by_name.get (); if (unlikely (!gids)) { @@ -175,14 +160,16 @@ gids[i] = i; hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this); - if (!hb_atomic_ptr_cmpexch (&gids_sorted_by_name, nullptr, gids)) { + if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids))) + { free (gids); goto retry; } } hb_bytes_t st (name, len); - const uint16_t *gid = (const uint16_t *) hb_bsearch_r (&st, gids, count, sizeof (gids[0]), cmp_key, (void *) this); + const uint16_t *gid = (const uint16_t *) hb_bsearch_r (hb_addressof (st), gids, count, + sizeof (gids[0]), cmp_key, (void *) this); if (gid) { *glyph = *gid; @@ -194,7 +181,7 @@ protected: - inline unsigned int get_glyph_count (void) const + unsigned int get_glyph_count () const { if (version == 0x00010000) return NUM_FORMAT1_NAMES; @@ -205,7 +192,7 @@ return 0; } - static inline int cmp_gids (const void *pa, const void *pb, void *arg) + static int cmp_gids (const void *pa, const void *pb, void *arg) { const accelerator_t *thiz = (const accelerator_t *) arg; uint16_t a = * (const uint16_t *) pa; @@ -213,7 +200,7 @@ return thiz->find_glyph_name (b).cmp (thiz->find_glyph_name (a)); } - static inline int cmp_key (const void *pk, const void *po, void *arg) + static int cmp_key (const void *pk, const void *po, void *arg) { const accelerator_t *thiz = (const accelerator_t *) arg; const hb_bytes_t *key = (const hb_bytes_t *) pk; @@ -221,7 +208,7 @@ return thiz->find_glyph_name (o).cmp (*key); } - inline hb_bytes_t find_glyph_name (hb_codepoint_t glyph) const + hb_bytes_t find_glyph_name (hb_codepoint_t glyph) const { if (version == 0x00010000) { @@ -239,9 +226,9 @@ return format1_names (index); index -= NUM_FORMAT1_NAMES; - if (index >= index_to_offset.len) + if (index >= index_to_offset.length) return hb_bytes_t (); - unsigned int offset = index_to_offset.arrayZ[index]; + unsigned int offset = index_to_offset[index]; const uint8_t *data = pool + offset; unsigned int name_length = *data; @@ -251,14 +238,23 @@ } private: - hb_blob_t *blob; + hb_blob_ptr_t table; uint32_t version; const ArrayOf *glyphNameIndex; - hb_vector_t index_to_offset; + hb_vector_t index_to_offset; const uint8_t *pool; - mutable uint16_t *gids_sorted_by_name; + hb_atomic_ptr_t gids_sorted_by_name; }; + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + (version.to_int () == 0x00010000 || + (version.to_int () == 0x00020000 && v2X.sanitize (c)) || + version.to_int () == 0x00030000))); + } + public: FixedVersion<>version; /* 0x00010000 for version 1.0 * 0x00020000 for version 2.0 @@ -291,10 +287,12 @@ * is downloaded as a Type 1 font. */ HBUINT32 maxMemType1; /* Maximum memory usage when an OpenType font * is downloaded as a Type 1 font. */ -/*postV2Tail v2[VAR];*/ - DEFINE_SIZE_STATIC (32); + postV2Tail v2X; + DEFINE_SIZE_MIN (32); }; +struct post_accelerator_t : post::accelerator_t {}; + } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-fallback.hh 2019-02-28 12:04:01.370502921 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-fallback.hh 2019-02-28 12:04:01.262502922 -0800 @@ -27,9 +27,9 @@ #ifndef HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH #define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH -#include "hb-private.hh" +#include "hb.hh" -#include "hb-ot-shape-private.hh" +#include "hb-ot-shape.hh" #include "hb-ot-layout-gsub-table.hh" @@ -79,18 +79,15 @@ * May not be good-enough for presidential candidate interviews, but good-enough for us... */ hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]); - OT::Supplier glyphs_supplier (glyphs, num_glyphs); - OT::Supplier substitutes_supplier (substitutes, num_glyphs); /* Each glyph takes four bytes max, and there's some overhead. */ char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128]; - OT::hb_serialize_context_t c (buf, sizeof (buf)); + hb_serialize_context_t c (buf, sizeof (buf)); OT::SubstLookup *lookup = c.start_serialize (); bool ret = lookup->serialize_single (&c, OT::LookupFlag::IgnoreMarks, - glyphs_supplier, - substitutes_supplier, - num_glyphs); + hb_array (glyphs, num_glyphs), + hb_array (substitutes, num_glyphs)); c.end_serialize (); /* TODO sanitize the results? */ @@ -155,25 +152,18 @@ if (!num_ligatures) return nullptr; - OT::Supplier first_glyphs_supplier (first_glyphs, num_first_glyphs); - OT::Supplier ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs); - OT::Supplier ligatures_supplier (ligature_list, num_ligatures); - OT::Supplier component_count_supplier (component_count_list, num_ligatures); - OT::Supplier component_supplier (component_list, num_ligatures); /* 16 bytes per ligature ought to be enough... */ char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128]; - OT::hb_serialize_context_t c (buf, sizeof (buf)); + hb_serialize_context_t c (buf, sizeof (buf)); OT::SubstLookup *lookup = c.start_serialize (); bool ret = lookup->serialize_ligature (&c, OT::LookupFlag::IgnoreMarks, - first_glyphs_supplier, - ligature_per_first_glyph_count_supplier, - num_first_glyphs, - ligatures_supplier, - component_count_supplier, - component_supplier); - + hb_array (first_glyphs, num_first_glyphs), + hb_array (ligature_per_first_glyph_count_list, num_first_glyphs), + hb_array (ligature_list, num_ligatures), + hb_array (component_count_list, num_ligatures), + hb_array (component_list, num_ligatures)); c.end_serialize (); /* TODO sanitize the results? */ @@ -195,19 +185,15 @@ struct arabic_fallback_plan_t { - ASSERT_POD (); - unsigned int num_lookups; bool free_lookups; hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS]; OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS]; - hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS]; + OT::hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS]; }; -static const arabic_fallback_plan_t arabic_fallback_plan_nil = {}; - -#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256) +#if defined(_WIN32) && !defined(HB_NO_WIN1256) #define HB_WITH_WIN1256 #endif @@ -215,16 +201,20 @@ #include "hb-ot-shape-complex-arabic-win1256.hh" #endif -struct ManifestLookup { +struct ManifestLookup +{ + public: OT::Tag tag; OT::OffsetTo lookupOffset; + public: + DEFINE_SIZE_STATIC (6); }; typedef OT::ArrayOf Manifest; static bool -arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan, - const hb_ot_shape_plan_t *plan, - hb_font_t *font) +arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED, + const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED) { #ifdef HB_WITH_WIN1256 /* Does this font look like it's Windows-1256-encoded? */ @@ -299,7 +289,7 @@ { arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t)); if (unlikely (!fallback_plan)) - return const_cast (&arabic_fallback_plan_nil); + return const_cast (&Null(arabic_fallback_plan_t)); fallback_plan->num_lookups = 0; fallback_plan->free_lookups = false; @@ -314,14 +304,15 @@ if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font)) return fallback_plan; + assert (fallback_plan->num_lookups == 0); free (fallback_plan); - return const_cast (&arabic_fallback_plan_nil); + return const_cast (&Null(arabic_fallback_plan_t)); } static void arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan) { - if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil) + if (!fallback_plan || fallback_plan->num_lookups == 0) return; for (unsigned int i = 0; i < fallback_plan->num_lookups; i++) --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-win1256.hh 2019-02-28 12:04:01.742502914 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-win1256.hh 2019-02-28 12:04:01.638502916 -0800 @@ -313,7 +313,7 @@ * Include a second time to get the table data... */ #if 0 -#include "hb-private.hh" /* Make check-includes.sh happy. */ +#include "hb.hh" /* Make check-includes.sh happy. */ #endif #ifdef OT_MEASURE #include "hb-ot-shape-complex-arabic-win1256.hh" --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic.cc 2019-02-28 12:04:02.058502909 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic.cc 2019-02-28 12:04:01.962502911 -0800 @@ -24,10 +24,9 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-private.hh" -#include "hb-debug.hh" -#include "hb-ot-shape-complex-arabic-private.hh" -#include "hb-ot-shape-private.hh" +#include "hb.hh" +#include "hb-ot-shape-complex-arabic.hh" +#include "hb-ot-shape.hh" /* buffer var allocations */ @@ -160,11 +159,6 @@ static void -nuke_joiners (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); - -static void arabic_fallback_shape (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); @@ -201,32 +195,38 @@ * work correctly. See https://github.com/harfbuzz/harfbuzz/issues/505 */ - map->add_gsub_pause (nuke_joiners); - map->add_global_bool_feature (HB_TAG('s','t','c','h')); + map->enable_feature (HB_TAG('s','t','c','h')); map->add_gsub_pause (record_stch); - map->add_global_bool_feature (HB_TAG('c','c','m','p')); - map->add_global_bool_feature (HB_TAG('l','o','c','l')); + map->enable_feature (HB_TAG('c','c','m','p')); + map->enable_feature (HB_TAG('l','o','c','l')); map->add_gsub_pause (nullptr); for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) { bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]); - map->add_feature (arabic_features[i], 1, has_fallback ? F_HAS_FALLBACK : F_NONE); + map->add_feature (arabic_features[i], has_fallback ? F_HAS_FALLBACK : F_NONE); map->add_gsub_pause (nullptr); } - map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK); + /* Normally, Unicode says a ZWNJ means "don't ligate". In Arabic script + * however, it says a ZWJ should also mean "don't ligate". So we run + * the main ligating features as MANUAL_ZWJ. */ + + map->enable_feature (HB_TAG('r','l','i','g'), F_MANUAL_ZWJ | F_HAS_FALLBACK); + if (plan->props.script == HB_SCRIPT_ARABIC) map->add_gsub_pause (arabic_fallback_shape); /* No pause after rclt. See 98460779bae19e4d64d29461ff154b3527bf8420. */ - map->add_global_bool_feature (HB_TAG('r','c','l','t')); - map->add_global_bool_feature (HB_TAG('c','a','l','t')); + map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ); + map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ); map->add_gsub_pause (nullptr); + /* And undo here. */ + /* The spec includes 'cswh'. Earlier versions of Windows * used to enable this by default, but testing suggests * that Windows 8 and later do not enable it by default, @@ -235,23 +235,21 @@ * Note that IranNastaliq uses this feature extensively * to fixup broken glyph sequences. Oh well... * Test case: U+0643,U+0640,U+0631. */ - //map->add_global_bool_feature (HB_TAG('c','s','w','h')); - map->add_global_bool_feature (HB_TAG('m','s','e','t')); + //map->enable_feature (HB_TAG('c','s','w','h')); + map->enable_feature (HB_TAG('m','s','e','t')); } #include "hb-ot-shape-complex-arabic-fallback.hh" struct arabic_shape_plan_t { - ASSERT_POD (); - /* The "+ 1" in the next array is to accommodate for the "NONE" command, * which is not an OpenType feature, but this simplifies the code by not * having to do a "if (... < NONE) ..." and just rely on the fact that * mask_array[NONE] == 0. */ hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1]; - arabic_fallback_plan_t *fallback_plan; + hb_atomic_ptr_t fallback_plan; unsigned int do_fallback : 1; unsigned int has_stch : 1; @@ -380,19 +378,6 @@ setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script); } - -static void -nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) -{ - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - for (unsigned int i = 0; i < count; i++) - if (_hb_glyph_info_is_zwj (&info[i])) - _hb_glyph_info_flip_joiners (&info[i]); -} - static void arabic_fallback_shape (const hb_ot_shape_plan_t *plan, hb_font_t *font, @@ -404,12 +389,13 @@ return; retry: - arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) hb_atomic_ptr_get (&arabic_plan->fallback_plan); + arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan; if (unlikely (!fallback_plan)) { /* This sucks. We need a font to build the fallback plan... */ fallback_plan = arabic_fallback_plan_create (plan, font); - if (unlikely (!hb_atomic_ptr_cmpexch (&(const_cast (arabic_plan))->fallback_plan, nullptr, fallback_plan))) { + if (unlikely (!arabic_plan->fallback_plan.cmpexch (nullptr, fallback_plan))) + { arabic_fallback_plan_destroy (fallback_plan); goto retry; } @@ -428,7 +414,7 @@ static void record_stch (const hb_ot_shape_plan_t *plan, - hb_font_t *font, + hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; @@ -452,7 +438,7 @@ } static void -apply_stch (const hb_ot_shape_plan_t *plan, +apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, hb_font_t *font) { @@ -470,9 +456,9 @@ int sign = font->x_scale < 0 ? -1 : +1; unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT - typedef enum { MEASURE, CUT } step_t; + enum { MEASURE, CUT } /* step_t */; - for (step_t step = MEASURE; step <= CUT; step = (step_t) (step + 1)) + for (unsigned int step = MEASURE; step <= CUT; step = step + 1) { unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; @@ -611,7 +597,7 @@ HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); } -/* https://unicode.org/reports/tr53/tr53-1.pdf */ +/* http://www.unicode.org/reports/tr53/ */ static hb_codepoint_t modifier_combining_marks[] = @@ -623,6 +609,7 @@ 0x06E3u, /* ARABIC SMALL LOW SEEN */ 0x06E7u, /* ARABIC SMALL HIGH YEH */ 0x06E8u, /* ARABIC SMALL HIGH NOON */ + 0x08D3u, /* ARABIC SMALL LOW WAW */ 0x08F3u, /* ARABIC SMALL HIGH WAW */ }; @@ -637,7 +624,7 @@ } static void -reorder_marks_arabic (const hb_ot_shape_plan_t *plan, +reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, unsigned int start, unsigned int end) @@ -714,7 +701,7 @@ nullptr, /* decompose */ nullptr, /* compose */ setup_masks_arabic, - nullptr, /* disable_otl */ + HB_TAG_NONE, /* gpos_tag */ reorder_marks_arabic, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-default.cc 2019-02-28 12:04:02.390502904 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-default.cc 2019-02-28 12:04:02.290502905 -0800 @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-ot-shape-complex-private.hh" +#include "hb-ot-shape-complex.hh" const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default = @@ -39,7 +39,7 @@ nullptr, /* decompose */ nullptr, /* compose */ nullptr, /* setup_masks */ - nullptr, /* disable_otl */ + HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hangul.cc 2019-02-28 12:04:02.718502898 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hangul.cc 2019-02-28 12:04:02.618502900 -0800 @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-ot-shape-complex-private.hh" +#include "hb-ot-shape-complex.hh" /* Hangul shaper */ @@ -56,7 +56,7 @@ hb_ot_map_builder_t *map = &plan->map; for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++) - map->add_feature (hangul_features[i], 1, F_NONE); + map->add_feature (hangul_features[i]); } static void @@ -65,13 +65,11 @@ /* Uniscribe does not apply 'calt' for Hangul, and certain fonts * (Noto Sans CJK, Source Sans Han, etc) apply all of jamo lookups * in calt, which is not desirable. */ - plan->map.add_feature (HB_TAG('c','a','l','t'), 0, F_GLOBAL); + plan->map.disable_feature (HB_TAG('c','a','l','t')); } struct hangul_shape_plan_t { - ASSERT_POD (); - hb_mask_t mask_array[HANGUL_FEATURE_COUNT]; }; @@ -128,7 +126,7 @@ } static void -preprocess_text_hangul (const hb_ot_shape_plan_t *plan, +preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, hb_font_t *font) { @@ -345,13 +343,6 @@ { unsigned int s_len = tindex ? 3 : 2; buffer->replace_glyphs (1, s_len, decomposed); - if (unlikely (!buffer->successful)) - return; - - /* We decomposed S: apply jamo features to the individual glyphs - * that are now in buffer->out_info. - */ - hb_glyph_info_t *info = buffer->out_info; /* If we decomposed an LV because of a non-combining T following, * we want to include this T in the syllable. @@ -361,6 +352,14 @@ buffer->next_glyph (); s_len++; } + + if (unlikely (!buffer->successful)) + return; + + /* We decomposed S: apply jamo features to the individual glyphs + * that are now in buffer->out_info. + */ + hb_glyph_info_t *info = buffer->out_info; end = start + s_len; unsigned int i = start; @@ -368,6 +367,7 @@ info[i++].hangul_shaping_feature() = VJMO; if (i < end) info[i++].hangul_shaping_feature() = TJMO; + if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) buffer->merge_out_clusters (start, end); continue; @@ -424,7 +424,7 @@ nullptr, /* decompose */ nullptr, /* compose */ setup_masks_hangul, - nullptr, /* disable_otl */ + HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hebrew.cc 2019-02-28 12:04:03.034502893 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hebrew.cc 2019-02-28 12:04:02.938502895 -0800 @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-ot-shape-complex-private.hh" +#include "hb-ot-shape-complex.hh" static bool @@ -70,7 +70,7 @@ bool found = (bool) c->unicode->compose (a, b, ab); - if (!found && !c->plan->has_mark) + if (!found && !c->plan->has_gpos_mark) { /* Special-case Hebrew presentation forms that are excluded from * standard normalization, but wanted for old fonts. */ @@ -154,18 +154,6 @@ return found; } -static bool -disable_otl_hebrew (const hb_ot_shape_plan_t *plan) -{ - /* For Hebrew shaper, use fallback if GPOS does not have 'hebr' - * script. This matches Uniscribe better, and makes fonts like - * Arial that have GSUB/GPOS/GDEF but no data for Hebrew work. - * See: - * https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 - */ - return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r'); -} - const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = { @@ -179,7 +167,7 @@ nullptr, /* decompose */ compose_hebrew, nullptr, /* setup_masks */ - disable_otl_hebrew, + HB_TAG ('h','e','b','r'), /* gpos_tag. https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 */ nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-machine.hh 2019-02-28 12:04:03.418502887 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-machine.hh 2019-02-28 12:04:03.286502889 -0800 @@ -29,892 +29,714 @@ #ifndef HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH #define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH -#include "hb-private.hh" +#include "hb.hh" #line 36 "hb-ot-shape-complex-indic-machine.hh" static const unsigned char _indic_syllable_machine_trans_keys[] = { - 8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, + 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, - 16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, - 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, - 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, - 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, - 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, - 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 8u, - 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, - 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, - 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, - 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, - 8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, - 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, - 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, - 16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, - 4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u, 5u, 8u, 5u, 8u, 5u, 7u, 5u, 8u, - 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, - 8u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, - 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 8u, 8u, 1u, 19u, 3u, 17u, - 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, - 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, - 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, - 5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, - 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, - 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, - 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, - 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, - 3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, - 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, - 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, - 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, - 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, - 5u, 10u, 3u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, - 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, - 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, - 1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, - 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, - 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, - 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, + 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, + 4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, + 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, + 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, + 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, + 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, + 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, + 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, + 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, + 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 8u, 8u, 4u, 8u, 5u, 7u, + 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, + 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, + 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, + 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u, + 5u, 8u, 8u, 8u, 1u, 19u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, + 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, + 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, + 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, - 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, - 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, - 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, - 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 13u, 3u, 17u, 4u, 8u, - 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, - 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, - 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, - 10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, + 3u, 10u, 4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, + 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, + 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, + 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, + 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, + 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, + 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, + 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 3u, 10u, + 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, + 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, + 1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 10u, 3u, 10u, 4u, 10u, 1u, 16u, + 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, + 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, + 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, + 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, + 5u, 10u, 3u, 10u, 4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, + 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, + 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 13u, + 3u, 10u, 4u, 8u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, + 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, + 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 5u, 10u, + 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, - 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, - 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, - 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, - 1u, 16u, 3u, 17u, 1u, 17u, 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, - 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, - 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, + 4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, + 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, + 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 1u, 16u, 3u, 13u, + 1u, 16u, 4u, 13u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 0 }; static const char _indic_syllable_machine_key_spans[] = { - 1, 4, 3, 1, 4, 3, 1, 4, + 1, 5, 3, 1, 4, 3, 1, 4, 3, 1, 4, 3, 1, 5, 1, 1, 5, 1, 1, 5, 1, 1, 5, 1, - 1, 5, 10, 5, 10, 5, 10, 5, - 10, 5, 10, 1, 4, 3, 1, 4, - 3, 1, 4, 3, 1, 4, 3, 1, - 5, 1, 1, 5, 1, 1, 5, 1, - 1, 5, 1, 1, 5, 10, 5, 10, - 5, 10, 5, 10, 5, 10, 1, 4, - 3, 1, 4, 3, 1, 4, 3, 1, - 4, 3, 1, 5, 1, 1, 5, 1, + 1, 10, 5, 10, 5, 10, 5, 10, + 5, 10, 1, 5, 3, 1, 4, 3, + 1, 4, 3, 1, 4, 3, 1, 5, + 1, 1, 5, 1, 1, 5, 1, 1, + 5, 1, 1, 10, 5, 10, 5, 10, + 5, 10, 5, 10, 1, 5, 3, 1, + 4, 3, 1, 4, 3, 1, 4, 3, 1, 5, 1, 1, 5, 1, 1, 5, - 10, 5, 10, 5, 10, 5, 10, 5, + 1, 1, 5, 1, 1, 10, 5, 10, + 5, 10, 5, 10, 5, 1, 5, 3, 1, 4, 3, 1, 4, 3, 1, 4, - 3, 1, 4, 3, 1, 5, 1, 1, - 5, 1, 1, 5, 1, 1, 5, 1, - 1, 5, 10, 5, 10, 5, 10, 5, - 10, 5, 10, 10, 4, 4, 3, 4, - 3, 1, 4, 3, 1, 4, 3, 1, - 1, 5, 1, 1, 5, 1, 1, 5, - 1, 1, 5, 1, 1, 1, 19, 15, - 15, 14, 16, 15, 15, 14, 16, 15, - 15, 14, 16, 15, 15, 14, 16, 15, - 15, 14, 6, 6, 6, 1, 1, 1, - 6, 8, 8, 7, 6, 8, 7, 6, - 8, 7, 6, 8, 7, 6, 8, 7, - 15, 15, 16, 16, 16, 16, 15, 15, - 16, 16, 16, 16, 15, 15, 16, 16, - 16, 16, 15, 15, 16, 16, 16, 16, - 15, 15, 15, 15, 14, 16, 15, 15, - 14, 16, 15, 15, 14, 16, 15, 15, - 14, 16, 15, 15, 14, 6, 6, 6, - 1, 1, 1, 6, 8, 8, 7, 6, - 8, 7, 6, 8, 7, 6, 8, 7, - 6, 8, 7, 15, 15, 16, 16, 16, - 16, 15, 15, 16, 16, 16, 16, 15, - 15, 16, 16, 16, 16, 15, 15, 16, - 16, 16, 16, 5, 15, 15, 14, 16, - 15, 15, 14, 16, 15, 15, 14, 16, - 15, 15, 14, 16, 15, 15, 14, 6, - 6, 6, 1, 1, 1, 6, 8, 8, + 3, 1, 5, 1, 1, 5, 1, 1, + 5, 1, 1, 5, 1, 1, 10, 5, + 10, 5, 10, 5, 10, 5, 10, 10, + 4, 1, 19, 11, 8, 7, 16, 11, + 8, 7, 16, 11, 8, 7, 16, 11, + 8, 7, 16, 11, 8, 7, 6, 6, + 6, 1, 1, 1, 6, 8, 6, 8, 7, 6, 8, 7, 6, 8, 7, 6, - 8, 7, 6, 8, 7, 15, 15, 16, - 16, 16, 16, 15, 15, 16, 16, 16, - 16, 15, 15, 16, 16, 16, 16, 15, - 15, 16, 16, 16, 16, 10, 15, 5, - 15, 15, 14, 16, 15, 15, 14, 16, - 15, 15, 14, 16, 15, 15, 14, 16, - 15, 15, 14, 6, 6, 6, 1, 1, - 1, 6, 8, 8, 7, 6, 8, 7, + 8, 7, 8, 11, 16, 16, 16, 8, + 11, 16, 16, 16, 8, 11, 16, 16, + 16, 8, 11, 16, 16, 16, 8, 11, + 11, 8, 7, 16, 11, 8, 7, 16, + 11, 8, 7, 16, 11, 8, 7, 16, + 11, 8, 7, 6, 6, 6, 1, 1, + 1, 6, 8, 6, 8, 7, 6, 8, + 7, 6, 8, 7, 6, 8, 7, 8, + 11, 16, 16, 16, 8, 11, 16, 16, + 16, 8, 11, 16, 16, 16, 8, 11, + 16, 16, 16, 5, 8, 8, 7, 16, + 11, 8, 7, 16, 11, 8, 7, 16, + 11, 8, 7, 16, 11, 8, 7, 6, + 6, 6, 1, 1, 1, 6, 8, 6, + 8, 7, 6, 8, 7, 6, 8, 7, + 6, 8, 7, 8, 11, 16, 16, 16, + 8, 11, 16, 16, 16, 8, 11, 16, + 16, 16, 8, 11, 16, 16, 16, 10, + 8, 5, 11, 8, 7, 16, 11, 8, + 7, 16, 11, 8, 7, 16, 11, 8, + 7, 16, 11, 8, 7, 6, 6, 6, + 1, 1, 1, 6, 8, 6, 8, 7, 6, 8, 7, 6, 8, 7, 6, 8, - 7, 15, 15, 16, 16, 16, 16, 15, - 15, 16, 16, 16, 16, 15, 15, 16, - 16, 16, 16, 15, 15, 16, 16, 16, - 16, 15, 17, 15, 17, 10, 6, 1, - 1, 1, 6, 16, 8, 7, 6, 8, - 7, 6, 8, 7, 6, 8, 7, 6, + 7, 8, 11, 16, 16, 16, 8, 11, + 16, 16, 16, 8, 11, 16, 16, 16, + 8, 11, 16, 16, 16, 8, 16, 11, + 16, 10, 6, 1, 1, 1, 6, 16, 8, 6, 6, 1, 1, 1, 6, 16 }; static const short _indic_syllable_machine_index_offsets[] = { - 0, 2, 7, 11, 13, 18, 22, 24, - 29, 33, 35, 40, 44, 46, 52, 54, - 56, 62, 64, 66, 72, 74, 76, 82, - 84, 86, 92, 103, 109, 120, 126, 137, - 143, 154, 160, 171, 173, 178, 182, 184, - 189, 193, 195, 200, 204, 206, 211, 215, - 217, 223, 225, 227, 233, 235, 237, 243, - 245, 247, 253, 255, 257, 263, 274, 280, - 291, 297, 308, 314, 325, 331, 342, 344, - 349, 353, 355, 360, 364, 366, 371, 375, - 377, 382, 386, 388, 394, 396, 398, 404, - 406, 408, 414, 416, 418, 424, 426, 428, - 434, 445, 451, 462, 468, 479, 485, 496, - 502, 504, 509, 513, 515, 520, 524, 526, - 531, 535, 537, 542, 546, 548, 554, 556, - 558, 564, 566, 568, 574, 576, 578, 584, - 586, 588, 594, 605, 611, 622, 628, 639, - 645, 656, 662, 673, 684, 689, 694, 698, - 703, 707, 709, 714, 718, 720, 725, 729, - 731, 733, 739, 741, 743, 749, 751, 753, - 759, 761, 763, 769, 771, 773, 775, 795, - 811, 827, 842, 859, 875, 891, 906, 923, - 939, 955, 970, 987, 1003, 1019, 1034, 1051, - 1067, 1083, 1098, 1105, 1112, 1119, 1121, 1123, - 1125, 1132, 1141, 1150, 1158, 1165, 1174, 1182, - 1189, 1198, 1206, 1213, 1222, 1230, 1237, 1246, - 1254, 1270, 1286, 1303, 1320, 1337, 1354, 1370, - 1386, 1403, 1420, 1437, 1454, 1470, 1486, 1503, - 1520, 1537, 1554, 1570, 1586, 1603, 1620, 1637, - 1654, 1670, 1686, 1702, 1718, 1733, 1750, 1766, - 1782, 1797, 1814, 1830, 1846, 1861, 1878, 1894, - 1910, 1925, 1942, 1958, 1974, 1989, 1996, 2003, - 2010, 2012, 2014, 2016, 2023, 2032, 2041, 2049, - 2056, 2065, 2073, 2080, 2089, 2097, 2104, 2113, - 2121, 2128, 2137, 2145, 2161, 2177, 2194, 2211, - 2228, 2245, 2261, 2277, 2294, 2311, 2328, 2345, - 2361, 2377, 2394, 2411, 2428, 2445, 2461, 2477, - 2494, 2511, 2528, 2545, 2551, 2567, 2583, 2598, - 2615, 2631, 2647, 2662, 2679, 2695, 2711, 2726, - 2743, 2759, 2775, 2790, 2807, 2823, 2839, 2854, - 2861, 2868, 2875, 2877, 2879, 2881, 2888, 2897, - 2906, 2914, 2921, 2930, 2938, 2945, 2954, 2962, - 2969, 2978, 2986, 2993, 3002, 3010, 3026, 3042, - 3059, 3076, 3093, 3110, 3126, 3142, 3159, 3176, - 3193, 3210, 3226, 3242, 3259, 3276, 3293, 3310, - 3326, 3342, 3359, 3376, 3393, 3410, 3421, 3437, - 3443, 3459, 3475, 3490, 3507, 3523, 3539, 3554, - 3571, 3587, 3603, 3618, 3635, 3651, 3667, 3682, - 3699, 3715, 3731, 3746, 3753, 3760, 3767, 3769, - 3771, 3773, 3780, 3789, 3798, 3806, 3813, 3822, - 3830, 3837, 3846, 3854, 3861, 3870, 3878, 3885, - 3894, 3902, 3918, 3934, 3951, 3968, 3985, 4002, - 4018, 4034, 4051, 4068, 4085, 4102, 4118, 4134, - 4151, 4168, 4185, 4202, 4218, 4234, 4251, 4268, - 4285, 4302, 4318, 4336, 4352, 4370, 4381, 4388, - 4390, 4392, 4394, 4401, 4418, 4427, 4435, 4442, - 4451, 4459, 4466, 4475, 4483, 4490, 4499, 4507, - 4514, 4523, 4530, 4537, 4539, 4541, 4543, 4550 + 0, 2, 8, 12, 14, 19, 23, 25, + 30, 34, 36, 41, 45, 47, 53, 55, + 57, 63, 65, 67, 73, 75, 77, 83, + 85, 87, 98, 104, 115, 121, 132, 138, + 149, 155, 166, 168, 174, 178, 180, 185, + 189, 191, 196, 200, 202, 207, 211, 213, + 219, 221, 223, 229, 231, 233, 239, 241, + 243, 249, 251, 253, 264, 270, 281, 287, + 298, 304, 315, 321, 332, 334, 340, 344, + 346, 351, 355, 357, 362, 366, 368, 373, + 377, 379, 385, 387, 389, 395, 397, 399, + 405, 407, 409, 415, 417, 419, 430, 436, + 447, 453, 464, 470, 481, 487, 489, 495, + 499, 501, 506, 510, 512, 517, 521, 523, + 528, 532, 534, 540, 542, 544, 550, 552, + 554, 560, 562, 564, 570, 572, 574, 585, + 591, 602, 608, 619, 625, 636, 642, 653, + 664, 669, 671, 691, 703, 712, 720, 737, + 749, 758, 766, 783, 795, 804, 812, 829, + 841, 850, 858, 875, 887, 896, 904, 911, + 918, 925, 927, 929, 931, 938, 947, 954, + 963, 971, 978, 987, 995, 1002, 1011, 1019, + 1026, 1035, 1043, 1052, 1064, 1081, 1098, 1115, + 1124, 1136, 1153, 1170, 1187, 1196, 1208, 1225, + 1242, 1259, 1268, 1280, 1297, 1314, 1331, 1340, + 1352, 1364, 1373, 1381, 1398, 1410, 1419, 1427, + 1444, 1456, 1465, 1473, 1490, 1502, 1511, 1519, + 1536, 1548, 1557, 1565, 1572, 1579, 1586, 1588, + 1590, 1592, 1599, 1608, 1615, 1624, 1632, 1639, + 1648, 1656, 1663, 1672, 1680, 1687, 1696, 1704, + 1713, 1725, 1742, 1759, 1776, 1785, 1797, 1814, + 1831, 1848, 1857, 1869, 1886, 1903, 1920, 1929, + 1941, 1958, 1975, 1992, 1998, 2007, 2016, 2024, + 2041, 2053, 2062, 2070, 2087, 2099, 2108, 2116, + 2133, 2145, 2154, 2162, 2179, 2191, 2200, 2208, + 2215, 2222, 2229, 2231, 2233, 2235, 2242, 2251, + 2258, 2267, 2275, 2282, 2291, 2299, 2306, 2315, + 2323, 2330, 2339, 2347, 2356, 2368, 2385, 2402, + 2419, 2428, 2440, 2457, 2474, 2491, 2500, 2512, + 2529, 2546, 2563, 2572, 2584, 2601, 2618, 2635, + 2646, 2655, 2661, 2673, 2682, 2690, 2707, 2719, + 2728, 2736, 2753, 2765, 2774, 2782, 2799, 2811, + 2820, 2828, 2845, 2857, 2866, 2874, 2881, 2888, + 2895, 2897, 2899, 2901, 2908, 2917, 2924, 2933, + 2941, 2948, 2957, 2965, 2972, 2981, 2989, 2996, + 3005, 3013, 3022, 3034, 3051, 3068, 3085, 3094, + 3106, 3123, 3140, 3157, 3166, 3178, 3195, 3212, + 3229, 3238, 3250, 3267, 3284, 3301, 3310, 3327, + 3339, 3356, 3367, 3374, 3376, 3378, 3380, 3387, + 3404, 3413, 3420, 3427, 3429, 3431, 3433, 3440 }; static const short _indic_syllable_machine_indicies[] = { - 1, 0, 2, 2, 3, 1, 0, 4, - 4, 3, 0, 3, 0, 5, 5, 6, - 1, 0, 7, 7, 6, 0, 6, 0, - 8, 8, 9, 1, 0, 10, 10, 9, - 0, 9, 0, 11, 11, 12, 1, 0, - 13, 13, 12, 0, 12, 0, 14, 0, - 0, 0, 1, 0, 15, 0, 16, 0, - 17, 11, 11, 12, 1, 0, 18, 0, - 19, 0, 20, 8, 8, 9, 1, 0, - 21, 0, 22, 0, 23, 5, 5, 6, - 1, 0, 24, 0, 25, 0, 26, 2, - 2, 3, 1, 0, 26, 2, 2, 3, - 1, 0, 0, 0, 0, 27, 0, 28, - 2, 2, 3, 1, 0, 28, 2, 2, - 3, 1, 0, 0, 0, 0, 29, 0, - 30, 2, 2, 3, 1, 0, 30, 2, - 2, 3, 1, 0, 0, 0, 0, 31, - 0, 32, 2, 2, 3, 1, 0, 32, - 2, 2, 3, 1, 0, 0, 0, 0, - 33, 0, 34, 2, 2, 3, 1, 0, - 34, 2, 2, 3, 1, 0, 0, 0, - 0, 35, 0, 37, 36, 38, 38, 39, - 37, 36, 40, 40, 39, 36, 39, 36, - 41, 41, 42, 37, 36, 43, 43, 42, - 36, 42, 36, 44, 44, 45, 37, 36, - 46, 46, 45, 36, 45, 36, 47, 47, - 48, 37, 36, 49, 49, 48, 36, 48, - 36, 50, 36, 36, 36, 37, 36, 51, - 36, 52, 36, 53, 47, 47, 48, 37, - 36, 54, 36, 55, 36, 56, 44, 44, - 45, 37, 36, 57, 36, 58, 36, 59, - 41, 41, 42, 37, 36, 60, 36, 61, - 36, 62, 38, 38, 39, 37, 36, 62, - 38, 38, 39, 37, 36, 36, 36, 36, - 63, 36, 64, 38, 38, 39, 37, 36, - 64, 38, 38, 39, 37, 36, 36, 36, - 36, 65, 36, 66, 38, 38, 39, 37, - 36, 66, 38, 38, 39, 37, 36, 36, - 36, 36, 67, 36, 68, 38, 38, 39, - 37, 36, 68, 38, 38, 39, 37, 36, - 36, 36, 36, 69, 36, 70, 38, 38, - 39, 37, 36, 70, 38, 38, 39, 37, - 36, 36, 36, 36, 71, 36, 73, 72, - 74, 74, 75, 73, 72, 77, 77, 75, - 76, 75, 76, 78, 78, 79, 73, 72, - 80, 80, 79, 72, 79, 72, 81, 81, - 82, 73, 72, 83, 83, 82, 72, 82, - 72, 84, 84, 85, 73, 72, 86, 86, - 85, 72, 85, 72, 87, 72, 72, 72, - 73, 72, 88, 72, 89, 72, 90, 84, - 84, 85, 73, 72, 91, 72, 92, 72, - 93, 81, 81, 82, 73, 72, 94, 72, - 95, 72, 96, 78, 78, 79, 73, 72, - 97, 72, 98, 72, 99, 74, 74, 75, - 73, 72, 99, 74, 74, 75, 73, 72, - 72, 72, 72, 100, 72, 101, 74, 74, - 75, 73, 72, 101, 74, 74, 75, 73, - 72, 72, 72, 72, 102, 72, 103, 74, - 74, 75, 73, 72, 103, 74, 74, 75, - 73, 72, 72, 72, 72, 104, 72, 105, - 74, 74, 75, 73, 72, 105, 74, 74, - 75, 73, 72, 72, 72, 72, 106, 72, - 107, 74, 74, 75, 73, 72, 109, 108, - 110, 110, 111, 109, 108, 112, 112, 111, - 108, 111, 108, 113, 113, 114, 109, 108, - 115, 115, 114, 108, 114, 108, 116, 116, - 117, 109, 108, 118, 118, 117, 108, 117, - 108, 119, 119, 120, 109, 108, 121, 121, - 120, 108, 120, 108, 122, 108, 108, 108, - 109, 108, 123, 108, 124, 108, 125, 119, - 119, 120, 109, 108, 126, 108, 127, 108, - 128, 116, 116, 117, 109, 108, 129, 108, - 130, 108, 131, 113, 113, 114, 109, 108, - 132, 108, 133, 108, 134, 110, 110, 111, - 109, 108, 134, 110, 110, 111, 109, 108, - 108, 108, 108, 135, 108, 136, 110, 110, - 111, 109, 108, 136, 110, 110, 111, 109, - 108, 108, 108, 108, 137, 108, 138, 110, - 110, 111, 109, 108, 138, 110, 110, 111, - 109, 108, 108, 108, 108, 139, 108, 140, - 110, 110, 111, 109, 108, 140, 110, 110, - 111, 109, 108, 108, 108, 108, 141, 108, - 142, 110, 110, 111, 109, 108, 142, 110, - 110, 111, 109, 108, 108, 108, 108, 143, - 108, 107, 74, 74, 75, 73, 72, 72, - 72, 72, 144, 72, 77, 77, 75, 1, - 0, 145, 145, 146, 1, 0, 4, 4, - 146, 0, 147, 147, 148, 149, 0, 150, - 150, 148, 0, 148, 0, 151, 151, 152, - 149, 0, 153, 153, 152, 0, 152, 0, - 154, 154, 155, 149, 0, 156, 156, 155, - 0, 155, 0, 149, 0, 157, 0, 0, - 0, 149, 0, 158, 0, 159, 0, 160, - 154, 154, 155, 149, 0, 161, 0, 162, - 0, 163, 151, 151, 152, 149, 0, 164, - 0, 165, 0, 166, 147, 147, 148, 149, - 0, 167, 0, 168, 0, 170, 169, 172, - 173, 174, 175, 176, 177, 75, 73, 171, - 178, 179, 179, 144, 171, 180, 181, 182, - 183, 184, 171, 186, 187, 188, 189, 3, - 1, 185, 190, 185, 185, 35, 185, 185, - 185, 191, 185, 192, 187, 193, 193, 3, - 1, 185, 190, 185, 185, 185, 185, 185, - 185, 191, 185, 187, 193, 193, 3, 1, - 185, 190, 185, 185, 185, 185, 185, 185, - 191, 185, 194, 185, 185, 185, 16, 195, - 185, 1, 185, 190, 185, 185, 185, 185, - 185, 194, 185, 196, 197, 198, 199, 3, - 1, 185, 190, 185, 185, 33, 185, 185, - 185, 191, 185, 200, 197, 201, 201, 3, - 1, 185, 190, 185, 185, 185, 185, 185, - 185, 191, 185, 197, 201, 201, 3, 1, - 185, 190, 185, 185, 185, 185, 185, 185, - 191, 185, 202, 185, 185, 185, 16, 203, - 185, 1, 185, 190, 185, 185, 185, 185, - 185, 202, 185, 204, 205, 206, 207, 3, - 1, 185, 190, 185, 185, 31, 185, 185, - 185, 191, 185, 208, 205, 209, 209, 3, - 1, 185, 190, 185, 185, 185, 185, 185, - 185, 191, 185, 205, 209, 209, 3, 1, - 185, 190, 185, 185, 185, 185, 185, 185, - 191, 185, 210, 185, 185, 185, 16, 211, - 185, 1, 185, 190, 185, 185, 185, 185, - 185, 210, 185, 212, 213, 214, 215, 3, - 1, 185, 190, 185, 185, 29, 185, 185, - 185, 191, 185, 216, 213, 217, 217, 3, - 1, 185, 190, 185, 185, 185, 185, 185, - 185, 191, 185, 213, 217, 217, 3, 1, - 185, 190, 185, 185, 185, 185, 185, 185, - 191, 185, 218, 185, 185, 185, 16, 219, - 185, 1, 185, 190, 185, 185, 185, 185, - 185, 218, 185, 220, 221, 222, 223, 3, - 1, 185, 190, 185, 185, 27, 185, 185, - 185, 191, 185, 224, 221, 225, 225, 3, - 1, 185, 190, 185, 185, 185, 185, 185, - 185, 191, 185, 221, 225, 225, 3, 1, - 185, 190, 185, 185, 185, 185, 185, 185, - 191, 185, 16, 226, 185, 1, 185, 190, - 185, 227, 227, 185, 1, 185, 190, 185, - 228, 185, 185, 229, 185, 190, 185, 190, - 185, 230, 185, 231, 185, 228, 185, 185, - 185, 185, 190, 185, 16, 185, 232, 232, - 3, 1, 185, 190, 185, 233, 25, 234, - 235, 6, 1, 185, 190, 185, 25, 234, - 235, 6, 1, 185, 190, 185, 234, 234, - 6, 1, 185, 190, 185, 236, 22, 237, - 238, 9, 1, 185, 190, 185, 22, 237, - 238, 9, 1, 185, 190, 185, 237, 237, - 9, 1, 185, 190, 185, 239, 19, 240, - 241, 12, 1, 185, 190, 185, 19, 240, - 241, 12, 1, 185, 190, 185, 240, 240, - 12, 1, 185, 190, 185, 242, 16, 227, - 243, 185, 1, 185, 190, 185, 16, 227, - 243, 185, 1, 185, 190, 185, 227, 244, - 185, 1, 185, 190, 185, 16, 185, 227, - 227, 185, 1, 185, 190, 185, 221, 225, - 225, 3, 1, 185, 190, 185, 220, 221, - 225, 225, 3, 1, 185, 190, 185, 185, - 185, 185, 185, 185, 191, 185, 220, 221, - 222, 225, 3, 1, 185, 190, 185, 185, - 27, 185, 185, 185, 191, 185, 218, 185, - 245, 185, 232, 232, 3, 1, 185, 190, - 185, 185, 185, 185, 185, 218, 185, 218, - 185, 185, 185, 227, 227, 185, 1, 185, - 190, 185, 185, 185, 185, 185, 218, 185, - 218, 185, 185, 185, 227, 246, 185, 1, - 185, 190, 185, 185, 185, 185, 185, 218, - 185, 218, 185, 245, 185, 227, 227, 185, - 1, 185, 190, 185, 185, 185, 185, 185, - 218, 185, 212, 213, 217, 217, 3, 1, - 185, 190, 185, 185, 185, 185, 185, 185, - 191, 185, 212, 213, 214, 217, 3, 1, - 185, 190, 185, 185, 29, 185, 185, 185, - 191, 185, 210, 185, 247, 185, 232, 232, - 3, 1, 185, 190, 185, 185, 185, 185, - 185, 210, 185, 210, 185, 185, 185, 227, - 227, 185, 1, 185, 190, 185, 185, 185, - 185, 185, 210, 185, 210, 185, 185, 185, - 227, 248, 185, 1, 185, 190, 185, 185, - 185, 185, 185, 210, 185, 210, 185, 247, - 185, 227, 227, 185, 1, 185, 190, 185, - 185, 185, 185, 185, 210, 185, 204, 205, - 209, 209, 3, 1, 185, 190, 185, 185, - 185, 185, 185, 185, 191, 185, 204, 205, - 206, 209, 3, 1, 185, 190, 185, 185, - 31, 185, 185, 185, 191, 185, 202, 185, - 249, 185, 232, 232, 3, 1, 185, 190, - 185, 185, 185, 185, 185, 202, 185, 202, - 185, 185, 185, 227, 227, 185, 1, 185, - 190, 185, 185, 185, 185, 185, 202, 185, - 202, 185, 185, 185, 227, 250, 185, 1, - 185, 190, 185, 185, 185, 185, 185, 202, - 185, 202, 185, 249, 185, 227, 227, 185, - 1, 185, 190, 185, 185, 185, 185, 185, - 202, 185, 196, 197, 201, 201, 3, 1, - 185, 190, 185, 185, 185, 185, 185, 185, - 191, 185, 196, 197, 198, 201, 3, 1, - 185, 190, 185, 185, 33, 185, 185, 185, - 191, 185, 194, 185, 251, 185, 232, 232, - 3, 1, 185, 190, 185, 185, 185, 185, - 185, 194, 185, 194, 185, 185, 185, 227, - 227, 185, 1, 185, 190, 185, 185, 185, - 185, 185, 194, 185, 194, 185, 185, 185, - 227, 252, 185, 1, 185, 190, 185, 185, - 185, 185, 185, 194, 185, 194, 185, 251, - 185, 227, 227, 185, 1, 185, 190, 185, - 185, 185, 185, 185, 194, 185, 186, 187, - 193, 193, 3, 1, 185, 190, 185, 185, - 185, 185, 185, 185, 191, 185, 186, 187, - 188, 193, 3, 1, 185, 190, 185, 185, - 35, 185, 185, 185, 191, 185, 254, 255, - 256, 257, 39, 37, 253, 258, 253, 253, - 71, 253, 253, 253, 259, 253, 260, 255, - 261, 257, 39, 37, 253, 258, 253, 253, - 253, 253, 253, 253, 259, 253, 255, 261, - 257, 39, 37, 253, 258, 253, 253, 253, - 253, 253, 253, 259, 253, 262, 253, 253, - 253, 52, 263, 253, 37, 253, 258, 253, - 253, 253, 253, 253, 262, 253, 264, 265, - 266, 267, 39, 37, 253, 258, 253, 253, - 69, 253, 253, 253, 259, 253, 268, 265, - 269, 269, 39, 37, 253, 258, 253, 253, - 253, 253, 253, 253, 259, 253, 265, 269, - 269, 39, 37, 253, 258, 253, 253, 253, - 253, 253, 253, 259, 253, 270, 253, 253, - 253, 52, 271, 253, 37, 253, 258, 253, - 253, 253, 253, 253, 270, 253, 272, 273, - 274, 275, 39, 37, 253, 258, 253, 253, - 67, 253, 253, 253, 259, 253, 276, 273, - 277, 277, 39, 37, 253, 258, 253, 253, - 253, 253, 253, 253, 259, 253, 273, 277, - 277, 39, 37, 253, 258, 253, 253, 253, - 253, 253, 253, 259, 253, 278, 253, 253, - 253, 52, 279, 253, 37, 253, 258, 253, - 253, 253, 253, 253, 278, 253, 280, 281, - 282, 283, 39, 37, 253, 258, 253, 253, - 65, 253, 253, 253, 259, 253, 284, 281, - 285, 285, 39, 37, 253, 258, 253, 253, - 253, 253, 253, 253, 259, 253, 281, 285, - 285, 39, 37, 253, 258, 253, 253, 253, - 253, 253, 253, 259, 253, 286, 253, 253, - 253, 52, 287, 253, 37, 253, 258, 253, - 253, 253, 253, 253, 286, 253, 288, 289, - 290, 291, 39, 37, 253, 258, 253, 253, - 63, 253, 253, 253, 259, 253, 292, 289, - 293, 293, 39, 37, 253, 258, 253, 253, - 253, 253, 253, 253, 259, 253, 289, 293, - 293, 39, 37, 253, 258, 253, 253, 253, - 253, 253, 253, 259, 253, 52, 294, 253, - 37, 253, 258, 253, 295, 295, 253, 37, - 253, 258, 253, 296, 253, 253, 297, 253, - 258, 253, 258, 253, 298, 253, 299, 253, - 296, 253, 253, 253, 253, 258, 253, 52, - 253, 300, 300, 39, 37, 253, 258, 253, - 301, 61, 302, 303, 42, 37, 253, 258, - 253, 61, 302, 303, 42, 37, 253, 258, - 253, 302, 302, 42, 37, 253, 258, 253, - 304, 58, 305, 306, 45, 37, 253, 258, - 253, 58, 305, 306, 45, 37, 253, 258, - 253, 305, 305, 45, 37, 253, 258, 253, - 307, 55, 308, 309, 48, 37, 253, 258, - 253, 55, 308, 309, 48, 37, 253, 258, - 253, 308, 308, 48, 37, 253, 258, 253, - 310, 52, 295, 311, 253, 37, 253, 258, - 253, 52, 295, 311, 253, 37, 253, 258, - 253, 295, 312, 253, 37, 253, 258, 253, - 52, 253, 295, 295, 253, 37, 253, 258, - 253, 289, 293, 293, 39, 37, 253, 258, - 253, 288, 289, 293, 293, 39, 37, 253, - 258, 253, 253, 253, 253, 253, 253, 259, - 253, 288, 289, 290, 293, 39, 37, 253, - 258, 253, 253, 63, 253, 253, 253, 259, - 253, 286, 253, 313, 253, 300, 300, 39, - 37, 253, 258, 253, 253, 253, 253, 253, - 286, 253, 286, 253, 253, 253, 295, 295, - 253, 37, 253, 258, 253, 253, 253, 253, - 253, 286, 253, 286, 253, 253, 253, 295, - 314, 253, 37, 253, 258, 253, 253, 253, - 253, 253, 286, 253, 286, 253, 313, 253, - 295, 295, 253, 37, 253, 258, 253, 253, - 253, 253, 253, 286, 253, 280, 281, 285, - 285, 39, 37, 253, 258, 253, 253, 253, - 253, 253, 253, 259, 253, 280, 281, 282, - 285, 39, 37, 253, 258, 253, 253, 65, - 253, 253, 253, 259, 253, 278, 253, 315, - 253, 300, 300, 39, 37, 253, 258, 253, - 253, 253, 253, 253, 278, 253, 278, 253, - 253, 253, 295, 295, 253, 37, 253, 258, - 253, 253, 253, 253, 253, 278, 253, 278, - 253, 253, 253, 295, 316, 253, 37, 253, - 258, 253, 253, 253, 253, 253, 278, 253, - 278, 253, 315, 253, 295, 295, 253, 37, - 253, 258, 253, 253, 253, 253, 253, 278, - 253, 272, 273, 277, 277, 39, 37, 253, - 258, 253, 253, 253, 253, 253, 253, 259, - 253, 272, 273, 274, 277, 39, 37, 253, - 258, 253, 253, 67, 253, 253, 253, 259, - 253, 270, 253, 317, 253, 300, 300, 39, - 37, 253, 258, 253, 253, 253, 253, 253, - 270, 253, 270, 253, 253, 253, 295, 295, - 253, 37, 253, 258, 253, 253, 253, 253, - 253, 270, 253, 270, 253, 253, 253, 295, - 318, 253, 37, 253, 258, 253, 253, 253, - 253, 253, 270, 253, 270, 253, 317, 253, - 295, 295, 253, 37, 253, 258, 253, 253, - 253, 253, 253, 270, 253, 264, 265, 269, - 269, 39, 37, 253, 258, 253, 253, 253, - 253, 253, 253, 259, 253, 264, 265, 266, - 269, 39, 37, 253, 258, 253, 253, 69, - 253, 253, 253, 259, 253, 262, 253, 319, - 253, 300, 300, 39, 37, 253, 258, 253, - 253, 253, 253, 253, 262, 253, 262, 253, - 253, 253, 295, 295, 253, 37, 253, 258, - 253, 253, 253, 253, 253, 262, 253, 262, - 253, 253, 253, 295, 320, 253, 37, 253, - 258, 253, 253, 253, 253, 253, 262, 253, - 262, 253, 319, 253, 295, 295, 253, 37, - 253, 258, 253, 253, 253, 253, 253, 262, - 253, 70, 38, 38, 39, 37, 253, 254, - 255, 261, 257, 39, 37, 253, 258, 253, - 253, 253, 253, 253, 253, 259, 253, 322, - 175, 323, 323, 75, 73, 321, 178, 321, - 321, 321, 321, 321, 321, 182, 321, 175, - 323, 323, 75, 73, 321, 178, 321, 321, - 321, 321, 321, 321, 182, 321, 324, 321, - 321, 321, 89, 325, 321, 73, 321, 178, - 321, 321, 321, 321, 321, 324, 321, 326, - 327, 328, 329, 75, 73, 321, 178, 321, - 321, 106, 321, 321, 321, 182, 321, 330, - 327, 331, 331, 75, 73, 321, 178, 321, - 321, 321, 321, 321, 321, 182, 321, 327, - 331, 331, 75, 73, 321, 178, 321, 321, - 321, 321, 321, 321, 182, 321, 332, 321, - 321, 321, 89, 333, 321, 73, 321, 178, - 321, 321, 321, 321, 321, 332, 321, 334, - 335, 336, 337, 75, 73, 321, 178, 321, - 321, 104, 321, 321, 321, 182, 321, 338, - 335, 339, 339, 75, 73, 321, 178, 321, - 321, 321, 321, 321, 321, 182, 321, 335, - 339, 339, 75, 73, 321, 178, 321, 321, - 321, 321, 321, 321, 182, 321, 340, 321, - 321, 321, 89, 341, 321, 73, 321, 178, - 321, 321, 321, 321, 321, 340, 321, 342, - 343, 344, 345, 75, 73, 321, 178, 321, - 321, 102, 321, 321, 321, 182, 321, 346, - 343, 347, 347, 75, 73, 321, 178, 321, - 321, 321, 321, 321, 321, 182, 321, 343, - 347, 347, 75, 73, 321, 178, 321, 321, - 321, 321, 321, 321, 182, 321, 348, 321, - 321, 321, 89, 349, 321, 73, 321, 178, - 321, 321, 321, 321, 321, 348, 321, 350, - 351, 352, 353, 75, 73, 321, 178, 321, - 321, 100, 321, 321, 321, 182, 321, 354, - 351, 355, 355, 75, 73, 321, 178, 321, - 321, 321, 321, 321, 321, 182, 321, 351, - 355, 355, 75, 73, 321, 178, 321, 321, - 321, 321, 321, 321, 182, 321, 89, 356, - 321, 73, 321, 178, 321, 357, 357, 321, - 73, 321, 178, 321, 358, 321, 321, 359, - 321, 178, 321, 178, 321, 360, 321, 361, - 321, 358, 321, 321, 321, 321, 178, 321, - 89, 321, 362, 362, 75, 73, 321, 178, - 321, 363, 98, 364, 365, 79, 73, 321, - 178, 321, 98, 364, 365, 79, 73, 321, - 178, 321, 364, 364, 79, 73, 321, 178, - 321, 366, 95, 367, 368, 82, 73, 321, - 178, 321, 95, 367, 368, 82, 73, 321, - 178, 321, 367, 367, 82, 73, 321, 178, - 321, 369, 92, 370, 371, 85, 73, 321, - 178, 321, 92, 370, 371, 85, 73, 321, - 178, 321, 370, 370, 85, 73, 321, 178, - 321, 372, 89, 357, 373, 321, 73, 321, - 178, 321, 89, 357, 373, 321, 73, 321, - 178, 321, 357, 374, 321, 73, 321, 178, - 321, 89, 321, 357, 357, 321, 73, 321, - 178, 321, 351, 355, 355, 75, 73, 321, - 178, 321, 350, 351, 355, 355, 75, 73, - 321, 178, 321, 321, 321, 321, 321, 321, - 182, 321, 350, 351, 352, 355, 75, 73, - 321, 178, 321, 321, 100, 321, 321, 321, - 182, 321, 348, 321, 375, 321, 362, 362, - 75, 73, 321, 178, 321, 321, 321, 321, - 321, 348, 321, 348, 321, 321, 321, 357, - 357, 321, 73, 321, 178, 321, 321, 321, - 321, 321, 348, 321, 348, 321, 321, 321, - 357, 376, 321, 73, 321, 178, 321, 321, - 321, 321, 321, 348, 321, 348, 321, 375, - 321, 357, 357, 321, 73, 321, 178, 321, - 321, 321, 321, 321, 348, 321, 342, 343, - 347, 347, 75, 73, 321, 178, 321, 321, - 321, 321, 321, 321, 182, 321, 342, 343, - 344, 347, 75, 73, 321, 178, 321, 321, - 102, 321, 321, 321, 182, 321, 340, 321, - 377, 321, 362, 362, 75, 73, 321, 178, - 321, 321, 321, 321, 321, 340, 321, 340, - 321, 321, 321, 357, 357, 321, 73, 321, - 178, 321, 321, 321, 321, 321, 340, 321, - 340, 321, 321, 321, 357, 378, 321, 73, - 321, 178, 321, 321, 321, 321, 321, 340, - 321, 340, 321, 377, 321, 357, 357, 321, - 73, 321, 178, 321, 321, 321, 321, 321, - 340, 321, 334, 335, 339, 339, 75, 73, - 321, 178, 321, 321, 321, 321, 321, 321, - 182, 321, 334, 335, 336, 339, 75, 73, - 321, 178, 321, 321, 104, 321, 321, 321, - 182, 321, 332, 321, 379, 321, 362, 362, - 75, 73, 321, 178, 321, 321, 321, 321, - 321, 332, 321, 332, 321, 321, 321, 357, - 357, 321, 73, 321, 178, 321, 321, 321, - 321, 321, 332, 321, 332, 321, 321, 321, - 357, 380, 321, 73, 321, 178, 321, 321, - 321, 321, 321, 332, 321, 332, 321, 379, - 321, 357, 357, 321, 73, 321, 178, 321, - 321, 321, 321, 321, 332, 321, 326, 327, - 331, 331, 75, 73, 321, 178, 321, 321, - 321, 321, 321, 321, 182, 321, 326, 327, - 328, 331, 75, 73, 321, 178, 321, 321, - 106, 321, 321, 321, 182, 321, 324, 321, - 381, 321, 362, 362, 75, 73, 321, 178, - 321, 321, 321, 321, 321, 324, 321, 324, - 321, 321, 321, 357, 357, 321, 73, 321, - 178, 321, 321, 321, 321, 321, 324, 321, - 324, 321, 321, 321, 357, 382, 321, 73, - 321, 178, 321, 321, 321, 321, 321, 324, - 321, 324, 321, 381, 321, 357, 357, 321, - 73, 321, 178, 321, 321, 321, 321, 321, - 324, 321, 107, 74, 74, 75, 73, 383, - 383, 383, 383, 144, 383, 174, 175, 323, - 323, 75, 73, 321, 178, 321, 321, 321, - 321, 321, 321, 182, 321, 107, 74, 74, - 75, 73, 383, 385, 386, 387, 388, 111, - 109, 384, 389, 384, 384, 143, 384, 384, - 384, 390, 384, 391, 386, 388, 388, 111, - 109, 384, 389, 384, 384, 384, 384, 384, - 384, 390, 384, 386, 388, 388, 111, 109, - 384, 389, 384, 384, 384, 384, 384, 384, - 390, 384, 392, 384, 384, 384, 124, 393, - 384, 109, 384, 389, 384, 384, 384, 384, - 384, 392, 384, 394, 395, 396, 397, 111, - 109, 384, 389, 384, 384, 141, 384, 384, - 384, 390, 384, 398, 395, 399, 399, 111, - 109, 384, 389, 384, 384, 384, 384, 384, - 384, 390, 384, 395, 399, 399, 111, 109, - 384, 389, 384, 384, 384, 384, 384, 384, - 390, 384, 400, 384, 384, 384, 124, 401, - 384, 109, 384, 389, 384, 384, 384, 384, - 384, 400, 384, 402, 403, 404, 405, 111, - 109, 384, 389, 384, 384, 139, 384, 384, - 384, 390, 384, 406, 403, 407, 407, 111, - 109, 384, 389, 384, 384, 384, 384, 384, - 384, 390, 384, 403, 407, 407, 111, 109, - 384, 389, 384, 384, 384, 384, 384, 384, - 390, 384, 408, 384, 384, 384, 124, 409, - 384, 109, 384, 389, 384, 384, 384, 384, - 384, 408, 384, 410, 411, 412, 413, 111, - 109, 384, 389, 384, 384, 137, 384, 384, - 384, 390, 384, 414, 411, 415, 415, 111, - 109, 384, 389, 384, 384, 384, 384, 384, - 384, 390, 384, 411, 415, 415, 111, 109, - 384, 389, 384, 384, 384, 384, 384, 384, - 390, 384, 416, 384, 384, 384, 124, 417, - 384, 109, 384, 389, 384, 384, 384, 384, - 384, 416, 384, 418, 419, 420, 421, 111, - 109, 384, 389, 384, 384, 135, 384, 384, - 384, 390, 384, 422, 419, 423, 423, 111, - 109, 384, 389, 384, 384, 384, 384, 384, - 384, 390, 384, 419, 423, 423, 111, 109, - 384, 389, 384, 384, 384, 384, 384, 384, - 390, 384, 124, 424, 384, 109, 384, 389, - 384, 425, 425, 384, 109, 384, 389, 384, - 426, 384, 384, 427, 384, 389, 384, 389, - 384, 428, 384, 429, 384, 426, 384, 384, - 384, 384, 389, 384, 124, 384, 430, 430, - 111, 109, 384, 389, 384, 431, 133, 432, - 433, 114, 109, 384, 389, 384, 133, 432, - 433, 114, 109, 384, 389, 384, 432, 432, - 114, 109, 384, 389, 384, 434, 130, 435, - 436, 117, 109, 384, 389, 384, 130, 435, - 436, 117, 109, 384, 389, 384, 435, 435, - 117, 109, 384, 389, 384, 437, 127, 438, - 439, 120, 109, 384, 389, 384, 127, 438, - 439, 120, 109, 384, 389, 384, 438, 438, - 120, 109, 384, 389, 384, 440, 124, 425, - 441, 384, 109, 384, 389, 384, 124, 425, - 441, 384, 109, 384, 389, 384, 425, 442, - 384, 109, 384, 389, 384, 124, 384, 425, - 425, 384, 109, 384, 389, 384, 419, 423, - 423, 111, 109, 384, 389, 384, 418, 419, - 423, 423, 111, 109, 384, 389, 384, 384, - 384, 384, 384, 384, 390, 384, 418, 419, - 420, 423, 111, 109, 384, 389, 384, 384, - 135, 384, 384, 384, 390, 384, 416, 384, - 443, 384, 430, 430, 111, 109, 384, 389, - 384, 384, 384, 384, 384, 416, 384, 416, - 384, 384, 384, 425, 425, 384, 109, 384, - 389, 384, 384, 384, 384, 384, 416, 384, - 416, 384, 384, 384, 425, 444, 384, 109, - 384, 389, 384, 384, 384, 384, 384, 416, - 384, 416, 384, 443, 384, 425, 425, 384, - 109, 384, 389, 384, 384, 384, 384, 384, - 416, 384, 410, 411, 415, 415, 111, 109, - 384, 389, 384, 384, 384, 384, 384, 384, - 390, 384, 410, 411, 412, 415, 111, 109, - 384, 389, 384, 384, 137, 384, 384, 384, - 390, 384, 408, 384, 445, 384, 430, 430, - 111, 109, 384, 389, 384, 384, 384, 384, - 384, 408, 384, 408, 384, 384, 384, 425, - 425, 384, 109, 384, 389, 384, 384, 384, - 384, 384, 408, 384, 408, 384, 384, 384, - 425, 446, 384, 109, 384, 389, 384, 384, - 384, 384, 384, 408, 384, 408, 384, 445, - 384, 425, 425, 384, 109, 384, 389, 384, - 384, 384, 384, 384, 408, 384, 402, 403, - 407, 407, 111, 109, 384, 389, 384, 384, - 384, 384, 384, 384, 390, 384, 402, 403, - 404, 407, 111, 109, 384, 389, 384, 384, - 139, 384, 384, 384, 390, 384, 400, 384, - 447, 384, 430, 430, 111, 109, 384, 389, - 384, 384, 384, 384, 384, 400, 384, 400, - 384, 384, 384, 425, 425, 384, 109, 384, - 389, 384, 384, 384, 384, 384, 400, 384, - 400, 384, 384, 384, 425, 448, 384, 109, - 384, 389, 384, 384, 384, 384, 384, 400, - 384, 400, 384, 447, 384, 425, 425, 384, - 109, 384, 389, 384, 384, 384, 384, 384, - 400, 384, 394, 395, 399, 399, 111, 109, - 384, 389, 384, 384, 384, 384, 384, 384, - 390, 384, 394, 395, 396, 399, 111, 109, - 384, 389, 384, 384, 141, 384, 384, 384, - 390, 384, 392, 384, 449, 384, 430, 430, - 111, 109, 384, 389, 384, 384, 384, 384, - 384, 392, 384, 392, 384, 384, 384, 425, - 425, 384, 109, 384, 389, 384, 384, 384, - 384, 384, 392, 384, 392, 384, 384, 384, - 425, 450, 384, 109, 384, 389, 384, 384, - 384, 384, 384, 392, 384, 392, 384, 449, - 384, 425, 425, 384, 109, 384, 389, 384, - 384, 384, 384, 384, 392, 384, 385, 386, - 388, 388, 111, 109, 384, 389, 384, 384, - 384, 384, 384, 384, 390, 384, 172, 173, - 174, 175, 451, 323, 75, 73, 321, 178, - 179, 179, 144, 321, 321, 172, 182, 321, - 186, 452, 188, 189, 3, 1, 185, 190, - 185, 185, 35, 185, 185, 185, 191, 185, - 194, 173, 174, 175, 453, 454, 75, 149, - 185, 455, 185, 179, 144, 185, 185, 194, - 182, 185, 107, 456, 456, 75, 149, 185, - 190, 185, 185, 144, 185, 457, 185, 185, - 458, 185, 455, 185, 455, 185, 459, 185, - 231, 185, 457, 185, 185, 185, 185, 455, - 185, 194, 185, 251, 107, 460, 460, 146, - 149, 185, 190, 185, 185, 185, 185, 185, - 194, 185, 461, 168, 462, 463, 148, 149, - 185, 455, 185, 168, 462, 463, 148, 149, - 185, 455, 185, 462, 462, 148, 149, 185, - 455, 185, 464, 165, 465, 466, 152, 149, - 185, 455, 185, 165, 465, 466, 152, 149, - 185, 455, 185, 465, 465, 152, 149, 185, - 455, 185, 467, 162, 468, 469, 155, 149, - 185, 455, 185, 162, 468, 469, 155, 149, - 185, 455, 185, 468, 468, 155, 149, 185, - 455, 185, 470, 159, 471, 472, 185, 149, - 185, 455, 185, 159, 471, 472, 185, 149, - 185, 455, 185, 471, 471, 185, 149, 185, - 455, 185, 474, 473, 475, 475, 473, 170, - 473, 476, 473, 475, 475, 473, 170, 473, - 476, 473, 477, 473, 473, 478, 473, 476, - 473, 476, 473, 479, 473, 480, 473, 477, - 473, 473, 473, 473, 476, 473, 172, 383, - 383, 383, 383, 383, 383, 383, 383, 383, - 179, 383, 383, 383, 383, 172, 383, 0 + 1, 0, 2, 3, 3, 4, 1, 0, + 5, 5, 4, 0, 4, 0, 6, 6, + 7, 1, 0, 8, 8, 7, 0, 7, + 0, 9, 9, 10, 1, 0, 11, 11, + 10, 0, 10, 0, 12, 12, 13, 1, + 0, 14, 14, 13, 0, 13, 0, 15, + 0, 0, 0, 1, 0, 16, 0, 17, + 0, 18, 12, 12, 13, 1, 0, 19, + 0, 20, 0, 21, 9, 9, 10, 1, + 0, 22, 0, 23, 0, 24, 6, 6, + 7, 1, 0, 25, 0, 26, 0, 2, + 3, 3, 4, 1, 0, 0, 0, 0, + 27, 0, 28, 3, 3, 4, 1, 0, + 28, 3, 3, 4, 1, 0, 0, 0, + 0, 29, 0, 30, 3, 3, 4, 1, + 0, 30, 3, 3, 4, 1, 0, 0, + 0, 0, 31, 0, 32, 3, 3, 4, + 1, 0, 32, 3, 3, 4, 1, 0, + 0, 0, 0, 33, 0, 34, 3, 3, + 4, 1, 0, 34, 3, 3, 4, 1, + 0, 0, 0, 0, 35, 0, 37, 36, + 38, 39, 39, 40, 37, 36, 41, 41, + 40, 36, 40, 36, 42, 42, 43, 37, + 36, 44, 44, 43, 36, 43, 36, 45, + 45, 46, 37, 36, 47, 47, 46, 36, + 46, 36, 48, 48, 49, 37, 36, 50, + 50, 49, 36, 49, 36, 51, 36, 36, + 36, 37, 36, 52, 36, 53, 36, 54, + 48, 48, 49, 37, 36, 55, 36, 56, + 36, 57, 45, 45, 46, 37, 36, 58, + 36, 59, 36, 60, 42, 42, 43, 37, + 36, 61, 36, 62, 36, 38, 39, 39, + 40, 37, 36, 36, 36, 36, 63, 36, + 64, 39, 39, 40, 37, 36, 64, 39, + 39, 40, 37, 36, 36, 36, 36, 65, + 36, 66, 39, 39, 40, 37, 36, 66, + 39, 39, 40, 37, 36, 36, 36, 36, + 67, 36, 68, 39, 39, 40, 37, 36, + 68, 39, 39, 40, 37, 36, 36, 36, + 36, 69, 36, 70, 39, 39, 40, 37, + 36, 70, 39, 39, 40, 37, 36, 36, + 36, 36, 71, 36, 73, 72, 74, 75, + 75, 76, 73, 72, 78, 78, 76, 77, + 76, 77, 79, 79, 80, 73, 72, 81, + 81, 80, 72, 80, 72, 82, 82, 83, + 73, 72, 84, 84, 83, 72, 83, 72, + 85, 85, 86, 73, 72, 87, 87, 86, + 72, 86, 72, 88, 72, 72, 72, 73, + 72, 89, 72, 90, 72, 91, 85, 85, + 86, 73, 72, 92, 72, 93, 72, 94, + 82, 82, 83, 73, 72, 95, 72, 96, + 72, 97, 79, 79, 80, 73, 72, 98, + 72, 99, 72, 74, 75, 75, 76, 73, + 72, 72, 72, 72, 100, 72, 101, 75, + 75, 76, 73, 72, 101, 75, 75, 76, + 73, 72, 72, 72, 72, 102, 72, 103, + 75, 75, 76, 73, 72, 103, 75, 75, + 76, 73, 72, 72, 72, 72, 104, 72, + 105, 75, 75, 76, 73, 72, 105, 75, + 75, 76, 73, 72, 72, 72, 72, 106, + 72, 107, 75, 75, 76, 73, 72, 109, + 108, 110, 111, 111, 112, 109, 108, 113, + 113, 112, 108, 112, 108, 114, 114, 115, + 109, 108, 116, 116, 115, 108, 115, 108, + 117, 117, 118, 109, 108, 119, 119, 118, + 108, 118, 108, 120, 120, 121, 109, 108, + 122, 122, 121, 108, 121, 108, 123, 108, + 108, 108, 109, 108, 124, 108, 125, 108, + 126, 120, 120, 121, 109, 108, 127, 108, + 128, 108, 129, 117, 117, 118, 109, 108, + 130, 108, 131, 108, 132, 114, 114, 115, + 109, 108, 133, 108, 134, 108, 110, 111, + 111, 112, 109, 108, 108, 108, 108, 135, + 108, 136, 111, 111, 112, 109, 108, 136, + 111, 111, 112, 109, 108, 108, 108, 108, + 137, 108, 138, 111, 111, 112, 109, 108, + 138, 111, 111, 112, 109, 108, 108, 108, + 108, 139, 108, 140, 111, 111, 112, 109, + 108, 140, 111, 111, 112, 109, 108, 108, + 108, 108, 141, 108, 142, 111, 111, 112, + 109, 108, 142, 111, 111, 112, 109, 108, + 108, 108, 108, 143, 108, 107, 75, 75, + 76, 73, 72, 72, 72, 72, 144, 72, + 78, 78, 76, 1, 0, 146, 145, 148, + 149, 150, 151, 152, 153, 76, 73, 147, + 154, 155, 155, 144, 147, 156, 157, 147, + 158, 159, 147, 161, 162, 163, 164, 4, + 1, 160, 165, 160, 160, 35, 160, 166, + 162, 167, 167, 4, 1, 160, 165, 160, + 162, 167, 167, 4, 1, 160, 165, 160, + 168, 160, 160, 160, 17, 169, 160, 1, + 160, 165, 160, 160, 160, 160, 160, 168, + 160, 170, 171, 172, 173, 4, 1, 160, + 165, 160, 160, 33, 160, 174, 171, 175, + 175, 4, 1, 160, 165, 160, 171, 175, + 175, 4, 1, 160, 165, 160, 176, 160, + 160, 160, 17, 177, 160, 1, 160, 165, + 160, 160, 160, 160, 160, 176, 160, 178, + 179, 180, 181, 4, 1, 160, 165, 160, + 160, 31, 160, 182, 179, 183, 183, 4, + 1, 160, 165, 160, 179, 183, 183, 4, + 1, 160, 165, 160, 184, 160, 160, 160, + 17, 185, 160, 1, 160, 165, 160, 160, + 160, 160, 160, 184, 160, 186, 187, 188, + 189, 4, 1, 160, 165, 160, 160, 29, + 160, 190, 187, 191, 191, 4, 1, 160, + 165, 160, 187, 191, 191, 4, 1, 160, + 165, 160, 192, 160, 160, 160, 17, 193, + 160, 1, 160, 165, 160, 160, 160, 160, + 160, 192, 160, 194, 195, 196, 197, 4, + 1, 160, 165, 160, 160, 27, 160, 198, + 195, 199, 199, 4, 1, 160, 165, 160, + 195, 199, 199, 4, 1, 160, 165, 160, + 17, 200, 160, 1, 160, 165, 160, 201, + 201, 160, 1, 160, 165, 160, 202, 160, + 160, 203, 160, 165, 160, 165, 160, 204, + 160, 205, 160, 202, 160, 160, 160, 160, + 165, 160, 17, 160, 201, 201, 160, 1, + 160, 165, 160, 201, 200, 160, 1, 160, + 165, 160, 206, 26, 207, 208, 7, 1, + 160, 165, 160, 26, 207, 208, 7, 1, + 160, 165, 160, 207, 207, 7, 1, 160, + 165, 160, 209, 23, 210, 211, 10, 1, + 160, 165, 160, 23, 210, 211, 10, 1, + 160, 165, 160, 210, 210, 10, 1, 160, + 165, 160, 212, 20, 213, 214, 13, 1, + 160, 165, 160, 20, 213, 214, 13, 1, + 160, 165, 160, 213, 213, 13, 1, 160, + 165, 160, 215, 17, 201, 216, 160, 1, + 160, 165, 160, 17, 201, 216, 160, 1, + 160, 165, 160, 194, 195, 199, 199, 4, + 1, 160, 165, 160, 194, 195, 196, 199, + 4, 1, 160, 165, 160, 160, 27, 160, + 192, 160, 217, 160, 201, 201, 160, 1, + 160, 165, 160, 160, 160, 160, 160, 192, + 160, 192, 160, 160, 160, 201, 201, 160, + 1, 160, 165, 160, 160, 160, 160, 160, + 192, 160, 192, 160, 160, 160, 201, 193, + 160, 1, 160, 165, 160, 160, 160, 160, + 160, 192, 160, 186, 187, 191, 191, 4, + 1, 160, 165, 160, 186, 187, 188, 191, + 4, 1, 160, 165, 160, 160, 29, 160, + 184, 160, 218, 160, 201, 201, 160, 1, + 160, 165, 160, 160, 160, 160, 160, 184, + 160, 184, 160, 160, 160, 201, 201, 160, + 1, 160, 165, 160, 160, 160, 160, 160, + 184, 160, 184, 160, 160, 160, 201, 185, + 160, 1, 160, 165, 160, 160, 160, 160, + 160, 184, 160, 178, 179, 183, 183, 4, + 1, 160, 165, 160, 178, 179, 180, 183, + 4, 1, 160, 165, 160, 160, 31, 160, + 176, 160, 219, 160, 201, 201, 160, 1, + 160, 165, 160, 160, 160, 160, 160, 176, + 160, 176, 160, 160, 160, 201, 201, 160, + 1, 160, 165, 160, 160, 160, 160, 160, + 176, 160, 176, 160, 160, 160, 201, 177, + 160, 1, 160, 165, 160, 160, 160, 160, + 160, 176, 160, 170, 171, 175, 175, 4, + 1, 160, 165, 160, 170, 171, 172, 175, + 4, 1, 160, 165, 160, 160, 33, 160, + 168, 160, 220, 160, 201, 201, 160, 1, + 160, 165, 160, 160, 160, 160, 160, 168, + 160, 168, 160, 160, 160, 201, 201, 160, + 1, 160, 165, 160, 160, 160, 160, 160, + 168, 160, 168, 160, 160, 160, 201, 169, + 160, 1, 160, 165, 160, 160, 160, 160, + 160, 168, 160, 161, 162, 167, 167, 4, + 1, 160, 165, 160, 161, 162, 163, 167, + 4, 1, 160, 165, 160, 160, 35, 160, + 222, 223, 224, 225, 40, 37, 221, 226, + 221, 221, 71, 221, 227, 223, 228, 225, + 40, 37, 221, 226, 221, 223, 228, 225, + 40, 37, 221, 226, 221, 229, 221, 221, + 221, 53, 230, 221, 37, 221, 226, 221, + 221, 221, 221, 221, 229, 221, 231, 232, + 233, 234, 40, 37, 221, 226, 221, 221, + 69, 221, 235, 232, 236, 236, 40, 37, + 221, 226, 221, 232, 236, 236, 40, 37, + 221, 226, 221, 237, 221, 221, 221, 53, + 238, 221, 37, 221, 226, 221, 221, 221, + 221, 221, 237, 221, 239, 240, 241, 242, + 40, 37, 221, 226, 221, 221, 67, 221, + 243, 240, 244, 244, 40, 37, 221, 226, + 221, 240, 244, 244, 40, 37, 221, 226, + 221, 245, 221, 221, 221, 53, 246, 221, + 37, 221, 226, 221, 221, 221, 221, 221, + 245, 221, 247, 248, 249, 250, 40, 37, + 221, 226, 221, 221, 65, 221, 251, 248, + 252, 252, 40, 37, 221, 226, 221, 248, + 252, 252, 40, 37, 221, 226, 221, 253, + 221, 221, 221, 53, 254, 221, 37, 221, + 226, 221, 221, 221, 221, 221, 253, 221, + 255, 256, 257, 258, 40, 37, 221, 226, + 221, 221, 63, 221, 259, 256, 260, 260, + 40, 37, 221, 226, 221, 256, 260, 260, + 40, 37, 221, 226, 221, 53, 261, 221, + 37, 221, 226, 221, 262, 262, 221, 37, + 221, 226, 221, 263, 221, 221, 264, 221, + 226, 221, 226, 221, 265, 221, 266, 221, + 263, 221, 221, 221, 221, 226, 221, 53, + 221, 262, 262, 221, 37, 221, 226, 221, + 262, 261, 221, 37, 221, 226, 221, 267, + 62, 268, 269, 43, 37, 221, 226, 221, + 62, 268, 269, 43, 37, 221, 226, 221, + 268, 268, 43, 37, 221, 226, 221, 270, + 59, 271, 272, 46, 37, 221, 226, 221, + 59, 271, 272, 46, 37, 221, 226, 221, + 271, 271, 46, 37, 221, 226, 221, 273, + 56, 274, 275, 49, 37, 221, 226, 221, + 56, 274, 275, 49, 37, 221, 226, 221, + 274, 274, 49, 37, 221, 226, 221, 276, + 53, 262, 277, 221, 37, 221, 226, 221, + 53, 262, 277, 221, 37, 221, 226, 221, + 255, 256, 260, 260, 40, 37, 221, 226, + 221, 255, 256, 257, 260, 40, 37, 221, + 226, 221, 221, 63, 221, 253, 221, 278, + 221, 262, 262, 221, 37, 221, 226, 221, + 221, 221, 221, 221, 253, 221, 253, 221, + 221, 221, 262, 262, 221, 37, 221, 226, + 221, 221, 221, 221, 221, 253, 221, 253, + 221, 221, 221, 262, 254, 221, 37, 221, + 226, 221, 221, 221, 221, 221, 253, 221, + 247, 248, 252, 252, 40, 37, 221, 226, + 221, 247, 248, 249, 252, 40, 37, 221, + 226, 221, 221, 65, 221, 245, 221, 279, + 221, 262, 262, 221, 37, 221, 226, 221, + 221, 221, 221, 221, 245, 221, 245, 221, + 221, 221, 262, 262, 221, 37, 221, 226, + 221, 221, 221, 221, 221, 245, 221, 245, + 221, 221, 221, 262, 246, 221, 37, 221, + 226, 221, 221, 221, 221, 221, 245, 221, + 239, 240, 244, 244, 40, 37, 221, 226, + 221, 239, 240, 241, 244, 40, 37, 221, + 226, 221, 221, 67, 221, 237, 221, 280, + 221, 262, 262, 221, 37, 221, 226, 221, + 221, 221, 221, 221, 237, 221, 237, 221, + 221, 221, 262, 262, 221, 37, 221, 226, + 221, 221, 221, 221, 221, 237, 221, 237, + 221, 221, 221, 262, 238, 221, 37, 221, + 226, 221, 221, 221, 221, 221, 237, 221, + 231, 232, 236, 236, 40, 37, 221, 226, + 221, 231, 232, 233, 236, 40, 37, 221, + 226, 221, 221, 69, 221, 229, 221, 281, + 221, 262, 262, 221, 37, 221, 226, 221, + 221, 221, 221, 221, 229, 221, 229, 221, + 221, 221, 262, 262, 221, 37, 221, 226, + 221, 221, 221, 221, 221, 229, 221, 229, + 221, 221, 221, 262, 230, 221, 37, 221, + 226, 221, 221, 221, 221, 221, 229, 221, + 70, 39, 39, 40, 37, 221, 222, 223, + 228, 225, 40, 37, 221, 226, 221, 283, + 151, 284, 284, 76, 73, 282, 154, 282, + 151, 284, 284, 76, 73, 282, 154, 282, + 285, 282, 282, 282, 90, 286, 282, 73, + 282, 154, 282, 282, 282, 282, 282, 285, + 282, 287, 288, 289, 290, 76, 73, 282, + 154, 282, 282, 106, 282, 291, 288, 292, + 292, 76, 73, 282, 154, 282, 288, 292, + 292, 76, 73, 282, 154, 282, 293, 282, + 282, 282, 90, 294, 282, 73, 282, 154, + 282, 282, 282, 282, 282, 293, 282, 295, + 296, 297, 298, 76, 73, 282, 154, 282, + 282, 104, 282, 299, 296, 300, 300, 76, + 73, 282, 154, 282, 296, 300, 300, 76, + 73, 282, 154, 282, 301, 282, 282, 282, + 90, 302, 282, 73, 282, 154, 282, 282, + 282, 282, 282, 301, 282, 303, 304, 305, + 306, 76, 73, 282, 154, 282, 282, 102, + 282, 307, 304, 308, 308, 76, 73, 282, + 154, 282, 304, 308, 308, 76, 73, 282, + 154, 282, 309, 282, 282, 282, 90, 310, + 282, 73, 282, 154, 282, 282, 282, 282, + 282, 309, 282, 311, 312, 313, 314, 76, + 73, 282, 154, 282, 282, 100, 282, 315, + 312, 316, 316, 76, 73, 282, 154, 282, + 312, 316, 316, 76, 73, 282, 154, 282, + 90, 317, 282, 73, 282, 154, 282, 318, + 318, 282, 73, 282, 154, 282, 319, 282, + 282, 320, 282, 154, 282, 154, 282, 321, + 282, 322, 282, 319, 282, 282, 282, 282, + 154, 282, 90, 282, 318, 318, 282, 73, + 282, 154, 282, 318, 317, 282, 73, 282, + 154, 282, 323, 99, 324, 325, 80, 73, + 282, 154, 282, 99, 324, 325, 80, 73, + 282, 154, 282, 324, 324, 80, 73, 282, + 154, 282, 326, 96, 327, 328, 83, 73, + 282, 154, 282, 96, 327, 328, 83, 73, + 282, 154, 282, 327, 327, 83, 73, 282, + 154, 282, 329, 93, 330, 331, 86, 73, + 282, 154, 282, 93, 330, 331, 86, 73, + 282, 154, 282, 330, 330, 86, 73, 282, + 154, 282, 332, 90, 318, 333, 282, 73, + 282, 154, 282, 90, 318, 333, 282, 73, + 282, 154, 282, 311, 312, 316, 316, 76, + 73, 282, 154, 282, 311, 312, 313, 316, + 76, 73, 282, 154, 282, 282, 100, 282, + 309, 282, 334, 282, 318, 318, 282, 73, + 282, 154, 282, 282, 282, 282, 282, 309, + 282, 309, 282, 282, 282, 318, 318, 282, + 73, 282, 154, 282, 282, 282, 282, 282, + 309, 282, 309, 282, 282, 282, 318, 310, + 282, 73, 282, 154, 282, 282, 282, 282, + 282, 309, 282, 303, 304, 308, 308, 76, + 73, 282, 154, 282, 303, 304, 305, 308, + 76, 73, 282, 154, 282, 282, 102, 282, + 301, 282, 335, 282, 318, 318, 282, 73, + 282, 154, 282, 282, 282, 282, 282, 301, + 282, 301, 282, 282, 282, 318, 318, 282, + 73, 282, 154, 282, 282, 282, 282, 282, + 301, 282, 301, 282, 282, 282, 318, 302, + 282, 73, 282, 154, 282, 282, 282, 282, + 282, 301, 282, 295, 296, 300, 300, 76, + 73, 282, 154, 282, 295, 296, 297, 300, + 76, 73, 282, 154, 282, 282, 104, 282, + 293, 282, 336, 282, 318, 318, 282, 73, + 282, 154, 282, 282, 282, 282, 282, 293, + 282, 293, 282, 282, 282, 318, 318, 282, + 73, 282, 154, 282, 282, 282, 282, 282, + 293, 282, 293, 282, 282, 282, 318, 294, + 282, 73, 282, 154, 282, 282, 282, 282, + 282, 293, 282, 287, 288, 292, 292, 76, + 73, 282, 154, 282, 287, 288, 289, 292, + 76, 73, 282, 154, 282, 282, 106, 282, + 285, 282, 337, 282, 318, 318, 282, 73, + 282, 154, 282, 282, 282, 282, 282, 285, + 282, 285, 282, 282, 282, 318, 318, 282, + 73, 282, 154, 282, 282, 282, 282, 282, + 285, 282, 285, 282, 282, 282, 318, 286, + 282, 73, 282, 154, 282, 282, 282, 282, + 282, 285, 282, 107, 75, 75, 76, 73, + 338, 338, 338, 338, 144, 338, 150, 151, + 284, 284, 76, 73, 282, 154, 282, 107, + 75, 75, 76, 73, 338, 340, 341, 342, + 343, 112, 109, 339, 344, 339, 339, 143, + 339, 345, 341, 343, 343, 112, 109, 339, + 344, 339, 341, 343, 343, 112, 109, 339, + 344, 339, 346, 339, 339, 339, 125, 347, + 339, 109, 339, 344, 339, 339, 339, 339, + 339, 346, 339, 348, 349, 350, 351, 112, + 109, 339, 344, 339, 339, 141, 339, 352, + 349, 353, 353, 112, 109, 339, 344, 339, + 349, 353, 353, 112, 109, 339, 344, 339, + 354, 339, 339, 339, 125, 355, 339, 109, + 339, 344, 339, 339, 339, 339, 339, 354, + 339, 356, 357, 358, 359, 112, 109, 339, + 344, 339, 339, 139, 339, 360, 357, 361, + 361, 112, 109, 339, 344, 339, 357, 361, + 361, 112, 109, 339, 344, 339, 362, 339, + 339, 339, 125, 363, 339, 109, 339, 344, + 339, 339, 339, 339, 339, 362, 339, 364, + 365, 366, 367, 112, 109, 339, 344, 339, + 339, 137, 339, 368, 365, 369, 369, 112, + 109, 339, 344, 339, 365, 369, 369, 112, + 109, 339, 344, 339, 370, 339, 339, 339, + 125, 371, 339, 109, 339, 344, 339, 339, + 339, 339, 339, 370, 339, 372, 373, 374, + 375, 112, 109, 339, 344, 339, 339, 135, + 339, 376, 373, 377, 377, 112, 109, 339, + 344, 339, 373, 377, 377, 112, 109, 339, + 344, 339, 125, 378, 339, 109, 339, 344, + 339, 379, 379, 339, 109, 339, 344, 339, + 380, 339, 339, 381, 339, 344, 339, 344, + 339, 382, 339, 383, 339, 380, 339, 339, + 339, 339, 344, 339, 125, 339, 379, 379, + 339, 109, 339, 344, 339, 379, 378, 339, + 109, 339, 344, 339, 384, 134, 385, 386, + 115, 109, 339, 344, 339, 134, 385, 386, + 115, 109, 339, 344, 339, 385, 385, 115, + 109, 339, 344, 339, 387, 131, 388, 389, + 118, 109, 339, 344, 339, 131, 388, 389, + 118, 109, 339, 344, 339, 388, 388, 118, + 109, 339, 344, 339, 390, 128, 391, 392, + 121, 109, 339, 344, 339, 128, 391, 392, + 121, 109, 339, 344, 339, 391, 391, 121, + 109, 339, 344, 339, 393, 125, 379, 394, + 339, 109, 339, 344, 339, 125, 379, 394, + 339, 109, 339, 344, 339, 372, 373, 377, + 377, 112, 109, 339, 344, 339, 372, 373, + 374, 377, 112, 109, 339, 344, 339, 339, + 135, 339, 370, 339, 395, 339, 379, 379, + 339, 109, 339, 344, 339, 339, 339, 339, + 339, 370, 339, 370, 339, 339, 339, 379, + 379, 339, 109, 339, 344, 339, 339, 339, + 339, 339, 370, 339, 370, 339, 339, 339, + 379, 371, 339, 109, 339, 344, 339, 339, + 339, 339, 339, 370, 339, 364, 365, 369, + 369, 112, 109, 339, 344, 339, 364, 365, + 366, 369, 112, 109, 339, 344, 339, 339, + 137, 339, 362, 339, 396, 339, 379, 379, + 339, 109, 339, 344, 339, 339, 339, 339, + 339, 362, 339, 362, 339, 339, 339, 379, + 379, 339, 109, 339, 344, 339, 339, 339, + 339, 339, 362, 339, 362, 339, 339, 339, + 379, 363, 339, 109, 339, 344, 339, 339, + 339, 339, 339, 362, 339, 356, 357, 361, + 361, 112, 109, 339, 344, 339, 356, 357, + 358, 361, 112, 109, 339, 344, 339, 339, + 139, 339, 354, 339, 397, 339, 379, 379, + 339, 109, 339, 344, 339, 339, 339, 339, + 339, 354, 339, 354, 339, 339, 339, 379, + 379, 339, 109, 339, 344, 339, 339, 339, + 339, 339, 354, 339, 354, 339, 339, 339, + 379, 355, 339, 109, 339, 344, 339, 339, + 339, 339, 339, 354, 339, 348, 349, 353, + 353, 112, 109, 339, 344, 339, 348, 349, + 350, 353, 112, 109, 339, 344, 339, 339, + 141, 339, 346, 339, 398, 339, 379, 379, + 339, 109, 339, 344, 339, 339, 339, 339, + 339, 346, 339, 346, 339, 339, 339, 379, + 379, 339, 109, 339, 344, 339, 339, 339, + 339, 339, 346, 339, 346, 339, 339, 339, + 379, 347, 339, 109, 339, 344, 339, 339, + 339, 339, 339, 346, 339, 340, 341, 343, + 343, 112, 109, 339, 344, 339, 148, 149, + 150, 151, 399, 284, 76, 73, 282, 154, + 155, 155, 144, 282, 282, 148, 282, 161, + 400, 163, 164, 4, 1, 160, 165, 160, + 160, 35, 160, 168, 149, 150, 151, 401, + 402, 76, 403, 160, 404, 160, 155, 144, + 160, 160, 168, 160, 107, 405, 405, 76, + 403, 160, 165, 160, 160, 144, 160, 406, + 160, 160, 407, 160, 404, 160, 404, 160, + 408, 160, 205, 160, 406, 160, 160, 160, + 160, 404, 160, 168, 160, 220, 107, 405, + 405, 76, 403, 160, 165, 160, 160, 160, + 160, 160, 168, 160, 410, 409, 411, 411, + 409, 146, 409, 412, 409, 411, 411, 409, + 146, 409, 412, 409, 413, 409, 409, 414, + 409, 412, 409, 412, 409, 415, 409, 416, + 409, 413, 409, 409, 409, 409, 412, 409, + 148, 338, 338, 338, 338, 338, 338, 338, + 338, 338, 155, 338, 338, 338, 338, 148, + 338, 0 }; static const short _indic_syllable_machine_trans_targs[] = { - 166, 188, 2, 194, 3, 5, 197, 6, - 8, 200, 9, 11, 203, 12, 14, 15, - 187, 17, 18, 202, 20, 21, 199, 23, - 24, 196, 205, 208, 212, 214, 218, 220, - 224, 226, 230, 232, 166, 255, 37, 261, - 38, 40, 264, 41, 43, 267, 44, 46, - 270, 47, 49, 50, 254, 52, 53, 269, - 55, 56, 266, 58, 59, 263, 272, 275, - 279, 281, 285, 287, 291, 293, 297, 300, - 166, 321, 72, 327, 166, 73, 75, 330, - 76, 78, 333, 79, 81, 336, 82, 84, - 85, 320, 87, 88, 335, 90, 91, 332, - 93, 94, 329, 338, 341, 345, 347, 351, - 353, 357, 359, 363, 166, 389, 106, 395, - 107, 109, 398, 110, 112, 401, 113, 115, - 404, 116, 118, 119, 388, 121, 122, 403, - 124, 125, 400, 127, 128, 397, 406, 409, - 413, 415, 419, 421, 425, 427, 431, 433, - 366, 142, 444, 144, 447, 438, 145, 147, - 450, 148, 150, 453, 151, 154, 155, 455, - 157, 158, 452, 160, 161, 449, 163, 164, - 446, 166, 458, 166, 167, 234, 301, 303, - 365, 367, 323, 368, 434, 435, 340, 456, - 463, 166, 168, 170, 34, 233, 190, 207, - 169, 33, 171, 228, 172, 174, 32, 227, - 173, 31, 175, 222, 176, 178, 30, 221, - 177, 29, 179, 216, 180, 182, 28, 215, - 181, 27, 183, 210, 184, 186, 26, 209, - 185, 25, 193, 0, 189, 192, 191, 166, - 1, 195, 4, 22, 198, 7, 19, 201, - 10, 16, 204, 13, 206, 211, 213, 217, - 219, 223, 225, 229, 231, 166, 235, 237, - 69, 299, 257, 274, 236, 68, 238, 295, - 239, 241, 67, 294, 240, 66, 242, 289, - 243, 245, 65, 288, 244, 64, 246, 283, - 247, 249, 63, 282, 248, 62, 250, 277, - 251, 253, 61, 276, 252, 60, 260, 35, - 256, 259, 258, 166, 36, 262, 39, 57, - 265, 42, 54, 268, 45, 51, 271, 48, - 273, 278, 280, 284, 286, 290, 292, 296, - 298, 166, 302, 103, 304, 361, 305, 307, - 102, 360, 306, 101, 308, 355, 309, 311, - 100, 354, 310, 99, 312, 349, 313, 315, - 98, 348, 314, 97, 316, 343, 317, 319, - 96, 342, 318, 95, 326, 70, 322, 325, - 324, 166, 71, 328, 74, 92, 331, 77, - 89, 334, 80, 86, 337, 83, 339, 344, - 346, 350, 352, 356, 358, 362, 364, 166, - 166, 369, 371, 138, 137, 391, 408, 370, - 372, 429, 373, 375, 136, 428, 374, 135, - 376, 423, 377, 379, 134, 422, 378, 133, - 380, 417, 381, 383, 132, 416, 382, 131, - 384, 411, 385, 387, 130, 410, 386, 129, - 394, 104, 390, 393, 392, 166, 105, 396, - 108, 126, 399, 111, 123, 402, 114, 120, - 405, 117, 407, 412, 414, 418, 420, 424, - 426, 430, 432, 139, 436, 437, 443, 440, - 140, 439, 442, 441, 141, 445, 143, 162, - 448, 146, 159, 451, 149, 156, 454, 152, - 153, 166, 457, 165, 460, 459, 462, 461, - 166 + 138, 160, 166, 2, 167, 3, 5, 170, + 6, 8, 173, 9, 11, 176, 12, 14, + 15, 159, 17, 18, 175, 20, 21, 172, + 23, 24, 169, 178, 182, 183, 187, 188, + 192, 193, 197, 198, 138, 221, 227, 36, + 228, 37, 39, 231, 40, 42, 234, 43, + 45, 237, 46, 48, 49, 220, 51, 52, + 236, 54, 55, 233, 57, 58, 230, 239, + 243, 244, 248, 249, 253, 254, 258, 260, + 138, 281, 287, 70, 288, 138, 71, 73, + 291, 74, 76, 294, 77, 79, 297, 80, + 82, 83, 280, 85, 86, 296, 88, 89, + 293, 91, 92, 290, 299, 303, 304, 308, + 309, 313, 314, 318, 138, 343, 349, 103, + 350, 104, 106, 353, 107, 109, 356, 110, + 112, 359, 113, 115, 116, 342, 118, 119, + 358, 121, 122, 355, 124, 125, 352, 361, + 365, 366, 370, 371, 375, 376, 380, 381, + 320, 138, 394, 138, 139, 200, 261, 263, + 319, 321, 283, 322, 382, 383, 392, 399, + 138, 140, 142, 33, 199, 162, 141, 32, + 143, 195, 144, 146, 31, 194, 145, 30, + 147, 190, 148, 150, 29, 189, 149, 28, + 151, 185, 152, 154, 27, 184, 153, 26, + 155, 180, 156, 158, 25, 179, 157, 1, + 165, 0, 161, 164, 163, 138, 168, 4, + 22, 171, 7, 19, 174, 10, 16, 177, + 13, 181, 186, 191, 196, 138, 201, 203, + 67, 259, 223, 202, 66, 204, 256, 205, + 207, 65, 255, 206, 64, 208, 251, 209, + 211, 63, 250, 210, 62, 212, 246, 213, + 215, 61, 245, 214, 60, 216, 241, 217, + 219, 59, 240, 218, 35, 226, 34, 222, + 225, 224, 138, 229, 38, 56, 232, 41, + 53, 235, 44, 50, 238, 47, 242, 247, + 252, 257, 138, 262, 100, 264, 316, 265, + 267, 99, 315, 266, 98, 268, 311, 269, + 271, 97, 310, 270, 96, 272, 306, 273, + 275, 95, 305, 274, 94, 276, 301, 277, + 279, 93, 300, 278, 69, 286, 68, 282, + 285, 284, 138, 289, 72, 90, 292, 75, + 87, 295, 78, 84, 298, 81, 302, 307, + 312, 317, 138, 138, 323, 325, 134, 133, + 345, 324, 326, 378, 327, 329, 132, 377, + 328, 131, 330, 373, 331, 333, 130, 372, + 332, 129, 334, 368, 335, 337, 128, 367, + 336, 127, 338, 363, 339, 341, 126, 362, + 340, 102, 348, 101, 344, 347, 346, 138, + 351, 105, 123, 354, 108, 120, 357, 111, + 117, 360, 114, 364, 369, 374, 379, 135, + 384, 385, 391, 386, 388, 136, 387, 390, + 389, 138, 393, 137, 396, 395, 398, 397, + 138 }; static const char _indic_syllable_machine_trans_actions[] = { - 1, 0, 0, 2, 0, 0, 2, 0, - 0, 2, 0, 0, 2, 0, 0, 0, - 2, 0, 0, 2, 0, 0, 2, 0, - 0, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 3, 0, 0, 2, - 0, 0, 2, 0, 0, 2, 0, 0, - 2, 0, 0, 0, 2, 0, 0, 2, - 0, 0, 2, 0, 0, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 4, 0, 0, 2, 5, 0, 0, 2, + 1, 0, 2, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, - 0, 0, 2, 2, 6, 2, 6, 2, - 6, 2, 6, 2, 7, 0, 0, 2, - 0, 0, 2, 0, 0, 2, 0, 0, - 2, 0, 0, 0, 2, 0, 0, 2, - 0, 0, 2, 0, 0, 2, 2, 2, + 0, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 3, 0, 2, 0, + 2, 0, 0, 2, 0, 0, 2, 0, + 0, 2, 0, 0, 0, 2, 0, 0, + 2, 0, 0, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 6, 0, 2, 0, 2, 0, 0, 0, - 2, 0, 0, 2, 0, 0, 0, 2, + 4, 0, 2, 0, 2, 5, 0, 0, + 2, 0, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0, 2, 0, 0, - 2, 8, 0, 11, 2, 2, 6, 0, - 12, 12, 0, 2, 6, 2, 6, 2, - 0, 13, 2, 0, 0, 2, 0, 2, - 2, 0, 2, 2, 2, 0, 0, 2, - 2, 0, 2, 2, 2, 0, 0, 2, - 2, 0, 2, 2, 2, 0, 0, 2, - 2, 0, 2, 2, 2, 0, 0, 2, - 2, 0, 2, 0, 0, 0, 0, 14, - 0, 2, 0, 0, 2, 0, 0, 2, - 0, 0, 2, 0, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 15, 2, 0, - 0, 2, 0, 2, 2, 0, 2, 2, - 2, 0, 0, 2, 2, 0, 2, 2, - 2, 0, 0, 2, 2, 0, 2, 2, - 2, 0, 0, 2, 2, 0, 2, 2, - 2, 0, 0, 2, 2, 0, 2, 0, - 0, 0, 0, 16, 0, 2, 0, 0, + 2, 0, 0, 2, 6, 2, 6, 2, + 6, 2, 6, 2, 7, 0, 2, 0, 2, 0, 0, 2, 0, 0, 2, 0, + 0, 2, 0, 0, 0, 2, 0, 0, + 2, 0, 0, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 17, 6, 0, 6, 6, 6, 0, - 0, 6, 6, 0, 6, 6, 6, 0, - 0, 6, 6, 0, 6, 6, 6, 0, - 0, 6, 6, 0, 6, 6, 6, 0, - 0, 6, 6, 0, 6, 0, 0, 0, - 0, 18, 0, 2, 0, 0, 2, 0, - 0, 2, 0, 0, 2, 0, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 19, - 20, 2, 0, 0, 0, 0, 2, 2, + 6, 8, 0, 11, 2, 2, 6, 0, + 12, 12, 0, 2, 6, 2, 2, 0, + 13, 2, 0, 0, 2, 0, 2, 0, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 0, 0, 2, 2, 0, - 2, 0, 0, 0, 0, 21, 0, 2, - 0, 0, 2, 0, 0, 2, 0, 0, - 2, 0, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 0, 0, 22, 2, 0, - 0, 0, 0, 0, 0, 2, 0, 0, + 2, 0, 0, 0, 0, 14, 2, 0, + 0, 2, 0, 0, 2, 0, 0, 2, + 0, 2, 2, 2, 2, 15, 2, 0, + 0, 2, 0, 2, 0, 2, 2, 2, + 0, 0, 2, 2, 0, 2, 2, 2, + 0, 0, 2, 2, 0, 2, 2, 2, + 0, 0, 2, 2, 0, 2, 2, 2, + 0, 0, 2, 2, 0, 2, 0, 0, + 0, 0, 16, 2, 0, 0, 2, 0, + 0, 2, 0, 0, 2, 0, 2, 2, + 2, 2, 17, 6, 0, 6, 2, 6, + 0, 0, 6, 6, 0, 6, 2, 6, + 0, 0, 6, 6, 0, 6, 2, 6, + 0, 0, 6, 6, 0, 6, 2, 6, + 0, 0, 6, 6, 0, 2, 0, 0, + 0, 0, 18, 2, 0, 0, 2, 0, + 0, 2, 0, 0, 2, 0, 2, 2, + 2, 2, 19, 20, 2, 0, 0, 0, + 0, 2, 2, 2, 2, 0, 0, 2, + 2, 0, 2, 2, 2, 0, 0, 2, + 2, 0, 2, 2, 2, 0, 0, 2, + 2, 0, 2, 2, 2, 0, 0, 2, + 2, 0, 2, 0, 0, 0, 0, 21, 2, 0, 0, 2, 0, 0, 2, 0, + 0, 2, 0, 2, 2, 2, 2, 0, + 0, 22, 22, 0, 0, 0, 0, 0, 0, 23, 2, 0, 0, 0, 0, 0, 24 }; @@ -937,15 +759,7 @@ 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, - 0, 0, 0, 0, 0, 0, 9, 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, 9, 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, @@ -998,15 +812,7 @@ 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, - 0, 0, 0, 0, 0, 0, 10, 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, 10, 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, @@ -1046,67 +852,59 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 37, 37, 37, 37, 37, + 1, 1, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 73, 73, - 77, 77, 73, 73, 73, 73, 73, 73, + 37, 37, 37, 37, 73, 73, 78, 78, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, - 109, 109, 109, 109, 109, 109, 109, 109, - 109, 109, 109, 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, 170, 0, 186, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 254, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 322, 322, 322, - 322, 322, 322, 322, 322, 322, 322, 322, - 322, 322, 322, 322, 322, 322, 322, 322, - 322, 322, 322, 322, 322, 322, 322, 322, - 322, 322, 322, 322, 322, 322, 322, 322, - 322, 322, 322, 322, 322, 322, 322, 322, - 322, 322, 322, 322, 322, 322, 322, 322, - 322, 322, 322, 322, 322, 322, 322, 322, - 322, 322, 322, 322, 322, 384, 322, 384, - 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 322, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, - 474, 474, 474, 474, 474, 474, 474, 384 + 109, 109, 109, 109, 109, 109, 109, 73, + 1, 146, 0, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, + 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 339, + 283, 339, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 283, 161, + 161, 161, 161, 161, 161, 161, 161, 161, + 410, 410, 410, 410, 410, 410, 410, 339 }; -static const int indic_syllable_machine_start = 166; -static const int indic_syllable_machine_first_final = 166; +static const int indic_syllable_machine_start = 138; +static const int indic_syllable_machine_first_final = 138; static const int indic_syllable_machine_error = -1; -static const int indic_syllable_machine_en_main = 166; +static const int indic_syllable_machine_en_main = 138; #line 36 "hb-ot-shape-complex-indic-machine.rl" @@ -1118,10 +916,9 @@ #define found_syllable(syllable_type) \ HB_STMT_START { \ - if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ - for (unsigned int i = last; i < p+1; i++) \ + if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ + for (unsigned int i = ts; i < te; i++) \ info[i].syllable() = (syllable_serial << 4) | syllable_type; \ - last = p+1; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END @@ -1129,11 +926,11 @@ static void find_syllables (hb_buffer_t *buffer) { - unsigned int p, pe, eof, ts HB_UNUSED, te, act; + unsigned int p, pe, eof, ts, te, act; int cs; hb_glyph_info_t *info = buffer->info; -#line 1137 "hb-ot-shape-complex-indic-machine.hh" +#line 934 "hb-ot-shape-complex-indic-machine.hh" { cs = indic_syllable_machine_start; ts = 0; @@ -1141,16 +938,15 @@ act = 0; } -#line 113 "hb-ot-shape-complex-indic-machine.rl" +#line 112 "hb-ot-shape-complex-indic-machine.rl" p = 0; pe = eof = buffer->len; - unsigned int last = 0; unsigned int syllable_serial = 1; -#line 1154 "hb-ot-shape-complex-indic-machine.hh" +#line 950 "hb-ot-shape-complex-indic-machine.hh" { int _slen; int _trans; @@ -1164,7 +960,7 @@ #line 1 "NONE" {ts = p;} break; -#line 1168 "hb-ot-shape-complex-indic-machine.hh" +#line 964 "hb-ot-shape-complex-indic-machine.hh" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -1287,7 +1083,7 @@ #line 88 "hb-ot-shape-complex-indic-machine.rl" {act = 6;} break; -#line 1291 "hb-ot-shape-complex-indic-machine.hh" +#line 1087 "hb-ot-shape-complex-indic-machine.hh" } _again: @@ -1296,7 +1092,7 @@ #line 1 "NONE" {ts = 0;} break; -#line 1300 "hb-ot-shape-complex-indic-machine.hh" +#line 1096 "hb-ot-shape-complex-indic-machine.hh" } if ( ++p != pe ) @@ -1312,7 +1108,7 @@ } -#line 122 "hb-ot-shape-complex-indic-machine.rl" +#line 120 "hb-ot-shape-complex-indic-machine.rl" } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-table.cc 2019-02-28 12:04:03.762502881 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-table.cc 2019-02-28 12:04:03.658502883 -0800 @@ -14,8 +14,10 @@ * # Date: 2017-10-16, 24:39:00 GMT [KW] */ -#include "hb-ot-shape-complex-indic-private.hh" +#include "hb-ot-shape-complex-indic.hh" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-macros" #define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 16 chars; Avagraha */ #define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 83 chars; Bindu */ @@ -69,6 +71,7 @@ #define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 4 chars; Top_And_Left_And_Right */ #define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 13 chars; Top_And_Right */ #define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 19 chars; Visual_Order_Left */ +#pragma GCC diagnostic pop #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M) --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic.cc 2019-02-28 12:04:04.174502874 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic.cc 2019-02-28 12:04:04.030502877 -0800 @@ -24,8 +24,9 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-ot-shape-complex-indic-private.hh" -#include "hb-ot-layout-private.hh" +#include "hb-ot-shape-complex-indic.hh" +#include "hb-ot-shape-complex-vowel-constraints.hh" +#include "hb-ot-layout.hh" /* @@ -95,42 +96,41 @@ * Indic shaper. */ -struct feature_list_t { - hb_tag_t tag; - hb_ot_map_feature_flags_t flags; -}; - -static const feature_list_t +static const hb_ot_map_feature_t indic_features[] = { /* * Basic features. * These features are applied in order, one at a time, after initial_reordering. */ - {HB_TAG('n','u','k','t'), F_GLOBAL}, - {HB_TAG('a','k','h','n'), F_GLOBAL}, - {HB_TAG('r','p','h','f'), F_NONE}, - {HB_TAG('r','k','r','f'), F_GLOBAL}, - {HB_TAG('p','r','e','f'), F_NONE}, - {HB_TAG('b','l','w','f'), F_NONE}, - {HB_TAG('a','b','v','f'), F_NONE}, - {HB_TAG('h','a','l','f'), F_NONE}, - {HB_TAG('p','s','t','f'), F_NONE}, - {HB_TAG('v','a','t','u'), F_GLOBAL}, - {HB_TAG('c','j','c','t'), F_GLOBAL}, + {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('r','p','h','f'), F_MANUAL_JOINERS}, + {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS}, + {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS}, + {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS}, + {HB_TAG('h','a','l','f'), F_MANUAL_JOINERS}, + {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS}, + {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS}, /* * Other features. - * These features are applied all at once, after final_reordering. + * These features are applied all at once, after final_reordering + * but before clearing syllables. * Default Bengali font in Windows for example has intermixed * lookups for init,pres,abvs,blws features. */ - {HB_TAG('i','n','i','t'), F_NONE}, - {HB_TAG('p','r','e','s'), F_GLOBAL}, - {HB_TAG('a','b','v','s'), F_GLOBAL}, - {HB_TAG('b','l','w','s'), F_GLOBAL}, - {HB_TAG('p','s','t','s'), F_GLOBAL}, - {HB_TAG('h','a','l','n'), F_GLOBAL}, - /* Positioning features, though we don't care about the types. */ + {HB_TAG('i','n','i','t'), F_MANUAL_JOINERS}, + {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS}, + /* + * Positioning features. + * We don't care about the types. + */ {HB_TAG('d','i','s','t'), F_GLOBAL}, {HB_TAG('a','b','v','m'), F_GLOBAL}, {HB_TAG('b','l','w','m'), F_GLOBAL}, @@ -158,12 +158,13 @@ _BLWS, _PSTS, _HALN, + _DIST, _ABVM, _BLWM, INDIC_NUM_FEATURES, - INDIC_BASIC_FEATURES = INIT /* Don't forget to update this! */ + INDIC_BASIC_FEATURES = INIT, /* Don't forget to update this! */ }; static void @@ -191,25 +192,27 @@ /* Do this before any lookups have been applied. */ map->add_gsub_pause (setup_syllables); - map->add_global_bool_feature (HB_TAG('l','o','c','l')); + map->enable_feature (HB_TAG('l','o','c','l')); /* The Indic specs do not require ccmp, but we apply it here since if * there is a use of it, it's typically at the beginning. */ - map->add_global_bool_feature (HB_TAG('c','c','m','p')); + map->enable_feature (HB_TAG('c','c','m','p')); unsigned int i = 0; map->add_gsub_pause (initial_reordering); + for (; i < INDIC_BASIC_FEATURES; i++) { - map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); + map->add_feature (indic_features[i]); map->add_gsub_pause (nullptr); } + map->add_gsub_pause (final_reordering); - for (; i < INDIC_NUM_FEATURES; i++) { - map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); - } - map->add_global_bool_feature (HB_TAG('c','a','l','t')); - map->add_global_bool_feature (HB_TAG('c','l','i','g')); + for (; i < INDIC_NUM_FEATURES; i++) + map->add_feature (indic_features[i]); + + map->enable_feature (HB_TAG('c','a','l','t')); + map->enable_feature (HB_TAG('c','l','i','g')); map->add_gsub_pause (clear_syllables); } @@ -217,13 +220,13 @@ static void override_features_indic (hb_ot_shape_planner_t *plan) { - plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL); + plan->map.disable_feature (HB_TAG('l','i','g','a')); } struct would_substitute_feature_t { - inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_) + void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_) { zero_context = zero_context_; map->get_stage_lookups (0/*GSUB*/, @@ -231,9 +234,9 @@ &lookups, &count); } - inline bool would_substitute (const hb_codepoint_t *glyphs, - unsigned int glyphs_count, - hb_face_t *face) const + bool would_substitute (const hb_codepoint_t *glyphs, + unsigned int glyphs_count, + hb_face_t *face) const { for (unsigned int i = 0; i < count; i++) if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context)) @@ -249,12 +252,10 @@ struct indic_shape_plan_t { - ASSERT_POD (); - - inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const + bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const { - hb_codepoint_t glyph = virama_glyph; - if (unlikely (virama_glyph == (hb_codepoint_t) -1)) + hb_codepoint_t glyph = virama_glyph.get_relaxed (); + if (unlikely (glyph == (hb_codepoint_t) -1)) { if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph)) glyph = 0; @@ -262,8 +263,8 @@ * Maybe one day... */ /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph - * during shape planning... Instead, overwrite it here. It's safe. Don't worry! */ - virama_glyph = glyph; + * during shape planning... Instead, overwrite it here. */ + virama_glyph.set_relaxed ((int) glyph); } *pglyph = glyph; @@ -273,7 +274,8 @@ const indic_config_t *config; bool is_old_spec; - mutable hb_codepoint_t virama_glyph; + bool uniscribe_bug_compatible; + mutable hb_atomic_int_t virama_glyph; would_substitute_feature_t rphf; would_substitute_feature_t pref; @@ -298,7 +300,8 @@ } indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2'); - indic_plan->virama_glyph = (hb_codepoint_t) -1; + indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible; + indic_plan->virama_glyph.set_relaxed (-1); /* Use zero-context would_substitute() matching for new-spec of the main * Indic scripts, and scripts with one spec only, but not for old-specs. @@ -419,7 +422,7 @@ return; hb_codepoint_t virama; - if (indic_plan->get_virama_glyph (font, &virama)) + if (indic_plan->load_virama_glyph (font, &virama)) { hb_face_t *face = font->face; unsigned int count = buffer->len; @@ -667,10 +670,10 @@ * last consonant. * * Reports suggest that in some scripts Uniscribe does this only if there - * is *not* a Halant after last consonant already (eg. Kannada), while it - * does it unconditionally in other scripts (eg. Malayalam, Bengali). We - * don't currently know about other scripts, so we whitelist Malayalam and - * Bengali for now. + * is *not* a Halant after last consonant already. We know that is the + * case for Kannada, while it reorders unconditionally in other scripts, + * eg. Malayalam, Bengali, and Devanagari. We don't currently know about + * other scripts, so we blacklist Kannada. * * Kannada test case: * U+0C9A,U+0CCD,U+0C9A,U+0CCD @@ -681,15 +684,19 @@ * U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D * With lohit-ttf-20121122/Lohit-Malayalam.ttf * - * Bengali test case + * Bengali test case: * U+0998,U+09CD,U+09AF,U+09CD * With Windows XP vrinda.ttf * https://github.com/harfbuzz/harfbuzz/issues/1073 + * + * Devanagari test case: + * U+091F,U+094D,U+0930,U+094D + * With chandas.ttf + * https://github.com/harfbuzz/harfbuzz/issues/1071 */ if (indic_plan->is_old_spec) { - bool disallow_double_halants = buffer->props.script != HB_SCRIPT_MALAYALAM && - buffer->props.script != HB_SCRIPT_BENGALI; + bool disallow_double_halants = buffer->props.script == HB_SCRIPT_KANNADA; for (unsigned int i = base + 1; i < end; i++) if (info[i].indic_category() == OT_H) { @@ -713,7 +720,7 @@ indic_position_t last_pos = POS_START; for (unsigned int i = start; i < end; i++) { - if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_H)))) + if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | FLAG (OT_H)))) { info[i].indic_position() = last_pos; if (unlikely (info[i].indic_category() == OT_H && @@ -779,8 +786,10 @@ * * We could use buffer->sort() for this, if there was no special * reordering of pre-base stuff happening later... + * We don't want to merge_clusters all of that, which buffer->sort() + * would. */ - if (indic_plan->is_old_spec || end - base > 127) + if (indic_plan->is_old_spec || end - start > 127) buffer->merge_clusters (base, end); else { @@ -909,10 +918,12 @@ hb_buffer_t *buffer, unsigned int start, unsigned int end) { + const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data; + /* We treat placeholder/dotted-circle as if they are consonants, so we * should just chain. Only if not in compatibility mode that is... */ - if (hb_options ().uniscribe_bug_compatible) + if (indic_plan->uniscribe_bug_compatible) { /* For dotted-circle, this is what Uniscribe does: * If dotted-circle is the last glyph, it just does nothing. @@ -954,7 +965,8 @@ hb_font_t *font, hb_buffer_t *buffer) { - /* Note: This loop is extra overhead, but should not be measurable. */ + /* Note: This loop is extra overhead, but should not be measurable. + * TODO Use a buffer scratch flag to remove the loop. */ bool has_broken_syllables = false; unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; @@ -1006,7 +1018,6 @@ else buffer->next_glyph (); } - buffer->swap_buffers (); } @@ -1036,9 +1047,11 @@ * phase, and that might have messed up our properties. Recover * from a particular case of that where we're fairly sure that a * class of OT_H is desired but has been lost. */ - if (indic_plan->virama_glyph) + /* We don't call load_virama_glyph(), since we know it's already + * loaded. */ + hb_codepoint_t virama_glyph = indic_plan->virama_glyph.get_relaxed (); + if (virama_glyph) { - unsigned int virama_glyph = indic_plan->virama_glyph; for (unsigned int i = start; i < end; i++) if (info[i].codepoint == virama_glyph && _hb_glyph_info_ligated (&info[i]) && @@ -1127,6 +1140,24 @@ * defined as “after last standalone halant glyph, after initial matra * position and before the main consonant”. If ZWJ or ZWNJ follow this * halant, position is moved after it. + * + * IMPLEMENTATION NOTES: + * + * It looks like the last sentence is wrong. Testing, with Windows 7 Uniscribe + * and Devanagari shows that the behavior is best described as: + * + * "If ZWJ follows this halant, matra is NOT repositioned after this halant. + * If ZWNJ follows this halant, position is moved after it." + * + * Test case, with Adobe Devanagari or Nirmala UI: + * + * U+091F,U+094D,U+200C,U+092F,U+093F + * (Matra moves to the middle, after ZWNJ.) + * + * U+091F,U+094D,U+200D,U+092F,U+093F + * (Matra does NOT move, stays to the left.) + * + * https://github.com/harfbuzz/harfbuzz/issues/1070 */ if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */ @@ -1140,6 +1171,7 @@ */ if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL) { + search: while (new_pos > start && !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H))))) new_pos--; @@ -1150,9 +1182,27 @@ if (is_halant (info[new_pos]) && info[new_pos].indic_position() != POS_PRE_M) { +#if 0 // See comment above /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */ if (new_pos + 1 < end && is_joiner (info[new_pos + 1])) new_pos++; +#endif + if (new_pos + 1 < end) + { + /* -> If ZWJ follows this halant, matra is NOT repositioned after this halant. */ + if (info[new_pos + 1].indic_category() == OT_ZWJ) + { + /* Keep searching. */ + if (new_pos > start) + { + new_pos--; + goto search; + } + } + /* -> If ZWNJ follows this halant, position is moved after it. */ + if (info[new_pos + 1].indic_category() == OT_ZWNJ) + new_pos++; + } } else new_pos = start; /* No move. */ @@ -1313,7 +1363,7 @@ * Uniscribe doesn't do this. * TEST: U+0930,U+094D,U+0915,U+094B,U+094D */ - if (!hb_options ().uniscribe_bug_compatible && + if (!indic_plan->uniscribe_bug_compatible && unlikely (is_halant (info[new_reph_pos]))) { for (unsigned int i = base + 1; i < new_reph_pos; i++) if (info[i].indic_category() == OT_M) { @@ -1419,7 +1469,7 @@ /* * Finish off the clusters and go home! */ - if (hb_options ().uniscribe_bug_compatible) + if (indic_plan->uniscribe_bug_compatible) { switch ((hb_tag_t) plan->props.script) { @@ -1467,6 +1517,14 @@ } +static void +preprocess_text_indic (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) +{ + _hb_preprocess_text_vowel_constraints (plan, buffer, font); +} + static bool decompose_indic (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t ab, @@ -1566,13 +1624,13 @@ override_features_indic, data_create_indic, data_destroy_indic, - nullptr, /* preprocess_text */ + preprocess_text_indic, nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, decompose_indic, compose_indic, setup_masks_indic, - nullptr, /* disable_otl */ + HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer-machine.hh 2019-02-28 12:04:04.594502867 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer-machine.hh 2019-02-28 12:04:04.454502870 -0800 @@ -29,143 +29,212 @@ #ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH #define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH -#include "hb-private.hh" +#include "hb.hh" #line 36 "hb-ot-shape-complex-khmer-machine.hh" static const unsigned char _khmer_syllable_machine_trans_keys[] = { - 7u, 7u, 1u, 16u, 13u, 13u, 1u, 16u, 7u, 13u, 7u, 7u, 1u, 16u, 13u, 13u, - 1u, 16u, 7u, 13u, 1u, 16u, 3u, 14u, 3u, 14u, 5u, 14u, 3u, 14u, 5u, 14u, - 8u, 8u, 3u, 13u, 3u, 8u, 8u, 8u, 3u, 8u, 3u, 14u, 3u, 14u, 5u, 14u, - 3u, 14u, 5u, 14u, 8u, 8u, 3u, 13u, 3u, 8u, 8u, 8u, 3u, 8u, 3u, 14u, - 3u, 14u, 7u, 13u, 7u, 7u, 1u, 16u, 0 + 5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u, + 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, + 5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 16u, 1u, 29u, 5u, 29u, + 5u, 29u, 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 5u, 26u, + 5u, 29u, 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u, + 5u, 29u, 0 }; static const char _khmer_syllable_machine_key_spans[] = { - 1, 16, 1, 16, 7, 1, 16, 1, - 16, 7, 16, 12, 12, 10, 12, 10, - 1, 11, 6, 1, 6, 12, 12, 10, - 12, 10, 1, 11, 6, 1, 6, 12, - 12, 7, 1, 16 + 22, 17, 22, 17, 16, 17, 22, 17, + 22, 17, 16, 17, 22, 17, 16, 17, + 22, 17, 22, 17, 22, 16, 29, 25, + 25, 25, 1, 18, 25, 25, 25, 22, + 25, 25, 1, 18, 25, 25, 16, 25, + 25 }; static const short _khmer_syllable_machine_index_offsets[] = { - 0, 2, 19, 21, 38, 46, 48, 65, - 67, 84, 92, 109, 122, 135, 146, 159, - 170, 172, 184, 191, 193, 200, 213, 226, - 237, 250, 261, 263, 275, 282, 284, 291, - 304, 317, 325, 327 + 0, 23, 41, 64, 82, 99, 117, 140, + 158, 181, 199, 216, 234, 257, 275, 292, + 310, 333, 351, 374, 392, 415, 432, 462, + 488, 514, 540, 542, 561, 587, 613, 639, + 662, 688, 714, 716, 735, 761, 787, 804, + 830 }; static const char _khmer_syllable_machine_indicies[] = { - 1, 0, 2, 2, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, + 3, 0, 0, 0, 0, 4, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, + 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 0, 3, 0, 4, 4, 0, + 0, 3, 0, 0, 0, 0, 4, 0, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 1, 0, - 0, 0, 0, 0, 5, 0, 7, 6, - 8, 8, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 8, - 6, 9, 6, 10, 10, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 10, 6, 7, 6, 6, 6, - 6, 6, 11, 6, 4, 4, 13, 12, - 14, 15, 7, 16, 12, 12, 4, 4, - 11, 17, 12, 4, 12, 19, 18, 20, - 21, 1, 22, 18, 18, 18, 18, 5, - 23, 18, 24, 18, 21, 21, 1, 22, - 18, 18, 18, 18, 18, 23, 18, 21, - 21, 1, 22, 18, 18, 18, 18, 18, - 23, 18, 25, 18, 21, 21, 1, 22, - 18, 18, 18, 18, 18, 26, 18, 21, - 21, 1, 22, 18, 18, 18, 18, 18, - 26, 18, 27, 18, 28, 18, 29, 18, - 18, 22, 18, 18, 18, 18, 3, 18, - 30, 18, 18, 18, 18, 22, 18, 22, - 18, 28, 18, 18, 18, 18, 22, 18, - 19, 18, 21, 21, 1, 22, 18, 18, - 18, 18, 18, 23, 18, 32, 31, 33, - 33, 7, 16, 31, 31, 31, 31, 31, - 34, 31, 33, 33, 7, 16, 31, 31, - 31, 31, 31, 34, 31, 35, 31, 33, - 33, 7, 16, 31, 31, 31, 31, 31, - 36, 31, 33, 33, 7, 16, 31, 31, - 31, 31, 31, 36, 31, 37, 31, 38, - 31, 39, 31, 31, 16, 31, 31, 31, - 31, 9, 31, 40, 31, 31, 31, 31, - 16, 31, 16, 31, 38, 31, 31, 31, - 31, 16, 31, 13, 31, 41, 33, 7, - 16, 31, 31, 31, 31, 11, 34, 31, - 13, 31, 33, 33, 7, 16, 31, 31, - 31, 31, 31, 34, 31, 7, 42, 42, - 42, 42, 42, 11, 42, 7, 42, 10, - 10, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 10, 42, + 4, 0, 6, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 7, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 0, + 0, 0, 4, 0, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, 11, 11, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12, 0, + 0, 0, 0, 4, 0, 11, 11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 12, 0, 13, + 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, + 15, 15, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 16, 14, 15, 15, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 16, 17, 17, 17, 17, 18, + 17, 19, 19, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 18, 17, 20, 20, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 20, 17, 21, 21, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 22, 17, 23, 23, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 24, 17, + 17, 17, 17, 18, 17, 23, 23, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 24, 17, 25, + 25, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 26, + 17, 17, 17, 17, 18, 17, 25, 25, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 26, 17, + 15, 15, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 27, + 16, 17, 17, 17, 17, 18, 17, 28, + 28, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 28, 17, + 13, 13, 29, 29, 30, 30, 29, 29, + 29, 29, 2, 2, 29, 31, 29, 13, + 29, 29, 29, 29, 16, 20, 29, 29, + 29, 18, 24, 26, 22, 29, 33, 33, + 32, 32, 32, 32, 32, 32, 32, 34, + 32, 32, 32, 32, 32, 2, 3, 6, + 32, 32, 32, 4, 10, 12, 8, 32, + 35, 35, 32, 32, 32, 32, 32, 32, + 32, 36, 32, 32, 32, 32, 32, 32, + 3, 6, 32, 32, 32, 4, 10, 12, + 8, 32, 5, 5, 32, 32, 32, 32, + 32, 32, 32, 36, 32, 32, 32, 32, + 32, 32, 4, 6, 32, 32, 32, 32, + 32, 32, 8, 32, 6, 32, 7, 7, + 32, 32, 32, 32, 32, 32, 32, 36, + 32, 32, 32, 32, 32, 32, 8, 6, + 32, 37, 37, 32, 32, 32, 32, 32, + 32, 32, 36, 32, 32, 32, 32, 32, + 32, 10, 6, 32, 32, 32, 4, 32, + 32, 8, 32, 38, 38, 32, 32, 32, + 32, 32, 32, 32, 36, 32, 32, 32, + 32, 32, 32, 12, 6, 32, 32, 32, + 4, 10, 32, 8, 32, 35, 35, 32, + 32, 32, 32, 32, 32, 32, 34, 32, + 32, 32, 32, 32, 32, 3, 6, 32, + 32, 32, 4, 10, 12, 8, 32, 15, + 15, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 16, + 39, 39, 39, 39, 18, 39, 41, 41, + 40, 40, 40, 40, 40, 40, 40, 42, + 40, 40, 40, 40, 40, 40, 16, 20, + 40, 40, 40, 18, 24, 26, 22, 40, + 19, 19, 40, 40, 40, 40, 40, 40, + 40, 42, 40, 40, 40, 40, 40, 40, + 18, 20, 40, 40, 40, 40, 40, 40, + 22, 40, 20, 40, 21, 21, 40, 40, + 40, 40, 40, 40, 40, 42, 40, 40, + 40, 40, 40, 40, 22, 20, 40, 43, + 43, 40, 40, 40, 40, 40, 40, 40, + 42, 40, 40, 40, 40, 40, 40, 24, + 20, 40, 40, 40, 18, 40, 40, 22, + 40, 44, 44, 40, 40, 40, 40, 40, + 40, 40, 42, 40, 40, 40, 40, 40, + 40, 26, 20, 40, 40, 40, 18, 24, + 40, 22, 40, 28, 28, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 28, 39, 45, 45, 40, 40, + 40, 40, 40, 40, 40, 46, 40, 40, + 40, 40, 40, 27, 16, 20, 40, 40, + 40, 18, 24, 26, 22, 40, 41, 41, + 40, 40, 40, 40, 40, 40, 40, 46, + 40, 40, 40, 40, 40, 40, 16, 20, + 40, 40, 40, 18, 24, 26, 22, 40, 0 }; static const char _khmer_syllable_machine_trans_targs[] = { - 10, 14, 17, 20, 11, 21, 10, 24, - 27, 30, 31, 32, 10, 22, 33, 34, - 26, 35, 10, 12, 4, 0, 16, 3, - 13, 15, 1, 10, 18, 2, 19, 10, - 23, 5, 8, 25, 6, 10, 28, 7, - 29, 9, 10 + 22, 1, 30, 24, 25, 3, 26, 5, + 27, 7, 28, 9, 29, 23, 22, 11, + 32, 22, 33, 13, 34, 15, 35, 17, + 36, 19, 37, 40, 39, 22, 31, 38, + 22, 0, 10, 2, 4, 6, 8, 22, + 22, 12, 14, 16, 18, 20, 21 }; static const char _khmer_syllable_machine_trans_actions[] = { - 1, 2, 2, 0, 2, 2, 3, 2, - 2, 0, 2, 2, 6, 2, 0, 0, - 0, 0, 7, 2, 0, 0, 0, 0, - 2, 2, 0, 8, 0, 0, 0, 9, - 2, 0, 0, 2, 0, 10, 0, 0, - 0, 0, 11 + 1, 0, 2, 2, 2, 0, 0, 0, + 2, 0, 2, 0, 2, 2, 3, 0, + 4, 5, 2, 0, 0, 0, 2, 0, + 2, 0, 2, 4, 4, 8, 9, 0, + 10, 0, 0, 0, 0, 0, 0, 11, + 12, 0, 0, 0, 0, 0, 0 }; static const char _khmer_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0 }; static const char _khmer_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 + 0 }; static const unsigned char _khmer_syllable_machine_eof_trans[] = { - 1, 1, 1, 1, 1, 7, 7, 7, - 7, 7, 0, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 43, 43, 43 + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 15, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 0, 33, + 33, 33, 33, 33, 33, 33, 33, 40, + 41, 41, 41, 41, 41, 41, 40, 41, + 41 }; -static const int khmer_syllable_machine_start = 10; -static const int khmer_syllable_machine_first_final = 10; +static const int khmer_syllable_machine_start = 22; +static const int khmer_syllable_machine_first_final = 22; static const int khmer_syllable_machine_error = -1; -static const int khmer_syllable_machine_en_main = 10; +static const int khmer_syllable_machine_en_main = 22; #line 36 "hb-ot-shape-complex-khmer-machine.rl" -#line 74 "hb-ot-shape-complex-khmer-machine.rl" +#line 80 "hb-ot-shape-complex-khmer-machine.rl" #define found_syllable(syllable_type) \ HB_STMT_START { \ - if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ - for (unsigned int i = last; i < p+1; i++) \ + if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ + for (unsigned int i = ts; i < te; i++) \ info[i].syllable() = (syllable_serial << 4) | syllable_type; \ - last = p+1; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END @@ -173,11 +242,11 @@ static void find_syllables (hb_buffer_t *buffer) { - unsigned int p, pe, eof, ts HB_UNUSED, te, act HB_UNUSED; + unsigned int p, pe, eof, ts, te, act HB_UNUSED; int cs; hb_glyph_info_t *info = buffer->info; -#line 181 "hb-ot-shape-complex-khmer-machine.hh" +#line 250 "hb-ot-shape-complex-khmer-machine.hh" { cs = khmer_syllable_machine_start; ts = 0; @@ -185,16 +254,15 @@ act = 0; } -#line 95 "hb-ot-shape-complex-khmer-machine.rl" +#line 100 "hb-ot-shape-complex-khmer-machine.rl" p = 0; pe = eof = buffer->len; - unsigned int last = 0; unsigned int syllable_serial = 1; -#line 198 "hb-ot-shape-complex-khmer-machine.hh" +#line 266 "hb-ot-shape-complex-khmer-machine.hh" { int _slen; int _trans; @@ -204,11 +272,11 @@ goto _test_eof; _resume: switch ( _khmer_syllable_machine_from_state_actions[cs] ) { - case 5: + case 7: #line 1 "NONE" {ts = p;} break; -#line 212 "hb-ot-shape-complex-khmer-machine.hh" +#line 280 "hb-ot-shape-complex-khmer-machine.hh" } _keys = _khmer_syllable_machine_trans_keys + (cs<<1); @@ -231,47 +299,63 @@ {te = p+1;} break; case 8: -#line 68 "hb-ot-shape-complex-khmer-machine.rl" - {te = p+1;{ found_syllable (consonant_syllable); }} - break; - case 10: -#line 69 "hb-ot-shape-complex-khmer-machine.rl" - {te = p+1;{ found_syllable (broken_cluster); }} - break; - case 6: -#line 70 "hb-ot-shape-complex-khmer-machine.rl" +#line 76 "hb-ot-shape-complex-khmer-machine.rl" {te = p+1;{ found_syllable (non_khmer_cluster); }} break; - case 7: -#line 68 "hb-ot-shape-complex-khmer-machine.rl" + case 10: +#line 74 "hb-ot-shape-complex-khmer-machine.rl" {te = p;p--;{ found_syllable (consonant_syllable); }} break; - case 9: -#line 69 "hb-ot-shape-complex-khmer-machine.rl" + case 12: +#line 75 "hb-ot-shape-complex-khmer-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; case 11: -#line 70 "hb-ot-shape-complex-khmer-machine.rl" +#line 76 "hb-ot-shape-complex-khmer-machine.rl" {te = p;p--;{ found_syllable (non_khmer_cluster); }} break; case 1: -#line 68 "hb-ot-shape-complex-khmer-machine.rl" +#line 74 "hb-ot-shape-complex-khmer-machine.rl" {{p = ((te))-1;}{ found_syllable (consonant_syllable); }} break; - case 3: -#line 69 "hb-ot-shape-complex-khmer-machine.rl" + case 5: +#line 75 "hb-ot-shape-complex-khmer-machine.rl" {{p = ((te))-1;}{ found_syllable (broken_cluster); }} break; -#line 266 "hb-ot-shape-complex-khmer-machine.hh" + case 3: +#line 1 "NONE" + { switch( act ) { + case 2: + {{p = ((te))-1;} found_syllable (broken_cluster); } + break; + case 3: + {{p = ((te))-1;} found_syllable (non_khmer_cluster); } + break; + } + } + break; + case 4: +#line 1 "NONE" + {te = p+1;} +#line 75 "hb-ot-shape-complex-khmer-machine.rl" + {act = 2;} + break; + case 9: +#line 1 "NONE" + {te = p+1;} +#line 76 "hb-ot-shape-complex-khmer-machine.rl" + {act = 3;} + break; +#line 350 "hb-ot-shape-complex-khmer-machine.hh" } _again: switch ( _khmer_syllable_machine_to_state_actions[cs] ) { - case 4: + case 6: #line 1 "NONE" {ts = 0;} break; -#line 275 "hb-ot-shape-complex-khmer-machine.hh" +#line 359 "hb-ot-shape-complex-khmer-machine.hh" } if ( ++p != pe ) @@ -287,7 +371,7 @@ } -#line 104 "hb-ot-shape-complex-khmer-machine.rl" +#line 108 "hb-ot-shape-complex-khmer-machine.rl" } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer.cc 2019-02-28 12:04:04.954502861 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer.cc 2019-02-28 12:04:04.854502863 -0800 @@ -24,42 +24,38 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-ot-shape-complex-khmer-private.hh" -#include "hb-ot-layout-private.hh" +#include "hb-ot-shape-complex-khmer.hh" +#include "hb-ot-layout.hh" /* * Khmer shaper. */ -struct feature_list_t { - hb_tag_t tag; - hb_ot_map_feature_flags_t flags; -}; - -static const feature_list_t +static const hb_ot_map_feature_t khmer_features[] = { /* * Basic features. - * These features are applied in order, one at a time, after initial_reordering. + * These features are applied in order, one at a time, after reordering. */ - {HB_TAG('p','r','e','f'), F_NONE}, - {HB_TAG('b','l','w','f'), F_NONE}, - {HB_TAG('a','b','v','f'), F_NONE}, - {HB_TAG('p','s','t','f'), F_NONE}, - {HB_TAG('c','f','a','r'), F_NONE}, + {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS}, + {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS}, + {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS}, + {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS}, + {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS}, /* * Other features. - * These features are applied all at once, after final_reordering. - * Default Bengali font in Windows for example has intermixed - * lookups for init,pres,abvs,blws features. + * These features are applied all at once after clearing syllables. + */ + {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS}, + /* + * Positioning features. + * We don't care about the types. */ - {HB_TAG('p','r','e','s'), F_GLOBAL}, - {HB_TAG('a','b','v','s'), F_GLOBAL}, - {HB_TAG('b','l','w','s'), F_GLOBAL}, - {HB_TAG('p','s','t','s'), F_GLOBAL}, - /* Positioning features, though we don't care about the types. */ {HB_TAG('d','i','s','t'), F_GLOBAL}, {HB_TAG('a','b','v','m'), F_GLOBAL}, {HB_TAG('b','l','w','m'), F_GLOBAL}, @@ -79,12 +75,13 @@ _ABVS, _BLWS, _PSTS, + _DIST, _ABVM, _BLWM, KHMER_NUM_FEATURES, - KHMER_BASIC_FEATURES = _PRES /* Don't forget to update this! */ + KHMER_BASIC_FEATURES = _PRES, /* Don't forget to update this! */ }; static void @@ -92,13 +89,9 @@ hb_font_t *font, hb_buffer_t *buffer); static void -initial_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); -static void -final_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); +reorder (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void clear_syllables (const hb_ot_shape_plan_t *plan, hb_font_t *font, @@ -111,46 +104,54 @@ /* Do this before any lookups have been applied. */ map->add_gsub_pause (setup_syllables); + map->add_gsub_pause (reorder); - map->add_global_bool_feature (HB_TAG('l','o','c','l')); - /* The Indic specs do not require ccmp, but we apply it here since if - * there is a use of it, it's typically at the beginning. */ - map->add_global_bool_feature (HB_TAG('c','c','m','p')); - + /* Testing suggests that Uniscribe does NOT pause between basic + * features. Test with KhmerUI.ttf and the following three + * sequences: + * + * U+1789,U+17BC + * U+1789,U+17D2,U+1789 + * U+1789,U+17D2,U+1789,U+17BC + * + * https://github.com/harfbuzz/harfbuzz/issues/974 + */ + map->enable_feature (HB_TAG('l','o','c','l')); + map->enable_feature (HB_TAG('c','c','m','p')); unsigned int i = 0; - map->add_gsub_pause (initial_reordering); - for (; i < KHMER_BASIC_FEATURES; i++) { - map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); - map->add_gsub_pause (nullptr); - } - map->add_gsub_pause (final_reordering); - for (; i < KHMER_NUM_FEATURES; i++) { - map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); - } - - map->add_global_bool_feature (HB_TAG('c','a','l','t')); - map->add_global_bool_feature (HB_TAG('c','l','i','g')); + for (; i < KHMER_BASIC_FEATURES; i++) + map->add_feature (khmer_features[i]); map->add_gsub_pause (clear_syllables); + + for (; i < KHMER_NUM_FEATURES; i++) + map->add_feature (khmer_features[i]); } static void override_features_khmer (hb_ot_shape_planner_t *plan) { + hb_ot_map_builder_t *map = &plan->map; + + /* Khmer spec has 'clig' as part of required shaping features: + * "Apply feature 'clig' to form ligatures that are desired for + * typographical correctness.", hence in overrides... */ + map->enable_feature (HB_TAG('c','l','i','g')); + /* Uniscribe does not apply 'kern' in Khmer. */ if (hb_options ().uniscribe_bug_compatible) { - plan->map.add_feature (HB_TAG('k','e','r','n'), 0, F_GLOBAL); + map->disable_feature (HB_TAG('k','e','r','n')); } - plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL); + map->disable_feature (HB_TAG('l','i','g','a')); } struct would_substitute_feature_t { - inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_) + void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_) { zero_context = zero_context_; map->get_stage_lookups (0/*GSUB*/, @@ -158,9 +159,9 @@ &lookups, &count); } - inline bool would_substitute (const hb_codepoint_t *glyphs, - unsigned int glyphs_count, - hb_face_t *face) const + bool would_substitute (const hb_codepoint_t *glyphs, + unsigned int glyphs_count, + hb_face_t *face) const { for (unsigned int i = 0; i < count; i++) if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context)) @@ -176,9 +177,7 @@ struct khmer_shape_plan_t { - ASSERT_POD (); - - inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const + bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const { hb_codepoint_t glyph = virama_glyph; if (unlikely (virama_glyph == (hb_codepoint_t) -1)) @@ -243,7 +242,6 @@ hb_font_t *font HB_UNUSED) { HB_BUFFER_ALLOCATE_VAR (buffer, khmer_category); - HB_BUFFER_ALLOCATE_VAR (buffer, khmer_position); /* We cannot setup masks here. We save information about characters * and setup masks later on in a pause-callback. */ @@ -264,162 +262,58 @@ buffer->unsafe_to_break (start, end); } -static int -compare_khmer_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) -{ - int a = pa->khmer_position(); - int b = pb->khmer_position(); - - return a < b ? -1 : a == b ? 0 : +1; -} - /* Rules from: * https://docs.microsoft.com/en-us/typography/script-development/devanagari */ static void -initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, - hb_face_t *face, - hb_buffer_t *buffer, - unsigned int start, unsigned int end) +reorder_consonant_syllable (const hb_ot_shape_plan_t *plan, + hb_face_t *face HB_UNUSED, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) { const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data; hb_glyph_info_t *info = buffer->info; - /* 1. Khmer shaping assumes that a syllable will begin with a Cons, IndV, or Number. */ - - /* The first consonant is always the base. */ - unsigned int base = start; - info[base].khmer_position() = POS_BASE_C; - - /* Mark all subsequent consonants as below. */ - for (unsigned int i = base + 1; i < end; i++) - if (is_consonant_or_vowel (info[i])) - info[i].khmer_position() = POS_BELOW_C; - - /* Mark final consonants. A final consonant is one appearing after a matra, - * like in Khmer. */ - for (unsigned int i = base + 1; i < end; i++) - if (info[i].khmer_category() == OT_M) { - for (unsigned int j = i + 1; j < end; j++) - if (is_consonant_or_vowel (info[j])) { - info[j].khmer_position() = POS_FINAL_C; - break; - } - break; - } - - /* Attach misc marks to previous char to move with them. */ + /* Setup masks. */ { - khmer_position_t last_pos = POS_START; - for (unsigned int i = start; i < end; i++) - { - if ((FLAG_UNSAFE (info[i].khmer_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_Coeng)))) - { - info[i].khmer_position() = last_pos; - if (unlikely (info[i].khmer_category() == OT_Coeng && - info[i].khmer_position() == POS_PRE_M)) - { - /* - * Uniscribe doesn't move the Halant with Left Matra. - * TEST: U+092B,U+093F,U+094DE - * We follow. This is important for the Sinhala - * U+0DDA split matra since it decomposes to U+0DD9,U+0DCA - * where U+0DD9 is a left matra and U+0DCA is the virama. - * We don't want to move the virama with the left matra. - * TEST: U+0D9A,U+0DDA - */ - for (unsigned int j = i; j > start; j--) - if (info[j - 1].khmer_position() != POS_PRE_M) { - info[i].khmer_position() = info[j - 1].khmer_position(); - break; - } - } - } else if (info[i].khmer_position() != POS_SMVD) { - last_pos = (khmer_position_t) info[i].khmer_position(); - } - } - } - /* For post-base consonants let them own anything before them - * since the last consonant or matra. */ - { - unsigned int last = base; - for (unsigned int i = base + 1; i < end; i++) - if (is_consonant_or_vowel (info[i])) - { - for (unsigned int j = last + 1; j < i; j++) - if (info[j].khmer_position() < POS_SMVD) - info[j].khmer_position() = info[i].khmer_position(); - last = i; - } else if (info[i].khmer_category() == OT_M) - last = i; - } - - { - /* Use syllable() for sort accounting temporarily. */ - unsigned int syllable = info[start].syllable(); - for (unsigned int i = start; i < end; i++) - info[i].syllable() = i - start; - - /* Sit tight, rock 'n roll! */ - hb_stable_sort (info + start, end - start, compare_khmer_order); - /* Find base again */ - base = end; - for (unsigned int i = start; i < end; i++) - if (info[i].khmer_position() == POS_BASE_C) - { - base = i; - break; - } - - if (unlikely (end - start >= 127)) - buffer->merge_clusters (start, end); - else - /* Note! syllable() is a one-byte field. */ - for (unsigned int i = base; i < end; i++) - if (info[i].syllable() != 255) - { - unsigned int max = i; - unsigned int j = start + info[i].syllable(); - while (j != i) - { - max = MAX (max, j); - unsigned int next = start + info[j].syllable(); - info[j].syllable() = 255; /* So we don't process j later again. */ - j = next; - } - if (i != max) - buffer->merge_clusters (i, max + 1); - } - - /* Put syllable back in. */ - for (unsigned int i = start; i < end; i++) - info[i].syllable() = syllable; - } - - /* Setup masks now */ - - { - hb_mask_t mask; - /* Post-base */ - mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF]; - for (unsigned int i = base + 1; i < end; i++) + hb_mask_t mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF]; + for (unsigned int i = start + 1; i < end; i++) info[i].mask |= mask; } - unsigned int pref_len = 2; - if (khmer_plan->mask_array[PREF] && base + pref_len < end) + unsigned int num_coengs = 0; + for (unsigned int i = start + 1; i < end; i++) { - /* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */ - for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) { - hb_codepoint_t glyphs[2]; - for (unsigned int j = 0; j < pref_len; j++) - glyphs[j] = info[i + j].codepoint; - if (khmer_plan->pref.would_substitute (glyphs, pref_len, face)) + /* """ + * When a COENG + (Cons | IndV) combination are found (and subscript count + * is less than two) the character combination is handled according to the + * subscript type of the character following the COENG. + * + * ... + * + * Subscript Type 2 - The COENG + RO characters are reordered to immediately + * before the base glyph. Then the COENG + RO characters are assigned to have + * the 'pref' OpenType feature applied to them. + * """ + */ + if (info[i].khmer_category() == OT_Coeng && num_coengs <= 2 && i + 1 < end) + { + num_coengs++; + + if (info[i + 1].khmer_category() == OT_Ra) { - for (unsigned int j = 0; j < pref_len; j++) - info[i++].mask |= khmer_plan->mask_array[PREF]; + for (unsigned int j = 0; j < 2; j++) + info[i + j].mask |= khmer_plan->mask_array[PREF]; + + /* Move the Coeng,Ro sequence to the start. */ + buffer->merge_clusters (start, i + 2); + hb_glyph_info_t t0 = info[i]; + hb_glyph_info_t t1 = info[i + 1]; + memmove (&info[start + 2], &info[start], (i - start) * sizeof (info[0])); + info[start] = t0; + info[start + 1] = t1; /* Mark the subsequent stuff with 'cfar'. Used in Khmer. * Read the feature spec. @@ -428,12 +322,22 @@ * U+1784,U+17D2,U+1782,U+17D2,U+179A */ if (khmer_plan->mask_array[CFAR]) - for (; i < end; i++) - info[i].mask |= khmer_plan->mask_array[CFAR]; + for (unsigned int j = i + 2; j < end; j++) + info[j].mask |= khmer_plan->mask_array[CFAR]; - break; + num_coengs = 2; /* Done. */ } } + + /* Reorder left matra piece. */ + else if (info[i].khmer_category() == OT_VPre) + { + /* Move to the start. */ + buffer->merge_clusters (start, i + 1); + hb_glyph_info_t t = info[i]; + memmove (&info[start + 1], &info[start], (i - start) * sizeof (info[0])); + info[start] = t; + } } } @@ -448,7 +352,7 @@ { case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */ case consonant_syllable: - initial_reordering_consonant_syllable (plan, face, buffer, start, end); + reorder_consonant_syllable (plan, face, buffer, start, end); break; case non_khmer_cluster: @@ -513,263 +417,22 @@ else buffer->next_glyph (); } - buffer->swap_buffers (); } static void -initial_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer) +reorder (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { insert_dotted_circles (plan, font, buffer); foreach_syllable (buffer, start, end) initial_reordering_syllable (plan, font->face, buffer, start, end); -} - -static void -final_reordering_syllable (const hb_ot_shape_plan_t *plan, - hb_buffer_t *buffer, - unsigned int start, unsigned int end) -{ - const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data; - hb_glyph_info_t *info = buffer->info; - - - /* This function relies heavily on halant glyphs. Lots of ligation - * and possibly multiple substitutions happened prior to this - * phase, and that might have messed up our properties. Recover - * from a particular case of that where we're fairly sure that a - * class of OT_Coeng is desired but has been lost. */ - if (khmer_plan->virama_glyph) - { - unsigned int virama_glyph = khmer_plan->virama_glyph; - for (unsigned int i = start; i < end; i++) - if (info[i].codepoint == virama_glyph && - _hb_glyph_info_ligated (&info[i]) && - _hb_glyph_info_multiplied (&info[i])) - { - /* This will make sure that this glyph passes is_coeng() test. */ - info[i].khmer_category() = OT_Coeng; - _hb_glyph_info_clear_ligated_and_multiplied (&info[i]); - } - } - - - /* 4. Final reordering: - * - * After the localized forms and basic shaping forms GSUB features have been - * applied (see below), the shaping engine performs some final glyph - * reordering before applying all the remaining font features to the entire - * syllable. - */ - - bool try_pref = !!khmer_plan->mask_array[PREF]; - - /* Find base again */ - unsigned int base; - for (base = start; base < end; base++) - if (info[base].khmer_position() >= POS_BASE_C) - { - if (try_pref && base + 1 < end) - { - for (unsigned int i = base + 1; i < end; i++) - if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0) - { - if (!(_hb_glyph_info_substituted (&info[i]) && - _hb_glyph_info_ligated_and_didnt_multiply (&info[i]))) - { - /* Ok, this was a 'pref' candidate but didn't form any. - * Base is around here... */ - base = i; - while (base < end && is_coeng (info[base])) - base++; - info[base].khmer_position() = POS_BASE_C; - - try_pref = false; - } - break; - } - } - - if (start < base && info[base].khmer_position() > POS_BASE_C) - base--; - break; - } - if (base == end && start < base && - is_one_of (info[base - 1], FLAG (OT_ZWJ))) - base--; - if (base < end) - while (start < base && - is_one_of (info[base], (FLAG (OT_N) | FLAG (OT_Coeng)))) - base--; - - - /* o Reorder matras: - * - * If a pre-base matra character had been reordered before applying basic - * features, the glyph can be moved closer to the main consonant based on - * whether half-forms had been formed. Actual position for the matra is - * defined as “after last standalone halant glyph, after initial matra - * position and before the main consonant”. If ZWJ or ZWNJ follow this - * halant, position is moved after it. - */ - - if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */ - { - /* If we lost track of base, alas, position before last thingy. */ - unsigned int new_pos = base == end ? base - 2 : base - 1; - - while (new_pos > start && - !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_Coeng))))) - new_pos--; - - /* If we found no Halant we are done. - * Otherwise only proceed if the Halant does - * not belong to the Matra itself! */ - if (is_coeng (info[new_pos]) && - info[new_pos].khmer_position() != POS_PRE_M) - { - /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */ - if (new_pos + 1 < end && is_joiner (info[new_pos + 1])) - new_pos++; - } - else - new_pos = start; /* No move. */ - - if (start < new_pos && info[new_pos].khmer_position () != POS_PRE_M) - { - /* Now go see if there's actually any matras... */ - for (unsigned int i = new_pos; i > start; i--) - if (info[i - 1].khmer_position () == POS_PRE_M) - { - unsigned int old_pos = i - 1; - if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */ - base--; - - hb_glyph_info_t tmp = info[old_pos]; - memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0])); - info[new_pos] = tmp; - - /* Note: this merge_clusters() is intentionally *after* the reordering. - * Indic matra reordering is special and tricky... */ - buffer->merge_clusters (new_pos, MIN (end, base + 1)); - - new_pos--; - } - } else { - for (unsigned int i = start; i < base; i++) - if (info[i].khmer_position () == POS_PRE_M) { - buffer->merge_clusters (i, MIN (end, base + 1)); - break; - } - } - } - - - /* o Reorder pre-base-reordering consonants: - * - * If a pre-base-reordering consonant is found, reorder it according to - * the following rules: - */ - - if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */ - { - for (unsigned int i = base + 1; i < end; i++) - if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0) - { - /* 1. Only reorder a glyph produced by substitution during application - * of the feature. (Note that a font may shape a Ra consonant with - * the feature generally but block it in certain contexts.) - */ - /* Note: We just check that something got substituted. We don't check that - * the feature actually did it... - * - * Reorder pref only if it ligated. */ - if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i])) - { - /* - * 2. Try to find a target position the same way as for pre-base matra. - * If it is found, reorder pre-base consonant glyph. - * - * 3. If position is not found, reorder immediately before main - * consonant. - */ - - unsigned int new_pos = base; - while (new_pos > start && - !(is_one_of (info[new_pos - 1], FLAG(OT_M) | FLAG (OT_Coeng)))) - new_pos--; - - /* In Khmer coeng model, a H,Ra can go *after* matras. If it goes after a - * split matra, it should be reordered to *before* the left part of such matra. */ - if (new_pos > start && info[new_pos - 1].khmer_category() == OT_M) - { - unsigned int old_pos = i; - for (unsigned int j = base + 1; j < old_pos; j++) - if (info[j].khmer_category() == OT_M) - { - new_pos--; - break; - } - } - - if (new_pos > start && is_coeng (info[new_pos - 1])) - { - /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */ - if (new_pos < end && is_joiner (info[new_pos])) - new_pos++; - } - - { - unsigned int old_pos = i; - - buffer->merge_clusters (new_pos, old_pos + 1); - hb_glyph_info_t tmp = info[old_pos]; - memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0])); - info[new_pos] = tmp; - - if (new_pos <= base && base < old_pos) - base++; - } - } - - break; - } - } - - - /* - * Finish off the clusters and go home! - */ - if (hb_options ().uniscribe_bug_compatible) - { - /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala. - * This means, half forms are submerged into the main consonant's cluster. - * This is unnecessary, and makes cursor positioning harder, but that's what - * Uniscribe does. */ - buffer->merge_clusters (start, end); - } -} - - -static void -final_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) -{ - unsigned int count = buffer->len; - if (unlikely (!count)) return; - - foreach_syllable (buffer, start, end) - final_reordering_syllable (plan, buffer, start, end); HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category); - HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_position); } - static void clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font HB_UNUSED, @@ -831,7 +494,7 @@ decompose_khmer, compose_khmer, setup_masks_khmer, - nullptr, /* disable_otl */ + HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar-machine.hh 2019-02-28 12:04:05.302502856 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar-machine.hh 2019-02-28 12:04:05.186502858 -0800 @@ -29,7 +29,7 @@ #ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH #define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH -#include "hb-private.hh" +#include "hb.hh" #line 36 "hb-ot-shape-complex-myanmar-machine.hh" @@ -283,10 +283,9 @@ #define found_syllable(syllable_type) \ HB_STMT_START { \ - if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ - for (unsigned int i = last; i < p+1; i++) \ + if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ + for (unsigned int i = ts; i < te; i++) \ info[i].syllable() = (syllable_serial << 4) | syllable_type; \ - last = p+1; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END @@ -294,11 +293,11 @@ static void find_syllables (hb_buffer_t *buffer) { - unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED; + unsigned int p, pe, eof, ts, te, act HB_UNUSED; int cs; hb_glyph_info_t *info = buffer->info; -#line 302 "hb-ot-shape-complex-myanmar-machine.hh" +#line 301 "hb-ot-shape-complex-myanmar-machine.hh" { cs = myanmar_syllable_machine_start; ts = 0; @@ -306,16 +305,15 @@ act = 0; } -#line 115 "hb-ot-shape-complex-myanmar-machine.rl" +#line 114 "hb-ot-shape-complex-myanmar-machine.rl" p = 0; pe = eof = buffer->len; - unsigned int last = 0; unsigned int syllable_serial = 1; -#line 319 "hb-ot-shape-complex-myanmar-machine.hh" +#line 317 "hb-ot-shape-complex-myanmar-machine.hh" { int _slen; int _trans; @@ -329,7 +327,7 @@ #line 1 "NONE" {ts = p;} break; -#line 333 "hb-ot-shape-complex-myanmar-machine.hh" +#line 331 "hb-ot-shape-complex-myanmar-machine.hh" } _keys = _myanmar_syllable_machine_trans_keys + (cs<<1); @@ -379,7 +377,7 @@ #line 90 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (non_myanmar_cluster); }} break; -#line 383 "hb-ot-shape-complex-myanmar-machine.hh" +#line 381 "hb-ot-shape-complex-myanmar-machine.hh" } _again: @@ -388,7 +386,7 @@ #line 1 "NONE" {ts = 0;} break; -#line 392 "hb-ot-shape-complex-myanmar-machine.hh" +#line 390 "hb-ot-shape-complex-myanmar-machine.hh" } if ( ++p != pe ) @@ -404,7 +402,7 @@ } -#line 124 "hb-ot-shape-complex-myanmar-machine.rl" +#line 122 "hb-ot-shape-complex-myanmar-machine.rl" } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar.cc 2019-02-28 12:04:05.646502850 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar.cc 2019-02-28 12:04:05.546502852 -0800 @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-ot-shape-complex-myanmar-private.hh" +#include "hb-ot-shape-complex-myanmar.hh" /* @@ -36,7 +36,7 @@ { /* * Basic features. - * These features are applied in order, one at a time, after initial_reordering. + * These features are applied in order, one at a time, after reordering. */ HB_TAG('r','p','h','f'), HB_TAG('p','r','e','f'), @@ -48,13 +48,20 @@ { /* * Other features. - * These features are applied all at once, after final_reordering. + * These features are applied all at once, after clearing syllables. */ HB_TAG('p','r','e','s'), HB_TAG('a','b','v','s'), HB_TAG('b','l','w','s'), HB_TAG('p','s','t','s'), - /* Positioning features, though we don't care about the types. */ +}; +static const hb_tag_t +positioning_features[] = +{ + /* + * Positioning features. + * We don't care about the types. + */ HB_TAG('d','i','s','t'), /* Pre-release version of Windows 8 Myanmar font had abvm,blwm * features. The released Windows 8 version of the font (as well @@ -73,13 +80,13 @@ hb_font_t *font, hb_buffer_t *buffer); static void -initial_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); -static void -final_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); +reorder (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); +static void +clear_syllables (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void collect_features_myanmar (hb_ot_shape_planner_t *plan) @@ -89,27 +96,33 @@ /* Do this before any lookups have been applied. */ map->add_gsub_pause (setup_syllables); - map->add_global_bool_feature (HB_TAG('l','o','c','l')); + map->enable_feature (HB_TAG('l','o','c','l')); /* The Indic specs do not require ccmp, but we apply it here since if * there is a use of it, it's typically at the beginning. */ - map->add_global_bool_feature (HB_TAG('c','c','m','p')); + map->enable_feature (HB_TAG('c','c','m','p')); + + map->add_gsub_pause (reorder); - map->add_gsub_pause (initial_reordering); for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) { - map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); + map->enable_feature (basic_features[i], F_MANUAL_ZWJ); map->add_gsub_pause (nullptr); } - map->add_gsub_pause (final_reordering); + + map->add_gsub_pause (clear_syllables); + for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) - map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); + map->enable_feature (other_features[i], F_MANUAL_ZWJ); + + for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++) + map->enable_feature (positioning_features[i]); } static void override_features_myanmar (hb_ot_shape_planner_t *plan) { - plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL); + plan->map.disable_feature (HB_TAG('l','i','g','a')); } @@ -261,8 +274,8 @@ } static void -initial_reordering_syllable (const hb_ot_shape_plan_t *plan, - hb_face_t *face, +initial_reordering_syllable (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_face_t *face HB_UNUSED, hb_buffer_t *buffer, unsigned int start, unsigned int end) { @@ -330,72 +343,71 @@ else buffer->next_glyph (); } - buffer->swap_buffers (); } static void -initial_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer) +reorder (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { insert_dotted_circles (plan, font, buffer); foreach_syllable (buffer, start, end) initial_reordering_syllable (plan, font->face, buffer, start, end); + + HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category); + HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position); } static void -final_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) +clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) { hb_glyph_info_t *info = buffer->info; unsigned int count = buffer->len; - - /* Zero syllables now... */ for (unsigned int i = 0; i < count; i++) info[i].syllable() = 0; - - HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category); - HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position); } -/* Uniscribe seems to have a shaper for 'mymr' that is like the - * generic shaper, except that it zeros mark advances GDEF_LATE. */ -const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old = +const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = { - nullptr, /* collect_features */ - nullptr, /* override_features */ + collect_features_myanmar, + override_features_myanmar, nullptr, /* data_create */ nullptr, /* data_destroy */ nullptr, /* preprocess_text */ nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, nullptr, /* decompose */ nullptr, /* compose */ - nullptr, /* setup_masks */ - nullptr, /* disable_otl */ + setup_masks_myanmar, + HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ - HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, - true, /* fallback_position */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, + false, /* fallback_position */ }; -const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = + +/* Ugly Zawgyi encoding. + * Disable all auto processing. + * https://github.com/harfbuzz/harfbuzz/issues/1162 */ +const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_zawgyi = { - collect_features_myanmar, - override_features_myanmar, + nullptr, /* collect_features */ + nullptr, /* override_features */ nullptr, /* data_create */ nullptr, /* data_destroy */ nullptr, /* preprocess_text */ nullptr, /* postprocess_glyphs */ - HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, + HB_OT_SHAPE_NORMALIZATION_MODE_NONE, nullptr, /* decompose */ nullptr, /* compose */ - setup_masks_myanmar, - nullptr, /* disable_otl */ + nullptr, /* setup_masks */ + HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ - HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-thai.cc 2019-02-28 12:04:05.974502845 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-thai.cc 2019-02-28 12:04:05.874502846 -0800 @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-ot-shape-complex-private.hh" +#include "hb-ot-shape-complex.hh" /* Thai / Lao shaper */ @@ -324,9 +324,9 @@ } /* Is SARA AM. Decompose and reorder. */ - hb_codepoint_t decomposed[2] = {hb_codepoint_t (NIKHAHIT_FROM_SARA_AM (u)), - hb_codepoint_t (SARA_AA_FROM_SARA_AM (u))}; - buffer->replace_glyphs (1, 2, decomposed); + hb_glyph_info_t &nikhahit = buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u)); + _hb_glyph_info_set_continuation (&nikhahit); + buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u)); if (unlikely (!buffer->successful)) return; @@ -376,7 +376,7 @@ nullptr, /* decompose */ nullptr, /* compose */ nullptr, /* setup_masks */ - nullptr, /* disable_otl */ + HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, false,/* fallback_position */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-machine.hh 2019-02-28 12:04:06.330502839 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-machine.hh 2019-02-28 12:04:06.222502841 -0800 @@ -31,232 +31,271 @@ #ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH #define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH -#include "hb-private.hh" +#include "hb.hh" #line 38 "hb-ot-shape-complex-use-machine.hh" static const unsigned char _use_syllable_machine_trans_keys[] = { - 12u, 12u, 1u, 15u, 1u, 1u, 12u, 12u, 0u, 43u, 21u, 21u, 8u, 39u, 8u, 39u, - 1u, 15u, 1u, 1u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, - 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, - 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 13u, 21u, 4u, 4u, 13u, 13u, 8u, 39u, - 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, - 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, - 8u, 39u, 1u, 15u, 12u, 12u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u, 42u, 42u, - 1u, 5u, 0 + 12u, 44u, 1u, 15u, 1u, 1u, 12u, 44u, 0u, 44u, 21u, 21u, 8u, 44u, 8u, 44u, + 1u, 15u, 1u, 1u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, + 8u, 39u, 8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, + 8u, 44u, 8u, 44u, 8u, 44u, 1u, 39u, 8u, 44u, 13u, 21u, 4u, 4u, 13u, 13u, + 8u, 44u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, + 8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, + 8u, 44u, 8u, 44u, 1u, 39u, 1u, 15u, 12u, 44u, 1u, 44u, 8u, 44u, 21u, 42u, + 41u, 42u, 42u, 42u, 1u, 5u, 0 }; static const char _use_syllable_machine_key_spans[] = { - 1, 15, 1, 1, 44, 1, 32, 32, - 15, 1, 32, 32, 32, 19, 19, 19, - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 9, 1, 1, 32, - 32, 32, 32, 19, 19, 19, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 15, 1, 39, 32, 22, 2, 1, - 5 + 33, 15, 1, 33, 45, 1, 37, 37, + 15, 1, 37, 37, 32, 19, 19, 19, + 32, 32, 32, 37, 37, 37, 37, 37, + 37, 37, 37, 39, 37, 9, 1, 1, + 37, 37, 37, 32, 19, 19, 19, 32, + 32, 32, 37, 37, 37, 37, 37, 37, + 37, 37, 39, 15, 33, 44, 37, 22, + 2, 1, 5 }; static const short _use_syllable_machine_index_offsets[] = { - 0, 2, 18, 20, 22, 67, 69, 102, - 135, 151, 153, 186, 219, 252, 272, 292, - 312, 345, 378, 411, 444, 477, 510, 543, - 576, 609, 642, 675, 708, 718, 720, 722, - 755, 788, 821, 854, 874, 894, 914, 947, - 980, 1013, 1046, 1079, 1112, 1145, 1178, 1211, - 1244, 1277, 1293, 1295, 1335, 1368, 1391, 1394, - 1396 + 0, 34, 50, 52, 86, 132, 134, 172, + 210, 226, 228, 266, 304, 337, 357, 377, + 397, 430, 463, 496, 534, 572, 610, 648, + 686, 724, 762, 800, 840, 878, 888, 890, + 892, 930, 968, 1006, 1039, 1059, 1079, 1099, + 1132, 1165, 1198, 1236, 1274, 1312, 1350, 1388, + 1426, 1464, 1502, 1542, 1558, 1592, 1637, 1675, + 1698, 1701, 1703 }; static const char _use_syllable_machine_indicies[] = { + 1, 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, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 4, 2, 3, 2, 6, 5, 7, 8, + 4, 2, 3, 2, 6, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 6, 5, 7, 8, 9, 7, 10, 8, 9, 9, 11, 9, 9, 3, 12, 9, 9, 13, 7, 7, 14, 15, 9, 9, 16, 17, 18, 19, 20, 21, 22, 16, 23, 24, 25, 26, 27, 28, 9, 29, 30, 31, 9, 9, - 9, 32, 9, 34, 33, 36, 35, 35, - 37, 1, 35, 35, 38, 35, 35, 35, - 35, 35, 39, 40, 41, 42, 43, 44, - 45, 46, 40, 47, 39, 48, 49, 50, - 51, 35, 52, 53, 54, 35, 36, 35, - 35, 37, 1, 35, 35, 38, 35, 35, - 35, 35, 35, 55, 40, 41, 42, 43, - 44, 45, 46, 40, 47, 48, 48, 49, - 50, 51, 35, 52, 53, 54, 35, 37, - 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 57, 56, 37, - 56, 36, 35, 35, 37, 1, 35, 35, - 38, 35, 35, 35, 35, 35, 35, 40, - 41, 42, 43, 44, 45, 46, 40, 47, - 48, 48, 49, 50, 51, 35, 52, 53, - 54, 35, 36, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 40, 41, 42, 43, 44, 35, 35, 35, - 35, 35, 35, 49, 50, 51, 35, 52, - 53, 54, 35, 36, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 41, 42, 43, 44, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 52, 53, 54, 35, 36, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 42, 43, 44, 35, - 36, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 43, 44, 35, 36, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 44, 35, - 36, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 42, 43, 44, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 52, 53, 54, - 35, 36, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 42, 43, 44, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 53, - 54, 35, 36, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 42, 43, 44, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 54, 35, 36, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 41, 42, 43, 44, 35, 35, - 35, 35, 35, 35, 49, 50, 51, 35, - 52, 53, 54, 35, 36, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 41, 42, 43, 44, 35, - 35, 35, 35, 35, 35, 35, 50, 51, - 35, 52, 53, 54, 35, 36, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 41, 42, 43, 44, - 35, 35, 35, 35, 35, 35, 35, 35, - 51, 35, 52, 53, 54, 35, 36, 35, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 40, 41, 42, 43, - 44, 35, 46, 40, 35, 35, 35, 49, - 50, 51, 35, 52, 53, 54, 35, 36, - 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 40, 41, 42, - 43, 44, 35, 58, 40, 35, 35, 35, - 49, 50, 51, 35, 52, 53, 54, 35, - 36, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 40, 41, - 42, 43, 44, 35, 35, 40, 35, 35, - 35, 49, 50, 51, 35, 52, 53, 54, - 35, 36, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 40, - 41, 42, 43, 44, 45, 46, 40, 35, - 35, 35, 49, 50, 51, 35, 52, 53, - 54, 35, 36, 35, 35, 37, 1, 35, - 35, 38, 35, 35, 35, 35, 35, 35, - 40, 41, 42, 43, 44, 45, 46, 40, - 47, 35, 48, 49, 50, 51, 35, 52, - 53, 54, 35, 36, 35, 35, 37, 1, - 35, 35, 38, 35, 35, 35, 35, 35, - 35, 40, 41, 42, 43, 44, 45, 46, - 40, 47, 39, 48, 49, 50, 51, 35, - 52, 53, 54, 35, 60, 59, 59, 59, - 59, 59, 59, 59, 61, 59, 10, 62, - 60, 59, 11, 63, 63, 3, 6, 63, - 63, 64, 63, 63, 63, 63, 63, 65, + 9, 32, 33, 9, 35, 34, 37, 36, + 36, 38, 1, 36, 36, 39, 36, 36, + 36, 36, 36, 40, 41, 42, 43, 44, + 45, 46, 47, 41, 48, 40, 49, 50, + 51, 52, 36, 53, 54, 55, 36, 36, + 36, 36, 56, 36, 37, 36, 36, 38, + 1, 36, 36, 39, 36, 36, 36, 36, + 36, 57, 41, 42, 43, 44, 45, 46, + 47, 41, 48, 49, 49, 50, 51, 52, + 36, 53, 54, 55, 36, 36, 36, 36, + 56, 36, 38, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, + 59, 58, 38, 58, 37, 36, 36, 38, + 1, 36, 36, 39, 36, 36, 36, 36, + 36, 36, 41, 42, 43, 44, 45, 46, + 47, 41, 48, 49, 49, 50, 51, 52, + 36, 53, 54, 55, 36, 36, 36, 36, + 56, 36, 37, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 41, 42, 43, 44, 45, 36, 36, 36, + 36, 36, 36, 50, 51, 52, 36, 53, + 54, 55, 36, 36, 36, 36, 42, 36, + 37, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 42, + 43, 44, 45, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 53, 54, 55, + 36, 37, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 43, 44, 45, 36, 37, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 44, 45, + 36, 37, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 45, 36, 37, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 43, 44, 45, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 53, 54, 55, 36, 37, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 43, 44, + 45, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 54, 55, 36, 37, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 43, + 44, 45, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 55, 36, + 37, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 42, + 43, 44, 45, 36, 36, 36, 36, 36, + 36, 50, 51, 52, 36, 53, 54, 55, + 36, 36, 36, 36, 42, 36, 37, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 42, 43, 44, + 45, 36, 36, 36, 36, 36, 36, 36, + 51, 52, 36, 53, 54, 55, 36, 36, + 36, 36, 42, 36, 37, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 42, 43, 44, 45, 36, + 36, 36, 36, 36, 36, 36, 36, 52, + 36, 53, 54, 55, 36, 36, 36, 36, + 42, 36, 37, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 41, 42, 43, 44, 45, 36, 47, 41, + 36, 36, 36, 50, 51, 52, 36, 53, + 54, 55, 36, 36, 36, 36, 42, 36, + 37, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 41, 42, + 43, 44, 45, 36, 60, 41, 36, 36, + 36, 50, 51, 52, 36, 53, 54, 55, + 36, 36, 36, 36, 42, 36, 37, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 41, 42, 43, 44, + 45, 36, 36, 41, 36, 36, 36, 50, + 51, 52, 36, 53, 54, 55, 36, 36, + 36, 36, 42, 36, 37, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 41, 42, 43, 44, 45, 46, + 47, 41, 36, 36, 36, 50, 51, 52, + 36, 53, 54, 55, 36, 36, 36, 36, + 42, 36, 37, 36, 36, 38, 1, 36, + 36, 39, 36, 36, 36, 36, 36, 36, + 41, 42, 43, 44, 45, 46, 47, 41, + 48, 36, 49, 50, 51, 52, 36, 53, + 54, 55, 36, 36, 36, 36, 56, 36, + 38, 58, 58, 58, 58, 58, 58, 37, + 58, 58, 58, 58, 58, 58, 59, 58, + 58, 58, 58, 58, 58, 58, 42, 43, + 44, 45, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 53, 54, 55, 58, + 37, 36, 36, 38, 1, 36, 36, 39, + 36, 36, 36, 36, 36, 36, 41, 42, + 43, 44, 45, 46, 47, 41, 48, 40, + 49, 50, 51, 52, 36, 53, 54, 55, + 36, 36, 36, 36, 56, 36, 62, 61, + 61, 61, 61, 61, 61, 61, 63, 61, + 10, 64, 62, 61, 11, 65, 65, 3, + 6, 65, 65, 66, 65, 65, 65, 65, + 65, 67, 16, 17, 18, 19, 20, 21, + 22, 16, 23, 25, 25, 26, 27, 28, + 65, 29, 30, 31, 65, 65, 65, 65, + 33, 65, 11, 65, 65, 3, 6, 65, + 65, 66, 65, 65, 65, 65, 65, 65, 16, 17, 18, 19, 20, 21, 22, 16, - 23, 25, 25, 26, 27, 28, 63, 29, - 30, 31, 63, 11, 63, 63, 3, 6, - 63, 63, 64, 63, 63, 63, 63, 63, - 63, 16, 17, 18, 19, 20, 21, 22, - 16, 23, 25, 25, 26, 27, 28, 63, - 29, 30, 31, 63, 11, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 16, 17, 18, 19, 20, 63, - 63, 63, 63, 63, 63, 26, 27, 28, - 63, 29, 30, 31, 63, 11, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 17, 18, 19, 20, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 29, 30, 31, 63, 11, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 18, 19, - 20, 63, 11, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 19, 20, 63, 11, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 20, 63, 11, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 18, 19, 20, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 29, - 30, 31, 63, 11, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 18, 19, 20, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 30, 31, 63, 11, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 18, 19, 20, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 31, 63, 11, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 17, 18, 19, 20, - 63, 63, 63, 63, 63, 63, 26, 27, - 28, 63, 29, 30, 31, 63, 11, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 17, 18, 19, - 20, 63, 63, 63, 63, 63, 63, 63, - 27, 28, 63, 29, 30, 31, 63, 11, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 17, 18, - 19, 20, 63, 63, 63, 63, 63, 63, - 63, 63, 28, 63, 29, 30, 31, 63, - 11, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 16, 17, - 18, 19, 20, 63, 22, 16, 63, 63, - 63, 26, 27, 28, 63, 29, 30, 31, - 63, 11, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 16, - 17, 18, 19, 20, 63, 66, 16, 63, - 63, 63, 26, 27, 28, 63, 29, 30, - 31, 63, 11, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 16, 17, 18, 19, 20, 63, 63, 16, - 63, 63, 63, 26, 27, 28, 63, 29, - 30, 31, 63, 11, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 16, 17, 18, 19, 20, 21, 22, - 16, 63, 63, 63, 26, 27, 28, 63, - 29, 30, 31, 63, 11, 63, 63, 3, - 6, 63, 63, 64, 63, 63, 63, 63, - 63, 63, 16, 17, 18, 19, 20, 21, - 22, 16, 23, 63, 25, 26, 27, 28, - 63, 29, 30, 31, 63, 3, 67, 67, - 67, 67, 67, 67, 67, 67, 67, 67, - 67, 67, 67, 4, 67, 6, 67, 8, - 63, 63, 63, 8, 63, 63, 11, 63, - 63, 3, 6, 63, 63, 64, 63, 63, - 63, 63, 63, 63, 16, 17, 18, 19, - 20, 21, 22, 16, 23, 24, 25, 26, - 27, 28, 63, 29, 30, 31, 63, 11, - 63, 63, 3, 6, 63, 63, 64, 63, - 63, 63, 63, 63, 63, 16, 17, 18, + 23, 25, 25, 26, 27, 28, 65, 29, + 30, 31, 65, 65, 65, 65, 33, 65, + 11, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 16, 17, + 18, 19, 20, 65, 65, 65, 65, 65, + 65, 26, 27, 28, 65, 29, 30, 31, + 65, 65, 65, 65, 17, 65, 11, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 17, 18, 19, + 20, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 29, 30, 31, 65, 11, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 18, + 19, 20, 65, 11, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 19, 20, 65, 11, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 20, 65, 11, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 18, 19, 20, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 29, 30, 31, 65, 11, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 18, 19, 20, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 30, 31, 65, 11, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 18, 19, 20, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 31, 65, 11, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 17, 18, 19, + 20, 65, 65, 65, 65, 65, 65, 26, + 27, 28, 65, 29, 30, 31, 65, 65, + 65, 65, 17, 65, 11, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 17, 18, 19, 20, 65, + 65, 65, 65, 65, 65, 65, 27, 28, + 65, 29, 30, 31, 65, 65, 65, 65, + 17, 65, 11, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 17, 18, 19, 20, 65, 65, 65, + 65, 65, 65, 65, 65, 28, 65, 29, + 30, 31, 65, 65, 65, 65, 17, 65, + 11, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 16, 17, + 18, 19, 20, 65, 22, 16, 65, 65, + 65, 26, 27, 28, 65, 29, 30, 31, + 65, 65, 65, 65, 17, 65, 11, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 16, 17, 18, 19, + 20, 65, 68, 16, 65, 65, 65, 26, + 27, 28, 65, 29, 30, 31, 65, 65, + 65, 65, 17, 65, 11, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 16, 17, 18, 19, 20, 65, + 65, 16, 65, 65, 65, 26, 27, 28, + 65, 29, 30, 31, 65, 65, 65, 65, + 17, 65, 11, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 16, 17, 18, 19, 20, 21, 22, 16, + 65, 65, 65, 26, 27, 28, 65, 29, + 30, 31, 65, 65, 65, 65, 17, 65, + 11, 65, 65, 3, 6, 65, 65, 66, + 65, 65, 65, 65, 65, 65, 16, 17, + 18, 19, 20, 21, 22, 16, 23, 65, + 25, 26, 27, 28, 65, 29, 30, 31, + 65, 65, 65, 65, 33, 65, 3, 65, + 65, 65, 65, 65, 65, 11, 65, 65, + 65, 65, 65, 65, 4, 65, 65, 65, + 65, 65, 65, 65, 17, 18, 19, 20, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 29, 30, 31, 65, 3, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 4, 69, 6, 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, 69, 69, 69, 69, 69, 6, 69, + 8, 65, 65, 65, 8, 65, 65, 11, + 65, 65, 3, 6, 65, 65, 66, 65, + 65, 65, 65, 65, 65, 16, 17, 18, 19, 20, 21, 22, 16, 23, 24, 25, - 26, 27, 28, 63, 29, 30, 31, 63, - 69, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 69, 70, 68, 69, - 70, 68, 70, 68, 8, 67, 67, 67, - 8, 67, 0 + 26, 27, 28, 65, 29, 30, 31, 65, + 65, 65, 65, 33, 65, 11, 65, 65, + 3, 6, 65, 65, 66, 65, 65, 65, + 65, 65, 65, 16, 17, 18, 19, 20, + 21, 22, 16, 23, 24, 25, 26, 27, + 28, 65, 29, 30, 31, 65, 65, 65, + 65, 33, 65, 71, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 71, + 72, 70, 71, 72, 70, 72, 70, 8, + 69, 69, 69, 8, 69, 0 }; static const char _use_syllable_machine_trans_targs[] = { - 4, 8, 4, 31, 2, 4, 1, 5, - 6, 4, 28, 4, 49, 50, 51, 53, - 33, 34, 35, 36, 37, 44, 45, 47, - 52, 48, 41, 42, 43, 38, 39, 40, - 56, 4, 4, 4, 4, 7, 0, 27, - 11, 12, 13, 14, 15, 22, 23, 25, - 26, 19, 20, 21, 16, 17, 18, 10, - 4, 9, 24, 4, 29, 30, 4, 4, - 3, 32, 46, 4, 4, 54, 55 + 4, 8, 4, 32, 2, 4, 1, 5, + 6, 4, 29, 4, 51, 52, 53, 55, + 34, 35, 36, 37, 38, 45, 46, 48, + 54, 49, 42, 43, 44, 39, 40, 41, + 58, 50, 4, 4, 4, 4, 7, 0, + 28, 11, 12, 13, 14, 15, 22, 23, + 25, 26, 19, 20, 21, 16, 17, 18, + 27, 10, 4, 9, 24, 4, 30, 31, + 4, 4, 3, 33, 47, 4, 4, 56, + 57 }; static const char _use_syllable_machine_trans_actions[] = { @@ -264,11 +303,12 @@ 7, 8, 0, 9, 10, 10, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, - 0, 11, 12, 13, 14, 7, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, - 7, 0, 0, 0, 0, 0, 0, 7, - 15, 0, 0, 16, 0, 0, 17, 18, - 0, 3, 0, 19, 20, 0, 0 + 0, 3, 11, 12, 13, 14, 7, 0, + 7, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, + 0, 7, 15, 0, 0, 16, 0, 0, + 17, 18, 0, 3, 0, 19, 20, 0, + 0 }; static const char _use_syllable_machine_to_state_actions[] = { @@ -279,7 +319,7 @@ 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 }; static const char _use_syllable_machine_from_state_actions[] = { @@ -290,18 +330,18 @@ 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 }; static const short _use_syllable_machine_eof_trans[] = { - 1, 3, 3, 6, 0, 34, 36, 36, - 57, 57, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 60, 63, 60, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 68, 68, 64, 64, 69, 69, 69, - 68 + 1, 3, 3, 6, 0, 35, 37, 37, + 59, 59, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 59, 37, 62, 65, 62, + 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 70, 70, 66, 66, 71, + 71, 71, 70 }; static const int use_syllable_machine_start = 4; @@ -315,15 +355,14 @@ -#line 141 "hb-ot-shape-complex-use-machine.rl" +#line 143 "hb-ot-shape-complex-use-machine.rl" #define found_syllable(syllable_type) \ HB_STMT_START { \ - if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ - for (unsigned int i = last; i < p+1; i++) \ + if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ + for (unsigned int i = ts; i < te; i++) \ info[i].syllable() = (syllable_serial << 4) | syllable_type; \ - last = p+1; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END @@ -331,11 +370,11 @@ static void find_syllables (hb_buffer_t *buffer) { - unsigned int p, pe, eof, ts HB_UNUSED, te, act; + unsigned int p, pe, eof, ts, te, act; int cs; hb_glyph_info_t *info = buffer->info; -#line 339 "hb-ot-shape-complex-use-machine.hh" +#line 378 "hb-ot-shape-complex-use-machine.hh" { cs = use_syllable_machine_start; ts = 0; @@ -343,16 +382,15 @@ act = 0; } -#line 162 "hb-ot-shape-complex-use-machine.rl" +#line 163 "hb-ot-shape-complex-use-machine.rl" p = 0; pe = eof = buffer->len; - unsigned int last = 0; unsigned int syllable_serial = 1; -#line 356 "hb-ot-shape-complex-use-machine.hh" +#line 394 "hb-ot-shape-complex-use-machine.hh" { int _slen; int _trans; @@ -366,7 +404,7 @@ #line 1 "NONE" {ts = p;} break; -#line 370 "hb-ot-shape-complex-use-machine.hh" +#line 408 "hb-ot-shape-complex-use-machine.hh" } _keys = _use_syllable_machine_trans_keys + (cs<<1); @@ -389,59 +427,59 @@ {te = p+1;} break; case 12: -#line 130 "hb-ot-shape-complex-use-machine.rl" +#line 132 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (independent_cluster); }} break; case 14: -#line 132 "hb-ot-shape-complex-use-machine.rl" +#line 134 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (standard_cluster); }} break; case 9: -#line 136 "hb-ot-shape-complex-use-machine.rl" +#line 138 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (broken_cluster); }} break; case 8: -#line 137 "hb-ot-shape-complex-use-machine.rl" +#line 139 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (non_cluster); }} break; case 11: -#line 130 "hb-ot-shape-complex-use-machine.rl" +#line 132 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (independent_cluster); }} break; case 15: -#line 131 "hb-ot-shape-complex-use-machine.rl" +#line 133 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (virama_terminated_cluster); }} break; case 13: -#line 132 "hb-ot-shape-complex-use-machine.rl" +#line 134 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (standard_cluster); }} break; case 17: -#line 133 "hb-ot-shape-complex-use-machine.rl" +#line 135 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }} break; case 16: -#line 134 "hb-ot-shape-complex-use-machine.rl" +#line 136 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (numeral_cluster); }} break; case 20: -#line 135 "hb-ot-shape-complex-use-machine.rl" +#line 137 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (symbol_cluster); }} break; case 18: -#line 136 "hb-ot-shape-complex-use-machine.rl" +#line 138 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; case 19: -#line 137 "hb-ot-shape-complex-use-machine.rl" +#line 139 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (non_cluster); }} break; case 1: -#line 132 "hb-ot-shape-complex-use-machine.rl" +#line 134 "hb-ot-shape-complex-use-machine.rl" {{p = ((te))-1;}{ found_syllable (standard_cluster); }} break; case 4: -#line 136 "hb-ot-shape-complex-use-machine.rl" +#line 138 "hb-ot-shape-complex-use-machine.rl" {{p = ((te))-1;}{ found_syllable (broken_cluster); }} break; case 2: @@ -459,16 +497,16 @@ case 3: #line 1 "NONE" {te = p+1;} -#line 136 "hb-ot-shape-complex-use-machine.rl" +#line 138 "hb-ot-shape-complex-use-machine.rl" {act = 7;} break; case 10: #line 1 "NONE" {te = p+1;} -#line 137 "hb-ot-shape-complex-use-machine.rl" +#line 139 "hb-ot-shape-complex-use-machine.rl" {act = 8;} break; -#line 472 "hb-ot-shape-complex-use-machine.hh" +#line 510 "hb-ot-shape-complex-use-machine.hh" } _again: @@ -477,7 +515,7 @@ #line 1 "NONE" {ts = 0;} break; -#line 481 "hb-ot-shape-complex-use-machine.hh" +#line 519 "hb-ot-shape-complex-use-machine.hh" } if ( ++p != pe ) --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-table.cc 2019-02-28 12:04:06.646502834 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-table.cc 2019-02-28 12:04:06.546502835 -0800 @@ -15,8 +15,10 @@ * UnicodeData.txt does not have a header. */ -#include "hb-ot-shape-complex-use-private.hh" +#include "hb-ot-shape-complex-use.hh" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-macros" #define B USE_B /* BASE */ #define CGJ USE_CGJ /* CGJ */ #define CS USE_CS /* CONS_WITH_STACKER */ @@ -24,6 +26,7 @@ #define GB USE_GB /* BASE_OTHER */ #define H USE_H /* HALANT */ #define HN USE_HN /* HALANT_NUM */ +#define HVM USE_HVM /* HALANT_OR_VOWEL_MODIFIER */ #define IND USE_IND /* BASE_IND */ #define N USE_N /* BASE_NUM */ #define O USE_O /* OTHER */ @@ -54,6 +57,7 @@ #define VMBlw USE_VMBlw #define VMPst USE_VMPst #define VMAbv USE_VMAbv +#pragma GCC diagnostic pop static const USE_TABLE_ELEMENT_TYPE use_table[] = { @@ -101,7 +105,7 @@ /* 0990 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 09A0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 09B0 */ B, O, B, O, O, O, B, B, B, B, O, O, CMBlw, B, VPst, VPre, - /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, IND, O, + /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPst, VPst, H, IND, O, /* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B, /* 09E0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FM, O, @@ -134,7 +138,7 @@ /* 0B10 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0B20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 0B30 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv, - /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O, + /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPst, O, O, VPst, VPst, H, O, O, /* 0B50 */ O, O, O, O, O, O, VAbv, VAbv, O, O, O, O, B, B, O, B, /* 0B60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, /* 0B70 */ O, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, @@ -145,7 +149,7 @@ /* 0B90 */ B, O, B, B, B, B, O, O, O, B, B, O, B, O, B, B, /* 0BA0 */ O, O, O, B, B, O, O, O, B, B, B, O, O, O, B, B, /* 0BB0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, VPst, VPst, - /* 0BC0 */ VAbv, VPst, VPst, O, O, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, O, O, + /* 0BC0 */ VAbv, VPst, VPst, O, O, O, VPre, VPre, VPre, O, VPst, VPst, VPst, H, O, O, /* 0BD0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O, /* 0BE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, /* 0BF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, @@ -178,7 +182,7 @@ /* 0D10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, VAbv, VAbv, B, VPst, VPst, - /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, R, O, + /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, O, VPre, VPre, VPre, O, VPst, VPst, VPst, H, R, O, /* 0D50 */ O, O, O, O, IND, IND, IND, VPst, O, O, O, O, O, O, O, B, /* 0D60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, /* 0D70 */ O, O, O, O, O, O, O, O, O, O, IND, IND, IND, IND, IND, IND, @@ -190,11 +194,28 @@ /* 0DA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0DB0 */ B, B, O, B, B, B, B, B, B, B, B, B, O, B, O, O, /* 0DC0 */ B, B, B, B, B, B, B, O, O, O, H, O, O, O, O, VPst, - /* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, O, VBlw, O, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst, + /* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, O, VBlw, O, VPst, VPre, VPst, VPre, VPst, VPst, VPst, VPst, /* 0DE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, /* 0DF0 */ O, O, VPst, VPst, O, O, O, O, -#define use_offset_0x1000u 1360 +#define use_offset_0x0f18u 1360 + + + /* Tibetan */ + VBlw, VBlw, O, O, O, O, O, O, + /* 0F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 0F30 */ B, B, B, B, O, FM, O, FM, O, CMAbv, O, O, O, O, VPst, VPre, + /* 0F40 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B, + /* 0F50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 0F60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, + /* 0F70 */ O, VBlw, VBlw, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VMAbv, VMPst, + /* 0F80 */ VBlw, VAbv, VMAbv, VMAbv, VBlw, IND, VMAbv, VMAbv, B, B, B, B, B, SUB, SUB, SUB, + /* 0F90 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, + /* 0FA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, + /* 0FB0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, O, O, + /* 0FC0 */ O, O, O, O, O, O, FM, O, + +#define use_offset_0x1000u 1536 /* Myanmar */ @@ -210,7 +231,7 @@ /* 1080 */ B, B, MBlw, VPst, VPre, VAbv, VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw, B, VMPst, /* 1090 */ B, B, B, B, B, B, B, B, B, B, VMPst, VMPst, VPst, VAbv, O, O, -#define use_offset_0x1700u 1520 +#define use_offset_0x1700u 1696 /* Tagalog */ @@ -238,12 +259,12 @@ /* 1780 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 17A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 17B0 */ B, B, B, B, O, O, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre, - /* 17C0 */ VPre, VPre, VPre, VPre, VPre, VPre, VMAbv, VMPst, VPst, VMAbv, VMAbv, FM, FAbv, CMAbv, FM, FM, + /* 17B0 */ B, B, B, B, O, O, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPst, VPst, + /* 17C0 */ VPst, VPre, VPre, VPre, VPst, VPst, VMAbv, VMPst, VPst, VMAbv, VMAbv, FM, FAbv, CMAbv, FM, FM, /* 17D0 */ FM, VAbv, H, FM, O, O, O, O, O, O, O, O, B, VAbv, O, O, /* 17E0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x1900u 1760 +#define use_offset_0x1900u 1936 /* Limbu */ @@ -287,7 +308,7 @@ /* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, /* 1A90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x1b00u 2176 +#define use_offset_0x1b00u 2352 /* Balinese */ @@ -296,7 +317,7 @@ /* 1B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre, - /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, O, O, O, O, + /* 1B40 */ VPst, VPst, VAbv, VAbv, H, B, B, B, B, B, B, B, O, O, O, O, /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, /* 1B60 */ O, O, O, O, O, O, O, O, O, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv, /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, O, @@ -319,11 +340,11 @@ /* 1C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPre, VPst, VPst, VBlw, FAbv, FAbv, FAbv, + /* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPst, VPst, VPst, VBlw, FAbv, FAbv, FAbv, /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FM, CMBlw, O, O, O, O, O, O, O, O, /* 1C40 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, B, B, -#define use_offset_0x1cd0u 2512 +#define use_offset_0x1cd0u 2688 /* Vedic Extensions */ @@ -332,20 +353,20 @@ /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O, /* 1CF0 */ O, O, VMPst, VMPst, VMAbv, CS, CS, VMPst, VMAbv, VMAbv, O, O, O, O, O, O, -#define use_offset_0x1df8u 2560 +#define use_offset_0x1df8u 2736 /* Combining Diacritical Marks Supplement */ O, O, O, FM, O, O, O, O, -#define use_offset_0x2008u 2568 +#define use_offset_0x2008u 2744 /* General Punctuation */ O, O, O, O, ZWNJ, ZWJ, O, O, /* 2010 */ GB, GB, GB, GB, GB, O, O, O, -#define use_offset_0x2060u 2584 +#define use_offset_0x2060u 2760 /* 2060 */ WJ, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, @@ -354,20 +375,20 @@ /* 2070 */ O, O, O, O, FM, O, O, O, O, O, O, O, O, O, O, O, /* 2080 */ O, O, FM, FM, FM, O, O, O, -#define use_offset_0x20f0u 2624 +#define use_offset_0x20f0u 2800 /* Combining Diacritical Marks for Symbols */ /* 20F0 */ VMAbv, O, O, O, O, O, O, O, -#define use_offset_0x25c8u 2632 +#define use_offset_0x25c8u 2808 /* Geometric Shapes */ O, O, O, O, GB, O, O, O, -#define use_offset_0xa800u 2640 +#define use_offset_0xa800u 2816 /* Syloti Nagri */ @@ -454,7 +475,7 @@ /* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst, /* AAF0 */ O, O, O, O, O, VMPst, H, O, -#define use_offset_0xabc0u 3400 +#define use_offset_0xabc0u 3576 /* Meetei Mayek */ @@ -464,14 +485,14 @@ /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, O, O, /* ABF0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0xfe00u 3464 +#define use_offset_0xfe00u 3640 /* Variation Selectors */ /* FE00 */ VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, -#define use_offset_0x10a00u 3480 +#define use_offset_0x10a00u 3656 /* Kharoshthi */ @@ -482,7 +503,7 @@ /* 10A30 */ B, B, B, B, B, B, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H, /* 10A40 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, -#define use_offset_0x11000u 3560 +#define use_offset_0x11000u 3736 /* Brahmi */ @@ -491,7 +512,7 @@ /* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, - /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, O, O, + /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, HVM, O, O, O, O, O, O, O, O, O, /* 11050 */ O, O, N, N, N, N, N, N, N, N, N, N, N, N, N, N, /* 11060 */ N, N, N, N, N, N, B, B, B, B, B, B, B, B, B, B, /* 11070 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, HN, @@ -503,15 +524,15 @@ /* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O, -#define use_offset_0x11100u 3752 +#define use_offset_0x11100u 3928 /* Chakma */ /* 11100 */ VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11120 */ B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VAbv, VAbv, - /* 11130 */ VAbv, VBlw, VBlw, H, VAbv, O, B, B, B, B, B, B, B, B, B, B, + /* 11120 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VBlw, VAbv, VAbv, + /* 11130 */ VBlw, VAbv, VAbv, H, CMBlw, O, B, B, B, B, B, B, B, B, B, B, /* 11140 */ O, O, O, O, B, VPst, VPst, O, O, O, O, O, O, O, O, O, /* Mahajani */ @@ -526,7 +547,7 @@ /* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, - /* 111C0 */ H, B, R, R, O, O, O, O, O, FM, CMBlw, VAbv, VBlw, O, O, O, + /* 111C0 */ H, B, R, R, O, O, O, O, GB, FBlw, CMBlw, VAbv, VBlw, O, O, O, /* 111D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, /* Sinhala Archaic Numbers */ @@ -541,7 +562,7 @@ /* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw, /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, O, -#define use_offset_0x11280u 4072 +#define use_offset_0x11280u 4248 /* Multani */ @@ -560,16 +581,16 @@ /* Grantha */ - /* 11300 */ VMAbv, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B, + /* 11300 */ VMAbv, VMAbv, VMAbv, VMPst, O, B, B, B, B, B, B, B, B, O, O, B, /* 11310 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 11330 */ B, O, B, B, O, B, B, B, B, B, O, CMBlw, CMBlw, B, VPst, VPst, - /* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O, + /* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPst, VPst, HVM, O, O, /* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, B, B, /* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, -#define use_offset_0x11400u 4320 +#define use_offset_0x11400u 4496 /* Newa */ @@ -588,11 +609,11 @@ /* 11480 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11490 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 114A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPre, VPre, VPst, VPre, VMAbv, + /* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPst, VPst, VPst, VPst, VMAbv, /* 114C0 */ VMAbv, VMPst, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O, /* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x11580u 4544 +#define use_offset_0x11580u 4720 /* Siddham */ @@ -600,7 +621,7 @@ /* 11580 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11590 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 115A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst, - /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H, + /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPst, VPst, VPst, VMAbv, VMAbv, VMPst, H, /* 115C0 */ CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* 115D0 */ O, O, O, O, O, O, O, O, B, B, B, B, VBlw, VBlw, O, O, /* 115E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, @@ -635,7 +656,7 @@ /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O, /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, -#define use_offset_0x11800u 4992 +#define use_offset_0x11800u 5168 /* Dogra */ @@ -645,7 +666,7 @@ /* 11820 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPre, VPst, VBlw, /* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, O, O, O, O, -#define use_offset_0x11a00u 5056 +#define use_offset_0x11a00u 5232 /* Zanabazar Square */ @@ -664,7 +685,7 @@ /* 11A80 */ B, B, B, B, O, O, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, H, O, O, O, B, O, O, -#define use_offset_0x11c00u 5216 +#define use_offset_0x11c00u 5392 /* Bhaiksuki */ @@ -673,7 +694,7 @@ /* 11C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst, /* 11C30 */ VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VBlw, O, VAbv, VAbv, VAbv, VAbv, VMAbv, VMAbv, VMPst, H, - /* 11C40 */ B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 11C40 */ B, O, O, O, GB, GB, O, O, O, O, O, O, O, O, O, O, /* 11C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, @@ -685,7 +706,7 @@ /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, O, -#define use_offset_0x11d00u 5400 +#define use_offset_0x11d00u 5576 /* Masaram Gondi */ @@ -705,7 +726,7 @@ /* 11D90 */ VAbv, VAbv, O, VPst, VPst, VMAbv, VMPst, H, O, O, O, O, O, O, O, O, /* 11DA0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x11ee0u 5576 +#define use_offset_0x11ee0u 5752 /* Makasar */ @@ -713,7 +734,7 @@ /* 11EE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11EF0 */ B, B, GB, VAbv, VBlw, VPre, VPst, O, -}; /* Table items: 5600; occupancy: 73% */ +}; /* Table items: 5776; occupancy: 74% */ USE_TABLE_ELEMENT_TYPE hb_use_get_category (hb_codepoint_t u) @@ -725,6 +746,7 @@ if (hb_in_range (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u]; if (hb_in_range (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u]; if (hb_in_range (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u]; + if (hb_in_range (u, 0x0F18u, 0x0FC7u)) return use_table[u - 0x0F18u + use_offset_0x0f18u]; break; case 0x1u: @@ -782,6 +804,7 @@ #undef GB #undef H #undef HN +#undef HVM #undef IND #undef N #undef O --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use.cc 2019-02-28 12:04:06.982502828 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use.cc 2019-02-28 12:04:06.882502830 -0800 @@ -26,8 +26,9 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-ot-shape-complex-use-private.hh" -#include "hb-ot-shape-complex-arabic-private.hh" +#include "hb-ot-shape-complex-use.hh" +#include "hb-ot-shape-complex-arabic.hh" +#include "hb-ot-shape-complex-vowel-constraints.hh" /* buffer var allocations */ #define use_category() complex_var_u8_0() @@ -79,14 +80,22 @@ { /* * Other features. - * These features are applied all at once, after reordering. + * These features are applied all at once, after reordering and + * clearing syllables. */ HB_TAG('a','b','v','s'), HB_TAG('b','l','w','s'), HB_TAG('h','a','l','n'), HB_TAG('p','r','e','s'), HB_TAG('p','s','t','s'), - /* Positioning features, though we don't care about the types. */ +}; +static const hb_tag_t +positioning_features[] = +{ + /* + * Positioning features. + * We don't care about the types. + */ HB_TAG('d','i','s','t'), HB_TAG('a','b','v','m'), HB_TAG('b','l','w','m'), @@ -112,6 +121,10 @@ reorder (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); +static void +clear_syllables (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void collect_features_use (hb_ot_shape_planner_t *plan) @@ -122,39 +135,42 @@ map->add_gsub_pause (setup_syllables); /* "Default glyph pre-processing group" */ - map->add_global_bool_feature (HB_TAG('l','o','c','l')); - map->add_global_bool_feature (HB_TAG('c','c','m','p')); - map->add_global_bool_feature (HB_TAG('n','u','k','t')); - map->add_global_bool_feature (HB_TAG('a','k','h','n')); + map->enable_feature (HB_TAG('l','o','c','l')); + map->enable_feature (HB_TAG('c','c','m','p')); + map->enable_feature (HB_TAG('n','u','k','t')); + map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ); /* "Reordering group" */ map->add_gsub_pause (clear_substitution_flags); - map->add_feature (HB_TAG('r','p','h','f'), 1, F_MANUAL_ZWJ); + map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ); map->add_gsub_pause (record_rphf); map->add_gsub_pause (clear_substitution_flags); - map->add_feature (HB_TAG('p','r','e','f'), 1, F_GLOBAL | F_MANUAL_ZWJ); + map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ); map->add_gsub_pause (record_pref); /* "Orthographic unit shaping group" */ for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) - map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); + map->enable_feature (basic_features[i], F_MANUAL_ZWJ); map->add_gsub_pause (reorder); + map->add_gsub_pause (clear_syllables); /* "Topographical features" */ for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++) - map->add_feature (arabic_features[i], 1, F_NONE); + map->add_feature (arabic_features[i]); map->add_gsub_pause (nullptr); - /* "Standard typographic presentation" and "Positional feature application" */ + /* "Standard typographic presentation" */ for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) - map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); + map->enable_feature (other_features[i], F_MANUAL_ZWJ); + + /* "Positional feature application" */ + for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++) + map->enable_feature (positioning_features[i]); } struct use_shape_plan_t { - ASSERT_POD (); - hb_mask_t rphf_mask; arabic_shape_plan_t *arabic_plan; @@ -361,7 +377,7 @@ } static void -clear_substitution_flags (const hb_ot_shape_plan_t *plan, +clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { @@ -373,7 +389,7 @@ static void record_rphf (const hb_ot_shape_plan_t *plan, - hb_font_t *font, + hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data; @@ -395,8 +411,8 @@ } static void -record_pref (const hb_ot_shape_plan_t *plan, - hb_font_t *font, +record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { hb_glyph_info_t *info = buffer->info; @@ -416,7 +432,8 @@ static inline bool is_halant (const hb_glyph_info_t &info) { - return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info); + return (info.use_category() == USE_H || info.use_category() == USE_HVM) && + !_hb_glyph_info_ligated (&info); } static void @@ -433,19 +450,38 @@ hb_glyph_info_t *info = buffer->info; -#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB)) +#define POST_BASE_FLAGS64 (FLAG64 (USE_FM) | \ + FLAG64 (USE_FAbv) | \ + FLAG64 (USE_FBlw) | \ + FLAG64 (USE_FPst) | \ + FLAG64 (USE_MAbv) | \ + FLAG64 (USE_MBlw) | \ + FLAG64 (USE_MPst) | \ + FLAG64 (USE_MPre) | \ + FLAG64 (USE_VAbv) | \ + FLAG64 (USE_VBlw) | \ + FLAG64 (USE_VPst) | \ + FLAG64 (USE_VPre) | \ + FLAG64 (USE_VMAbv) | \ + FLAG64 (USE_VMBlw) | \ + FLAG64 (USE_VMPst) | \ + FLAG64 (USE_VMPre)) /* Move things forward. */ if (info[start].use_category() == USE_R && end - start > 1) { - /* Got a repha. Reorder it to after first base, before first halant. */ + /* Got a repha. Reorder it towards the end, but before the first post-base + * glyph. */ for (unsigned int i = start + 1; i < end; i++) - if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i])) + { + bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) || + is_halant (info[i]); + if (is_post_base_glyph || i == end - 1) { - /* If we hit a halant, move before it; otherwise it's a base: move to it's - * place, and shift things in between backward. */ + /* If we hit a post-base glyph, move before it; otherwise move to the + * end. Shift things in between backward. */ - if (is_halant (info[i])) + if (is_post_base_glyph) i--; buffer->merge_clusters (start, i + 1); @@ -455,21 +491,19 @@ break; } + } } /* Move things back. */ - unsigned int j = end; + unsigned int j = start; for (unsigned int i = start; i < end; i++) { uint32_t flag = FLAG_UNSAFE (info[i].use_category()); - if ((flag & (BASE_FLAGS)) || is_halant (info[i])) + if (is_halant (info[i])) { - /* If we hit a halant, move after it; otherwise it's a base: move to it's - * place, and shift things in between backward. */ - if (is_halant (info[i])) - j = i + 1; - else - j = i; + /* If we hit a halant, move after it; otherwise move to the beginning, and + * shift things in between forward. */ + j = i + 1; } else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) && /* Only move the first component of a MultipleSubst. */ @@ -536,7 +570,6 @@ else buffer->next_glyph (); } - buffer->swap_buffers (); } @@ -547,36 +580,30 @@ { insert_dotted_circles (plan, font, buffer); - hb_glyph_info_t *info = buffer->info; - foreach_syllable (buffer, start, end) reorder_syllable (buffer, start, end); - /* Zero syllables now... */ + HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); +} + +static void +clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) +{ + hb_glyph_info_t *info = buffer->info; unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) info[i].syllable() = 0; - - HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); } -static bool -decompose_use (const hb_ot_shape_normalize_context_t *c, - hb_codepoint_t ab, - hb_codepoint_t *a, - hb_codepoint_t *b) -{ - switch (ab) - { - /* Chakma: - * Special case where the Unicode decomp gives matras in the wrong order - * for cluster validation. - */ - case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; - case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; - } - return (bool) c->unicode->decompose (ab, a, b); +static void +preprocess_text_use (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) +{ + _hb_preprocess_text_vowel_constraints (plan, buffer, font); } static bool @@ -599,13 +626,13 @@ nullptr, /* override_features */ data_create_use, data_destroy_use, - nullptr, /* preprocess_text */ + preprocess_text_use, nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, - decompose_use, + nullptr, /* decompose */ compose_use, setup_masks_use, - nullptr, /* disable_otl */ + HB_TAG_NONE, /* gpos_tag */ nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.cc 2019-02-28 12:04:07.326502822 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.cc 2019-02-28 12:04:07.206502824 -0800 @@ -24,8 +24,8 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-ot-shape-fallback-private.hh" -#include "hb-ot-layout-gsubgpos-private.hh" +#include "hb-ot-shape-fallback.hh" +#include "hb-kern.hh" static unsigned int recategorize_combining_class (hb_codepoint_t u, @@ -162,9 +162,9 @@ } void -_hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) +_hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) { unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; @@ -180,19 +180,25 @@ static void zero_mark_advances (hb_buffer_t *buffer, unsigned int start, - unsigned int end) + unsigned int end, + bool adjust_offsets_when_zeroing) { hb_glyph_info_t *info = buffer->info; for (unsigned int i = start; i < end; i++) if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { + if (adjust_offsets_when_zeroing) + { + buffer->pos[i].x_offset -= buffer->pos[i].x_advance; + buffer->pos[i].y_offset -= buffer->pos[i].y_advance; + } buffer->pos[i].x_advance = 0; buffer->pos[i].y_advance = 0; } } static inline void -position_mark (const hb_ot_shape_plan_t *plan, +position_mark (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font, hb_buffer_t *buffer, hb_glyph_extents_t &base_extents, @@ -303,7 +309,8 @@ hb_font_t *font, hb_buffer_t *buffer, unsigned int base, - unsigned int end) + unsigned int end, + bool adjust_offsets_when_zeroing) { hb_direction_t horiz_dir = HB_DIRECTION_INVALID; @@ -314,11 +321,15 @@ &base_extents)) { /* If extents don't work, zero marks and go home. */ - zero_mark_advances (buffer, base + 1, end); + zero_mark_advances (buffer, base + 1, end, adjust_offsets_when_zeroing); return; } - base_extents.x_bearing += buffer->pos[base].x_offset; base_extents.y_bearing += buffer->pos[base].y_offset; + /* Use horizontal advance for horizontal positioning. + * Generally a better idea. Also works for zero-ink glyphs. See: + * https://github.com/harfbuzz/harfbuzz/issues/1532 */ + base_extents.x_bearing = 0; + base_extents.width = font->get_glyph_h_advance (buffer->info[base].codepoint); unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]); /* Use integer for num_lig_components such that it doesn't convert to unsigned @@ -394,7 +405,8 @@ hb_font_t *font, hb_buffer_t *buffer, unsigned int start, - unsigned int end) + unsigned int end, + bool adjust_offsets_when_zeroing) { if (end - start < 2) return; @@ -410,16 +422,17 @@ if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j]))) break; - position_around_base (plan, font, buffer, i, j); + position_around_base (plan, font, buffer, i, j, adjust_offsets_when_zeroing); i = j - 1; } } void -_hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer) +_hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer, + bool adjust_offsets_when_zeroing) { _hb_buffer_assert_gsubgpos_vars (buffer); @@ -428,81 +441,66 @@ hb_glyph_info_t *info = buffer->info; for (unsigned int i = 1; i < count; i++) if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) { - position_cluster (plan, font, buffer, start, i); + position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing); start = i; } - position_cluster (plan, font, buffer, start, count); + position_cluster (plan, font, buffer, start, count, adjust_offsets_when_zeroing); } -/* Performs old-style TrueType kerning. */ +struct hb_ot_shape_fallback_kern_driver_t +{ + hb_ot_shape_fallback_kern_driver_t (hb_font_t *font_, + hb_buffer_t *buffer) : + font (font_), direction (buffer->props.direction) {} + + hb_position_t get_kerning (hb_codepoint_t first, hb_codepoint_t second) const + { + hb_position_t kern = 0; + font->get_glyph_kerning_for_direction (first, second, + direction, + &kern, &kern); + return kern; + } + + hb_font_t *font; + hb_direction_t direction; +}; + +/* Performs font-assisted kerning. */ void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, hb_font_t *font, - hb_buffer_t *buffer) + hb_buffer_t *buffer) { - if (!plan->has_kern) return; - - OT::hb_ot_apply_context_t c (1, font, buffer); - c.set_lookup_mask (plan->kern_mask); - c.set_lookup_props (OT::LookupFlag::IgnoreMarks); - OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input; - skippy_iter.init (&c); - - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - hb_glyph_position_t *pos = buffer->pos; - for (unsigned int idx = 0; idx < count;) - { - skippy_iter.reset (idx, 1); - if (!skippy_iter.next ()) - { - idx++; - continue; - } + if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ? + !font->has_glyph_h_kerning_func () : + !font->has_glyph_v_kerning_func ()) + return; - hb_position_t x_kern, y_kern; - font->get_glyph_kerning_for_direction (info[idx].codepoint, - info[skippy_iter.idx].codepoint, - buffer->props.direction, - &x_kern, &y_kern); + bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); - if (x_kern) - { - hb_position_t kern1 = x_kern >> 1; - hb_position_t kern2 = x_kern - kern1; - pos[idx].x_advance += kern1; - pos[skippy_iter.idx].x_advance += kern2; - pos[skippy_iter.idx].x_offset += kern2; - buffer->unsafe_to_break (idx, skippy_iter.idx + 1); - } + if (reverse) + buffer->reverse (); - if (y_kern) - { - hb_position_t kern1 = y_kern >> 1; - hb_position_t kern2 = y_kern - kern1; - pos[idx].y_advance += kern1; - pos[skippy_iter.idx].y_advance += kern2; - pos[skippy_iter.idx].y_offset += kern2; - buffer->unsafe_to_break (idx, skippy_iter.idx + 1); - } + hb_ot_shape_fallback_kern_driver_t driver (font, buffer); + OT::hb_kern_machine_t machine (driver); + machine.kern (font, buffer, plan->kern_mask, false); - idx = skippy_iter.idx; - } + if (reverse) + buffer->reverse (); } /* Adjusts width of various spaces. */ void -_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan, +_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font, hb_buffer_t *buffer) { - if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) - return; - hb_glyph_info_t *info = buffer->info; hb_glyph_position_t *pos = buffer->pos; + bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction); unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i])) @@ -523,27 +521,40 @@ case t::SPACE_EM_5: case t::SPACE_EM_6: case t::SPACE_EM_16: - pos[i].x_advance = (font->x_scale + ((int) space_type)/2) / (int) space_type; + if (horizontal) + pos[i].x_advance = +(font->x_scale + ((int) space_type)/2) / (int) space_type; + else + pos[i].y_advance = -(font->y_scale + ((int) space_type)/2) / (int) space_type; break; case t::SPACE_4_EM_18: - pos[i].x_advance = (int64_t) font->x_scale * 4 / 18; + if (horizontal) + pos[i].x_advance = (int64_t) +font->x_scale * 4 / 18; + else + pos[i].y_advance = (int64_t) -font->y_scale * 4 / 18; break; case t::SPACE_FIGURE: for (char u = '0'; u <= '9'; u++) if (font->get_nominal_glyph (u, &glyph)) { - pos[i].x_advance = font->get_glyph_h_advance (glyph); + if (horizontal) + pos[i].x_advance = font->get_glyph_h_advance (glyph); + else + pos[i].y_advance = font->get_glyph_v_advance (glyph); break; } break; case t::SPACE_PUNCTUATION: - if (font->get_nominal_glyph ('.', &glyph)) - pos[i].x_advance = font->get_glyph_h_advance (glyph); - else if (font->get_nominal_glyph (',', &glyph)) - pos[i].x_advance = font->get_glyph_h_advance (glyph); + if (font->get_nominal_glyph ('.', &glyph) || + font->get_nominal_glyph (',', &glyph)) + { + if (horizontal) + pos[i].x_advance = font->get_glyph_h_advance (glyph); + else + pos[i].y_advance = font->get_glyph_v_advance (glyph); + } break; case t::SPACE_NARROW: @@ -552,7 +563,10 @@ * However, in my testing, many fonts have their regular space being about that * size. To me, a percentage of the space width makes more sense. Half is as * good as any. */ - pos[i].x_advance /= 2; + if (horizontal) + pos[i].x_advance /= 2; + else + pos[i].y_advance /= 2; break; } } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize.cc 2019-02-28 12:04:07.662502817 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize.cc 2019-02-28 12:04:07.558502819 -0800 @@ -24,9 +24,9 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-ot-shape-normalize-private.hh" -#include "hb-ot-shape-complex-private.hh" -#include "hb-ot-shape-private.hh" +#include "hb-ot-shape-normalize.hh" +#include "hb-ot-shape-complex.hh" +#include "hb-ot-shape.hh" /* @@ -213,17 +213,19 @@ } static inline void -handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit) +handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, + unsigned int end, + bool short_circuit HB_UNUSED) { /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */ hb_buffer_t * const buffer = c->buffer; hb_font_t * const font = c->font; for (; buffer->idx < end - 1 && buffer->successful;) { if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) { - /* The next two lines are some ugly lines... But work. */ if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) { - buffer->replace_glyphs (2, 1, &buffer->cur().codepoint); + hb_codepoint_t unicode = buffer->cur().codepoint; + buffer->replace_glyphs (2, 1, &unicode); } else { @@ -264,15 +266,6 @@ decompose_current_character (c, short_circuit); } -static inline void -decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit) -{ - if (likely (c->buffer->idx + 1 == end)) - decompose_current_character (c, might_short_circuit); - else - decompose_multi_char_cluster (c, end, always_short_circuit); -} - static int compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) @@ -294,6 +287,16 @@ _hb_buffer_assert_unicode_vars (buffer); hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference; + if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_AUTO) + { + if (plan->has_gpos_mark) + // https://github.com/harfbuzz/harfbuzz/issues/653#issuecomment-423905920 + //mode = HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED; + mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS; + else + mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS; + } + const hb_ot_shape_normalize_context_t c = { plan, buffer, @@ -318,105 +321,81 @@ /* First round, decompose */ - buffer->clear_output (); - count = buffer->len; - for (buffer->idx = 0; buffer->idx < count && buffer->successful;) + bool all_simple = true; { - unsigned int end; - for (end = buffer->idx + 1; end < count; end++) - if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))) - break; - - decompose_cluster (&c, end, might_short_circuit, always_short_circuit); - } - buffer->swap_buffers (); - + buffer->clear_output (); + count = buffer->len; + buffer->idx = 0; + do + { + unsigned int end; + for (end = buffer->idx + 1; end < count; end++) + if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))) + break; - /* Second round, reorder (inplace) */ + if (end < count) + end--; /* Leave one base for the marks to cluster with. */ - count = buffer->len; - for (unsigned int i = 0; i < count; i++) - { - if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0) - continue; + /* From idx to end are simple clusters. */ + if (might_short_circuit) + { + unsigned int done = font->get_nominal_glyphs (end - buffer->idx, + &buffer->cur().codepoint, + sizeof (buffer->info[0]), + &buffer->cur().glyph_index(), + sizeof (buffer->info[0])); + buffer->next_glyphs (done); + } + while (buffer->idx < end && buffer->successful) + decompose_current_character (&c, might_short_circuit); - unsigned int end; - for (end = i + 1; end < count; end++) - if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0) + if (buffer->idx == count || !buffer->successful) break; - /* We are going to do a O(n^2). Only do this if the sequence is short. */ - if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) { - i = end; - continue; - } - - buffer->sort (i, end, compare_combining_class); + all_simple = false; - if (plan->shaper->reorder_marks) - plan->shaper->reorder_marks (plan, buffer, i, end); + /* Find all the marks now. */ + for (end = buffer->idx + 1; end < count; end++) + if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))) + break; - i = end; + /* idx to end is one non-simple cluster. */ + decompose_multi_char_cluster (&c, end, always_short_circuit); + } + while (buffer->idx < count && buffer->successful); + buffer->swap_buffers (); } - if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE || - mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED) - return; - - /* Third round, recompose */ - - /* As noted in the comment earlier, we don't try to combine - * ccc=0 chars with their previous Starter. */ + /* Second round, reorder (inplace) */ - buffer->clear_output (); - count = buffer->len; - unsigned int starter = 0; - buffer->next_glyph (); - while (buffer->idx < count && buffer->successful) + if (!all_simple) { - hb_codepoint_t composed, glyph; - if (/* We don't try to compose a non-mark character with it's preceding starter. - * This is both an optimization to avoid trying to compose every two neighboring - * glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul - * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */ - HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur()))) + count = buffer->len; + for (unsigned int i = 0; i < count; i++) { - if (/* If there's anything between the starter and this char, they should have CCC - * smaller than this character's. */ - (starter == buffer->out_len - 1 || - info_cc (buffer->prev()) < info_cc (buffer->cur())) && - /* And compose. */ - c.compose (&c, - buffer->out_info[starter].codepoint, - buffer->cur().codepoint, - &composed) && - /* And the font has glyph for the composite. */ - font->get_nominal_glyph (composed, &glyph)) - { - /* Composes. */ - buffer->next_glyph (); /* Copy to out-buffer. */ - if (unlikely (!buffer->successful)) - return; - buffer->merge_out_clusters (starter, buffer->out_len); - buffer->out_len--; /* Remove the second composable. */ - /* Modify starter and carry on. */ - buffer->out_info[starter].codepoint = composed; - buffer->out_info[starter].glyph_index() = glyph; - _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); + if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0) + continue; + unsigned int end; + for (end = i + 1; end < count; end++) + if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0) + break; + + /* We are going to do a O(n^2). Only do this if the sequence is short. */ + if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) { + i = end; continue; } - } - /* Blocked, or doesn't compose. */ - buffer->next_glyph (); + buffer->sort (i, end, compare_combining_class); - if (info_cc (buffer->prev()) == 0) - starter = buffer->out_len - 1; - } - buffer->swap_buffers (); + if (plan->shaper->reorder_marks) + plan->shaper->reorder_marks (plan, buffer, i, end); + i = end; + } + } if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_CGJ) { /* For all CGJ, check if it prevented any reordering at all. @@ -430,4 +409,63 @@ _hb_glyph_info_unhide (&buffer->info[i]); } } + + + /* Third round, recompose */ + + if (!all_simple && + (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS || + mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT)) + { + /* As noted in the comment earlier, we don't try to combine + * ccc=0 chars with their previous Starter. */ + + buffer->clear_output (); + count = buffer->len; + unsigned int starter = 0; + buffer->next_glyph (); + while (buffer->idx < count && buffer->successful) + { + hb_codepoint_t composed, glyph; + if (/* We don't try to compose a non-mark character with it's preceding starter. + * This is both an optimization to avoid trying to compose every two neighboring + * glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul + * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */ + HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur()))) + { + if (/* If there's anything between the starter and this char, they should have CCC + * smaller than this character's. */ + (starter == buffer->out_len - 1 || + info_cc (buffer->prev()) < info_cc (buffer->cur())) && + /* And compose. */ + c.compose (&c, + buffer->out_info[starter].codepoint, + buffer->cur().codepoint, + &composed) && + /* And the font has glyph for the composite. */ + font->get_nominal_glyph (composed, &glyph)) + { + /* Composes. */ + buffer->next_glyph (); /* Copy to out-buffer. */ + if (unlikely (!buffer->successful)) + return; + buffer->merge_out_clusters (starter, buffer->out_len); + buffer->out_len--; /* Remove the second composable. */ + /* Modify starter and carry on. */ + buffer->out_info[starter].codepoint = composed; + buffer->out_info[starter].glyph_index() = glyph; + _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); + + continue; + } + } + + /* Blocked, or doesn't compose. */ + buffer->next_glyph (); + + if (info_cc (buffer->prev()) == 0) + starter = buffer->out_len - 1; + } + buffer->swap_buffers (); + } } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape.cc 2019-02-28 12:04:07.990502811 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape.cc 2019-02-28 12:04:07.886502813 -0800 @@ -26,62 +26,246 @@ * Google Author(s): Behdad Esfahbod */ -#define HB_SHAPER ot -#define hb_ot_shaper_face_data_t hb_ot_layout_t -#define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t -#include "hb-shaper-impl-private.hh" - -#include "hb-ot-shape-private.hh" -#include "hb-ot-shape-complex-private.hh" -#include "hb-ot-shape-fallback-private.hh" -#include "hb-ot-shape-normalize-private.hh" - -#include "hb-ot-layout-private.hh" -#include "hb-unicode-private.hh" -#include "hb-set-private.hh" - -#include "hb-ot-layout-gsubgpos-private.hh" -//#include "hb-aat-layout-private.hh" - -static hb_tag_t common_features[] = { - HB_TAG('c','c','m','p'), - HB_TAG('l','o','c','l'), - HB_TAG('m','a','r','k'), - HB_TAG('m','k','m','k'), - HB_TAG('r','l','i','g'), -}; +#include "hb-shaper-impl.hh" + +#include "hb-ot-shape.hh" +#include "hb-ot-shape-complex.hh" +#include "hb-ot-shape-fallback.hh" +#include "hb-ot-shape-normalize.hh" + +#include "hb-ot-face.hh" + +#include "hb-set.hh" + +#include "hb-aat-layout.hh" + + +/** + * SECTION:hb-ot-shape + * @title: hb-ot-shape + * @short_description: OpenType shaping support + * @include: hb-ot.h + * + * Support functions for OpenType shaping related queries. + **/ + + +static void +hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, + const hb_feature_t *user_features, + unsigned int num_user_features); + +static bool +_hb_apply_morx (hb_face_t *face) +{ + if (hb_options ().aat && + hb_aat_layout_has_substitution (face)) + return true; + + /* Ignore empty GSUB tables. */ + return (!hb_ot_layout_has_substitution (face) || + !hb_ot_layout_table_get_script_tags (face, + HB_OT_TAG_GSUB, + 0, nullptr, nullptr)) && + hb_aat_layout_has_substitution (face); +} + +hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *face, + const hb_segment_properties_t *props) : + face (face), + props (*props), + map (face, props), + aat_map (face, props), + apply_morx (_hb_apply_morx (face)) +{ + shaper = hb_ot_shape_complex_categorize (this); + + script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE; + script_fallback_mark_positioning = shaper->fallback_position; + + if (apply_morx) + shaper = &_hb_ot_complex_shaper_default; +} + +void +hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, + const hb_ot_shape_plan_key_t &key) +{ + plan.props = props; + plan.shaper = shaper; + map.compile (plan.map, key); + if (apply_morx) + aat_map.compile (plan.aat_map); + + plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); + plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r')); + plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m')); + plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask); + plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); + hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ? + HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'); + plan.kern_mask = plan.map.get_mask (kern_tag); + plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k')); + + plan.requested_kerning = !!plan.kern_mask; + plan.requested_tracking = !!plan.trak_mask; + bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX; + bool disable_gpos = plan.shaper->gpos_tag && + plan.shaper->gpos_tag != plan.map.chosen_script[1]; + + /* + * Decide who provides glyph classes. GDEF or Unicode. + */ + + if (!hb_ot_layout_has_glyph_classes (face)) + plan.fallback_glyph_classes = true; + + /* + * Decide who does substitutions. GSUB, morx, or fallback. + */ + + plan.apply_morx = apply_morx; + + /* + * Decide who does positioning. GPOS, kerx, kern, or fallback. + */ + + if (hb_options ().aat && hb_aat_layout_has_positioning (face)) + plan.apply_kerx = true; + else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face)) + plan.apply_gpos = true; + else if (hb_aat_layout_has_positioning (face)) + plan.apply_kerx = true; + + if (!plan.apply_kerx && !has_gpos_kern) + { + /* Apparently Apple applies kerx if GPOS kern was not applied. */ + if (hb_aat_layout_has_positioning (face)) + plan.apply_kerx = true; + else if (hb_ot_layout_has_kerning (face)) + plan.apply_kern = true; + } + + plan.zero_marks = script_zero_marks && + !plan.apply_kerx && + (!plan.apply_kern || !hb_ot_layout_has_machine_kerning (face)); + plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k')); + + plan.adjust_mark_positioning_when_zeroing = !plan.apply_gpos && + !plan.apply_kerx && + (!plan.apply_kern || !hb_ot_layout_has_cross_kerning (face)); + + plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing && + script_fallback_mark_positioning; + + /* Currently we always apply trak. */ + plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face); +} + +bool +hb_ot_shape_plan_t::init0 (hb_face_t *face, + const hb_shape_plan_key_t *key) +{ + map.init (); + aat_map.init (); + + hb_ot_shape_planner_t planner (face, + &key->props); + + hb_ot_shape_collect_features (&planner, + key->user_features, + key->num_user_features); + + planner.compile (*this, key->ot); + + if (shaper->data_create) + { + data = shaper->data_create (this); + if (unlikely (!data)) + return false; + } + + return true; +} + +void +hb_ot_shape_plan_t::fini () +{ + if (shaper->data_destroy) + shaper->data_destroy (const_cast (data)); + + map.fini (); + aat_map.fini (); +} + +void +hb_ot_shape_plan_t::substitute (hb_font_t *font, + hb_buffer_t *buffer) const +{ + if (unlikely (apply_morx)) + hb_aat_layout_substitute (this, font, buffer); + else + map.substitute (this, font, buffer); +} + +void +hb_ot_shape_plan_t::position (hb_font_t *font, + hb_buffer_t *buffer) const +{ + if (this->apply_gpos) + map.position (this, font, buffer); + else if (this->apply_kerx) + hb_aat_layout_position (this, font, buffer); + else if (this->apply_kern) + hb_ot_layout_kern (this, font, buffer); + else + _hb_ot_shape_fallback_kern (this, font, buffer); + + if (this->apply_trak) + hb_aat_layout_track (this, font, buffer); +} -static hb_tag_t horizontal_features[] = { - HB_TAG('c','a','l','t'), - HB_TAG('c','l','i','g'), - HB_TAG('c','u','r','s'), - HB_TAG('k','e','r','n'), - HB_TAG('l','i','g','a'), - HB_TAG('r','c','l','t'), +static const hb_ot_map_feature_t +common_features[] = +{ + {HB_TAG('c','c','m','p'), F_GLOBAL}, + {HB_TAG('l','o','c','l'), F_GLOBAL}, + {HB_TAG('m','a','r','k'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('m','k','m','k'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('r','l','i','g'), F_GLOBAL}, }; +static const hb_ot_map_feature_t +horizontal_features[] = +{ + {HB_TAG('c','a','l','t'), F_GLOBAL}, + {HB_TAG('c','l','i','g'), F_GLOBAL}, + {HB_TAG('c','u','r','s'), F_GLOBAL}, + {HB_TAG('k','e','r','n'), F_GLOBAL_HAS_FALLBACK}, + {HB_TAG('l','i','g','a'), F_GLOBAL}, + {HB_TAG('r','c','l','t'), F_GLOBAL}, +}; static void hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, - const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features) { hb_ot_map_builder_t *map = &planner->map; - map->add_global_bool_feature (HB_TAG('r','v','r','n')); + map->enable_feature (HB_TAG('r','v','r','n')); map->add_gsub_pause (nullptr); - switch (props->direction) { + switch (planner->props.direction) { case HB_DIRECTION_LTR: - map->add_global_bool_feature (HB_TAG ('l','t','r','a')); - map->add_global_bool_feature (HB_TAG ('l','t','r','m')); + map->enable_feature (HB_TAG ('l','t','r','a')); + map->enable_feature (HB_TAG ('l','t','r','m')); break; case HB_DIRECTION_RTL: - map->add_global_bool_feature (HB_TAG ('r','t','l','a')); - map->add_feature (HB_TAG ('r','t','l','m'), 1, F_NONE); + map->enable_feature (HB_TAG ('r','t','l','a')); + map->add_feature (HB_TAG ('r','t','l','m')); break; case HB_DIRECTION_TTB: case HB_DIRECTION_BTT: @@ -90,39 +274,62 @@ break; } - map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE); - map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE); - map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE); + /* Automatic fractions. */ + map->add_feature (HB_TAG ('f','r','a','c')); + map->add_feature (HB_TAG ('n','u','m','r')); + map->add_feature (HB_TAG ('d','n','o','m')); + + /* Random! */ + map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE); + + /* Tracking. We enable dummy feature here just to allow disabling + * AAT 'trak' table using features. + * https://github.com/harfbuzz/harfbuzz/issues/1303 */ + map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK); + + map->enable_feature (HB_TAG ('H','A','R','F')); if (planner->shaper->collect_features) planner->shaper->collect_features (planner); + map->enable_feature (HB_TAG ('B','U','Z','Z')); + for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++) - map->add_global_bool_feature (common_features[i]); + map->add_feature (common_features[i]); - if (HB_DIRECTION_IS_HORIZONTAL (props->direction)) + if (HB_DIRECTION_IS_HORIZONTAL (planner->props.direction)) for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++) - map->add_feature (horizontal_features[i], 1, F_GLOBAL | - (horizontal_features[i] == HB_TAG('k','e','r','n') ? - F_HAS_FALLBACK : F_NONE)); + map->add_feature (horizontal_features[i]); else { /* We really want to find a 'vert' feature if there's any in the font, no * matter which script/langsys it is listed (or not) under. * See various bugs referenced from: * https://github.com/harfbuzz/harfbuzz/issues/63 */ - map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH); + map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH); } - if (planner->shaper->override_features) - planner->shaper->override_features (planner); - - for (unsigned int i = 0; i < num_user_features; i++) { + for (unsigned int i = 0; i < num_user_features; i++) + { const hb_feature_t *feature = &user_features[i]; - map->add_feature (feature->tag, feature->value, - (feature->start == 0 && feature->end == (unsigned int) -1) ? - F_GLOBAL : F_NONE); + map->add_feature (feature->tag, + (feature->start == HB_FEATURE_GLOBAL_START && + feature->end == HB_FEATURE_GLOBAL_END) ? F_GLOBAL : F_NONE, + feature->value); } + + if (planner->apply_morx) + { + hb_aat_map_builder_t *aat_map = &planner->aat_map; + for (unsigned int i = 0; i < num_user_features; i++) + { + const hb_feature_t *feature = &user_features[i]; + aat_map->add_feature (feature->tag, feature->value); + } + } + + if (planner->shaper->override_features) + planner->shaper->override_features (planner); } @@ -130,18 +337,17 @@ * shaper face data */ -HB_SHAPER_DATA_ENSURE_DEFINE(ot, face) +struct hb_ot_face_data_t {}; -hb_ot_shaper_face_data_t * +hb_ot_face_data_t * _hb_ot_shaper_face_data_create (hb_face_t *face) { - return _hb_ot_layout_create (face); + return (hb_ot_face_data_t *) HB_SHAPER_DATA_SUCCEEDED; } void -_hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data) +_hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data) { - _hb_ot_layout_destroy (data); } @@ -149,68 +355,17 @@ * shaper font data */ -HB_SHAPER_DATA_ENSURE_DEFINE(ot, font) - -struct hb_ot_shaper_font_data_t {}; +struct hb_ot_font_data_t {}; -hb_ot_shaper_font_data_t * +hb_ot_font_data_t * _hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED) { - return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; -} - -void -_hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data) -{ -} - - -/* - * shaper shape_plan data - */ - -hb_ot_shaper_shape_plan_data_t * -_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, - const hb_feature_t *user_features, - unsigned int num_user_features, - const int *coords, - unsigned int num_coords) -{ - hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t)); - if (unlikely (!plan)) - return nullptr; - - plan->init (); - - hb_ot_shape_planner_t planner (shape_plan); - - planner.shaper = hb_ot_shape_complex_categorize (&planner); - - hb_ot_shape_collect_features (&planner, &shape_plan->props, - user_features, num_user_features); - - planner.compile (*plan, coords, num_coords); - - if (plan->shaper->data_create) { - plan->data = plan->shaper->data_create (plan); - if (unlikely (!plan->data)) { - free(plan); - return nullptr; - } - } - - return plan; + return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; } void -_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan) +_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data HB_UNUSED) { - if (plan->shaper->data_destroy) - plan->shaper->data_destroy (const_cast (plan->data)); - - plan->fini (); - - free (plan); } @@ -228,8 +383,6 @@ unsigned int num_user_features; /* Transient stuff */ - bool fallback_positioning; - bool fallback_glyph_classes; hb_direction_t target_direction; }; @@ -243,10 +396,53 @@ static void hb_set_unicode_props (hb_buffer_t *buffer) { + /* Implement enough of Unicode Graphemes here that shaping + * in reverse-direction wouldn't break graphemes. Namely, + * we mark all marks and ZWJ and ZWJ,Extended_Pictographic + * sequences as continuations. The foreach_grapheme() + * macro uses this bit. + * + * https://www.unicode.org/reports/tr29/#Regex_Definitions + */ unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) + { _hb_glyph_info_set_unicode_props (&info[i], buffer); + + /* Marks are already set as continuation by the above line. + * Handle Emoji_Modifier and ZWJ-continuation. */ + if (unlikely (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL && + hb_in_range (info[i].codepoint, 0x1F3FBu, 0x1F3FFu))) + { + _hb_glyph_info_set_continuation (&info[i]); + } + else if (unlikely (_hb_glyph_info_is_zwj (&info[i]))) + { + _hb_glyph_info_set_continuation (&info[i]); + if (i + 1 < count && + _hb_unicode_is_emoji_Extended_Pictographic (info[i + 1].codepoint)) + { + i++; + _hb_glyph_info_set_unicode_props (&info[i], buffer); + _hb_glyph_info_set_continuation (&info[i]); + } + } + /* Or part of the Other_Grapheme_Extend that is not marks. + * As of Unicode 11 that is just: + * + * 200C ; Other_Grapheme_Extend # Cf ZERO WIDTH NON-JOINER + * FF9E..FF9F ; Other_Grapheme_Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK + * E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG + * + * ZWNJ is special, we don't want to merge it as there's no need, and keeping + * it separate results in more granular clusters. Ignore Katakana for now. + * Tags are used for Emoji sub-region flag sequences: + * https://github.com/harfbuzz/harfbuzz/issues/1556 + */ + else if (unlikely (hb_in_range (info[i].codepoint, 0xE0020u, 0xE007Fu))) + _hb_glyph_info_set_continuation (&info[i]); + } } static void @@ -254,8 +450,7 @@ { if (!(buffer->flags & HB_BUFFER_FLAG_BOT) || buffer->context_len[0] || - _hb_glyph_info_get_general_category (&buffer->info[0]) != - HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + !_hb_glyph_info_is_unicode_mark (&buffer->info[0])) return; if (!font->has_glyph (0x25CCu)) @@ -274,7 +469,6 @@ buffer->output_info (info); while (buffer->idx < buffer->len && buffer->successful) buffer->next_glyph (); - buffer->swap_buffers (); } @@ -284,26 +478,12 @@ if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII)) return; - /* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */ - unsigned int base = 0; - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - for (unsigned int i = 1; i < count; i++) - { - if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) && - !_hb_glyph_info_is_joiner (&info[i]))) - { - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) - buffer->merge_clusters (base, i); - else - buffer->unsafe_to_break (base, i); - base = i; - } - } if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) - buffer->merge_clusters (base, count); + foreach_grapheme (buffer, start, end) + buffer->merge_clusters (start, end); else - buffer->unsafe_to_break (base, count); + foreach_grapheme (buffer, start, end) + buffer->unsafe_to_break (start, end); } static void @@ -321,25 +501,17 @@ (HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB)) { - /* Same loop as hb_form_clusters(). - * Since form_clusters() merged clusters already, we don't merge. */ - unsigned int base = 0; - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - for (unsigned int i = 1; i < count; i++) - { - if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) - { - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) - buffer->merge_clusters (base, i); - buffer->reverse_range (base, i); - base = i; - } - } if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) - buffer->merge_clusters (base, count); - buffer->reverse_range (base, count); + foreach_grapheme (buffer, start, end) + { + buffer->merge_clusters (start, end); + buffer->reverse_range (start, end); + } + else + foreach_grapheme (buffer, start, end) + /* form_clusters() merged clusters already, we don't merge. */ + buffer->reverse_range (start, end); buffer->reverse (); @@ -348,10 +520,12 @@ } -/* Substitute */ +/* + * Substitute + */ static inline void -hb_ot_mirror_chars (hb_ot_shape_context_t *c) +hb_ot_mirror_chars (const hb_ot_shape_context_t *c) { if (HB_DIRECTION_IS_FORWARD (c->target_direction)) return; @@ -372,7 +546,7 @@ } static inline void -hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) +hb_ot_shape_setup_masks_fraction (const hb_ot_shape_context_t *c) { if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) || !c->plan->has_frac) @@ -422,7 +596,7 @@ } static inline void -hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c) +hb_ot_shape_initialize_masks (const hb_ot_shape_context_t *c) { hb_ot_map_t *map = &c->plan->map; hb_buffer_t *buffer = c->buffer; @@ -432,7 +606,7 @@ } static inline void -hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) +hb_ot_shape_setup_masks (const hb_ot_shape_context_t *c) { hb_ot_map_t *map = &c->plan->map; hb_buffer_t *buffer = c->buffer; @@ -454,10 +628,8 @@ } static void -hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c) +hb_ot_zero_width_default_ignorables (const hb_buffer_t *buffer) { - hb_buffer_t *buffer = c->buffer; - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) || (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) || (buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES)) @@ -473,83 +645,29 @@ } static void -hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) +hb_ot_hide_default_ignorables (hb_buffer_t *buffer, + hb_font_t *font) { - hb_buffer_t *buffer = c->buffer; - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) || (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)) return; unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; - hb_glyph_position_t *pos = buffer->pos; - unsigned int i = 0; - for (i = 0; i < count; i++) - { - if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i]))) - break; - } - - /* No default-ignorables found; return. */ - if (i == count) - return; - hb_codepoint_t space; + hb_codepoint_t invisible = buffer->invisible; if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) && - c->font->get_nominal_glyph (' ', &space)) + (invisible || font->get_nominal_glyph (' ', &invisible))) { - /* Replace default-ignorables with a zero-advance space glyph. */ - for (/*continue*/; i < count; i++) + /* Replace default-ignorables with a zero-advance invisible glyph. */ + for (unsigned int i = 0; i < count; i++) { if (_hb_glyph_info_is_default_ignorable (&info[i])) - info[i].codepoint = space; + info[i].codepoint = invisible; } } else - { - /* Merge clusters and delete default-ignorables. - * NOTE! We can't use out-buffer as we have positioning data. */ - unsigned int j = i; - for (; i < count; i++) - { - if (_hb_glyph_info_is_default_ignorable (&info[i])) - { - /* Merge clusters. - * Same logic as buffer->delete_glyph(), but for in-place removal. */ - - unsigned int cluster = info[i].cluster; - if (i + 1 < count && cluster == info[i + 1].cluster) - continue; /* Cluster survives; do nothing. */ - - if (j) - { - /* Merge cluster backward. */ - if (cluster < info[j - 1].cluster) - { - unsigned int mask = info[i].mask; - unsigned int old_cluster = info[j - 1].cluster; - for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) - buffer->set_cluster (info[k - 1], cluster, mask); - } - continue; - } - - if (i + 1 < count) - buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */ - - continue; - } - - if (j != i) - { - info[j] = info[i]; - pos[j] = pos[i]; - } - j++; - } - buffer->len = j; - } + hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable); } @@ -566,10 +684,10 @@ } static inline void -hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) +hb_synthesize_glyph_classes (hb_buffer_t *buffer) { - unsigned int count = c->buffer->len; - hb_glyph_info_t *info = c->buffer->info; + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) { hb_ot_layout_glyph_props_flags_t klass; @@ -592,7 +710,7 @@ } static inline void -hb_ot_substitute_default (hb_ot_shape_context_t *c) +hb_ot_substitute_default (const hb_ot_shape_context_t *c) { hb_buffer_t *buffer = c->buffer; @@ -605,8 +723,8 @@ hb_ot_shape_setup_masks (c); /* This is unfortunate to go here, but necessary... */ - if (c->fallback_positioning) - _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer); + if (c->plan->fallback_mark_positioning) + _hb_ot_shape_fallback_mark_position_recategorize_marks (c->plan, c->font, buffer); hb_ot_map_glyphs_fast (buffer); @@ -614,23 +732,20 @@ } static inline void -hb_ot_substitute_complex (hb_ot_shape_context_t *c) +hb_ot_substitute_complex (const hb_ot_shape_context_t *c) { hb_buffer_t *buffer = c->buffer; hb_ot_layout_substitute_start (c->font, buffer); - if (!hb_ot_layout_has_glyph_classes (c->face)) - hb_synthesize_glyph_classes (c); + if (c->plan->fallback_glyph_classes) + hb_synthesize_glyph_classes (c->buffer); c->plan->substitute (c->font, buffer); - - /* XXX Call morx instead. */ - //hb_aat_layout_substitute (c->font, c->buffer); } static inline void -hb_ot_substitute (hb_ot_shape_context_t *c) +hb_ot_substitute_pre (const hb_ot_shape_context_t *c) { hb_ot_substitute_default (c); @@ -639,7 +754,21 @@ hb_ot_substitute_complex (c); } -/* Position */ +static inline void +hb_ot_substitute_post (const hb_ot_shape_context_t *c) +{ + hb_ot_hide_default_ignorables (c->buffer, c->font); + if (c->plan->apply_morx) + hb_aat_layout_remove_deleted_glyphs (c->buffer); + + if (c->plan->shaper->postprocess_glyphs) + c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font); +} + + +/* + * Position + */ static inline void adjust_mark_offsets (hb_glyph_position_t *pos) @@ -670,7 +799,7 @@ } static inline void -hb_ot_position_default (hb_ot_shape_context_t *c) +hb_ot_position_default (const hb_ot_shape_context_t *c) { hb_direction_t direction = c->buffer->props.direction; unsigned int count = c->buffer->len; @@ -679,8 +808,8 @@ if (HB_DIRECTION_IS_HORIZONTAL (direction)) { - for (unsigned int i = 0; i < count; i++) - pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint); + c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]), + &pos[0].x_advance, sizeof(pos[0])); /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ if (c->font->has_glyph_h_origin_func ()) for (unsigned int i = 0; i < count; i++) @@ -690,9 +819,10 @@ } else { + c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]), + &pos[0].y_advance, sizeof(pos[0])); for (unsigned int i = 0; i < count; i++) { - pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint); c->font->subtract_glyph_v_origin (info[i].codepoint, &pos[i].x_offset, &pos[i].y_offset); @@ -703,23 +833,22 @@ } static inline void -hb_ot_position_complex (hb_ot_shape_context_t *c) +hb_ot_position_complex (const hb_ot_shape_context_t *c) { unsigned int count = c->buffer->len; hb_glyph_info_t *info = c->buffer->info; hb_glyph_position_t *pos = c->buffer->pos; - /* If the font has no GPOS, AND, no fallback positioning will - * happen, AND, direction is forward, then when zeroing mark - * widths, we shift the mark with it, such that the mark - * is positioned hanging over the previous glyph. When + /* If the font has no GPOS and direction is forward, then when + * zeroing mark widths, we shift the mark with it, such that the + * mark is positioned hanging over the previous glyph. When * direction is backward we don't shift and it will end up * hanging over the next glyph after the final reordering. - * If fallback positinoing happens or GPOS is present, we don't - * care. + * + * Note: If fallback positinoing happens, we don't care about + * this as it will be overriden. */ - bool adjust_offsets_when_zeroing = c->fallback_positioning && - !c->plan->shaper->fallback_position && + bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing && HB_DIRECTION_IS_FORWARD (c->buffer->props.direction); /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */ @@ -733,36 +862,39 @@ hb_ot_layout_position_start (c->font, c->buffer); - switch (c->plan->shaper->zero_width_marks) - { - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: - zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); - break; - - default: - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: - break; - } - - if (likely (!c->fallback_positioning)) - c->plan->position (c->font, c->buffer); + if (c->plan->zero_marks) + switch (c->plan->shaper->zero_width_marks) + { + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: + zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); + break; + + default: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: + break; + } - switch (c->plan->shaper->zero_width_marks) - { - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: - zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); - break; + c->plan->position (c->font, c->buffer); - default: - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: - break; - } + if (c->plan->zero_marks) + switch (c->plan->shaper->zero_width_marks) + { + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: + zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); + break; + + default: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: + break; + } - /* Finishing off GPOS has to follow a certain order. */ + /* Finish off. Has to follow a certain order. */ hb_ot_layout_position_finish_advances (c->font, c->buffer); - hb_ot_zero_width_default_ignorables (c); + hb_ot_zero_width_default_ignorables (c->buffer); + if (c->plan->apply_morx) + hb_aat_layout_zero_width_deleted_glyphs (c->buffer); hb_ot_layout_position_finish_offsets (c->font, c->buffer); /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ @@ -771,10 +903,14 @@ c->font->subtract_glyph_h_origin (info[i].codepoint, &pos[i].x_offset, &pos[i].y_offset); + + if (c->plan->fallback_mark_positioning) + _hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer, + adjust_offsets_when_zeroing); } static inline void -hb_ot_position (hb_ot_shape_context_t *c) +hb_ot_position (const hb_ot_shape_context_t *c) { c->buffer->clear_positions (); @@ -782,20 +918,10 @@ hb_ot_position_complex (c); - if (c->fallback_positioning && c->plan->shaper->fallback_position) - _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer); - if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)) hb_buffer_reverse (c->buffer); - /* Visual fallback goes here. */ - - if (c->fallback_positioning) - _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); - _hb_buffer_deallocate_gsubgpos_vars (c->buffer); - - //hb_aat_layout_position (c->font, c->buffer); } static inline void @@ -831,22 +957,17 @@ { c->buffer->deallocate_var_all (); c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; - if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR))) + if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR))) { c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR, (unsigned) HB_BUFFER_MAX_LEN_MIN); } - if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR))) + if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR))) { c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR, (unsigned) HB_BUFFER_MAX_OPS_MIN); } - bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan); - //c->fallback_substitute = disable_otl || !hb_ot_layout_has_substitution (c->face); - c->fallback_positioning = disable_otl || !hb_ot_layout_has_positioning (c->face); - c->fallback_glyph_classes = disable_otl || !hb_ot_layout_has_glyph_classes (c->face); - /* Save the original direction, we use it later. */ c->target_direction = c->buffer->props.direction; @@ -865,13 +986,9 @@ if (c->plan->shaper->preprocess_text) c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font); - hb_ot_substitute (c); + hb_ot_substitute_pre (c); hb_ot_position (c); - - hb_ot_hide_default_ignorables (c); - - if (c->plan->shaper->postprocess_glyphs) - c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font); + hb_ot_substitute_post (c); hb_propagate_flags (c->buffer); @@ -892,7 +1009,7 @@ const hb_feature_t *features, unsigned int num_features) { - hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features}; + hb_ot_shape_context_t c = {&shape_plan->ot, font, font->face, buffer, features, num_features}; hb_ot_shape_internal (&c); return true; @@ -909,8 +1026,7 @@ hb_tag_t table_tag, hb_set_t *lookup_indexes /* OUT */) { - /* XXX Does the first part always succeed? */ - HB_SHAPER_DATA_GET (shape_plan)->collect_lookups (table_tag, lookup_indexes); + shape_plan->ot.collect_lookups (table_tag, lookup_indexes); } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag.cc 2019-02-28 12:04:08.346502806 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag.cc 2019-02-28 12:04:08.226502808 -0800 @@ -26,7 +26,7 @@ * Google Author(s): Behdad Esfahbod, Roozbeh Pournader */ -#include "hb-private.hh" +#include "hb.hh" /* hb_script_t */ @@ -36,7 +36,8 @@ { /* This seems to be accurate as of end of 2012. */ - switch ((hb_tag_t) script) { + switch ((hb_tag_t) script) + { case HB_SCRIPT_INVALID: return HB_OT_TAG_DEFAULT_SCRIPT; /* KATAKANA and HIRAGANA both map to 'kana' */ @@ -49,8 +50,6 @@ case HB_SCRIPT_NKO: return HB_TAG('n','k','o',' '); /* Unicode-5.1 additions */ case HB_SCRIPT_VAI: return HB_TAG('v','a','i',' '); - /* Unicode-5.2 additions */ - /* Unicode-6.0 additions */ } /* Else, just change first char to lowercase and return */ @@ -114,6 +113,18 @@ return HB_SCRIPT_UNKNOWN; } +void +hb_ot_tags_from_script (hb_script_t script, + hb_tag_t *script_tag_1, + hb_tag_t *script_tag_2) +{ + unsigned int count = 2; + hb_tag_t tags[2]; + hb_ot_tags_from_script_and_language (script, HB_LANGUAGE_INVALID, &count, tags, nullptr, nullptr); + *script_tag_1 = count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_SCRIPT; + *script_tag_2 = count > 1 ? tags[1] : HB_OT_TAG_DEFAULT_SCRIPT; +} + /* * Complete list at: * https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags @@ -122,28 +133,37 @@ * So we just do that, and handle the exceptional cases in a switch. */ -void -hb_ot_tags_from_script (hb_script_t script, - hb_tag_t *script_tag_1, - hb_tag_t *script_tag_2) +static void +hb_ot_all_tags_from_script (hb_script_t script, + unsigned int *count /* IN/OUT */, + hb_tag_t *tags /* OUT */) { - hb_tag_t new_tag; + unsigned int i = 0; - *script_tag_2 = HB_OT_TAG_DEFAULT_SCRIPT; - *script_tag_1 = hb_ot_old_tag_from_script (script); + hb_tag_t new_tag = hb_ot_new_tag_from_script (script); + if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT)) + { + tags[i++] = new_tag | '3'; + if (*count > i) + tags[i++] = new_tag; + } - new_tag = hb_ot_new_tag_from_script (script); - if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT)) { - *script_tag_2 = *script_tag_1; - *script_tag_1 = new_tag; + if (*count > i) + { + hb_tag_t old_tag = hb_ot_old_tag_from_script (script); + if (old_tag != HB_OT_TAG_DEFAULT_SCRIPT) + tags[i++] = old_tag; } + + *count = i; } hb_script_t hb_ot_tag_to_script (hb_tag_t tag) { - if (unlikely ((tag & 0x000000FFu) == '2')) - return hb_ot_new_tag_to_script (tag); + unsigned char digit = tag & 0x000000FFu; + if (unlikely (digit == '2' || digit == '3')) + return hb_ot_new_tag_to_script (tag & 0xFFFFFF32); return hb_ot_old_tag_to_script (tag); } @@ -151,732 +171,6 @@ /* hb_language_t */ -typedef struct { - char language[4]; - hb_tag_t tag; -} LangTag; - -/* - * Complete list at: - * https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags - * - * Generated by intersecting the OpenType language tag list from - * Draft OpenType 1.5 spec, with with the ISO 639-3 codes from - * 2008-08-04, matching on name, and finally adjusted manually. - * - * Updated on 2012-12-07 with more research into remaining codes. - * - * Updated on 2013-11-23 based on usage in SIL and Microsoft fonts, - * the new proposal from Microsoft, and latest ISO 639-3 names. - * - * Some items still missing. Those are commented out at the end. - * Keep sorted for bsearch. - * - * Updated as of 2015-05-06: OT1.7 on MS website has some newer - * items that we don't have here, eg. Zazaki. This is the new - * items in OpenType 1.7 (red items), most of which we have: - * https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags - */ - -static const LangTag ot_languages[] = { - {"aa", HB_TAG('A','F','R',' ')}, /* Afar */ - {"ab", HB_TAG('A','B','K',' ')}, /* Abkhazian */ - {"abq", HB_TAG('A','B','A',' ')}, /* Abaza */ - {"acf", HB_TAG('F','A','N',' ')}, /* French Antillean */ - {"ach", HB_TAG('A','C','H',' ')}, /* Acoli */ - {"acr", HB_TAG('A','C','R',' ')}, /* Achi */ - {"ada", HB_TAG('D','N','G',' ')}, /* Dangme */ - {"ady", HB_TAG('A','D','Y',' ')}, /* Adyghe */ - {"af", HB_TAG('A','F','K',' ')}, /* Afrikaans */ - {"ahg", HB_TAG('A','G','W',' ')}, /* Agaw */ - {"aii", HB_TAG('S','W','A',' ')}, /* Swadaya Aramaic */ - {"aio", HB_TAG('A','I','O',' ')}, /* Aiton */ - {"aiw", HB_TAG('A','R','I',' ')}, /* Aari */ - {"ak", HB_TAG('T','W','I',' ')}, /* Akan [macrolanguage] */ - {"aka", HB_TAG('A','K','A',' ')}, /* Akan */ - {"alt", HB_TAG('A','L','T',' ')}, /* [Southern] Altai */ - {"am", HB_TAG('A','M','H',' ')}, /* Amharic */ - {"amf", HB_TAG('H','B','N',' ')}, /* Hammer-Banna */ - {"amw", HB_TAG('S','Y','R',' ')}, /* Western Neo-Aramaic */ - {"an", HB_TAG('A','R','G',' ')}, /* Aragonese */ - {"ang", HB_TAG('A','N','G',' ')}, /* Old English (ca. 450-1100) */ - {"ar", HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */ - {"arb", HB_TAG('A','R','A',' ')}, /* Standard Arabic */ - {"arn", HB_TAG('M','A','P',' ')}, /* Mapudungun */ - {"ary", HB_TAG('M','O','R',' ')}, /* Moroccan Arabic */ - {"as", HB_TAG('A','S','M',' ')}, /* Assamese */ - {"ast", HB_TAG('A','S','T',' ')}, /* Asturian/Asturleonese/Bable/Leonese */ - {"ath", HB_TAG('A','T','H',' ')}, /* Athapaskan [family] */ - {"atj", HB_TAG('R','C','R',' ')}, /* R-Cree */ - {"atv", HB_TAG('A','L','T',' ')}, /* [Northern] Altai */ - {"av", HB_TAG('A','V','R',' ')}, /* Avaric */ - {"awa", HB_TAG('A','W','A',' ')}, /* Awadhi */ - {"ay", HB_TAG('A','Y','M',' ')}, /* Aymara [macrolanguage] */ - {"az", HB_TAG('A','Z','E',' ')}, /* Azerbaijani [macrolanguage] */ - {"azb", HB_TAG('A','Z','B',' ')}, /* South Azerbaijani */ - {"azj", HB_TAG('A','Z','E',' ')}, /* North Azerbaijani */ - {"ba", HB_TAG('B','S','H',' ')}, /* Bashkir */ - {"bad", HB_TAG('B','A','D','0')}, /* Banda */ - {"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [family] */ - {"bal", HB_TAG('B','L','I',' ')}, /* Baluchi [macrolangauge] */ - {"ban", HB_TAG('B','A','N',' ')}, /* Balinese */ - {"bar", HB_TAG('B','A','R',' ')}, /* Bavarian */ - {"bbc", HB_TAG('B','B','C',' ')}, /* Batak Toba */ - {"bci", HB_TAG('B','A','U',' ')}, /* Baoulé */ - {"bcl", HB_TAG('B','I','K',' ')}, /* Central Bikol */ - {"bcq", HB_TAG('B','C','H',' ')}, /* Bench */ - {"bdy", HB_TAG('B','D','Y',' ')}, /* Bandjalang */ - {"be", HB_TAG('B','E','L',' ')}, /* Belarusian */ - {"bem", HB_TAG('B','E','M',' ')}, /* Bemba (Zambia) */ - {"ber", HB_TAG('B','E','R',' ')}, /* Berber [family] */ - {"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */ - {"bft", HB_TAG('B','L','T',' ')}, /* Balti */ - {"bfu", HB_TAG('L','A','H',' ')}, /* Lahuli */ - {"bfy", HB_TAG('B','A','G',' ')}, /* Baghelkhandi */ - {"bg", HB_TAG('B','G','R',' ')}, /* Bulgarian */ - {"bgc", HB_TAG('B','G','C',' ')}, /* Haryanvi */ - {"bgq", HB_TAG('B','G','Q',' ')}, /* Bagri */ - {"bgr", HB_TAG('Q','I','N',' ')}, /* Bawm Chin */ - {"bhb", HB_TAG('B','H','I',' ')}, /* Bhili */ - {"bhk", HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) */ - {"bho", HB_TAG('B','H','O',' ')}, /* Bhojpuri */ - {"bi", HB_TAG('B','I','S',' ')}, /* Bislama */ - {"bik", HB_TAG('B','I','K',' ')}, /* Bikol [macrolanguage] */ - {"bin", HB_TAG('E','D','O',' ')}, /* Bini */ - {"bjj", HB_TAG('B','J','J',' ')}, /* Kanauji */ - {"bjt", HB_TAG('B','L','N',' ')}, /* Balanta-Ganja */ - {"bla", HB_TAG('B','K','F',' ')}, /* Blackfoot */ - {"ble", HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe */ - {"blk", HB_TAG('B','L','K',' ')}, /* Pa'O/Pa'o Karen */ - {"bln", HB_TAG('B','I','K',' ')}, /* Southern Catanduanes Bikol */ - {"bm", HB_TAG('B','M','B',' ')}, /* Bambara */ - {"bn", HB_TAG('B','E','N',' ')}, /* Bengali */ - {"bo", HB_TAG('T','I','B',' ')}, /* Tibetan */ - {"bpy", HB_TAG('B','P','Y',' ')}, /* Bishnupriya */ - {"bqi", HB_TAG('L','R','C',' ')}, /* Bakhtiari */ - {"br", HB_TAG('B','R','E',' ')}, /* Breton */ - {"bra", HB_TAG('B','R','I',' ')}, /* Braj Bhasha */ - {"brh", HB_TAG('B','R','H',' ')}, /* Brahui */ - {"brx", HB_TAG('B','R','X',' ')}, /* Bodo (India) */ - {"bs", HB_TAG('B','O','S',' ')}, /* Bosnian */ - {"btb", HB_TAG('B','T','I',' ')}, /* Beti (Cameroon) */ - {"bto", HB_TAG('B','I','K',' ')}, /* Rinconada Bikol */ - {"bts", HB_TAG('B','T','S',' ')}, /* Batak Simalungun */ - {"bug", HB_TAG('B','U','G',' ')}, /* Buginese */ - {"bxr", HB_TAG('R','B','U',' ')}, /* Russian Buriat */ - {"byn", HB_TAG('B','I','L',' ')}, /* Bilen */ - {"ca", HB_TAG('C','A','T',' ')}, /* Catalan */ - {"cak", HB_TAG('C','A','K',' ')}, /* Kaqchikel */ - {"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano */ - {"cbl", HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin */ - {"cco", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"ce", HB_TAG('C','H','E',' ')}, /* Chechen */ - {"ceb", HB_TAG('C','E','B',' ')}, /* Cebuano */ - {"cfm", HB_TAG('H','A','L',' ')}, /* Halam/Falam Chin */ - {"cgg", HB_TAG('C','G','G',' ')}, /* Chiga */ - {"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */ - {"chj", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"chk", HB_TAG('C','H','K','0')}, /* Chuukese */ - {"cho", HB_TAG('C','H','O',' ')}, /* Choctaw */ - {"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */ - {"chq", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"chr", HB_TAG('C','H','R',' ')}, /* Cherokee */ - {"chy", HB_TAG('C','H','Y',' ')}, /* Cheyenne */ - {"chz", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"cja", HB_TAG('C','J','A',' ')}, /* Western Cham */ - {"cjm", HB_TAG('C','J','M',' ')}, /* Eastern Cham */ - {"cka", HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin */ - {"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish (Sorani) */ - {"ckt", HB_TAG('C','H','K',' ')}, /* Chukchi */ - {"cld", HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic */ - {"cle", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"cmr", HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin */ - {"cnb", HB_TAG('Q','I','N',' ')}, /* Chinbon Chin */ - {"cnh", HB_TAG('Q','I','N',' ')}, /* Hakha Chin */ - {"cnk", HB_TAG('Q','I','N',' ')}, /* Khumi Chin */ - {"cnl", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"cnt", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"cnw", HB_TAG('Q','I','N',' ')}, /* Ngawn Chin */ - {"cop", HB_TAG('C','O','P',' ')}, /* Coptic */ - {"cpa", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"cpp", HB_TAG('C','P','P',' ')}, /* Creoles */ - {"cr", HB_TAG('C','R','E',' ')}, /* Cree */ - {"cre", HB_TAG('Y','C','R',' ')}, /* Y-Cree */ - {"crh", HB_TAG('C','R','T',' ')}, /* Crimean Tatar */ - {"crj", HB_TAG('E','C','R',' ')}, /* [Southern] East Cree */ - {"crk", HB_TAG('W','C','R',' ')}, /* West-Cree */ - {"crl", HB_TAG('E','C','R',' ')}, /* [Northern] East Cree */ - {"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */ - {"crx", HB_TAG('C','R','R',' ')}, /* Carrier */ - {"cs", HB_TAG('C','S','Y',' ')}, /* Czech */ - {"csa", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"csb", HB_TAG('C','S','B',' ')}, /* Kashubian */ - {"csh", HB_TAG('Q','I','N',' ')}, /* Asho Chin */ - {"cso", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"csy", HB_TAG('Q','I','N',' ')}, /* Siyin Chin */ - {"ctd", HB_TAG('Q','I','N',' ')}, /* Tedim Chin */ - {"cte", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"ctg", HB_TAG('C','T','G',' ')}, /* Chittagonian */ - {"ctl", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol */ - {"cu", HB_TAG('C','S','L',' ')}, /* Church Slavic */ - {"cuc", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"cuk", HB_TAG('C','U','K',' ')}, /* San Blas Kuna */ - {"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */ - {"cvn", HB_TAG('C','C','H','N')}, /* Chinantec */ - {"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */ - {"cy", HB_TAG('W','E','L',' ')}, /* Welsh */ - {"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin */ - {"da", HB_TAG('D','A','N',' ')}, /* Danish */ - {"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin */ - {"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) */ - {"dar", HB_TAG('D','A','R',' ')}, /* Dargwa */ - {"dax", HB_TAG('D','A','X',' ')}, /* Dayi */ - {"de", HB_TAG('D','E','U',' ')}, /* German */ - {"dgo", HB_TAG('D','G','O',' ')}, /* Dogri */ - {"dhd", HB_TAG('M','A','W',' ')}, /* Dhundari */ - {"dhg", HB_TAG('D','H','G',' ')}, /* Dhangu */ - {"din", HB_TAG('D','N','K',' ')}, /* Dinka [macrolanguage] */ - {"diq", HB_TAG('D','I','Q',' ')}, /* Dimli */ - {"dje", HB_TAG('D','J','R',' ')}, /* Zarma */ - {"djr", HB_TAG('D','J','R','0')}, /* Djambarrpuyngu */ - {"dng", HB_TAG('D','U','N',' ')}, /* Dungan */ - {"dnj", HB_TAG('D','N','J',' ')}, /* Dan */ - {"doi", HB_TAG('D','G','R',' ')}, /* Dogri [macrolanguage] */ - {"dsb", HB_TAG('L','S','B',' ')}, /* Lower Sorbian */ - {"duj", HB_TAG('D','U','J',' ')}, /* Dhuwal */ - {"dv", HB_TAG('D','I','V',' ')}, /* Dhivehi/Divehi/Maldivian */ - {"dyu", HB_TAG('J','U','L',' ')}, /* Jula */ - {"dz", HB_TAG('D','Z','N',' ')}, /* Dzongkha */ - {"ee", HB_TAG('E','W','E',' ')}, /* Ewe */ - {"efi", HB_TAG('E','F','I',' ')}, /* Efik */ - {"ekk", HB_TAG('E','T','I',' ')}, /* Standard Estonian */ - {"el", HB_TAG('E','L','L',' ')}, /* Modern Greek (1453-) */ - {"emk", HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan */ - {"en", HB_TAG('E','N','G',' ')}, /* English */ - {"enf", HB_TAG('F','N','E',' ')}, /* Forest Nenets */ - {"enh", HB_TAG('T','N','E',' ')}, /* Tundra Nenets */ - {"eo", HB_TAG('N','T','O',' ')}, /* Esperanto */ - {"eot", HB_TAG('B','T','I',' ')}, /* Beti (Côte d'Ivoire) */ - {"es", HB_TAG('E','S','P',' ')}, /* Spanish */ - {"esu", HB_TAG('E','S','U',' ')}, /* Central Yupik */ - {"et", HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */ - {"eu", HB_TAG('E','U','Q',' ')}, /* Basque */ - {"eve", HB_TAG('E','V','N',' ')}, /* Even */ - {"evn", HB_TAG('E','V','K',' ')}, /* Evenki */ - {"fa", HB_TAG('F','A','R',' ')}, /* Persian [macrolanguage] */ - {"fan", HB_TAG('F','A','N','0')}, /* Fang */ - {"fat", HB_TAG('F','A','T',' ')}, /* Fanti */ - {"ff", HB_TAG('F','U','L',' ')}, /* Fulah [macrolanguage] */ - {"fi", HB_TAG('F','I','N',' ')}, /* Finnish */ - {"fil", HB_TAG('P','I','L',' ')}, /* Filipino */ - {"fj", HB_TAG('F','J','I',' ')}, /* Fijian */ - {"flm", HB_TAG('H','A','L',' ')}, /* Halam/Falam Chin [retired ISO639 code] */ - {"fo", HB_TAG('F','O','S',' ')}, /* Faroese */ - {"fon", HB_TAG('F','O','N',' ')}, /* Fon */ - {"fr", HB_TAG('F','R','A',' ')}, /* French */ - {"frc", HB_TAG('F','R','C',' ')}, /* Cajun French */ - {"frp", HB_TAG('F','R','P',' ')}, /* Arpitan/Francoprovençal */ - {"fuf", HB_TAG('F','T','A',' ')}, /* Futa */ - {"fur", HB_TAG('F','R','L',' ')}, /* Friulian */ - {"fuv", HB_TAG('F','U','V',' ')}, /* Nigerian Fulfulde */ - {"fy", HB_TAG('F','R','I',' ')}, /* Western Frisian */ - {"ga", HB_TAG('I','R','I',' ')}, /* Irish */ - {"gaa", HB_TAG('G','A','D',' ')}, /* Ga */ - {"gag", HB_TAG('G','A','G',' ')}, /* Gagauz */ - {"gbm", HB_TAG('G','A','W',' ')}, /* Garhwali */ - {"gd", HB_TAG('G','A','E',' ')}, /* Scottish Gaelic */ - {"gez", HB_TAG('G','E','Z',' ')}, /* Ge'ez */ - {"ggo", HB_TAG('G','O','N',' ')}, /* Southern Gondi */ - {"gih", HB_TAG('G','I','H',' ')}, /* Githabul */ - {"gil", HB_TAG('G','I','L','0')}, /* Kiribati (Gilbertese) */ - {"gkp", HB_TAG('G','K','P',' ')}, /* Kpelle (Guinea) */ - {"gl", HB_TAG('G','A','L',' ')}, /* Galician */ - {"gld", HB_TAG('N','A','N',' ')}, /* Nanai */ - {"glk", HB_TAG('G','L','K',' ')}, /* Gilaki */ - {"gn", HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */ - {"gnn", HB_TAG('G','N','N',' ')}, /* Gumatj */ - {"gno", HB_TAG('G','O','N',' ')}, /* Northern Gondi */ - {"gog", HB_TAG('G','O','G',' ')}, /* Gogo */ - {"gon", HB_TAG('G','O','N',' ')}, /* Gondi [macrolanguage] */ - {"grt", HB_TAG('G','R','O',' ')}, /* Garo */ - {"gru", HB_TAG('S','O','G',' ')}, /* Sodo Gurage */ - {"gsw", HB_TAG('A','L','S',' ')}, /* Alsatian */ - {"gu", HB_TAG('G','U','J',' ')}, /* Gujarati */ - {"guc", HB_TAG('G','U','C',' ')}, /* Wayuu */ - {"guf", HB_TAG('G','U','F',' ')}, /* Gupapuyngu */ - {"guk", HB_TAG('G','M','Z',' ')}, /* Gumuz */ -/*{"guk", HB_TAG('G','U','K',' ')},*/ /* Gumuz (in SIL fonts) */ - {"guz", HB_TAG('G','U','Z',' ')}, /* Ekegusii/Gusii */ - {"gv", HB_TAG('M','N','X',' ')}, /* Manx */ - {"ha", HB_TAG('H','A','U',' ')}, /* Hausa */ - {"har", HB_TAG('H','R','I',' ')}, /* Harari */ - {"haw", HB_TAG('H','A','W',' ')}, /* Hawaiian */ - {"hay", HB_TAG('H','A','Y',' ')}, /* Haya */ - {"haz", HB_TAG('H','A','Z',' ')}, /* Hazaragi */ - {"he", HB_TAG('I','W','R',' ')}, /* Hebrew */ - {"hi", HB_TAG('H','I','N',' ')}, /* Hindi */ - {"hil", HB_TAG('H','I','L',' ')}, /* Hiligaynon */ - {"hlt", HB_TAG('Q','I','N',' ')}, /* Matu Chin */ - {"hmn", HB_TAG('H','M','N',' ')}, /* Hmong */ - {"hnd", HB_TAG('H','N','D',' ')}, /* [Southern] Hindko */ - {"hne", HB_TAG('C','H','H',' ')}, /* Chattisgarhi */ - {"hno", HB_TAG('H','N','D',' ')}, /* [Northern] Hindko */ - {"ho", HB_TAG('H','M','O',' ')}, /* Hiri Motu */ - {"hoc", HB_TAG('H','O',' ',' ')}, /* Ho */ - {"hoj", HB_TAG('H','A','R',' ')}, /* Harauti */ - {"hr", HB_TAG('H','R','V',' ')}, /* Croatian */ - {"hsb", HB_TAG('U','S','B',' ')}, /* Upper Sorbian */ - {"ht", HB_TAG('H','A','I',' ')}, /* Haitian/Haitian Creole */ - {"hu", HB_TAG('H','U','N',' ')}, /* Hungarian */ - {"hy", HB_TAG('H','Y','E',' ')}, /* Armenian */ - {"hz", HB_TAG('H','E','R',' ')}, /* Herero */ - {"ia", HB_TAG('I','N','A',' ')}, /* Interlingua (International Auxiliary Language Association) */ - {"iba", HB_TAG('I','B','A',' ')}, /* Iban */ - {"ibb", HB_TAG('I','B','B',' ')}, /* Ibibio */ - {"id", HB_TAG('I','N','D',' ')}, /* Indonesian */ - {"ie", HB_TAG('I','L','E',' ')}, /* Interlingue/Occidental */ - {"ig", HB_TAG('I','B','O',' ')}, /* Igbo */ - {"igb", HB_TAG('E','B','I',' ')}, /* Ebira */ - {"ii", HB_TAG('Y','I','M',' ')}, /* Yi Modern */ - {"ijc", HB_TAG('I','J','O',' ')}, /* Izon */ - {"ijo", HB_TAG('I','J','O',' ')}, /* Ijo [family] */ - {"ik", HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] */ - {"ilo", HB_TAG('I','L','O',' ')}, /* Ilokano */ - {"inh", HB_TAG('I','N','G',' ')}, /* Ingush */ - {"io", HB_TAG('I','D','O',' ')}, /* Ido */ - {"is", HB_TAG('I','S','L',' ')}, /* Icelandic */ - {"it", HB_TAG('I','T','A',' ')}, /* Italian */ - {"iu", HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */ - {"ja", HB_TAG('J','A','N',' ')}, /* Japanese */ - {"jam", HB_TAG('J','A','M',' ')}, /* Jamaican Creole English */ - {"jbo", HB_TAG('J','B','O',' ')}, /* Lojban */ - {"jv", HB_TAG('J','A','V',' ')}, /* Javanese */ - {"ka", HB_TAG('K','A','T',' ')}, /* Georgian */ - {"kaa", HB_TAG('K','R','K',' ')}, /* Karakalpak */ - {"kab", HB_TAG('K','A','B','0')}, /* Kabyle */ - {"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */ - {"kar", HB_TAG('K','R','N',' ')}, /* Karen [family] */ - {"kat", HB_TAG('K','G','E',' ')}, /* Khutsuri Georgian */ - {"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */ - {"kde", HB_TAG('K','D','E',' ')}, /* Makonde */ - {"kdr", HB_TAG('K','R','M',' ')}, /* Karaim */ - {"kdt", HB_TAG('K','U','Y',' ')}, /* Kuy */ - {"kea", HB_TAG('K','E','A',' ')}, /* Kabuverdianu (Crioulo) */ - {"kek", HB_TAG('K','E','K',' ')}, /* Kekchi */ - {"kex", HB_TAG('K','K','N',' ')}, /* Kokni */ - {"kfa", HB_TAG('K','O','D',' ')}, /* Kodagu */ - {"kfr", HB_TAG('K','A','C',' ')}, /* Kachchi */ - {"kfx", HB_TAG('K','U','L',' ')}, /* Kulvi */ - {"kfy", HB_TAG('K','M','N',' ')}, /* Kumaoni */ - {"kg", HB_TAG('K','O','N',' ')}, /* Kongo [macrolanguage] */ - {"kha", HB_TAG('K','S','I',' ')}, /* Khasi */ - {"khb", HB_TAG('X','B','D',' ')}, /* Lü */ - {"kht", HB_TAG('K','H','N',' ')}, /* Khamti (Microsoft fonts) */ -/*{"kht", HB_TAG('K','H','T',' ')},*/ /* Khamti (OpenType spec and SIL fonts) */ - {"khw", HB_TAG('K','H','W',' ')}, /* Khowar */ - {"ki", HB_TAG('K','I','K',' ')}, /* Gikuyu/Kikuyu */ - {"kiu", HB_TAG('K','I','U',' ')}, /* Kirmanjki */ - {"kj", HB_TAG('K','U','A',' ')}, /* Kuanyama/Kwanyama */ - {"kjd", HB_TAG('K','J','D',' ')}, /* Southern Kiwai */ - {"kjh", HB_TAG('K','H','A',' ')}, /* Khakass */ - {"kjp", HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen */ - {"kk", HB_TAG('K','A','Z',' ')}, /* Kazakh */ - {"kl", HB_TAG('G','R','N',' ')}, /* Kalaallisut */ - {"kln", HB_TAG('K','A','L',' ')}, /* Kalenjin */ - {"km", HB_TAG('K','H','M',' ')}, /* Central Khmer */ - {"kmb", HB_TAG('M','B','N',' ')}, /* Kimbundu */ - {"kmw", HB_TAG('K','M','O',' ')}, /* Komo (Democratic Republic of Congo) */ - {"kn", HB_TAG('K','A','N',' ')}, /* Kannada */ - {"knn", HB_TAG('K','O','K',' ')}, /* Konkani */ - {"ko", HB_TAG('K','O','R',' ')}, /* Korean */ - {"koi", HB_TAG('K','O','P',' ')}, /* Komi-Permyak */ - {"kok", HB_TAG('K','O','K',' ')}, /* Konkani [macrolanguage] */ - {"kon", HB_TAG('K','O','N','0')}, /* Kongo */ - {"kos", HB_TAG('K','O','S',' ')}, /* Kosraean */ - {"kpe", HB_TAG('K','P','L',' ')}, /* Kpelle [macrolanguage] */ - {"kpv", HB_TAG('K','O','Z',' ')}, /* Komi-Zyrian */ - {"kpy", HB_TAG('K','Y','K',' ')}, /* Koryak */ - {"kqy", HB_TAG('K','R','T',' ')}, /* Koorete */ - {"kr", HB_TAG('K','N','R',' ')}, /* Kanuri [macrolanguage] */ - {"kri", HB_TAG('K','R','I',' ')}, /* Krio */ - {"krl", HB_TAG('K','R','L',' ')}, /* Karelian */ - {"kru", HB_TAG('K','U','U',' ')}, /* Kurukh */ - {"ks", HB_TAG('K','S','H',' ')}, /* Kashmiri */ - {"ksh", HB_TAG('K','S','H','0')}, /* Ripuarian, Kölsch */ -/*{"ksw", HB_TAG('K','R','N',' ')},*/ /* S'gaw Karen (Microsoft fonts?) */ - {"ksw", HB_TAG('K','S','W',' ')}, /* S'gaw Karen (OpenType spec and SIL fonts) */ - {"ktb", HB_TAG('K','E','B',' ')}, /* Kebena */ - {"ktu", HB_TAG('K','O','N',' ')}, /* Kikongo */ - {"ku", HB_TAG('K','U','R',' ')}, /* Kurdish [macrolanguage] */ - {"kum", HB_TAG('K','U','M',' ')}, /* Kumyk */ - {"kv", HB_TAG('K','O','M',' ')}, /* Komi [macrolanguage] */ - {"kvd", HB_TAG('K','U','I',' ')}, /* Kui (Indonesia) */ - {"kw", HB_TAG('C','O','R',' ')}, /* Cornish */ - {"kxc", HB_TAG('K','M','S',' ')}, /* Komso */ - {"kxu", HB_TAG('K','U','I',' ')}, /* Kui (India) */ - {"ky", HB_TAG('K','I','R',' ')}, /* Kirghiz/Kyrgyz */ - {"kyu", HB_TAG('K','Y','U',' ')}, /* Western Kayah */ - {"la", HB_TAG('L','A','T',' ')}, /* Latin */ - {"lad", HB_TAG('J','U','D',' ')}, /* Ladino */ - {"lb", HB_TAG('L','T','Z',' ')}, /* Luxembourgish */ - {"lbe", HB_TAG('L','A','K',' ')}, /* Lak */ - {"lbj", HB_TAG('L','D','K',' ')}, /* Ladakhi */ - {"lez", HB_TAG('L','E','Z',' ')}, /* Lezgi */ - {"lg", HB_TAG('L','U','G',' ')}, /* Ganda */ - {"li", HB_TAG('L','I','M',' ')}, /* Limburgan/Limburger/Limburgish */ - {"lif", HB_TAG('L','M','B',' ')}, /* Limbu */ - {"lij", HB_TAG('L','I','J',' ')}, /* Ligurian */ - {"lis", HB_TAG('L','I','S',' ')}, /* Lisu */ - {"ljp", HB_TAG('L','J','P',' ')}, /* Lampung Api */ - {"lki", HB_TAG('L','K','I',' ')}, /* Laki */ - {"lld", HB_TAG('L','A','D',' ')}, /* Ladin */ - {"lmn", HB_TAG('L','A','M',' ')}, /* Lambani */ - {"lmo", HB_TAG('L','M','O',' ')}, /* Lombard */ - {"ln", HB_TAG('L','I','N',' ')}, /* Lingala */ - {"lo", HB_TAG('L','A','O',' ')}, /* Lao */ - {"lom", HB_TAG('L','O','M',' ')}, /* Loma */ - {"lrc", HB_TAG('L','R','C',' ')}, /* Northern Luri */ - {"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */ - {"lu", HB_TAG('L','U','B',' ')}, /* Luba-Katanga */ - {"lua", HB_TAG('L','U','B',' ')}, /* Luba-Kasai */ - {"luo", HB_TAG('L','U','O',' ')}, /* Luo (Kenya and Tanzania) */ - {"lus", HB_TAG('M','I','Z',' ')}, /* Mizo */ - {"luy", HB_TAG('L','U','H',' ')}, /* Luyia/Oluluyia [macrolanguage] */ - {"luz", HB_TAG('L','R','C',' ')}, /* Southern Luri */ - {"lv", HB_TAG('L','V','I',' ')}, /* Latvian */ - {"lzz", HB_TAG('L','A','Z',' ')}, /* Laz */ - {"mad", HB_TAG('M','A','D',' ')}, /* Madurese */ - {"mag", HB_TAG('M','A','G',' ')}, /* Magahi */ - {"mai", HB_TAG('M','T','H',' ')}, /* Maithili */ - {"mak", HB_TAG('M','K','R',' ')}, /* Makasar */ - {"mam", HB_TAG('M','A','M',' ')}, /* Mam */ - {"man", HB_TAG('M','N','K',' ')}, /* Manding/Mandingo [macrolanguage] */ - {"mdc", HB_TAG('M','L','E',' ')}, /* Male (Papua New Guinea) */ - {"mdf", HB_TAG('M','O','K',' ')}, /* Moksha */ - {"mdr", HB_TAG('M','D','R',' ')}, /* Mandar */ - {"mdy", HB_TAG('M','L','E',' ')}, /* Male (Ethiopia) */ - {"men", HB_TAG('M','D','E',' ')}, /* Mende (Sierra Leone) */ - {"mer", HB_TAG('M','E','R',' ')}, /* Meru */ - {"mfe", HB_TAG('M','F','E',' ')}, /* Morisyen */ - {"mg", HB_TAG('M','L','G',' ')}, /* Malagasy [macrolanguage] */ - {"mh", HB_TAG('M','A','H',' ')}, /* Marshallese */ - {"mhr", HB_TAG('L','M','A',' ')}, /* Low Mari */ - {"mi", HB_TAG('M','R','I',' ')}, /* Maori */ - {"min", HB_TAG('M','I','N',' ')}, /* Minangkabau */ - {"mk", HB_TAG('M','K','D',' ')}, /* Macedonian */ - {"mku", HB_TAG('M','N','K',' ')}, /* Konyanka Maninka */ - {"mkw", HB_TAG('M','K','W',' ')}, /* Kituba (Congo) */ - {"ml", HB_TAG('M','L','R',' ')}, /* Malayalam */ - {"mlq", HB_TAG('M','N','K',' ')}, /* Western Maninkakan */ - {"mn", HB_TAG('M','N','G',' ')}, /* Mongolian [macrolanguage] */ - {"mnc", HB_TAG('M','C','H',' ')}, /* Manchu */ - {"mni", HB_TAG('M','N','I',' ')}, /* Manipuri */ - {"mnk", HB_TAG('M','N','D',' ')}, /* Mandinka */ - {"mns", HB_TAG('M','A','N',' ')}, /* Mansi */ - {"mnw", HB_TAG('M','O','N',' ')}, /* Mon */ - {"mo", HB_TAG('M','O','L',' ')}, /* Moldavian */ - {"moh", HB_TAG('M','O','H',' ')}, /* Mohawk */ - {"mos", HB_TAG('M','O','S',' ')}, /* Mossi */ - {"mpe", HB_TAG('M','A','J',' ')}, /* Majang */ - {"mr", HB_TAG('M','A','R',' ')}, /* Marathi */ - {"mrh", HB_TAG('Q','I','N',' ')}, /* Mara Chin */ - {"mrj", HB_TAG('H','M','A',' ')}, /* High Mari */ - {"ms", HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */ - {"msc", HB_TAG('M','N','K',' ')}, /* Sankaran Maninka */ - {"mt", HB_TAG('M','T','S',' ')}, /* Maltese */ - {"mtr", HB_TAG('M','A','W',' ')}, /* Mewari */ - {"mus", HB_TAG('M','U','S',' ')}, /* Creek */ - {"mve", HB_TAG('M','A','W',' ')}, /* Marwari (Pakistan) */ - {"mwk", HB_TAG('M','N','K',' ')}, /* Kita Maninkakan */ - {"mwl", HB_TAG('M','W','L',' ')}, /* Mirandese */ - {"mwr", HB_TAG('M','A','W',' ')}, /* Marwari [macrolanguage] */ - {"mww", HB_TAG('M','W','W',' ')}, /* Hmong Daw */ - {"my", HB_TAG('B','R','M',' ')}, /* Burmese */ - {"mym", HB_TAG('M','E','N',' ')}, /* Me'en */ - {"myn", HB_TAG('M','Y','N',' ')}, /* Mayan */ - {"myq", HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) */ - {"myv", HB_TAG('E','R','Z',' ')}, /* Erzya */ - {"mzn", HB_TAG('M','Z','N',' ')}, /* Mazanderani */ - {"na", HB_TAG('N','A','U',' ')}, /* Nauru */ - {"nag", HB_TAG('N','A','G',' ')}, /* Naga-Assamese */ - {"nah", HB_TAG('N','A','H',' ')}, /* Nahuatl [family] */ - {"nap", HB_TAG('N','A','P',' ')}, /* Neapolitan */ - {"nb", HB_TAG('N','O','R',' ')}, /* Norwegian Bokmål */ - {"nco", HB_TAG('S','I','B',' ')}, /* Sibe */ - {"nd", HB_TAG('N','D','B',' ')}, /* [North] Ndebele */ - {"ndc", HB_TAG('N','D','C',' ')}, /* Ndau */ - {"nds", HB_TAG('N','D','S',' ')}, /* Low German/Low Saxon */ - {"ne", HB_TAG('N','E','P',' ')}, /* Nepali */ - {"new", HB_TAG('N','E','W',' ')}, /* Newari */ - {"ng", HB_TAG('N','D','G',' ')}, /* Ndonga */ - {"nga", HB_TAG('N','G','A',' ')}, /* Ngabaka */ - {"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */ - {"ngo", HB_TAG('S','X','T',' ')}, /* Sutu */ - {"niu", HB_TAG('N','I','U',' ')}, /* Niuean */ - {"niv", HB_TAG('G','I','L',' ')}, /* Gilyak */ - {"nl", HB_TAG('N','L','D',' ')}, /* Dutch */ - {"nn", HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk */ - {"no", HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */ - {"nod", HB_TAG('N','T','A',' ')}, /* Northern Thai */ - {"noe", HB_TAG('N','O','E',' ')}, /* Nimadi */ - {"nog", HB_TAG('N','O','G',' ')}, /* Nogai */ - {"nov", HB_TAG('N','O','V',' ')}, /* Novial */ - {"nqo", HB_TAG('N','K','O',' ')}, /* N'Ko */ - {"nr", HB_TAG('N','D','B',' ')}, /* [South] Ndebele */ - {"nsk", HB_TAG('N','A','S',' ')}, /* Naskapi */ - {"nso", HB_TAG('S','O','T',' ')}, /* [Northern] Sotho */ - {"nv", HB_TAG('N','A','V',' ')}, /* Navajo */ - {"ny", HB_TAG('C','H','I',' ')}, /* Chewa/Chichwa/Nyanja */ - {"nym", HB_TAG('N','Y','M',' ')}, /* Nyamwezi */ - {"nyn", HB_TAG('N','K','L',' ')}, /* Nyankole */ - {"oc", HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */ - {"oj", HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] */ - {"ojs", HB_TAG('O','C','R',' ')}, /* Oji-Cree */ - {"okm", HB_TAG('K','O','H',' ')}, /* Korean Old Hangul */ - {"om", HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */ - {"or", HB_TAG('O','R','I',' ')}, /* Oriya */ - {"os", HB_TAG('O','S','S',' ')}, /* Ossetian */ - {"pa", HB_TAG('P','A','N',' ')}, /* Panjabi */ - {"pag", HB_TAG('P','A','G',' ')}, /* Pangasinan */ - {"pam", HB_TAG('P','A','M',' ')}, /* Kapampangan/Pampanga */ - {"pap", HB_TAG('P','A','P','0')}, /* Papiamento */ - {"pau", HB_TAG('P','A','U',' ')}, /* Palauan */ - {"pcc", HB_TAG('P','C','C',' ')}, /* Bouyei */ - {"pcd", HB_TAG('P','C','D',' ')}, /* Picard */ - {"pce", HB_TAG('P','L','G',' ')}, /* [Ruching] Palaung */ - {"pck", HB_TAG('Q','I','N',' ')}, /* Paite Chin */ - {"pdc", HB_TAG('P','D','C',' ')}, /* Pennsylvania German */ - {"pes", HB_TAG('F','A','R',' ')}, /* Iranian Persian */ - {"phk", HB_TAG('P','H','K',' ')}, /* Phake */ - {"pi", HB_TAG('P','A','L',' ')}, /* Pali */ - {"pih", HB_TAG('P','I','H',' ')}, /* Pitcairn-Norfolk */ - {"pl", HB_TAG('P','L','K',' ')}, /* Polish */ - {"pll", HB_TAG('P','L','G',' ')}, /* [Shwe] Palaung */ - {"plp", HB_TAG('P','A','P',' ')}, /* Palpa */ - {"pms", HB_TAG('P','M','S',' ')}, /* Piemontese */ - {"pnb", HB_TAG('P','N','B',' ')}, /* Western Panjabi */ - {"poh", HB_TAG('P','O','H',' ')}, /* Pocomchi */ - {"pon", HB_TAG('P','O','N',' ')}, /* Pohnpeian */ - {"prs", HB_TAG('D','R','I',' ')}, /* Afghan Persian/Dari */ - {"ps", HB_TAG('P','A','S',' ')}, /* Pashto/Pushto [macrolanguage] */ - {"pt", HB_TAG('P','T','G',' ')}, /* Portuguese */ - {"pwo", HB_TAG('P','W','O',' ')}, /* Pwo Western Karen */ - {"qu", HB_TAG('Q','U','Z',' ')}, /* Quechua [macrolanguage] */ - {"quc", HB_TAG('Q','U','C',' ')}, /* K'iche'/Quiché */ - {"quh", HB_TAG('Q','U','H',' ')}, /* Quechua (Bolivia) */ - {"quz", HB_TAG('Q','U','Z',' ')}, /* Cusco Quechua */ - {"qvi", HB_TAG('Q','V','I',' ')}, /* Quechua (Ecuador) */ - {"qwh", HB_TAG('Q','W','H',' ')}, /* Quechua (Peru) */ - {"raj", HB_TAG('R','A','J',' ')}, /* Rajasthani [macrolanguage] */ - {"rar", HB_TAG('R','A','R',' ')}, /* Rarotongan */ - {"rbb", HB_TAG('P','L','G',' ')}, /* Rumai Palaung */ - {"rej", HB_TAG('R','E','J',' ')}, /* Rejang */ - {"ria", HB_TAG('R','I','A',' ')}, /* Riang (India) */ - {"rif", HB_TAG('R','I','F',' ')}, /* Tarifit */ - {"ril", HB_TAG('R','I','A',' ')}, /* Riang (Myanmar) */ - {"rit", HB_TAG('R','I','T',' ')}, /* Ritarungo */ - {"rki", HB_TAG('A','R','K',' ')}, /* Rakhine */ - {"rkw", HB_TAG('R','K','W',' ')}, /* Arakwal */ - {"rm", HB_TAG('R','M','S',' ')}, /* Romansh */ - {"rmy", HB_TAG('R','M','Y',' ')}, /* Vlax Romani */ - {"rn", HB_TAG('R','U','N',' ')}, /* Rundi */ - {"ro", HB_TAG('R','O','M',' ')}, /* Romanian */ - {"rom", HB_TAG('R','O','Y',' ')}, /* Romany [macrolanguage] */ - {"rtm", HB_TAG('R','T','M',' ')}, /* Rotuman */ - {"ru", HB_TAG('R','U','S',' ')}, /* Russian */ - {"rue", HB_TAG('R','S','Y',' ')}, /* Rusyn */ - {"rup", HB_TAG('R','U','P',' ')}, /* Aromanian/Arumanian/Macedo-Romanian */ - {"rw", HB_TAG('R','U','A',' ')}, /* Kinyarwanda */ - {"rwr", HB_TAG('M','A','W',' ')}, /* Marwari (India) */ - {"sa", HB_TAG('S','A','N',' ')}, /* Sanskrit */ - {"sah", HB_TAG('Y','A','K',' ')}, /* Yakut */ - {"sam", HB_TAG('P','A','A',' ')}, /* Palestinian Aramaic */ - {"sas", HB_TAG('S','A','S',' ')}, /* Sasak */ - {"sat", HB_TAG('S','A','T',' ')}, /* Santali */ - {"sc", HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */ - {"sck", HB_TAG('S','A','D',' ')}, /* Sadri */ - {"scn", HB_TAG('S','C','N',' ')}, /* Sicilian */ - {"sco", HB_TAG('S','C','O',' ')}, /* Scots */ - {"scs", HB_TAG('S','L','A',' ')}, /* [North] Slavey */ - {"sd", HB_TAG('S','N','D',' ')}, /* Sindhi */ - {"se", HB_TAG('N','S','M',' ')}, /* Northern Sami */ - {"seh", HB_TAG('S','N','A',' ')}, /* Sena */ - {"sel", HB_TAG('S','E','L',' ')}, /* Selkup */ - {"sez", HB_TAG('Q','I','N',' ')}, /* Senthang Chin */ - {"sg", HB_TAG('S','G','O',' ')}, /* Sango */ - {"sga", HB_TAG('S','G','A',' ')}, /* Old Irish (to 900) */ - {"sgs", HB_TAG('S','G','S',' ')}, /* Samogitian */ - {"sgw", HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage */ -/*{"sgw", HB_TAG('S','G','W',' ')},*/ /* Sebat Bet Gurage (in SIL fonts) */ - {"shi", HB_TAG('S','H','I',' ')}, /* Tachelhit */ - {"shn", HB_TAG('S','H','N',' ')}, /* Shan */ - {"si", HB_TAG('S','N','H',' ')}, /* Sinhala */ - {"sid", HB_TAG('S','I','D',' ')}, /* Sidamo */ - {"sjd", HB_TAG('K','S','M',' ')}, /* Kildin Sami */ - {"sk", HB_TAG('S','K','Y',' ')}, /* Slovak */ - {"skr", HB_TAG('S','R','K',' ')}, /* Seraiki */ - {"sl", HB_TAG('S','L','V',' ')}, /* Slovenian */ - {"sm", HB_TAG('S','M','O',' ')}, /* Samoan */ - {"sma", HB_TAG('S','S','M',' ')}, /* Southern Sami */ - {"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */ - {"smn", HB_TAG('I','S','M',' ')}, /* Inari Sami */ - {"sms", HB_TAG('S','K','S',' ')}, /* Skolt Sami */ - {"sn", HB_TAG('S','N','A','0')}, /* Shona */ - {"snk", HB_TAG('S','N','K',' ')}, /* Soninke */ - {"so", HB_TAG('S','M','L',' ')}, /* Somali */ - {"sop", HB_TAG('S','O','P',' ')}, /* Songe */ - {"sq", HB_TAG('S','Q','I',' ')}, /* Albanian [macrolanguage] */ - {"sr", HB_TAG('S','R','B',' ')}, /* Serbian */ - {"srr", HB_TAG('S','R','R',' ')}, /* Serer */ - {"ss", HB_TAG('S','W','Z',' ')}, /* Swati */ - {"st", HB_TAG('S','O','T',' ')}, /* [Southern] Sotho */ - {"stq", HB_TAG('S','T','Q',' ')}, /* Saterfriesisch */ - {"stv", HB_TAG('S','I','G',' ')}, /* Silt'e */ - {"su", HB_TAG('S','U','N',' ')}, /* Sundanese */ - {"suk", HB_TAG('S','U','K',' ')}, /* Sukama */ - {"suq", HB_TAG('S','U','R',' ')}, /* Suri */ - {"sv", HB_TAG('S','V','E',' ')}, /* Swedish */ - {"sva", HB_TAG('S','V','A',' ')}, /* Svan */ - {"sw", HB_TAG('S','W','K',' ')}, /* Swahili [macrolanguage] */ - {"swb", HB_TAG('C','M','R',' ')}, /* Comorian */ - {"swh", HB_TAG('S','W','K',' ')}, /* Kiswahili/Swahili */ - {"swv", HB_TAG('M','A','W',' ')}, /* Shekhawati */ - {"sxu", HB_TAG('S','X','U',' ')}, /* Upper Saxon */ - {"syc", HB_TAG('S','Y','R',' ')}, /* Classical Syriac */ - {"syl", HB_TAG('S','Y','L',' ')}, /* Sylheti */ - {"syr", HB_TAG('S','Y','R',' ')}, /* Syriac [macrolanguage] */ - {"szl", HB_TAG('S','Z','L',' ')}, /* Silesian */ - {"ta", HB_TAG('T','A','M',' ')}, /* Tamil */ - {"tab", HB_TAG('T','A','B',' ')}, /* Tabasaran */ - {"tcp", HB_TAG('Q','I','N',' ')}, /* Tawr Chin */ - {"tcy", HB_TAG('T','U','L',' ')}, /* Tulu */ - {"tcz", HB_TAG('Q','I','N',' ')}, /* Thado Chin */ - {"tdd", HB_TAG('T','D','D',' ')}, /* Tai Nüa */ - {"te", HB_TAG('T','E','L',' ')}, /* Telugu */ - {"tem", HB_TAG('T','M','N',' ')}, /* Temne */ - {"tet", HB_TAG('T','E','T',' ')}, /* Tetum */ - {"tg", HB_TAG('T','A','J',' ')}, /* Tajik */ - {"th", HB_TAG('T','H','A',' ')}, /* Thai */ - {"ti", HB_TAG('T','G','Y',' ')}, /* Tigrinya */ - {"tig", HB_TAG('T','G','R',' ')}, /* Tigre */ - {"tiv", HB_TAG('T','I','V',' ')}, /* Tiv */ - {"tk", HB_TAG('T','K','M',' ')}, /* Turkmen */ - {"tl", HB_TAG('T','G','L',' ')}, /* Tagalog */ - {"tmh", HB_TAG('T','M','H',' ')}, /* Tamashek */ - {"tn", HB_TAG('T','N','A',' ')}, /* Tswana */ - {"to", HB_TAG('T','G','N',' ')}, /* Tonga (Tonga Islands) */ - {"tod", HB_TAG('T','O','D','0')}, /* Toma */ - {"toi", HB_TAG('T','N','G',' ')}, /* Tonga */ - {"tpi", HB_TAG('T','P','I',' ')}, /* Tok Pisin */ - {"tr", HB_TAG('T','R','K',' ')}, /* Turkish */ - {"tru", HB_TAG('T','U','A',' ')}, /* Turoyo Aramaic */ - {"ts", HB_TAG('T','S','G',' ')}, /* Tsonga */ - {"tt", HB_TAG('T','A','T',' ')}, /* Tatar */ - {"tum", HB_TAG('T','U','M',' ')}, /* Tumbuka */ - {"tvl", HB_TAG('T','V','L',' ')}, /* Tuvalu */ - {"tw", HB_TAG('T','W','I',' ')}, /* Twi */ - {"ty", HB_TAG('T','H','T',' ')}, /* Tahitian */ - {"tyv", HB_TAG('T','U','V',' ')}, /* Tuvin */ - {"tyz", HB_TAG('T','Y','Z',' ')}, /* Tày */ - {"tzm", HB_TAG('T','Z','M',' ')}, /* Central Atlas Tamazight */ - {"tzo", HB_TAG('T','Z','O',' ')}, /* Tzotzil */ - {"udm", HB_TAG('U','D','M',' ')}, /* Udmurt */ - {"ug", HB_TAG('U','Y','G',' ')}, /* Uighur */ - {"uk", HB_TAG('U','K','R',' ')}, /* Ukrainian */ - {"umb", HB_TAG('U','M','B',' ')}, /* Umbundu */ - {"unr", HB_TAG('M','U','N',' ')}, /* Mundari */ - {"ur", HB_TAG('U','R','D',' ')}, /* Urdu */ - {"uz", HB_TAG('U','Z','B',' ')}, /* Uzbek [macrolanguage] */ - {"uzn", HB_TAG('U','Z','B',' ')}, /* Northern Uzbek */ - {"uzs", HB_TAG('U','Z','B',' ')}, /* Southern Uzbek */ - {"ve", HB_TAG('V','E','N',' ')}, /* Venda */ - {"vec", HB_TAG('V','E','C',' ')}, /* Venetian */ - {"vi", HB_TAG('V','I','T',' ')}, /* Vietnamese */ - {"vls", HB_TAG('F','L','E',' ')}, /* Vlaams */ - {"vmw", HB_TAG('M','A','K',' ')}, /* Makhuwa */ - {"vo", HB_TAG('V','O','L',' ')}, /* Volapük */ - {"vro", HB_TAG('V','R','O',' ')}, /* Võro */ - {"wa", HB_TAG('W','L','N',' ')}, /* Walloon */ - {"war", HB_TAG('W','A','R',' ')}, /* Waray (Philippines) */ - {"wbm", HB_TAG('W','A',' ',' ')}, /* Wa */ - {"wbr", HB_TAG('W','A','G',' ')}, /* Wagdi */ - {"wle", HB_TAG('S','I','G',' ')}, /* Wolane */ - {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */ - {"wry", HB_TAG('M','A','W',' ')}, /* Merwari */ - {"wtm", HB_TAG('W','T','M',' ')}, /* Mewati */ - {"xal", HB_TAG('K','L','M',' ')}, /* Kalmyk */ - {"xan", HB_TAG('S','E','K',' ')}, /* Sekota */ - {"xh", HB_TAG('X','H','S',' ')}, /* Xhosa */ - {"xjb", HB_TAG('X','J','B',' ')}, /* Minjangbal */ - {"xog", HB_TAG('X','O','G',' ')}, /* Soga */ - {"xom", HB_TAG('K','M','O',' ')}, /* Komo (Sudan) */ - {"xpe", HB_TAG('X','P','E',' ')}, /* Kpelle (Liberia) */ - {"xsl", HB_TAG('S','S','L',' ')}, /* South Slavey */ - {"xst", HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) */ - {"xwo", HB_TAG('T','O','D',' ')}, /* Written Oirat (Todo) */ - {"yao", HB_TAG('Y','A','O',' ')}, /* Yao */ - {"yap", HB_TAG('Y','A','P',' ')}, /* Yapese */ - {"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */ - {"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */ - {"yos", HB_TAG('Q','I','N',' ')}, /* Yos, deprecated by IANA in favor of Zou [zom] */ - {"yso", HB_TAG('N','I','S',' ')}, /* Nisi (China) */ - {"za", HB_TAG('Z','H','A',' ')}, /* Chuang/Zhuang [macrolanguage] */ - {"zea", HB_TAG('Z','E','A',' ')}, /* Zeeuws */ - {"zgh", HB_TAG('Z','G','H',' ')}, /* Standard Morrocan Tamazigh */ - {"zne", HB_TAG('Z','N','D',' ')}, /* Zande */ - {"zom", HB_TAG('Q','I','N',' ')}, /* Zou */ - {"zu", HB_TAG('Z','U','L',' ')}, /* Zulu */ - {"zum", HB_TAG('L','R','C',' ')}, /* Kumzari */ - {"zza", HB_TAG('Z','Z','A',' ')}, /* Zazaki */ - - /* The corresponding languages IDs for the following IDs are unclear, - * overlap, or are architecturally weird. Needs more research. */ - -/*{"chp", HB_TAG('S','A','Y',' ')},*/ /* Sayisi */ -/*{"cwd", HB_TAG('T','C','R',' ')},*/ /* TH-Cree */ -/*{"emk", HB_TAG('E','M','K',' ')},*/ /* Eastern Maninkakan */ -/*{"krc", HB_TAG('B','A','L',' ')},*/ /* Balkar */ -/*{"??", HB_TAG('B','C','R',' ')},*/ /* Bible Cree */ -/*{"zh?", HB_TAG('C','H','N',' ')},*/ /* Chinese (seen in Microsoft fonts) */ -/*{"ar-Syrc?", HB_TAG('G','A','R',' ')},*/ /* Garshuni */ -/*{"hy?", HB_TAG('H','Y','E','0')},*/ /* Armenian East (ISO 639-3 hye according to Microsoft, but that’s equivalent to ISO 639-1 hy) */ -/*{"ga-Latg?/" HB_TAG('I','R','T',' ')},*/ /* Irish Traditional */ -/*{"krc", HB_TAG('K','A','R',' ')},*/ /* Karachay */ -/*{"ka-Geok?", HB_TAG('K','G','E',' ')},*/ /* Khutsuri Georgian */ -/*{"kca", HB_TAG('K','H','K',' ')},*/ /* Khanty-Kazim */ -/*{"kca", HB_TAG('K','H','S',' ')},*/ /* Khanty-Shurishkar */ -/*{"kca", HB_TAG('K','H','V',' ')},*/ /* Khanty-Vakhi */ -/*{"kqs, kss", HB_TAG('K','I','S',' ')},*/ /* Kisii */ -/*{"lua", HB_TAG('L','U','A',' ')},*/ /* Luba-Lulua */ -/*{"mlq", HB_TAG('M','L','N',' ')},*/ /* Malinke */ -/*{"nso", HB_TAG('N','S','O',' ')},*/ /* Sotho, Northern */ -/*{"??", HB_TAG('M','A','L',' ')},*/ /* Malayalam Traditional */ -/*{"csw", HB_TAG('N','C','R',' ')},*/ /* N-Cree */ -/*{"csw", HB_TAG('N','H','C',' ')},*/ /* Norway House Cree */ -/*{"el-polyton", HB_TAG('P','G','R',' ')},*/ /* Polytonic Greek */ -/*{"bgr, cnh, cnw, czt, sez, tcp, csy, ctd, flm, pck, tcz, zom, cmr, dao, hlt, cka, cnk, mrh, mwg, cbl, cnb, csh", HB_TAG('Q','I','N',' ')},*/ /* Chin */ -/*{"??", HB_TAG('Y','I','C',' ')},*/ /* Yi Classic */ -/*{"zh-Latn-pinyin", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */ -}; - -typedef struct { - char language[11]; - hb_tag_t tag; -} LangTagLong; -static const LangTagLong ot_languages_zh[] = { - /* Store longest-first, if one is a prefix of another. */ - {"zh-cn", HB_TAG('Z','H','S',' ')}, /* Chinese (China) */ - {"zh-hk", HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */ - {"zh-mo", HB_TAG('Z','H','H',' ')}, /* Chinese (Macao) */ - {"zh-sg", HB_TAG('Z','H','S',' ')}, /* Chinese (Singapore) */ - {"zh-tw", HB_TAG('Z','H','T',' ')}, /* Chinese (Taiwan) */ - {"zh-hans", HB_TAG('Z','H','S',' ')}, /* Chinese (Simplified) */ - {"zh-hant-hk",HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */ - {"zh-hant-mo",HB_TAG('Z','H','H',' ')}, /* Chinese (Macao) */ - {"zh-hant", HB_TAG('Z','H','T',' ')}, /* Chinese (Traditional) */ -}; - static int lang_compare_first_component (const void *pa, const void *pb) @@ -895,6 +189,21 @@ return strncmp (a, b, MAX (da, db)); } +static bool +subtag_matches (const char *lang_str, + const char *limit, + const char *subtag) +{ + do { + const char *s = strstr (lang_str, subtag); + if (!s || s >= limit) + return false; + if (!ISALNUM (s[strlen (subtag)])) + return true; + lang_str = s + strlen (subtag); + } while (true); +} + static hb_bool_t lang_matches (const char *lang_str, const char *spec) { @@ -904,106 +213,186 @@ (lang_str[len] == '\0' || lang_str[len] == '-'); } +typedef struct { + char language[4]; + hb_tag_t tags[HB_OT_MAX_TAGS_PER_LANGUAGE]; +} LangTag; + +#include "hb-ot-tag-table.hh" + +/* The corresponding languages IDs for the following IDs are unclear, + * overlap, or are architecturally weird. Needs more research. */ + +/*{"??", {HB_TAG('B','C','R',' ')}},*/ /* Bible Cree */ +/*{"zh?", {HB_TAG('C','H','N',' ')}},*/ /* Chinese (seen in Microsoft fonts) */ +/*{"ar-Syrc?", {HB_TAG('G','A','R',' ')}},*/ /* Garshuni */ +/*{"??", {HB_TAG('N','G','R',' ')}},*/ /* Nagari */ +/*{"??", {HB_TAG('Y','I','C',' ')}},*/ /* Yi Classic */ +/*{"zh?", {HB_TAG('Z','H','P',' ')}},*/ /* Chinese Phonetic */ + hb_tag_t hb_ot_tag_from_language (hb_language_t language) { - const char *lang_str, *s; + unsigned int count = 1; + hb_tag_t tags[1]; + hb_ot_tags_from_script_and_language (HB_SCRIPT_UNKNOWN, language, nullptr, nullptr, &count, tags); + return count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_LANGUAGE; +} - if (language == HB_LANGUAGE_INVALID) - return HB_OT_TAG_DEFAULT_LANGUAGE; +static void +hb_ot_tags_from_language (const char *lang_str, + const char *limit, + unsigned int *count, + hb_tag_t *tags) +{ + const char *s; - lang_str = hb_language_to_string (language); + /* Check for matches of multiple subtags. */ + if (hb_ot_tags_from_complex_language (lang_str, limit, count, tags)) + return; - s = strstr (lang_str, "x-hbot"); - if (s) { - char tag[4]; - int i; - s += 6; - for (i = 0; i < 4 && ISALNUM (s[i]); i++) - tag[i] = TOUPPER (s[i]); - if (i) { - for (; i < 4; i++) - tag[i] = ' '; - return HB_TAG (tag[0], tag[1], tag[2], tag[3]); + /* Find a language matching in the first component. */ + s = strchr (lang_str, '-'); + { + const LangTag *lang_tag; + if (s && limit - lang_str >= 6) + { + const char *extlang_end = strchr (s + 1, '-'); + /* If there is an extended language tag, use it. */ + if (3 == (extlang_end ? extlang_end - s - 1 : strlen (s + 1)) && + ISALPHA (s[1])) + lang_str = s + 1; + } + lang_tag = (LangTag *) bsearch (lang_str, ot_languages, + ARRAY_LENGTH (ot_languages), sizeof (LangTag), + lang_compare_first_component); + if (lang_tag) + { + unsigned int i; + for (i = 0; i < *count && lang_tag->tags[i] != HB_TAG_NONE; i++) + tags[i] = lang_tag->tags[i]; + *count = i; + return; } } - /* - * "fonipa" is a variant tag in BCP-47, meaning the International Phonetic Alphabet. - * It can be applied to any language. - */ - if (strstr (lang_str, "-fonipa")) { - return HB_TAG('I','P','P','H'); /* Phonetic transcription—IPA conventions */ - } - - /* - * "fonnapa" is a variant tag in BCP-47, meaning the North American Phonetic Alphabet - * also known as Americanist Phonetic Notation. It can be applied to any language. - */ - if (strstr (lang_str, "-fonnapa")) { - return HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */ + if (!s) + s = lang_str + strlen (lang_str); + if (s - lang_str == 3) { + /* Assume it's ISO-639-3 and upper-case and use it. */ + tags[0] = hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u; + *count = 1; + return; } - /* - * "Syre" is a BCP-47 script tag, meaning the Estrangela variant of the Syriac script. - * It can be applied to any language. - */ - if (strstr (lang_str, "-syre")) { - return HB_TAG('S','Y','R','E'); /* Estrangela Syriac */ - } + *count = 0; +} - /* - * "Syrj" is a BCP-47 script tag, meaning the Western variant of the Syriac script. - * It can be applied to any language. - */ - if (strstr (lang_str, "-syrj")) { - return HB_TAG('S','Y','R','J'); /* Western Syriac */ +static bool +parse_private_use_subtag (const char *private_use_subtag, + unsigned int *count, + hb_tag_t *tags, + const char *prefix, + unsigned char (*normalize) (unsigned char)) +{ + if (private_use_subtag && count && tags && *count) + { + const char *s = strstr (private_use_subtag, prefix); + if (s) + { + char tag[4]; + int i; + s += strlen (prefix); + for (i = 0; i < 4 && ISALNUM (s[i]); i++) + tag[i] = normalize (s[i]); + if (i) + { + for (; i < 4; i++) + tag[i] = ' '; + tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]); + if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT) + tags[0] ^= ~0xDFDFDFDF; + *count = 1; + return false; + } + } } + return true; +} - /* - * "Syrn" is a BCP-47 script tag, meaning the Eastern variant of the Syriac script. - * It can be applied to any language. - */ - if (strstr (lang_str, "-syrn")) { - return HB_TAG('S','Y','R','N'); /* Eastern Syriac */ - } +/** + * hb_ot_tags_from_script_and_language: + * @script: an #hb_script_t to convert. + * @language: an #hb_language_t to convert. + * @script_count: (allow-none): maximum number of script tags to retrieve (IN) + * and actual number of script tags retrieved (OUT) + * @script_tags: (out) (allow-none): array of size at least @script_count to store the + * script tag results + * @language_count: (allow-none): maximum number of language tags to retrieve + * (IN) and actual number of language tags retrieved (OUT) + * @language_tags: (out) (allow-none): array of size at least @language_count to store + * the language tag results + * + * Converts an #hb_script_t and an #hb_language_t to script and language tags. + * + * Since: 2.0.0 + **/ +void +hb_ot_tags_from_script_and_language (hb_script_t script, + hb_language_t language, + unsigned int *script_count /* IN/OUT */, + hb_tag_t *script_tags /* OUT */, + unsigned int *language_count /* IN/OUT */, + hb_tag_t *language_tags /* OUT */) +{ + bool needs_script = true; - /* Find a language matching in the first component */ + if (language == HB_LANGUAGE_INVALID) { - const LangTag *lang_tag; - lang_tag = (LangTag *) bsearch (lang_str, ot_languages, - ARRAY_LENGTH (ot_languages), sizeof (LangTag), - lang_compare_first_component); - if (lang_tag) - return lang_tag->tag; + if (language_count && language_tags && *language_count) + *language_count = 0; } - - /* Otherwise, check the Chinese ones */ - if (0 == lang_compare_first_component (lang_str, "zh")) + else { - unsigned int i; + const char *lang_str, *s, *limit, *private_use_subtag; + bool needs_language; - for (i = 0; i < ARRAY_LENGTH (ot_languages_zh); i++) + lang_str = hb_language_to_string (language); + limit = nullptr; + private_use_subtag = nullptr; + if (lang_str[0] == 'x' && lang_str[1] == '-') { - const LangTagLong *lang_tag; - lang_tag = &ot_languages_zh[i]; - if (lang_matches (lang_str, lang_tag->language)) - return lang_tag->tag; + private_use_subtag = lang_str; + } else { + for (s = lang_str + 1; *s; s++) + { + if (s[-1] == '-' && s[1] == '-') + { + if (s[0] == 'x') + { + private_use_subtag = s; + if (!limit) + limit = s - 1; + break; + } else if (!limit) + { + limit = s - 1; + } + } + } + if (!limit) + limit = s; } - /* Otherwise just return 'ZHS ' */ - return HB_TAG('Z','H','S',' '); - } + needs_script = parse_private_use_subtag (private_use_subtag, script_count, script_tags, "-hbsc", TOLOWER); + needs_language = parse_private_use_subtag (private_use_subtag, language_count, language_tags, "-hbot", TOUPPER); - s = strchr (lang_str, '-'); - if (!s) - s = lang_str + strlen (lang_str); - if (s - lang_str == 3) { - /* Assume it's ISO-639-3 and upper-case and use it. */ - return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u; + if (needs_language && language_count && language_tags && *language_count) + hb_ot_tags_from_language (lang_str, limit, language_count, language_tags); } - return HB_OT_TAG_DEFAULT_LANGUAGE; + if (needs_script && script_count && script_tags && *script_count) + hb_ot_all_tags_from_script (script, script_count, script_tags); } /** @@ -1023,36 +412,16 @@ if (tag == HB_OT_TAG_DEFAULT_LANGUAGE) return nullptr; - /* struct LangTag has only room for 3-letter language tags. */ - switch (tag) { - case HB_TAG('A','P','P','H'): /* Phonetic transcription—Americanist conventions */ - return hb_language_from_string ("und-fonnapa", -1); - case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */ - return hb_language_from_string ("und-fonipa", -1); - case HB_TAG('S','Y','R',' '): /* Syriac [macrolanguage] */ - return hb_language_from_string ("syr", -1); - case HB_TAG('S','Y','R','E'): /* Estrangela Syriac */ - return hb_language_from_string ("und-Syre", -1); - case HB_TAG('S','Y','R','J'): /* Western Syriac */ - return hb_language_from_string ("und-Syrj", -1); - case HB_TAG('S','Y','R','N'): /* Eastern Syriac */ - return hb_language_from_string ("und-Syrn", -1); + { + hb_language_t disambiguated_tag = hb_ot_ambiguous_tag_to_language (tag); + if (disambiguated_tag != HB_LANGUAGE_INVALID) + return disambiguated_tag; } for (i = 0; i < ARRAY_LENGTH (ot_languages); i++) - if (ot_languages[i].tag == tag) + if (ot_languages[i].tags[0] == tag) return hb_language_from_string (ot_languages[i].language, -1); - /* If tag starts with ZH, it's Chinese */ - if ((tag & 0xFFFF0000u) == 0x5A480000u) { - switch (tag) { - case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1); /* Hong Kong */ - case HB_TAG('Z','H','S',' '): return hb_language_from_string ("zh-Hans", -1); /* Simplified */ - case HB_TAG('Z','H','T',' '): return hb_language_from_string ("zh-Hant", -1); /* Traditional */ - default: break; /* Fall through */ - } - } - /* Else return a custom language in the form of "x-hbotABCD" */ { unsigned char buf[11] = "x-hbot"; @@ -1067,9 +436,74 @@ } } +/** + * hb_ot_tags_to_script_and_language: + * @script_tag: a script tag + * @language_tag: a language tag + * @script: (allow-none): the #hb_script_t corresponding to @script_tag (OUT). + * @language: (allow-none): the #hb_language_t corresponding to @script_tag and + * @language_tag (OUT). + * + * Converts a script tag and a language tag to an #hb_script_t and an + * #hb_language_t. + * + * Since: 2.0.0 + **/ +void +hb_ot_tags_to_script_and_language (hb_tag_t script_tag, + hb_tag_t language_tag, + hb_script_t *script /* OUT */, + hb_language_t *language /* OUT */) +{ + hb_script_t script_out = hb_ot_tag_to_script (script_tag); + if (script) + *script = script_out; + if (language) + { + unsigned int script_count = 1; + hb_tag_t primary_script_tag[1]; + hb_ot_tags_from_script_and_language (script_out, + HB_LANGUAGE_INVALID, + &script_count, + primary_script_tag, + nullptr, nullptr); + *language = hb_ot_tag_to_language (language_tag); + if (script_count == 0 || primary_script_tag[0] != script_tag) + { + unsigned char *buf; + const char *lang_str = hb_language_to_string (*language); + size_t len = strlen (lang_str); + buf = (unsigned char *) malloc (len + 11); + if (unlikely (!buf)) + { + *language = nullptr; + } + else + { + memcpy (buf, lang_str, len); + if (lang_str[0] != 'x' || lang_str[1] != '-') { + buf[len++] = '-'; + buf[len++] = 'x'; + } + buf[len++] = '-'; + buf[len++] = 'h'; + buf[len++] = 'b'; + buf[len++] = 's'; + buf[len++] = 'c'; + buf[len++] = script_tag >> 24; + buf[len++] = (script_tag >> 16) & 0xFF; + buf[len++] = (script_tag >> 8) & 0xFF; + buf[len++] = script_tag & 0xFF; + *language = hb_language_from_string ((char *) buf, len); + free (buf); + } + } + } +} + #ifdef MAIN static inline void -test_langs_sorted (void) +test_langs_sorted () { for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++) { @@ -1084,7 +518,7 @@ } int -main (void) +main () { test_langs_sorted (); return 0; --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-avar-table.hh 2019-02-28 12:04:08.698502800 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-avar-table.hh 2019-02-28 12:04:08.598502801 -0800 @@ -27,7 +27,7 @@ #ifndef HB_OT_VAR_AVAR_TABLE_HH #define HB_OT_VAR_AVAR_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" /* * avar -- Axis Variations @@ -42,7 +42,7 @@ struct AxisValueMap { - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -59,7 +59,7 @@ struct SegmentMaps : ArrayOf { - inline int map (int value) const + int map (int value) const { /* The following special-cases are not part of OpenType, which requires * that at least -1, 0, and +1 must be mapped. But we include these as @@ -93,14 +93,15 @@ (value - arrayZ[i-1].fromCoord) + denom/2) / denom; } - DEFINE_SIZE_ARRAY (2, arrayZ); + public: + DEFINE_SIZE_ARRAY (2, *this); }; struct avar { - static const hb_tag_t tableTag = HB_OT_TAG_avar; + static constexpr hb_tag_t tableTag = HB_OT_TAG_avar; - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (unlikely (!(version.sanitize (c) && @@ -108,7 +109,7 @@ c->check_struct (this)))) return_trace (false); - const SegmentMaps *map = axisSegmentMapsZ; + const SegmentMaps *map = &firstAxisSegmentMaps; unsigned int count = axisCount; for (unsigned int i = 0; i < count; i++) { @@ -120,11 +121,11 @@ return_trace (true); } - inline void map_coords (int *coords, unsigned int coords_length) const + void map_coords (int *coords, unsigned int coords_length) const { unsigned int count = MIN (coords_length, axisCount); - const SegmentMaps *map = axisSegmentMapsZ; + const SegmentMaps *map = &firstAxisSegmentMaps; for (unsigned int i = 0; i < count; i++) { coords[i] = map->map (coords[i]); @@ -139,7 +140,7 @@ HBUINT16 axisCount; /* The number of variation axes in the font. This * must be the same number as axisCount in the * 'fvar' table. */ - SegmentMaps axisSegmentMapsZ[VAR]; + SegmentMaps firstAxisSegmentMaps; public: DEFINE_SIZE_MIN (8); --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-fvar-table.hh 2019-02-28 12:04:09.034502794 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-fvar-table.hh 2019-02-28 12:04:08.918502796 -0800 @@ -27,7 +27,7 @@ #ifndef HB_OT_VAR_FVAR_TABLE_HH #define HB_OT_VAR_FVAR_TABLE_HH -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" /* * fvar -- Font Variations @@ -42,29 +42,40 @@ struct InstanceRecord { - inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const + friend struct fvar; + + hb_array_t get_coordinates (unsigned int axis_count) const + { return coordinatesZ.as_array (axis_count); } + + bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - c->check_array (coordinates, coordinates[0].static_size, axis_count)); + c->check_array (coordinatesZ.arrayZ, axis_count)); } protected: NameID subfamilyNameID;/* The name ID for entries in the 'name' table * that provide subfamily names for this instance. */ - HBUINT16 reserved; /* Reserved for future use — set to 0. */ - Fixed coordinates[VAR];/* The coordinates array for this instance. */ + HBUINT16 flags; /* Reserved for future use — set to 0. */ + UnsizedArrayOf + coordinatesZ; /* The coordinates array for this instance. */ //NameID postScriptNameIDX;/*Optional. The name ID for entries in the 'name' // * table that provide PostScript names for this // * instance. */ public: - DEFINE_SIZE_ARRAY (4, coordinates); + DEFINE_SIZE_UNBOUNDED (4); }; struct AxisRecord { - inline bool sanitize (hb_sanitize_context_t *c) const + enum + { + AXIS_FLAG_HIDDEN = 0x0001, + }; + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -75,7 +86,7 @@ Fixed minValue; /* The minimum coordinate value for the axis. */ Fixed defaultValue; /* The default coordinate value for the axis. */ Fixed maxValue; /* The maximum coordinate value for the axis. */ - HBUINT16 reserved; /* Reserved for future use — set to 0. */ + HBUINT16 flags; /* Axis flags. */ NameID axisNameID; /* The name ID for entries in the 'name' table that * provide a display name for this axis. */ @@ -85,50 +96,80 @@ struct fvar { - static const hb_tag_t tableTag = HB_OT_TAG_fvar; + static constexpr hb_tag_t tableTag = HB_OT_TAG_fvar; - inline bool sanitize (hb_sanitize_context_t *c) const + bool has_data () const { return version.to_int (); } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && likely (version.major == 1) && c->check_struct (this) && + axisSize == 20 && /* Assumed in our code. */ instanceSize >= axisCount * 4 + 4 && - axisSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */ - instanceSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */ - c->check_range (this, things) && - c->check_range (&StructAtOffset (this, things), - axisCount * axisSize + instanceCount * instanceSize)); + get_axes ().sanitize (c) && + c->check_range (get_instance (0), instanceCount, instanceSize)); } - inline unsigned int get_axis_count (void) const - { return axisCount; } + unsigned int get_axis_count () const { return axisCount; } + + void get_axis_deprecated (unsigned int axis_index, + hb_ot_var_axis_t *info) const + { + const AxisRecord &axis = get_axes ()[axis_index]; + info->tag = axis.axisTag; + info->name_id = axis.axisNameID; + info->default_value = axis.defaultValue / 65536.; + /* Ensure order, to simplify client math. */ + info->min_value = MIN (info->default_value, axis.minValue / 65536.); + info->max_value = MAX (info->default_value, axis.maxValue / 65536.); + } - inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const + void get_axis_info (unsigned int axis_index, + hb_ot_var_axis_info_t *info) const { - if (unlikely (index >= axisCount)) - return false; + const AxisRecord &axis = get_axes ()[axis_index]; + info->axis_index = axis_index; + info->tag = axis.axisTag; + info->name_id = axis.axisNameID; + info->flags = (hb_ot_var_axis_flags_t) (unsigned int) axis.flags; + info->default_value = axis.defaultValue / 65536.; + /* Ensure order, to simplify client math. */ + info->min_value = MIN (info->default_value, axis.minValue / 65536.); + info->max_value = MAX (info->default_value, axis.maxValue / 65536.); + info->reserved = 0; + } - if (info) + unsigned int get_axes_deprecated (unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_t *axes_array /* OUT */) const + { + if (axes_count) { - const AxisRecord &axis = get_axes ()[index]; - info->tag = axis.axisTag; - info->name_id = axis.axisNameID; - info->default_value = axis.defaultValue / 65536.; - /* Ensure order, to simplify client math. */ - info->min_value = MIN (info->default_value, axis.minValue / 65536.); - info->max_value = MAX (info->default_value, axis.maxValue / 65536.); - } + /* TODO Rewrite as hb_array_t<>::sub-array() */ + unsigned int count = axisCount; + start_offset = MIN (start_offset, count); - return true; + count -= start_offset; + axes_array += start_offset; + + count = MIN (count, *axes_count); + *axes_count = count; + + for (unsigned int i = 0; i < count; i++) + get_axis_deprecated (start_offset + i, axes_array + i); + } + return axisCount; } - inline unsigned int get_axis_infos (unsigned int start_offset, - unsigned int *axes_count /* IN/OUT */, - hb_ot_var_axis_t *axes_array /* OUT */) const + unsigned int get_axis_infos (unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_info_t *axes_array /* OUT */) const { if (axes_count) { + /* TODO Rewrite as hb_array_t<>::sub-array() */ unsigned int count = axisCount; start_offset = MIN (start_offset, count); @@ -139,32 +180,48 @@ *axes_count = count; for (unsigned int i = 0; i < count; i++) - get_axis (start_offset + i, axes_array + i); + get_axis_info (start_offset + i, axes_array + i); } return axisCount; } - inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const + bool find_axis_deprecated (hb_tag_t tag, + unsigned int *axis_index, + hb_ot_var_axis_t *info) const { const AxisRecord *axes = get_axes (); unsigned int count = get_axis_count (); for (unsigned int i = 0; i < count; i++) if (axes[i].axisTag == tag) { - if (index) - *index = i; - return get_axis (i, info); + if (axis_index) + *axis_index = i; + get_axis_deprecated (i, info); + return true; } - if (index) - *index = HB_OT_VAR_NO_AXIS_INDEX; + if (axis_index) + *axis_index = HB_OT_VAR_NO_AXIS_INDEX; return false; } - inline int normalize_axis_value (unsigned int axis_index, float v) const + bool find_axis_info (hb_tag_t tag, + hb_ot_var_axis_info_t *info) const { - hb_ot_var_axis_t axis; - if (!get_axis (axis_index, &axis)) - return 0; + const AxisRecord *axes = get_axes (); + unsigned int count = get_axis_count (); + for (unsigned int i = 0; i < count; i++) + if (axes[i].axisTag == tag) + { + get_axis_info (i, info); + return true; + } + return false; + } + + int normalize_axis_value (unsigned int axis_index, float v) const + { + hb_ot_var_axis_info_t axis; + get_axis_info (axis_index, &axis); v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */ @@ -174,20 +231,65 @@ v = (v - axis.default_value) / (axis.default_value - axis.min_value); else v = (v - axis.default_value) / (axis.max_value - axis.default_value); - return (int) (v * 16384. + (v >= 0. ? .5 : -.5)); + return (int) (v * 16384.f + (v >= 0.f ? .5f : -.5f)); + } + + unsigned int get_instance_count () const { return instanceCount; } + + hb_ot_name_id_t get_instance_subfamily_name_id (unsigned int instance_index) const + { + const InstanceRecord *instance = get_instance (instance_index); + if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID; + return instance->subfamilyNameID; + } + + hb_ot_name_id_t get_instance_postscript_name_id (unsigned int instance_index) const + { + const InstanceRecord *instance = get_instance (instance_index); + if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID; + if (instanceSize >= axisCount * 4 + 6) + return StructAfter (instance->get_coordinates (axisCount)); + return HB_OT_NAME_ID_INVALID; + } + + unsigned int get_instance_coords (unsigned int instance_index, + unsigned int *coords_length, /* IN/OUT */ + float *coords /* OUT */) const + { + const InstanceRecord *instance = get_instance (instance_index); + if (unlikely (!instance)) + { + if (coords_length) + *coords_length = 0; + return 0; + } + + if (coords_length && *coords_length) + { + hb_array_t instanceCoords = instance->get_coordinates (axisCount) + .sub_array (0, *coords_length); + for (unsigned int i = 0; i < instanceCoords.length; i++) + coords[i] = instanceCoords.arrayZ[i].to_float (); + } + return axisCount; } protected: - inline const AxisRecord * get_axes (void) const - { return &StructAtOffset (this, things); } + hb_array_t get_axes () const + { return hb_array (&(this+firstAxis), axisCount); } - inline const InstanceRecord * get_instances (void) const - { return &StructAtOffset (get_axes () + axisCount, 0); } + const InstanceRecord *get_instance (unsigned int i) const + { + if (unlikely (i >= instanceCount)) return nullptr; + return &StructAtOffset (&StructAfter (get_axes ()), + i * instanceSize); + } protected: FixedVersion<>version; /* Version of the fvar table * initially set to 0x00010000u */ - Offset16 things; /* Offset in bytes from the beginning of the table + OffsetTo + firstAxis; /* Offset in bytes from the beginning of the table * to the start of the AxisRecord array. */ HBUINT16 reserved; /* This field is permanently reserved. Set to 2. */ HBUINT16 axisCount; /* The number of variation axes in the font (the --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-hvar-table.hh 2019-02-28 12:04:09.394502788 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-hvar-table.hh 2019-02-28 12:04:09.278502790 -0800 @@ -27,7 +27,7 @@ #ifndef HB_OT_VAR_HVAR_TABLE_HH #define HB_OT_VAR_HVAR_TABLE_HH -#include "hb-ot-layout-common-private.hh" +#include "hb-ot-layout-common.hh" namespace OT { @@ -35,11 +35,13 @@ struct DeltaSetIndexMap { - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - c->check_array (mapData, get_width (), mapCount)); + c->check_range (mapDataZ.arrayZ, + mapCount, + get_width ())); } unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */ @@ -55,7 +57,7 @@ unsigned int u = 0; { /* Fetch it. */ unsigned int w = get_width (); - const HBUINT8 *p = mapData + w * v; + const HBUINT8 *p = mapDataZ.arrayZ + w * v; for (; w; w--) u = (u << 8) + *p++; } @@ -71,20 +73,19 @@ } protected: - inline unsigned int get_width (void) const - { return ((format >> 4) & 3) + 1; } + unsigned int get_width () const { return ((format >> 4) & 3) + 1; } - inline unsigned int get_inner_bitcount (void) const - { return (format & 0xF) + 1; } + unsigned int get_inner_bitcount () const { return (format & 0xF) + 1; } protected: HBUINT16 format; /* A packed field that describes the compressed * representation of delta-set indices. */ HBUINT16 mapCount; /* The number of mapping entries. */ - HBUINT8 mapData[VAR]; /* The delta-set index mapping data. */ + UnsizedArrayOf + mapDataZ; /* The delta-set index mapping data. */ public: - DEFINE_SIZE_ARRAY (4, mapData); + DEFINE_SIZE_ARRAY (4, mapDataZ); }; @@ -99,10 +100,10 @@ struct HVARVVAR { - static const hb_tag_t HVARTag = HB_OT_TAG_HVAR; - static const hb_tag_t VVARTag = HB_OT_TAG_VVAR; + static constexpr hb_tag_t HVARTag = HB_OT_TAG_HVAR; + static constexpr hb_tag_t VVARTag = HB_OT_TAG_VVAR; - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && @@ -113,15 +114,14 @@ rsbMap.sanitize (c, this)); } - inline float get_advance_var (hb_codepoint_t glyph, - int *coords, unsigned int coord_count) const + float get_advance_var (hb_codepoint_t glyph, + const int *coords, unsigned int coord_count) const { unsigned int varidx = (this+advMap).map (glyph); return (this+varStore).get_delta (varidx, coords, coord_count); } - inline bool has_sidebearing_deltas (void) const - { return lsbMap && rsbMap; } + bool has_sidebearing_deltas () const { return lsbMap && rsbMap; } protected: FixedVersion<>version; /* Version of the metrics variation table @@ -140,12 +140,12 @@ }; struct HVAR : HVARVVAR { - static const hb_tag_t tableTag = HB_OT_TAG_HVAR; + static constexpr hb_tag_t tableTag = HB_OT_TAG_HVAR; }; struct VVAR : HVARVVAR { - static const hb_tag_t tableTag = HB_OT_TAG_VVAR; + static constexpr hb_tag_t tableTag = HB_OT_TAG_VVAR; - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (static_cast (this)->sanitize (c) && --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-mvar-table.hh 2019-02-28 12:04:09.798502782 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-mvar-table.hh 2019-02-28 12:04:09.678502784 -0800 @@ -27,7 +27,7 @@ #ifndef HB_OT_VAR_MVAR_TABLE_HH #define HB_OT_VAR_MVAR_TABLE_HH -#include "hb-ot-layout-common-private.hh" +#include "hb-ot-layout-common.hh" namespace OT { @@ -35,7 +35,7 @@ struct VariationValueRecord { - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -58,9 +58,9 @@ struct MVAR { - static const hb_tag_t tableTag = HB_OT_TAG_MVAR; + static constexpr hb_tag_t tableTag = HB_OT_TAG_MVAR; - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && @@ -68,14 +68,16 @@ c->check_struct (this) && valueRecordSize >= VariationValueRecord::static_size && varStore.sanitize (c, this) && - c->check_array (values, valueRecordSize, valueRecordCount)); + c->check_range (valuesZ.arrayZ, + valueRecordCount, + valueRecordSize)); } - inline float get_var (hb_tag_t tag, - int *coords, unsigned int coord_count) const + float get_var (hb_tag_t tag, + const int *coords, unsigned int coord_count) const { const VariationValueRecord *record; - record = (VariationValueRecord *) bsearch (&tag, values, + record = (VariationValueRecord *) bsearch (&tag, valuesZ.arrayZ, valueRecordCount, valueRecordSize, tag_compare); if (!record) @@ -85,7 +87,7 @@ } protected: - static inline int tag_compare (const void *pa, const void *pb) + static int tag_compare (const void *pa, const void *pb) { const hb_tag_t *a = (const hb_tag_t *) pa; const Tag *b = (const Tag *) pb; @@ -101,11 +103,12 @@ HBUINT16 valueRecordCount;/* The number of value records — may be zero. */ OffsetTo varStore; /* Offset to item variation store table. */ - HBUINT8 values[VAR]; /* Array of value records. The records must be + UnsizedArrayOf + valuesZ; /* Array of value records. The records must be * in binary order of their valueTag field. */ public: - DEFINE_SIZE_ARRAY (12, values); + DEFINE_SIZE_ARRAY (12, valuesZ); }; } /* namespace OT */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.cc 2019-02-28 12:04:10.130502776 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.cc 2019-02-28 12:04:10.030502778 -0800 @@ -24,39 +24,35 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-open-type-private.hh" +#include "hb-open-type.hh" -#include "hb-ot-layout-private.hh" +#include "hb-ot-face.hh" #include "hb-ot-var-avar-table.hh" #include "hb-ot-var-fvar-table.hh" #include "hb-ot-var-mvar-table.hh" #include "hb-ot-var.h" + +/** + * SECTION:hb-ot-var + * @title: hb-ot-var + * @short_description: OpenType Font Variations + * @include: hb-ot.h + * + * Functions for fetching information about OpenType Variable Fonts. + **/ + + /* * fvar/avar */ -static inline const OT::fvar& -_get_fvar (hb_face_t *face) -{ - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::fvar); - hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - return *(layout->fvar.get ()); -} -static inline const OT::avar& -_get_avar (hb_face_t *face) -{ - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::avar); - hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - return *(layout->avar.get ()); -} /** * hb_ot_var_has_data: * @face: #hb_face_t to test * * This function allows to verify the presence of OpenType variation data on the face. - * Alternatively, use hb_ot_var_get_axis_count(). * * Return value: true if face has a `fvar' table and false otherwise * @@ -65,7 +61,7 @@ hb_bool_t hb_ot_var_has_data (hb_face_t *face) { - return &_get_fvar (face) != &Null(OT::fvar); + return face->table.fvar->has_data (); } /** @@ -76,14 +72,14 @@ unsigned int hb_ot_var_get_axis_count (hb_face_t *face) { - const OT::fvar &fvar = _get_fvar (face); - return fvar.get_axis_count (); + return face->table.fvar->get_axis_count (); } /** * hb_ot_var_get_axes: * * Since: 1.4.2 + * Deprecated: 2.2.0 **/ unsigned int hb_ot_var_get_axes (hb_face_t *face, @@ -91,14 +87,14 @@ unsigned int *axes_count /* IN/OUT */, hb_ot_var_axis_t *axes_array /* OUT */) { - const OT::fvar &fvar = _get_fvar (face); - return fvar.get_axis_infos (start_offset, axes_count, axes_array); + return face->table.fvar->get_axes_deprecated (start_offset, axes_count, axes_array); } /** * hb_ot_var_find_axis: * * Since: 1.4.2 + * Deprecated: 2.2.0 **/ hb_bool_t hb_ot_var_find_axis (hb_face_t *face, @@ -106,8 +102,68 @@ unsigned int *axis_index, hb_ot_var_axis_t *axis_info) { - const OT::fvar &fvar = _get_fvar (face); - return fvar.find_axis (axis_tag, axis_index, axis_info); + return face->table.fvar->find_axis_deprecated (axis_tag, axis_index, axis_info); +} + +/** + * hb_ot_var_get_axis_infos: + * + * Since: 2.2.0 + **/ +HB_EXTERN unsigned int +hb_ot_var_get_axis_infos (hb_face_t *face, + unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_info_t *axes_array /* OUT */) +{ + return face->table.fvar->get_axis_infos (start_offset, axes_count, axes_array); +} + +/** + * hb_ot_var_find_axis_info: + * + * Since: 2.2.0 + **/ +HB_EXTERN hb_bool_t +hb_ot_var_find_axis_info (hb_face_t *face, + hb_tag_t axis_tag, + hb_ot_var_axis_info_t *axis_info) +{ + return face->table.fvar->find_axis_info (axis_tag, axis_info); +} + + +/* + * Named instances. + */ + +unsigned int +hb_ot_var_get_named_instance_count (hb_face_t *face) +{ + return face->table.fvar->get_instance_count (); +} + +hb_ot_name_id_t +hb_ot_var_named_instance_get_subfamily_name_id (hb_face_t *face, + unsigned int instance_index) +{ + return face->table.fvar->get_instance_subfamily_name_id (instance_index); +} + +hb_ot_name_id_t +hb_ot_var_named_instance_get_postscript_name_id (hb_face_t *face, + unsigned int instance_index) +{ + return face->table.fvar->get_instance_postscript_name_id (instance_index); +} + +unsigned int +hb_ot_var_named_instance_get_design_coords (hb_face_t *face, + unsigned int instance_index, + unsigned int *coords_length, /* IN/OUT */ + float *coords /* OUT */) +{ + return face->table.fvar->get_instance_coords (instance_index, coords_length, coords); } @@ -126,17 +182,16 @@ for (unsigned int i = 0; i < coords_length; i++) coords[i] = 0; - const OT::fvar &fvar = _get_fvar (face); + const OT::fvar &fvar = *face->table.fvar; for (unsigned int i = 0; i < variations_length; i++) { - unsigned int axis_index; - if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, nullptr) && - axis_index < coords_length) - coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value); + hb_ot_var_axis_info_t info; + if (hb_ot_var_find_axis_info (face, variations[i].tag, &info) && + info.axis_index < coords_length) + coords[info.axis_index] = fvar.normalize_axis_value (info.axis_index, variations[i].value); } - const OT::avar &avar = _get_avar (face); - avar.map_coords (coords, coords_length); + face->table.avar->map_coords (coords, coords_length); } /** @@ -150,10 +205,9 @@ const float *design_coords, /* IN */ int *normalized_coords /* OUT */) { - const OT::fvar &fvar = _get_fvar (face); + const OT::fvar &fvar = *face->table.fvar; for (unsigned int i = 0; i < coords_length; i++) normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]); - const OT::avar &avar = _get_avar (face); - avar.map_coords (normalized_coords, coords_length); + face->table.avar->map_coords (normalized_coords, coords_length); } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.h 2019-02-28 12:04:10.450502771 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.h 2019-02-28 12:04:10.350502773 -0800 @@ -47,45 +47,86 @@ * fvar / avar */ +HB_EXTERN hb_bool_t +hb_ot_var_has_data (hb_face_t *face); + + +/* + * Variation axes. + */ + + +HB_EXTERN unsigned int +hb_ot_var_get_axis_count (hb_face_t *face); + /** - * hb_ot_var_axis_t: + * hb_ot_var_axis_flags_t: + * @HB_OT_VAR_AXIS_FLAG_HIDDEN: The axis should not be exposed directly in user interfaces. * - * Since: 1.4.2 + * Since: 2.2.0 */ -typedef struct hb_ot_var_axis_t { - hb_tag_t tag; - unsigned int name_id; - float min_value; - float default_value; - float max_value; -} hb_ot_var_axis_t; +typedef enum { /*< flags >*/ + HB_OT_VAR_AXIS_FLAG_HIDDEN = 0x00000001u, -HB_EXTERN hb_bool_t -hb_ot_var_has_data (hb_face_t *face); + _HB_OT_VAR_AXIS_FLAG_MAX_VALUE= 0x7FFFFFFFu /*< skip >*/ +} hb_ot_var_axis_flags_t; /** - * HB_OT_VAR_NO_AXIS_INDEX: + * hb_ot_var_axis_info_t: * - * Since: 1.4.2 + * Since: 2.2.0 */ -#define HB_OT_VAR_NO_AXIS_INDEX 0xFFFFFFFFu +typedef struct hb_ot_var_axis_info_t +{ + unsigned int axis_index; + hb_tag_t tag; + hb_ot_name_id_t name_id; + hb_ot_var_axis_flags_t flags; + float min_value; + float default_value; + float max_value; + /*< private >*/ + unsigned int reserved; +} hb_ot_var_axis_info_t; HB_EXTERN unsigned int -hb_ot_var_get_axis_count (hb_face_t *face); +hb_ot_var_get_axis_infos (hb_face_t *face, + unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_info_t *axes_array /* OUT */); + +HB_EXTERN hb_bool_t +hb_ot_var_find_axis_info (hb_face_t *face, + hb_tag_t axis_tag, + hb_ot_var_axis_info_t *axis_info); + + +/* + * Named instances. + */ HB_EXTERN unsigned int -hb_ot_var_get_axes (hb_face_t *face, - unsigned int start_offset, - unsigned int *axes_count /* IN/OUT */, - hb_ot_var_axis_t *axes_array /* OUT */); +hb_ot_var_get_named_instance_count (hb_face_t *face); -HB_EXTERN hb_bool_t -hb_ot_var_find_axis (hb_face_t *face, - hb_tag_t axis_tag, - unsigned int *axis_index, - hb_ot_var_axis_t *axis_info); +HB_EXTERN hb_ot_name_id_t +hb_ot_var_named_instance_get_subfamily_name_id (hb_face_t *face, + unsigned int instance_index); + +HB_EXTERN hb_ot_name_id_t +hb_ot_var_named_instance_get_postscript_name_id (hb_face_t *face, + unsigned int instance_index); + +HB_EXTERN unsigned int +hb_ot_var_named_instance_get_design_coords (hb_face_t *face, + unsigned int instance_index, + unsigned int *coords_length, /* IN/OUT */ + float *coords /* OUT */); +/* + * Conversions. + */ + HB_EXTERN void hb_ot_var_normalize_variations (hb_face_t *face, const hb_variation_t *variations, /* IN */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot.h 2019-02-28 12:04:10.782502765 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot.h 2019-02-28 12:04:10.674502767 -0800 @@ -30,10 +30,12 @@ #include "hb.h" +#include "hb-ot-color.h" +#include "hb-ot-deprecated.h" #include "hb-ot-font.h" #include "hb-ot-layout.h" #include "hb-ot-math.h" -#include "hb-ot-tag.h" +#include "hb-ot-name.h" #include "hb-ot-shape.h" #include "hb-ot-var.h" --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set.cc 2019-02-28 12:04:11.106502760 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set.cc 2019-02-28 12:04:11.006502762 -0800 @@ -24,10 +24,19 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-set-private.hh" +#include "hb-set.hh" -/* Public API */ +/** + * SECTION:hb-set + * @title: hb-set + * @short_description: Object representing a set of integers + * @include: hb.h + * + * Set objects represent a mathematical set of integer values. They are + * used in non-shaping API to query certain set of characters or glyphs, + * or other integer values. + **/ /** @@ -38,7 +47,7 @@ * Since: 0.9.2 **/ hb_set_t * -hb_set_create (void) +hb_set_create () { hb_set_t *set; @@ -58,7 +67,7 @@ * Since: 0.9.2 **/ hb_set_t * -hb_set_get_empty (void) +hb_set_get_empty () { return const_cast (&Null(hb_set_t)); } @@ -391,7 +400,7 @@ * Deprecated: 1.6.1 **/ void -hb_set_invert (hb_set_t *set) +hb_set_invert (hb_set_t *set HB_UNUSED) { } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan.cc 2019-02-28 12:04:11.454502754 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan.cc 2019-02-28 12:04:11.326502756 -0800 @@ -24,64 +24,132 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-private.hh" -#include "hb-debug.hh" -#include "hb-shape-plan-private.hh" -#include "hb-shaper-private.hh" -#include "hb-font-private.hh" -#include "hb-buffer-private.hh" +#include "hb.hh" +#include "hb-shape-plan.hh" +#include "hb-shaper.hh" +#include "hb-font.hh" +#include "hb-buffer.hh" -static void -hb_shape_plan_plan (hb_shape_plan_t *shape_plan, - const hb_feature_t *user_features, - unsigned int num_user_features, - const int *coords, - unsigned int num_coords, - const char * const *shaper_list) +/** + * SECTION:hb-shape-plan + * @title: hb-shape-plan + * @short_description: Object representing a shaping plan + * @include: hb.h + * + * Shape plans are not used for shaping directly, but can be access to query + * certain information about how shaping will perform given a set of input + * parameters (script, language, direction, features, etc.) + * Most client would not need to deal with shape plans directly. + **/ + + +/* + * hb_shape_plan_key_t + */ + +bool +hb_shape_plan_key_t::init (bool copy, + hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list) { - DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, - "num_features=%d num_coords=%d shaper_list=%p", - num_user_features, - num_coords, - shaper_list); + hb_feature_t *features = nullptr; + if (copy && num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t)))) + goto bail; - const hb_shaper_pair_t *shapers = _hb_shapers_get (); + this->props = *props; + this->num_user_features = num_user_features; + this->user_features = copy ? features : user_features; + if (copy && num_user_features) + { + memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); + /* Make start/end uniform to easier catch bugs. */ + for (unsigned int i = 0; i < num_user_features; i++) + { + if (features[0].start != HB_FEATURE_GLOBAL_START) + features[0].start = 1; + if (features[0].end != HB_FEATURE_GLOBAL_END) + features[0].end = 2; + } + } + this->shaper_func = nullptr; + this->shaper_name = nullptr; + this->ot.init (face, coords, num_coords); + + /* + * Choose shaper. + */ #define HB_SHAPER_PLAN(shaper) \ HB_STMT_START { \ - if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \ - HB_SHAPER_DATA (shaper, shape_plan) = \ - HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \ - user_features, num_user_features, \ - coords, num_coords); \ - shape_plan->shaper_func = _hb_##shaper##_shape; \ - shape_plan->shaper_name = #shaper; \ - return; \ + if (face->data.shaper) \ + { \ + this->shaper_func = _hb_##shaper##_shape; \ + this->shaper_name = #shaper; \ + return true; \ } \ } HB_STMT_END - if (likely (!shaper_list)) { - for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++) - if (0) + if (unlikely (shaper_list)) + { + for (; *shaper_list; shaper_list++) + if (false) ; #define HB_SHAPER_IMPLEMENT(shaper) \ - else if (shapers[i].func == _hb_##shaper##_shape) \ + else if (0 == strcmp (*shaper_list, #shaper)) \ HB_SHAPER_PLAN (shaper); #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT - } else { - for (; *shaper_list; shaper_list++) - if (0) + } + else + { + const hb_shaper_entry_t *shapers = _hb_shapers_get (); + for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++) + if (false) ; #define HB_SHAPER_IMPLEMENT(shaper) \ - else if (0 == strcmp (*shaper_list, #shaper)) \ + else if (shapers[i].func == _hb_##shaper##_shape) \ HB_SHAPER_PLAN (shaper); #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT } - #undef HB_SHAPER_PLAN + +bail: + ::free (features); + return false; +} + +bool +hb_shape_plan_key_t::user_features_match (const hb_shape_plan_key_t *other) +{ + if (this->num_user_features != other->num_user_features) + return false; + for (unsigned int i = 0; i < num_user_features; i++) + { + if (this->user_features[i].tag != other->user_features[i].tag || + this->user_features[i].value != other->user_features[i].value || + (this->user_features[i].start == HB_FEATURE_GLOBAL_START && + this->user_features[i].end == HB_FEATURE_GLOBAL_END) != + (other->user_features[i].start == HB_FEATURE_GLOBAL_START && + other->user_features[i].end == HB_FEATURE_GLOBAL_END)) + return false; + } + return true; +} + +bool +hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other) +{ + return hb_segment_properties_equal (&this->props, &other->props) && + this->user_features_match (other) && + this->ot.equal (&other->ot) && + this->shaper_func == other->shaper_func; } @@ -89,6 +157,7 @@ * hb_shape_plan_t */ + /** * hb_shape_plan_create: (Xconstructor) * @face: @@ -121,7 +190,7 @@ const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features, - const int *orig_coords, + const int *coords, unsigned int num_coords, const char * const *shaper_list) { @@ -132,49 +201,40 @@ num_coords, shaper_list); + assert (props->direction != HB_DIRECTION_INVALID); + hb_shape_plan_t *shape_plan; - hb_feature_t *features = nullptr; - int *coords = nullptr; - if (unlikely (!face)) - face = hb_face_get_empty (); if (unlikely (!props)) - return hb_shape_plan_get_empty (); - if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t)))) - return hb_shape_plan_get_empty (); - if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int)))) - { - free (features); - return hb_shape_plan_get_empty (); - } + goto bail; if (!(shape_plan = hb_object_create ())) - { - free (coords); - free (features); - return hb_shape_plan_get_empty (); - } - - assert (props->direction != HB_DIRECTION_INVALID); + goto bail; + if (unlikely (!face)) + face = hb_face_get_empty (); hb_face_make_immutable (face); - shape_plan->default_shaper_list = !shaper_list; shape_plan->face_unsafe = face; - shape_plan->props = *props; - shape_plan->num_user_features = num_user_features; - shape_plan->user_features = features; - if (num_user_features) - memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); - shape_plan->num_coords = num_coords; - shape_plan->coords = coords; - if (num_coords) - memcpy (coords, orig_coords, num_coords * sizeof (int)); - - hb_shape_plan_plan (shape_plan, - user_features, num_user_features, - coords, num_coords, - shaper_list); + + if (unlikely (!shape_plan->key.init (true, + face, + props, + user_features, + num_user_features, + coords, + num_coords, + shaper_list))) + goto bail2; + if (unlikely (!shape_plan->ot.init0 (face, &shape_plan->key))) + goto bail3; return shape_plan; + +bail3: + shape_plan->key.free (); +bail2: + free (shape_plan); +bail: + return hb_shape_plan_get_empty (); } /** @@ -187,32 +247,9 @@ * Since: 0.9.7 **/ hb_shape_plan_t * -hb_shape_plan_get_empty (void) +hb_shape_plan_get_empty () { - static const hb_shape_plan_t _hb_shape_plan_nil = { - HB_OBJECT_HEADER_STATIC, - - true, /* default_shaper_list */ - nullptr, /* face */ - HB_SEGMENT_PROPERTIES_DEFAULT, /* props */ - - nullptr, /* shaper_func */ - nullptr, /* shaper_name */ - - nullptr, /* user_features */ - 0, /* num_user_featurs */ - - nullptr, /* coords */ - 0, /* num_coords */ - - { -#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - } - }; - - return const_cast (&_hb_shape_plan_nil); + return const_cast (&Null(hb_shape_plan_t)); } /** @@ -244,13 +281,8 @@ { if (!hb_object_destroy (shape_plan)) return; -#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, shape_plan); -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - - free (shape_plan->user_features); - free (shape_plan->coords); - + shape_plan->ot.fini (); + shape_plan->key.free (); free (shape_plan); } @@ -296,6 +328,22 @@ return hb_object_get_user_data (shape_plan, key); } +/** + * hb_shape_plan_get_shaper: + * @shape_plan: a shape plan. + * + * + * + * Return value: (transfer none): + * + * Since: 0.9.7 + **/ +const char * +hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan) +{ + return shape_plan->key.shaper_name; +} + /** * hb_shape_plan_execute: @@ -321,32 +369,31 @@ DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, "num_features=%d shaper_func=%p, shaper_name=%s", num_features, - shape_plan->shaper_func, - shape_plan->shaper_name); + shape_plan->key.shaper_func, + shape_plan->key.shaper_name); if (unlikely (!buffer->len)) return true; - assert (!hb_object_is_inert (buffer)); + assert (!hb_object_is_immutable (buffer)); assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE); if (unlikely (hb_object_is_inert (shape_plan))) return false; assert (shape_plan->face_unsafe == font->face); - assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props)); + assert (hb_segment_properties_equal (&shape_plan->key.props, &buffer->props)); #define HB_SHAPER_EXECUTE(shaper) \ HB_STMT_START { \ - return HB_SHAPER_DATA (shaper, shape_plan) && \ - hb_##shaper##_shaper_font_data_ensure (font) && \ + return font->data.shaper && \ _hb_##shaper##_shape (shape_plan, font, buffer, features, num_features); \ } HB_STMT_END - if (0) + if (false) ; #define HB_SHAPER_IMPLEMENT(shaper) \ - else if (shape_plan->shaper_func == _hb_##shaper##_shape) \ + else if (shape_plan->key.shaper_func == _hb_##shaper##_shape) \ HB_SHAPER_EXECUTE (shaper); #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT @@ -358,92 +405,9 @@ /* - * caching + * Caching */ -#if 0 -static unsigned int -hb_shape_plan_hash (const hb_shape_plan_t *shape_plan) -{ - return hb_segment_properties_hash (&shape_plan->props) + - shape_plan->default_shaper_list ? 0 : (intptr_t) shape_plan->shaper_func; -} -#endif - -/* User-feature caching is currently somewhat dumb: - * it only finds matches where the feature array is identical, - * not cases where the feature lists would be compatible for plan purposes - * but have different ranges, for example. - */ -struct hb_shape_plan_proposal_t -{ - const hb_segment_properties_t props; - const char * const *shaper_list; - const hb_feature_t *user_features; - unsigned int num_user_features; - const int *coords; - unsigned int num_coords; - hb_shape_func_t *shaper_func; -}; - -static inline hb_bool_t -hb_shape_plan_user_features_match (const hb_shape_plan_t *shape_plan, - const hb_shape_plan_proposal_t *proposal) -{ - if (proposal->num_user_features != shape_plan->num_user_features) - return false; - for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++) - if (proposal->user_features[i].tag != shape_plan->user_features[i].tag || - proposal->user_features[i].value != shape_plan->user_features[i].value || - proposal->user_features[i].start != shape_plan->user_features[i].start || - proposal->user_features[i].end != shape_plan->user_features[i].end) - return false; - return true; -} - -static inline hb_bool_t -hb_shape_plan_coords_match (const hb_shape_plan_t *shape_plan, - const hb_shape_plan_proposal_t *proposal) -{ - if (proposal->num_coords != shape_plan->num_coords) - return false; - for (unsigned int i = 0, n = proposal->num_coords; i < n; i++) - if (proposal->coords[i] != shape_plan->coords[i]) - return false; - return true; -} - -static hb_bool_t -hb_shape_plan_matches (const hb_shape_plan_t *shape_plan, - const hb_shape_plan_proposal_t *proposal) -{ - return hb_segment_properties_equal (&shape_plan->props, &proposal->props) && - hb_shape_plan_user_features_match (shape_plan, proposal) && - hb_shape_plan_coords_match (shape_plan, proposal) && - ((shape_plan->default_shaper_list && !proposal->shaper_list) || - (shape_plan->shaper_func == proposal->shaper_func)); -} - -static inline hb_bool_t -hb_non_global_user_features_present (const hb_feature_t *user_features, - unsigned int num_user_features) -{ - while (num_user_features) { - if (user_features->start != 0 || user_features->end != (unsigned int) -1) - return true; - num_user_features--; - user_features++; - } - return false; -} - -static inline hb_bool_t -hb_coords_present (const int *coords, - unsigned int num_coords) -{ - return num_coords != 0; -} - /** * hb_shape_plan_create_cached: * @face: @@ -486,62 +450,38 @@ num_user_features, shaper_list); - hb_shape_plan_proposal_t proposal = { - *props, - shaper_list, - user_features, - num_user_features, - nullptr - }; - - if (shaper_list) { - /* Choose shaper. Adapted from hb_shape_plan_plan(). - * Must choose shaper exactly the same way as that function. */ - for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++) - if (0) - ; -#define HB_SHAPER_IMPLEMENT(shaper) \ - else if (0 == strcmp (*shaper_item, #shaper) && \ - hb_##shaper##_shaper_face_data_ensure (face)) \ - { \ - proposal.shaper_func = _hb_##shaper##_shape; \ - break; \ - } -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - - if (unlikely (!proposal.shaper_func)) - return hb_shape_plan_get_empty (); - } +retry: + hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans; + bool dont_cache = hb_object_is_inert (face); -retry: - hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans); + if (likely (!dont_cache)) + { + hb_shape_plan_key_t key; + if (!key.init (false, + face, + props, + user_features, + num_user_features, + coords, + num_coords, + shaper_list)) + return hb_shape_plan_get_empty (); - /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */ - if (!hb_coords_present (coords, num_coords)) for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next) - if (hb_shape_plan_matches (node->shape_plan, &proposal)) + if (node->shape_plan->key.equal (&key)) { DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache"); return hb_shape_plan_reference (node->shape_plan); } + } - /* Not found. */ hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props, user_features, num_user_features, coords, num_coords, shaper_list); - /* Don't add to the cache if face is inert. */ - if (unlikely (hb_object_is_inert (face))) - return shape_plan; - - /* Don't add the plan to the cache if there were user features with non-global ranges */ - if (hb_non_global_user_features_present (user_features, num_user_features)) - return shape_plan; - /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */ - if (hb_coords_present (coords, num_coords)) + if (unlikely (dont_cache)) return shape_plan; hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t)); @@ -551,7 +491,8 @@ node->shape_plan = shape_plan; node->next = cached_plan_nodes; - if (!hb_atomic_ptr_cmpexch (&face->shape_plans, cached_plan_nodes, node)) { + if (unlikely (!face->shape_plans.cmpexch (cached_plan_nodes, node))) + { hb_shape_plan_destroy (shape_plan); free (node); goto retry; @@ -560,19 +501,3 @@ return hb_shape_plan_reference (shape_plan); } - -/** - * hb_shape_plan_get_shaper: - * @shape_plan: a shape plan. - * - * - * - * Return value: (transfer none): - * - * Since: 0.9.7 - **/ -const char * -hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan) -{ - return shape_plan->shaper_name; -} --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape.cc 2019-02-28 12:04:11.854502748 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape.cc 2019-02-28 12:04:11.734502750 -0800 @@ -26,40 +26,70 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-private.hh" +#include "hb.hh" + +#include "hb-shaper.hh" +#include "hb-shape-plan.hh" +#include "hb-buffer.hh" +#include "hb-font.hh" +#include "hb-machinery.hh" -#include "hb-shaper-private.hh" -#include "hb-shape-plan-private.hh" -#include "hb-buffer-private.hh" -#include "hb-font-private.hh" /** * SECTION:hb-shape - * @title: Shaping + * @title: hb-shape * @short_description: Conversion of text strings into positioned glyphs * @include: hb.h * * Shaping is the central operation of HarfBuzz. Shaping operates on buffers, * which are sequences of Unicode characters that use the same font and have - * the same text direction, script and language. After shaping the buffer + * the same text direction, script, and language. After shaping the buffer * contains the output glyphs and their positions. **/ -static const char **static_shaper_list; -#ifdef HB_USE_ATEXIT -static -void free_static_shaper_list (void) +#if HB_USE_ATEXIT +static void free_static_shaper_list (); +#endif + +static const char *nil_shaper_list[] = {nullptr}; + +static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t { -retry: - const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list); - if (!hb_atomic_ptr_cmpexch (&static_shaper_list, shaper_list, nullptr)) - goto retry; + static const char ** create () + { + const char **shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *)); + if (unlikely (!shaper_list)) + return nullptr; + + const hb_shaper_entry_t *shapers = _hb_shapers_get (); + unsigned int i; + for (i = 0; i < HB_SHAPERS_COUNT; i++) + shaper_list[i] = shapers[i].name; + shaper_list[i] = nullptr; + +#if HB_USE_ATEXIT + atexit (free_static_shaper_list); +#endif + + return shaper_list; + } + static void destroy (const char **l) + { free (l); } + static const char ** get_null () + { return nil_shaper_list; } +} static_shaper_list; - free (shaper_list); +#if HB_USE_ATEXIT +static +void free_static_shaper_list () +{ + static_shaper_list.free_instance (); } #endif + /** * hb_shape_list_shapers: * @@ -71,37 +101,9 @@ * Since: 0.9.2 **/ const char ** -hb_shape_list_shapers (void) +hb_shape_list_shapers () { -retry: - const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list); - - if (unlikely (!shaper_list)) - { - /* Not found; allocate one. */ - shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *)); - if (unlikely (!shaper_list)) { - static const char *nil_shaper_list[] = {nullptr}; - return nil_shaper_list; - } - - const hb_shaper_pair_t *shapers = _hb_shapers_get (); - unsigned int i; - for (i = 0; i < HB_SHAPERS_COUNT; i++) - shaper_list[i] = shapers[i].name; - shaper_list[i] = nullptr; - - if (!hb_atomic_ptr_cmpexch (&static_shaper_list, nullptr, shaper_list)) { - free (shaper_list); - goto retry; - } - -#ifdef HB_USE_ATEXIT - atexit (free_static_shaper_list); /* First person registers atexit() callback. */ -#endif - } - - return shaper_list; + return static_shaper_list.get_unconst (); } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-list.hh 2019-02-28 12:04:12.210502742 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-list.hh 2019-02-28 12:04:12.106502744 -0800 @@ -34,14 +34,8 @@ /* Only picks up fonts that have a "Silf" table. */ HB_SHAPER_IMPLEMENT (graphite2) #endif -#ifdef HAVE_CORETEXT -/* Only picks up fonts that have a "mort" or "morx" table. */ -HB_SHAPER_IMPLEMENT (coretext_aat) -#endif -#ifdef HAVE_OT HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */ -#endif #ifdef HAVE_UNISCRIBE HB_SHAPER_IMPLEMENT (uniscribe) @@ -51,6 +45,10 @@ #endif #ifdef HAVE_CORETEXT HB_SHAPER_IMPLEMENT (coretext) + +/* Only picks up fonts that have a "mort" or "morx" table. + Probably going to be removed https://github.com/harfbuzz/harfbuzz/issues/1478 */ +HB_SHAPER_IMPLEMENT (coretext_aat) #endif #ifdef HAVE_FALLBACK --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper.cc 2019-02-28 12:04:12.522502737 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper.cc 2019-02-28 12:04:12.422502738 -0800 @@ -24,63 +24,41 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-private.hh" -#include "hb-shaper-private.hh" -#include "hb-atomic-private.hh" +#include "hb.hh" +#include "hb-shaper.hh" +#include "hb-machinery.hh" -static const hb_shaper_pair_t all_shapers[] = { +static const hb_shaper_entry_t all_shapers[] = { #define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape}, #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT }; - -/* Thread-safe, lock-free, shapers */ - -static const hb_shaper_pair_t *static_shapers; - -#ifdef HB_USE_ATEXIT -static -void free_static_shapers (void) -{ -retry: - hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers); - if (!hb_atomic_ptr_cmpexch (&static_shapers, shapers, nullptr)) - goto retry; - - if (unlikely (shapers != all_shapers)) - free ((void *) shapers); -} +#if HB_USE_ATEXIT +static void free_static_shapers (); #endif -const hb_shaper_pair_t * -_hb_shapers_get (void) +static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t { -retry: - hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers); - - if (unlikely (!shapers)) + static hb_shaper_entry_t *create () { char *env = getenv ("HB_SHAPER_LIST"); - if (!env || !*env) { - (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]); - return (const hb_shaper_pair_t *) all_shapers; - } + if (!env || !*env) + return nullptr; - /* Not found; allocate one. */ - shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers)); - if (unlikely (!shapers)) { - (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]); - return (const hb_shaper_pair_t *) all_shapers; - } + hb_shaper_entry_t *shapers = (hb_shaper_entry_t *) calloc (1, sizeof (all_shapers)); + if (unlikely (!shapers)) + return nullptr; memcpy (shapers, all_shapers, sizeof (all_shapers)); /* Reorder shaper list to prefer requested shapers. */ unsigned int i = 0; char *end, *p = env; - for (;;) { + for (;;) + { end = strchr (p, ','); if (!end) end = p + strlen (p); @@ -90,7 +68,7 @@ 0 == strncmp (shapers[j].name, p, end - p)) { /* Reorder this shaper to position i */ - struct hb_shaper_pair_t t = shapers[j]; + struct hb_shaper_entry_t t = shapers[j]; memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i)); shapers[i] = t; i++; @@ -102,15 +80,26 @@ p = end + 1; } - if (!hb_atomic_ptr_cmpexch (&static_shapers, nullptr, shapers)) { - free (shapers); - goto retry; - } - -#ifdef HB_USE_ATEXIT - atexit (free_static_shapers); /* First person registers atexit() callback. */ +#if HB_USE_ATEXIT + atexit (free_static_shapers); #endif + + return shapers; } + static void destroy (const hb_shaper_entry_t *p) { free ((void *) p); } + static const hb_shaper_entry_t *get_null () { return all_shapers; } +} static_shapers; - return shapers; +#if HB_USE_ATEXIT +static +void free_static_shapers () +{ + static_shapers.free_instance (); +} +#endif + +const hb_shaper_entry_t * +_hb_shapers_get () +{ + return static_shapers.get_unconst (); } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-static.cc 2019-02-28 12:04:12.854502731 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-static.cc 2019-02-28 12:04:12.754502733 -0800 @@ -24,9 +24,52 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-private.hh" +#include "hb.hh" + +#include "hb-open-type.hh" +#include "hb-face.hh" + +#include "hb-aat-layout-common.hh" +#include "hb-aat-layout-feat-table.hh" +#include "hb-ot-layout-common.hh" +#include "hb-ot-cmap-table.hh" +#include "hb-ot-head-table.hh" +#include "hb-ot-maxp-table.hh" #ifndef HB_NO_VISIBILITY -void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; -/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; + +hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {}; +/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {}; + +DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF}; +DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00}; +DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00}; +DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}; +DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF}; +/* Hand-coded because Lookup is a template. Sad. */ +const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF}; + + +unsigned int +hb_face_t::load_num_glyphs () const +{ + hb_sanitize_context_t c = hb_sanitize_context_t (); + c.set_num_glyphs (0); /* So we don't recurse ad infinitum. */ + hb_blob_t *maxp_blob = c.reference_table (this); + const OT::maxp *maxp_table = maxp_blob->as (); + + unsigned int ret = maxp_table->get_num_glyphs (); + num_glyphs.set_relaxed (ret); + hb_blob_destroy (maxp_blob); + return ret; +} + +unsigned int +hb_face_t::load_upem () const +{ + unsigned int ret = table.head->get_upem (); + upem.set_relaxed (ret); + return ret; +} + #endif --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-string-array.hh 2019-02-28 12:04:13.206502726 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-string-array.hh 2019-02-28 12:04:13.106502727 -0800 @@ -29,7 +29,7 @@ #define HB_STRING_ARRAY_HH #endif -#include "hb-private.hh" +#include "hb.hh" /* Based on Bruno Haible's code in Appendix B of Ulrich Drepper's dsohowto.pdf: * https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-glyf.hh 2019-02-28 12:04:13.530502720 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-glyf.hh 2019-02-28 12:04:13.422502722 -0800 @@ -27,14 +27,14 @@ #ifndef HB_SUBSET_GLYF_HH #define HB_SUBSET_GLYF_HH -#include "hb-private.hh" +#include "hb.hh" -#include "hb-subset-plan.hh" +#include "hb-subset.hh" HB_INTERNAL bool hb_subset_glyf_and_loca (hb_subset_plan_t *plan, bool *use_short_loca, /* OUT */ - hb_blob_t **glyf_prime /* OUT */, - hb_blob_t **loca_prime /* OUT */); + hb_blob_t **glyf_prime /* OUT */, + hb_blob_t **loca_prime /* OUT */); #endif /* HB_SUBSET_GLYF_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-plan.hh 2019-02-28 12:04:13.894502714 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-plan.hh 2019-02-28 12:04:13.786502716 -0800 @@ -27,28 +27,26 @@ #ifndef HB_SUBSET_PLAN_HH #define HB_SUBSET_PLAN_HH -#include "hb-private.hh" +#include "hb.hh" #include "hb-subset.h" -#include "hb-subset-private.hh" +#include "hb-subset-input.hh" -#include "hb-object-private.hh" -#include "hb-map-private.hh" +#include "hb-map.hh" struct hb_subset_plan_t { hb_object_header_t header; - ASSERT_POD (); - hb_bool_t drop_hints; - hb_bool_t drop_ot_layout; + bool drop_hints : 1; + bool drop_layout : 1; + bool desubroutinize : 1; // For each cp that we'd like to retain maps to the corresponding gid. hb_set_t *unicodes; - // This list contains the complete set of glyphs to retain and may contain - // more glyphs then the lists above. hb_vector_t glyphs; + hb_set_t *glyphset; hb_map_t *codepoint_to_glyph; hb_map_t *glyph_map; @@ -57,9 +55,8 @@ hb_face_t *source; hb_face_t *dest; - inline hb_bool_t - new_gid_for_codepoint (hb_codepoint_t codepoint, - hb_codepoint_t *new_gid) const + bool new_gid_for_codepoint (hb_codepoint_t codepoint, + hb_codepoint_t *new_gid) const { hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint); if (old_gid == HB_MAP_VALUE_INVALID) @@ -68,9 +65,8 @@ return new_gid_for_old_gid (old_gid, new_gid); } - inline hb_bool_t - new_gid_for_old_gid (hb_codepoint_t old_gid, - hb_codepoint_t *new_gid) const + bool new_gid_for_old_gid (hb_codepoint_t old_gid, + hb_codepoint_t *new_gid) const { hb_codepoint_t gid = glyph_map->get (old_gid); if (gid == HB_MAP_VALUE_INVALID) @@ -80,7 +76,7 @@ return true; } - inline hb_bool_t + bool add_table (hb_tag_t tag, hb_blob_t *contents) { @@ -90,7 +86,7 @@ hb_blob_get_length (contents), hb_blob_get_length (source_blob)); hb_blob_destroy (source_blob); - return hb_subset_face_add_table(dest, tag, contents); + return hb_face_builder_add_table (dest, tag, contents); } }; @@ -98,7 +94,6 @@ HB_INTERNAL hb_subset_plan_t * hb_subset_plan_create (hb_face_t *face, - hb_subset_profile_t *profile, hb_subset_input_t *input); HB_INTERNAL void --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.h 2019-02-28 12:04:14.210502709 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.h 2019-02-28 12:04:14.110502711 -0800 @@ -32,20 +32,6 @@ HB_BEGIN_DECLS /* - * hb_subset_profile_t - * Things that change based on target environment, e.g. OS. - * Threadsafe for multiple concurrent subset operations. - */ - -typedef struct hb_subset_profile_t hb_subset_profile_t; - -HB_EXTERN hb_subset_profile_t * -hb_subset_profile_create (void); - -HB_EXTERN void -hb_subset_profile_destroy (hb_subset_profile_t *profile); - -/* * hb_subset_input_t * * Things that change based on the input. Characters to keep, etc. @@ -68,21 +54,28 @@ HB_EXTERN hb_set_t * hb_subset_input_glyph_set (hb_subset_input_t *subset_input); -HB_EXTERN hb_bool_t * -hb_subset_input_drop_hints (hb_subset_input_t *subset_input); +HB_EXTERN void +hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input, + hb_bool_t drop_hints); +HB_EXTERN hb_bool_t +hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input); + +HB_EXTERN void +hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input, + hb_bool_t drop_layout); +HB_EXTERN hb_bool_t +hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input); -HB_EXTERN hb_bool_t * -hb_subset_input_drop_ot_layout (hb_subset_input_t *subset_input); +HB_EXTERN void +hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input, + hb_bool_t desubroutinize); +HB_EXTERN hb_bool_t +hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input); -/* hb_subset() */ +/* hb_subset () */ HB_EXTERN hb_face_t * -hb_subset (hb_face_t *source, - hb_subset_profile_t *profile, - hb_subset_input_t *input); +hb_subset (hb_face_t *source, hb_subset_input_t *input); -/* hb_subset_get_all_codepoints */ -HB_EXTERN void -hb_subset_get_all_codepoints (hb_face_t *source, hb_set_t *out); HB_END_DECLS --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn.cc 2019-02-28 12:04:14.526502704 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn.cc 2019-02-28 12:04:14.422502705 -0800 @@ -14,9 +14,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "hb-private.hh" +#include "hb.hh" -#include "hb-unicode-private.hh" +#include "hb-machinery.hh" #include "ucdn.h" @@ -181,15 +181,6 @@ return (hb_unicode_combining_class_t) ucdn_get_combining_class(unicode); } -static unsigned int -hb_ucdn_eastasian_width(hb_unicode_funcs_t *ufuncs HB_UNUSED, - hb_codepoint_t unicode, - void *user_data HB_UNUSED) -{ - int w = ucdn_get_east_asian_width(unicode); - return (w == UCDN_EAST_ASIAN_F || w == UCDN_EAST_ASIAN_W) ? 2 : 1; -} - static hb_unicode_general_category_t hb_ucdn_general_category(hb_unicode_funcs_t *ufuncs HB_UNUSED, hb_codepoint_t unicode, @@ -230,56 +221,48 @@ return ucdn_decompose(ab, a, b); } -static unsigned int -hb_ucdn_decompose_compatibility(hb_unicode_funcs_t *ufuncs HB_UNUSED, - hb_codepoint_t u, hb_codepoint_t *decomposed, - void *user_data HB_UNUSED) -{ - return ucdn_compat_decompose(u, decomposed); -} -static hb_unicode_funcs_t *static_ucdn_funcs = nullptr; - -#ifdef HB_USE_ATEXIT -static -void free_static_ucdn_funcs (void) -{ -retry: - hb_unicode_funcs_t *ucdn_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs); - if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, ucdn_funcs, nullptr)) - goto retry; - - hb_unicode_funcs_destroy (ucdn_funcs); -} +#if HB_USE_ATEXIT +static void free_static_ucdn_funcs (); #endif -extern "C" HB_INTERNAL -hb_unicode_funcs_t * -hb_ucdn_get_unicode_funcs (void) +static struct hb_ucdn_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t { -retry: - hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs); - - if (unlikely (!funcs)) + static hb_unicode_funcs_t *create () { - funcs = hb_unicode_funcs_create (nullptr); + hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr); -#define HB_UNICODE_FUNC_IMPLEMENT(name) \ - hb_unicode_funcs_set_##name##_func (funcs, hb_ucdn_##name, nullptr, nullptr); - HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_UNICODE_FUNC_IMPLEMENT + hb_unicode_funcs_set_combining_class_func (funcs, hb_ucdn_combining_class, nullptr, nullptr); + hb_unicode_funcs_set_general_category_func (funcs, hb_ucdn_general_category, nullptr, nullptr); + hb_unicode_funcs_set_mirroring_func (funcs, hb_ucdn_mirroring, nullptr, nullptr); + hb_unicode_funcs_set_script_func (funcs, hb_ucdn_script, nullptr, nullptr); + hb_unicode_funcs_set_compose_func (funcs, hb_ucdn_compose, nullptr, nullptr); + hb_unicode_funcs_set_decompose_func (funcs, hb_ucdn_decompose, nullptr, nullptr); hb_unicode_funcs_make_immutable (funcs); - if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, nullptr, funcs)) { - hb_unicode_funcs_destroy (funcs); - goto retry; - } +#if HB_USE_ATEXIT + atexit (free_static_ucdn_funcs); +#endif + + return funcs; + } +} static_ucdn_funcs; -#ifdef HB_USE_ATEXIT - atexit (free_static_ucdn_funcs); /* First person registers atexit() callback. */ +#if HB_USE_ATEXIT +static +void free_static_ucdn_funcs () +{ + static_ucdn_funcs.free_instance (); +} #endif - }; - return hb_unicode_funcs_reference (funcs); +extern "C" HB_INTERNAL +hb_unicode_funcs_t * +hb_ucdn_get_unicode_funcs (); + +hb_unicode_funcs_t * +hb_ucdn_get_unicode_funcs () +{ + return static_ucdn_funcs.get_unconst (); } --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn/ucdn.h 2019-02-28 12:04:14.862502698 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn/ucdn.h 2019-02-28 12:04:14.758502700 -0800 @@ -456,8 +456,6 @@ */ int ucdn_compose(uint32_t *code, uint32_t a, uint32_t b); -#ifdef __cplusplus -} -#endif +HB_END_HEADER #endif --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.cc 2019-02-28 12:04:15.178502693 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.cc 2019-02-28 12:04:15.074502695 -0800 @@ -28,11 +28,25 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-private.hh" +#include "hb.hh" -#include "hb-unicode-private.hh" +#include "hb-unicode.hh" +/** + * SECTION: hb-unicode + * @title: hb-unicode + * @short_description: Unicode character property access + * @include: hb.h + * + * Unicode functions are used to access Unicode character properties. + * Client can pass its own Unicode functions to HarfBuzz, or access + * the built-in Unicode functions that come with HarfBuzz. + * + * With the Unicode functions, one can query variour Unicode character + * properties, such as General Category, Script, Combining Class, etc. + **/ + /* * hb_unicode_funcs_t @@ -109,40 +123,23 @@ } -#define HB_UNICODE_FUNCS_IMPLEMENT_SET \ - HB_UNICODE_FUNCS_IMPLEMENT (glib) \ - HB_UNICODE_FUNCS_IMPLEMENT (icu) \ - HB_UNICODE_FUNCS_IMPLEMENT (ucdn) \ - HB_UNICODE_FUNCS_IMPLEMENT (nil) \ - /* ^--- Add new callbacks before nil */ - -#define hb_nil_get_unicode_funcs hb_unicode_funcs_get_empty - -/* Prototype them all */ -#define HB_UNICODE_FUNCS_IMPLEMENT(set) \ -extern "C" hb_unicode_funcs_t *hb_##set##_get_unicode_funcs (void); -HB_UNICODE_FUNCS_IMPLEMENT_SET -#undef HB_UNICODE_FUNCS_IMPLEMENT - +extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs (); +extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs (); +extern "C" hb_unicode_funcs_t *hb_ucdn_get_unicode_funcs (); hb_unicode_funcs_t * -hb_unicode_funcs_get_default (void) +hb_unicode_funcs_get_default () { -#define HB_UNICODE_FUNCS_IMPLEMENT(set) \ - return hb_##set##_get_unicode_funcs (); - #if defined(HAVE_UCDN) - HB_UNICODE_FUNCS_IMPLEMENT(ucdn) + return hb_ucdn_get_unicode_funcs (); #elif defined(HAVE_GLIB) - HB_UNICODE_FUNCS_IMPLEMENT(glib) + return hb_glib_get_unicode_funcs (); #elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN) - HB_UNICODE_FUNCS_IMPLEMENT(icu) + return hb_icu_get_unicode_funcs (); #else #define HB_UNICODE_FUNCS_NIL 1 - HB_UNICODE_FUNCS_IMPLEMENT(nil) + return hb_unicode_funcs_get_empty (); #endif - -#undef HB_UNICODE_FUNCS_IMPLEMENT } #if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL) @@ -185,11 +182,11 @@ } -const hb_unicode_funcs_t _hb_unicode_funcs_nil = { +DEFINE_NULL_INSTANCE (hb_unicode_funcs_t) = +{ HB_OBJECT_HEADER_STATIC, nullptr, /* parent */ - true, /* immutable */ { #define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_nil, HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS @@ -207,9 +204,9 @@ * Since: 0.9.2 **/ hb_unicode_funcs_t * -hb_unicode_funcs_get_empty (void) +hb_unicode_funcs_get_empty () { - return const_cast (&_hb_unicode_funcs_nil); + return const_cast (&Null(hb_unicode_funcs_t)); } /** @@ -305,10 +302,10 @@ void hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs) { - if (unlikely (hb_object_is_inert (ufuncs))) + if (hb_object_is_immutable (ufuncs)) return; - ufuncs->immutable = true; + hb_object_make_immutable (ufuncs); } /** @@ -324,7 +321,7 @@ hb_bool_t hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs) { - return ufuncs->immutable; + return hb_object_is_immutable (ufuncs); } /** @@ -352,7 +349,7 @@ void *user_data, \ hb_destroy_func_t destroy) \ { \ - if (ufuncs->immutable) \ + if (hb_object_is_immutable (ufuncs)) \ return; \ \ if (ufuncs->destroy.name) \ @@ -439,6 +436,7 @@ * Return value: * * Since: 0.9.2 + * Deprecated: 2.0.0 **/ unsigned int hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, @@ -449,7 +447,7 @@ } -/* See hb-unicode-private.hh for details. */ +/* See hb-unicode.hh for details. */ const uint8_t _hb_modified_combining_class[256] = { @@ -561,3 +559,19 @@ 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, /* HB_UNICODE_COMBINING_CLASS_INVALID */ }; + + +/* + * Emoji + */ + +#include "hb-unicode-emoji-table.hh" + +bool +_hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp) +{ + return hb_bsearch (&cp, _hb_unicode_emoji_Extended_Pictographic_table, + ARRAY_LENGTH (_hb_unicode_emoji_Extended_Pictographic_table), + sizeof (hb_unicode_range_t), + hb_unicode_range_t::cmp); +} --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.h 2019-02-28 12:04:15.510502688 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.h 2019-02-28 12:04:15.406502689 -0800 @@ -40,6 +40,14 @@ HB_BEGIN_DECLS +/** + * HB_UNICODE_MAX + * + * Since: 1.9.0 + **/ +#define HB_UNICODE_MAX 0x10FFFFu + + /* hb_unicode_general_category_t */ /* Unicode Character Database property: General_Category (gc) */ @@ -222,9 +230,6 @@ typedef hb_unicode_combining_class_t (*hb_unicode_combining_class_func_t) (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode, void *user_data); -typedef unsigned int (*hb_unicode_eastasian_width_func_t) (hb_unicode_funcs_t *ufuncs, - hb_codepoint_t unicode, - void *user_data); typedef hb_unicode_general_category_t (*hb_unicode_general_category_func_t) (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode, void *user_data); @@ -246,32 +251,6 @@ hb_codepoint_t *b, void *user_data); -/** - * hb_unicode_decompose_compatibility_func_t: - * @ufuncs: a Unicode function structure - * @u: codepoint to decompose - * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into - * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func() - * - * Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed. - * The complete length of the decomposition will be returned. - * - * If @u has no compatibility decomposition, zero should be returned. - * - * The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any - * compatibility decomposition plus an terminating value of 0. Consequently, @decompose must be allocated by the caller to be at least this length. Implementations - * of this function type must ensure that they do not write past the provided array. - * - * Return value: number of codepoints in the full compatibility decomposition of @u, or 0 if no decomposition available. - */ -typedef unsigned int (*hb_unicode_decompose_compatibility_func_t) (hb_unicode_funcs_t *ufuncs, - hb_codepoint_t u, - hb_codepoint_t *decomposed, - void *user_data); - -/* See Unicode 6.1 for details on the maximum decomposition length. */ -#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */ - /* setters */ /** @@ -291,22 +270,6 @@ void *user_data, hb_destroy_func_t destroy); /** - * hb_unicode_funcs_set_eastasian_width_func: - * @ufuncs: a Unicode function structure - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: - * - * - * - * Since: 0.9.2 - **/ -HB_EXTERN void -hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs, - hb_unicode_eastasian_width_func_t func, - void *user_data, hb_destroy_func_t destroy); - -/** * hb_unicode_funcs_set_general_category_func: * @ufuncs: a Unicode function structure * @func: (closure user_data) (destroy destroy) (scope notified): @@ -386,22 +349,6 @@ hb_unicode_decompose_func_t func, void *user_data, hb_destroy_func_t destroy); -/** - * hb_unicode_funcs_set_decompose_compatibility_func: - * @ufuncs: a Unicode function structure - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: - * - * - * - * Since: 0.9.2 - **/ -HB_EXTERN void -hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs, - hb_unicode_decompose_compatibility_func_t func, - void *user_data, hb_destroy_func_t destroy); - /* accessors */ /** @@ -414,15 +361,6 @@ hb_codepoint_t unicode); /** - * hb_unicode_eastasian_width: - * - * Since: 0.9.2 - **/ -HB_EXTERN unsigned int -hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs, - hb_codepoint_t unicode); - -/** * hb_unicode_general_category: * * Since: 0.9.2 @@ -461,11 +399,6 @@ hb_codepoint_t *a, hb_codepoint_t *b); -HB_EXTERN unsigned int -hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, - hb_codepoint_t u, - hb_codepoint_t *decomposed); - HB_END_DECLS #endif /* HB_UNICODE_H */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-version.h 2019-02-28 12:04:15.906502681 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-version.h 2019-02-28 12:04:15.786502683 -0800 @@ -36,11 +36,11 @@ HB_BEGIN_DECLS -#define HB_VERSION_MAJOR 1 -#define HB_VERSION_MINOR 8 -#define HB_VERSION_MICRO 2 +#define HB_VERSION_MAJOR 2 +#define HB_VERSION_MINOR 3 +#define HB_VERSION_MICRO 1 -#define HB_VERSION_STRING "1.8.2" +#define HB_VERSION_STRING "2.3.1" #define HB_VERSION_ATLEAST(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) <= \ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-warning.cc 2019-02-28 12:04:16.290502675 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-warning.cc 2019-02-28 12:04:16.186502676 -0800 @@ -24,16 +24,14 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-atomic-private.hh" -#include "hb-mutex-private.hh" - +#include "hb.hh" #if defined(HB_ATOMIC_INT_NIL) #error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe" -#error "Check hb-atomic-private.hh for possible resolutions." +#error "Check hb-atomic.hh for possible resolutions." #endif #if defined(HB_MUTEX_IMPL_NIL) #error "Could not find any system to define mutex macros, library WILL NOT be thread-safe" -#error "Check hb-mutex-private.hh for possible resolutions." +#error "Check hb-mutex.hh for possible resolutions." #endif --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb.h 2019-02-28 12:04:16.614502669 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb.h 2019-02-28 12:04:16.506502671 -0800 @@ -28,10 +28,6 @@ #define HB_H #define HB_H_IN -#ifndef HB_EXTERN -#define HB_EXTERN extern -#endif - #include "hb-blob.h" #include "hb-buffer.h" #include "hb-common.h" --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic-private.hh 2019-02-28 12:04:17.010502663 -0800 +++ /dev/null 2019-02-21 13:14:21.200397537 -0800 @@ -1,182 +0,0 @@ -/* - * 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 defined(hb_atomic_int_impl_add) \ - && defined(hb_atomic_ptr_impl_get) \ - && defined(hb_atomic_ptr_impl_cmpexch) - -/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */ - - -#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) - -#include - -/* MinGW has a convoluted history of supporting MemoryBarrier - * properly. As such, define a function to wrap the whole - * thing. */ -static inline void _HBMemoryBarrier (void) { -#if !defined(MemoryBarrier) - long dummy = 0; - InterlockedExchange (&dummy, 1); -#else - MemoryBarrier (); -#endif -} - -typedef LONG hb_atomic_int_impl_t; -#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd (&(AI), (V)) - -#define hb_atomic_ptr_impl_get(P) (_HBMemoryBarrier (), (void *) *(P)) -#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O)) - - -#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) - -typedef int hb_atomic_int_impl_t; -#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add (&(AI), (V)) - -#define hb_atomic_ptr_impl_get(P) (void *) (__sync_synchronize (), *(P)) -#define hb_atomic_ptr_impl_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_impl_t; -#define hb_atomic_int_impl_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V)) - -#define hb_atomic_ptr_impl_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P)) -#define hb_atomic_ptr_impl_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) && defined(__APPLE__) - -#include -#ifdef __MAC_OS_X_MIN_REQUIRED -#include -#elif defined(__IPHONE_OS_MIN_REQUIRED) -#include -#endif - - -typedef int32_t hb_atomic_int_impl_t; -#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V)) - -#define hb_atomic_ptr_impl_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_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P)) -#else -#if __ppc64__ || __x86_64__ || __aarch64__ -#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (void *) (O), (int64_t) (void *) (N), (int64_t*) (P)) -#else -#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (void *) (O), (int32_t) (void *) (N), (int32_t*) (P)) -#endif -#endif - - -#elif !defined(HB_NO_MT) && defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__)) - -#include - - -static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) { - __lwsync(); - int result = __fetch_and_add(AI, V); - __isync(); - return result; -} -static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) { - __sync(); - int result = __compare_and_swaplp (P, &O, N); - __sync(); - return result; -} - -typedef int hb_atomic_int_impl_t; -#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add (&(AI), (V)) - -#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P)) -#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N)) - -#elif !defined(HB_NO_MT) - -#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ - -typedef volatile int hb_atomic_int_impl_t; -#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V)) - -#define hb_atomic_ptr_impl_get(P) ((void *) *(P)) -#define hb_atomic_ptr_impl_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_impl_t; -#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V)) - -#define hb_atomic_ptr_impl_get(P) ((void *) *(P)) -#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) - - -#endif - - -#define HB_ATOMIC_INT_INIT(V) {V} - -struct hb_atomic_int_t -{ - hb_atomic_int_impl_t v; - - inline void set_unsafe (int v_) { v = v_; } - inline int get_unsafe (void) const { return v; } - inline int inc (void) { return hb_atomic_int_impl_add (const_cast (v), 1); } - inline int dec (void) { return hb_atomic_int_impl_add (const_cast (v), -1); } -}; - - -#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P) -#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N)) - - -#endif /* HB_ATOMIC_PRIVATE_HH */ --- /dev/null 2019-02-21 13:14:21.200397537 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic.hh 2019-02-28 12:04:16.854502665 -0800 @@ -0,0 +1,300 @@ +/* + * 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_HH +#define HB_ATOMIC_HH + +#include "hb.hh" + + +/* + * Atomic integers and pointers. + */ + + +/* We need external help for these */ + +#if defined(hb_atomic_int_impl_add) \ + && defined(hb_atomic_ptr_impl_get) \ + && defined(hb_atomic_ptr_impl_cmpexch) + +/* Defined externally, i.e. in config.h. */ + + +#elif !defined(HB_NO_MT) && defined(__ATOMIC_ACQUIRE) + +/* C++11-style GCC primitives. */ + +#define _hb_memory_barrier() __sync_synchronize () + +#define hb_atomic_int_impl_add(AI, V) __atomic_fetch_add ((AI), (V), __ATOMIC_ACQ_REL) +#define hb_atomic_int_impl_set_relaxed(AI, V) __atomic_store_n ((AI), (V), __ATOMIC_RELAXED) +#define hb_atomic_int_impl_set(AI, V) __atomic_store_n ((AI), (V), __ATOMIC_RELEASE) +#define hb_atomic_int_impl_get_relaxed(AI) __atomic_load_n ((AI), __ATOMIC_RELAXED) +#define hb_atomic_int_impl_get(AI) __atomic_load_n ((AI), __ATOMIC_ACQUIRE) + +#define hb_atomic_ptr_impl_set_relaxed(P, V) __atomic_store_n ((P), (V), __ATOMIC_RELAXED) +#define hb_atomic_ptr_impl_get_relaxed(P) __atomic_load_n ((P), __ATOMIC_RELAXED) +#define hb_atomic_ptr_impl_get(P) __atomic_load_n ((P), __ATOMIC_ACQUIRE) +static inline bool +_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N) +{ + const void *O = O_; // Need lvalue + return __atomic_compare_exchange_n ((void **) P, (void **) &O, (void *) N, true, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED); +} +#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N)) + +#elif !defined(HB_NO_MT) && __cplusplus >= 201103L + +/* C++11 atomics. */ + +#include + +#define _hb_memory_barrier() std::atomic_thread_fence(std::memory_order_ack_rel) +#define _hb_memory_r_barrier() std::atomic_thread_fence(std::memory_order_acquire) +#define _hb_memory_w_barrier() std::atomic_thread_fence(std::memory_order_release) + +#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast *> (AI)->fetch_add ((V), std::memory_order_acq_rel)) +#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast *> (AI)->store ((V), std::memory_order_relaxed)) +#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast *> (AI)->store ((V), std::memory_order_release)) +#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast *> (AI)->load (std::memory_order_relaxed)) +#define hb_atomic_int_impl_get(AI) (reinterpret_cast *> (AI)->load (std::memory_order_acquire)) + +#define hb_atomic_ptr_impl_set_relaxed(P, V) (reinterpret_cast *> (P)->store ((V), std::memory_order_relaxed)) +#define hb_atomic_ptr_impl_get_relaxed(P) (reinterpret_cast *> (P)->load (std::memory_order_relaxed)) +#define hb_atomic_ptr_impl_get(P) (reinterpret_cast *> (P)->load (std::memory_order_acquire)) +static inline bool +_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N) +{ + const void *O = O_; // Need lvalue + return reinterpret_cast *> (P)->compare_exchange_weak (O, N, std::memory_order_acq_rel, std::memory_order_relaxed); +} +#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N)) + + +#elif !defined(HB_NO_MT) && defined(_WIN32) + +#include + +static inline void _hb_memory_barrier () +{ +#if !defined(MemoryBarrier) + /* MinGW has a convoluted history of supporting MemoryBarrier. */ + LONG dummy = 0; + InterlockedExchange (&dummy, 1); +#else + MemoryBarrier (); +#endif +} +#define _hb_memory_barrier() _hb_memory_barrier () + +#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd ((LONG *) (AI), (V)) +static_assert ((sizeof (LONG) == sizeof (int)), ""); + +#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((P), (N), (O)) == (O)) + + +#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) + +#define _hb_memory_barrier() __sync_synchronize () + +#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add ((AI), (V)) + +#define hb_atomic_ptr_impl_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N)) + + +#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS) + +#include +#include + +#define _hb_memory_r_barrier() __machine_r_barrier () +#define _hb_memory_w_barrier() __machine_w_barrier () +#define _hb_memory_barrier() __machine_rw_barrier () + +static inline int _hb_fetch_and_add (int *AI, int V) +{ + _hb_memory_w_barrier (); + int result = atomic_add_int_nv ((uint_t *) AI, V) - V; + _hb_memory_r_barrier (); + return result; +} +static inline bool _hb_compare_and_swap_ptr (void **P, void *O, void *N) +{ + _hb_memory_w_barrier (); + bool result = atomic_cas_ptr (P, O, N) == O; + _hb_memory_r_barrier (); + return result; +} + +#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V)) + +#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swap_ptr ((P), (O), (N)) + + +#elif !defined(HB_NO_MT) && defined(__APPLE__) + +#include +#ifdef __MAC_OS_X_MIN_REQUIRED +#include +#elif defined(__IPHONE_OS_MIN_REQUIRED) +#include +#endif + +#define _hb_memory_barrier() OSMemoryBarrier () + +#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), (AI)) - (V)) + +#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((O), (N), (P)) +#else +#if __ppc64__ || __x86_64__ || __aarch64__ +#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P)) +#else +#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P)) +#endif +#endif + + +#elif !defined(HB_NO_MT) && defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__)) + +#include + +#define _hb_memory_barrier() __lwsync () + +static inline int _hb_fetch_and_add (int *AI, int V) +{ + _hb_memory_barrier (); + int result = __fetch_and_add (AI, V); + _hb_memory_barrier (); + return result; +} +static inline bool _hb_compare_and_swaplp (long *P, long O, long N) +{ + _hb_memory_barrier (); + bool result = __compare_and_swaplp (P, &O, N); + _hb_memory_barrier (); + return result; +} + +#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V)) + +#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N)) +static_assert ((sizeof (long) == sizeof (void *)), ""); + + +#elif !defined(HB_NO_MT) + +#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ + +#define _hb_memory_barrier() + +#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V)) + +#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) + + +#else /* HB_NO_MT */ + +#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V)) + +#define _hb_memory_barrier() + +#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) + + +#endif + + +#ifndef _hb_memory_r_barrier +#define _hb_memory_r_barrier() _hb_memory_barrier () +#endif +#ifndef _hb_memory_w_barrier +#define _hb_memory_w_barrier() _hb_memory_barrier () +#endif +#ifndef hb_atomic_int_impl_set_relaxed +#define hb_atomic_int_impl_set_relaxed(AI, V) (*(AI) = (V)) +#endif +#ifndef hb_atomic_int_impl_get_relaxed +#define hb_atomic_int_impl_get_relaxed(AI) (*(AI)) +#endif + +#ifndef hb_atomic_ptr_impl_set_relaxed +#define hb_atomic_ptr_impl_set_relaxed(P, V) (*(P) = (V)) +#endif +#ifndef hb_atomic_ptr_impl_get_relaxed +#define hb_atomic_ptr_impl_get_relaxed(P) (*(P)) +#endif +#ifndef hb_atomic_int_impl_set +inline void hb_atomic_int_impl_set (int *AI, int v) { _hb_memory_w_barrier (); *AI = v; } +#endif +#ifndef hb_atomic_int_impl_get +inline int hb_atomic_int_impl_get (const int *AI) { int v = *AI; _hb_memory_r_barrier (); return v; } +#endif +#ifndef hb_atomic_ptr_impl_get +inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory_r_barrier (); return v; } +#endif + + +#define HB_ATOMIC_INT_INIT(V) {V} +struct hb_atomic_int_t +{ + void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); } + void set (int v_) { hb_atomic_int_impl_set (&v, v_); } + int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); } + int get () const { return hb_atomic_int_impl_get (&v); } + int inc () { return hb_atomic_int_impl_add (&v, 1); } + int dec () { return hb_atomic_int_impl_add (&v, -1); } + + int v; +}; + + +#define HB_ATOMIC_PTR_INIT(V) {V} +template +struct hb_atomic_ptr_t +{ + typedef typename hb_remove_pointer (P) T; + + void init (T* v_ = nullptr) { set_relaxed (v_); } + void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); } + T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); } + T *get () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); } + bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); } + + T * operator -> () const { return get (); } + template operator C * () const { return get (); } + + T *v; +}; + + +#endif /* HB_ATOMIC_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob-private.hh 2019-02-28 12:04:17.386502657 -0800 +++ /dev/null 2019-02-21 13:14:21.200397537 -0800 @@ -1,88 +0,0 @@ -/* - * Copyright © 2009 Red Hat, Inc. - * Copyright © 2018 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_BLOB_PRIVATE_HH -#define HB_BLOB_PRIVATE_HH - -#include "hb-private.hh" - -#include "hb-object-private.hh" - - -/* - * hb_blob_t - */ - -struct hb_blob_t -{ - inline void fini_shallow (void) - { - destroy_user_data (); - } - - inline void destroy_user_data (void) - { - if (destroy) - { - destroy (user_data); - user_data = nullptr; - destroy = nullptr; - } - } - - HB_INTERNAL bool try_make_writable (void); - HB_INTERNAL bool try_make_writable_inplace (void); - HB_INTERNAL bool try_make_writable_inplace_unix (void); - - inline void lock (void) - { - hb_blob_make_immutable (this); - } - - template - inline const Type* as (void) const - { - return unlikely (!data) ? &Null(Type) : reinterpret_cast (data); - } - - public: - 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; -}; - - -#endif /* HB_BLOB_PRIVATE_HH */ --- /dev/null 2019-02-21 13:14:21.200397537 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.hh 2019-02-28 12:04:17.230502659 -0800 @@ -0,0 +1,101 @@ +/* + * Copyright © 2009 Red Hat, Inc. + * Copyright © 2018 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_BLOB_HH +#define HB_BLOB_HH + +#include "hb.hh" + + +/* + * hb_blob_t + */ + +struct hb_blob_t +{ + void fini_shallow () { destroy_user_data (); } + + void destroy_user_data () + { + if (destroy) + { + destroy (user_data); + user_data = nullptr; + destroy = nullptr; + } + } + + HB_INTERNAL bool try_make_writable (); + HB_INTERNAL bool try_make_writable_inplace (); + HB_INTERNAL bool try_make_writable_inplace_unix (); + + template + const Type* as () const + { + return length < hb_null_size (Type) ? &Null(Type) : reinterpret_cast (data); + } + hb_bytes_t as_bytes () const + { return hb_bytes_t (data, length); } + + public: + hb_object_header_t header; + + const char *data; + unsigned int length; + hb_memory_mode_t mode; + + void *user_data; + hb_destroy_func_t destroy; +}; + + +/* + * hb_blob_ptr_t + */ + +template +struct hb_blob_ptr_t +{ + typedef typename hb_remove_pointer (P) T; + + hb_blob_ptr_t (hb_blob_t *b_ = nullptr) : b (b_) {} + hb_blob_t * operator = (hb_blob_t *b_) { return b = b_; } + const T * operator -> () const { return get (); } + const T & operator * () const { return *get (); } + template operator const C * () const { return get (); } + operator const char * () const { return (const char *) get (); } + const T * get () const { return b->as (); } + hb_blob_t * get_blob () const { return b.get_raw (); } + unsigned int get_length () const { return b.get ()->length; } + void destroy () { hb_blob_destroy (b.get ()); b = nullptr; } + + hb_nonnull_ptr_t b; +}; + + +#endif /* HB_BLOB_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-private.hh 2019-02-28 12:04:17.770502650 -0800 +++ /dev/null 2019-02-21 13:14:21.200397537 -0800 @@ -1,388 +0,0 @@ -/* - * 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-object-private.hh" -#include "hb-unicode-private.hh" - - -#ifndef HB_BUFFER_MAX_LEN_FACTOR -#define HB_BUFFER_MAX_LEN_FACTOR 32 -#endif -#ifndef HB_BUFFER_MAX_LEN_MIN -#define HB_BUFFER_MAX_LEN_MIN 8192 -#endif -#ifndef HB_BUFFER_MAX_LEN_DEFAULT -#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */ -#endif - -#ifndef HB_BUFFER_MAX_OPS_FACTOR -#define HB_BUFFER_MAX_OPS_FACTOR 64 -#endif -#ifndef HB_BUFFER_MAX_OPS_MIN -#define HB_BUFFER_MAX_OPS_MIN 1024 -#endif -#ifndef HB_BUFFER_MAX_OPS_DEFAULT -#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */ -#endif - -static_assert ((sizeof (hb_glyph_info_t) == 20), ""); -static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), ""); - -HB_MARK_AS_FLAG_T (hb_buffer_flags_t); -HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t); -HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t); - -enum hb_buffer_scratch_flags_t { - HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u, - HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII = 0x00000001u, - HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u, - HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u, - HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u, - HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u, - HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000020u, - - /* Reserved for complex shapers' internal use. */ - HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u, - HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u, - HB_BUFFER_SCRATCH_FLAG_COMPLEX2 = 0x04000000u, - HB_BUFFER_SCRATCH_FLAG_COMPLEX3 = 0x08000000u, -}; -HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_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_buffer_flags_t flags; /* BOT / EOT / etc. */ - hb_buffer_cluster_level_t cluster_level; - hb_codepoint_t replacement; /* U+FFFD or something else. */ - hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ - unsigned int max_len; /* Maximum allowed len. */ - int max_ops; /* Maximum allowed operations. */ - - /* Buffer contents */ - hb_buffer_content_type_t content_type; - hb_segment_properties_t props; /* Script, language, direction */ - - bool successful; /* Allocations successful */ - 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; - - unsigned int serial; - - /* 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]; - - /* Debugging API */ - hb_buffer_message_func_t message_func; - void *message_data; - hb_destroy_func_t message_destroy; - - /* Internal debugging. */ - /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ -#ifndef HB_NDEBUG - uint8_t allocated_var_bits; -#endif - - - /* Methods */ - - inline void allocate_var (unsigned int start, unsigned int count) - { -#ifndef HB_NDEBUG - unsigned int end = start + count; - assert (end <= 8); - unsigned int bits = (1u< (cluster, infos[i].cluster); - return cluster; - } - inline void - _unsafe_to_break_set_mask (hb_glyph_info_t *infos, - unsigned int start, unsigned int end, - unsigned int cluster) - { - for (unsigned int i = start; i < end; i++) - if (cluster != infos[i].cluster) - { - scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK; - infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK; - } - } - - inline void - unsafe_to_break_all (void) - { - unsafe_to_break_impl (0, len); - } - inline void - safe_to_break_all (void) - { - for (unsigned int i = 0; i < len; i++) - info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK; - } -}; - - -/* Loop over clusters. Duplicated in foreach_syllable(). */ -#define foreach_cluster(buffer, start, end) \ - for (unsigned int \ - _count = buffer->len, \ - start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \ - start < _count; \ - start = end, end = _next_cluster (buffer, start)) - -static inline unsigned int -_next_cluster (hb_buffer_t *buffer, unsigned int start) -{ - hb_glyph_info_t *info = buffer->info; - unsigned int count = buffer->len; - - unsigned int cluster = info[start].cluster; - while (++start < count && cluster == info[start].cluster) - ; - - return start; -} - - -#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \ - b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \ - sizeof (b->info[0].var)) -#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ()) -#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ()) -#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ()) - - -#endif /* HB_BUFFER_PRIVATE_HH */ --- /dev/null 2019-02-21 13:14:21.200397537 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.hh 2019-02-28 12:04:17.606502653 -0800 @@ -0,0 +1,439 @@ +/* + * 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_HH +#define HB_BUFFER_HH + +#include "hb.hh" +#include "hb-unicode.hh" + + +#ifndef HB_BUFFER_MAX_LEN_FACTOR +#define HB_BUFFER_MAX_LEN_FACTOR 32 +#endif +#ifndef HB_BUFFER_MAX_LEN_MIN +#define HB_BUFFER_MAX_LEN_MIN 8192 +#endif +#ifndef HB_BUFFER_MAX_LEN_DEFAULT +#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */ +#endif + +#ifndef HB_BUFFER_MAX_OPS_FACTOR +#define HB_BUFFER_MAX_OPS_FACTOR 64 +#endif +#ifndef HB_BUFFER_MAX_OPS_MIN +#define HB_BUFFER_MAX_OPS_MIN 1024 +#endif +#ifndef HB_BUFFER_MAX_OPS_DEFAULT +#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */ +#endif + +static_assert ((sizeof (hb_glyph_info_t) == 20), ""); +static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), ""); + +HB_MARK_AS_FLAG_T (hb_buffer_flags_t); +HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t); +HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t); + +enum hb_buffer_scratch_flags_t { + HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u, + HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII = 0x00000001u, + HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u, + HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u, + HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u, + HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u, + HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000020u, + + /* Reserved for complex shapers' internal use. */ + HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u, + HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u, + HB_BUFFER_SCRATCH_FLAG_COMPLEX2 = 0x04000000u, + HB_BUFFER_SCRATCH_FLAG_COMPLEX3 = 0x08000000u, +}; +HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t); + + +/* + * hb_buffer_t + */ + +struct hb_buffer_t +{ + hb_object_header_t header; + + /* Information about how the text in the buffer should be treated */ + hb_unicode_funcs_t *unicode; /* Unicode functions */ + hb_buffer_flags_t flags; /* BOT / EOT / etc. */ + hb_buffer_cluster_level_t cluster_level; + hb_codepoint_t replacement; /* U+FFFD or something else. */ + hb_codepoint_t invisible; /* 0 or something else. */ + hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ + unsigned int max_len; /* Maximum allowed len. */ + int max_ops; /* Maximum allowed operations. */ + + /* Buffer contents */ + hb_buffer_content_type_t content_type; + hb_segment_properties_t props; /* Script, language, direction */ + + bool successful; /* Allocations successful */ + 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; + + unsigned int serial; + + /* Text before / after the main buffer contents. + * Always in Unicode, and ordered outward. + * Index 0 is for "pre-context", 1 for "post-context". */ + static constexpr unsigned CONTEXT_LENGTH = 5u; + hb_codepoint_t context[2][CONTEXT_LENGTH]; + unsigned int context_len[2]; + + /* Debugging API */ + hb_buffer_message_func_t message_func; + void *message_data; + hb_destroy_func_t message_destroy; + + /* Internal debugging. */ + /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ +#ifndef HB_NDEBUG + uint8_t allocated_var_bits; +#endif + + + /* Methods */ + + bool in_error () const { return !successful; } + + void allocate_var (unsigned int start, unsigned int count) + { +#ifndef HB_NDEBUG + unsigned int end = start + count; + assert (end <= 8); + unsigned int bits = (1u< (cluster, infos[i].cluster); + return cluster; + } + void + _unsafe_to_break_set_mask (hb_glyph_info_t *infos, + unsigned int start, unsigned int end, + unsigned int cluster) + { + for (unsigned int i = start; i < end; i++) + if (cluster != infos[i].cluster) + { + scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK; + infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + } + } + + void unsafe_to_break_all () + { unsafe_to_break_impl (0, len); } + void safe_to_break_all () + { + for (unsigned int i = 0; i < len; i++) + info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + } +}; +DECLARE_NULL_INSTANCE (hb_buffer_t); + + +/* Loop over clusters. Duplicated in foreach_syllable(). */ +#define foreach_cluster(buffer, start, end) \ + for (unsigned int \ + _count = buffer->len, \ + start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \ + start < _count; \ + start = end, end = _next_cluster (buffer, start)) + +static inline unsigned int +_next_cluster (hb_buffer_t *buffer, unsigned int start) +{ + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + + unsigned int cluster = info[start].cluster; + while (++start < count && cluster == info[start].cluster) + ; + + return start; +} + + +#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \ + b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \ + sizeof (b->info[0].var)) +#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ()) +#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ()) +#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ()) + + +#endif /* HB_BUFFER_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face-private.hh 2019-02-28 12:04:18.150502644 -0800 +++ /dev/null 2019-02-21 13:14:21.200397537 -0800 @@ -1,111 +0,0 @@ -/* - * 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_FACE_PRIVATE_HH -#define HB_FACE_PRIVATE_HH - -#include "hb-private.hh" - -#include "hb-object-private.hh" -#include "hb-shaper-private.hh" -#include "hb-shape-plan-private.hh" - - -/* - * 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; /* Face index in a collection, zero-based. */ - mutable unsigned int upem; /* Units-per-EM. */ - mutable unsigned int num_glyphs; /* Number of glyphs. */ - - struct hb_shaper_data_t shaper_data; /* Various shaper data. */ - - /* Various non-shaping data. */ - /* ... */ - - /* Cache */ - 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 (!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; -}; - -extern HB_INTERNAL const hb_face_t _hb_face_nil; - -#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 - - -#endif /* HB_FACE_PRIVATE_HH */ --- /dev/null 2019-02-21 13:14:21.200397537 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.hh 2019-02-28 12:04:17.994502647 -0800 @@ -0,0 +1,109 @@ +/* + * 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_FACE_HH +#define HB_FACE_HH + +#include "hb.hh" + +#include "hb-shaper.hh" +#include "hb-shape-plan.hh" +#include "hb-ot-face.hh" + + +/* + * hb_face_t + */ + +#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, face); +#include "hb-shaper-list.hh" +#undef HB_SHAPER_IMPLEMENT + +struct hb_face_t +{ + hb_object_header_t header; + + hb_reference_table_func_t reference_table_func; + void *user_data; + hb_destroy_func_t destroy; + + unsigned int index; /* Face index in a collection, zero-based. */ + mutable hb_atomic_int_t upem; /* Units-per-EM. */ + mutable hb_atomic_int_t num_glyphs; /* Number of glyphs. */ + + hb_shaper_object_dataset_t data;/* Various shaper data. */ + hb_ot_face_t table; /* All the face's tables. */ + + /* Cache */ + struct plan_node_t + { + hb_shape_plan_t *shape_plan; + plan_node_t *next; + }; + hb_atomic_ptr_t shape_plans; + + hb_blob_t *reference_table (hb_tag_t tag) const + { + hb_blob_t *blob; + + if (unlikely (!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; + } + + HB_PURE_FUNC unsigned int get_upem () const + { + unsigned int ret = upem.get_relaxed (); + if (unlikely (!ret)) + { + return load_upem (); + } + return ret; + } + + unsigned int get_num_glyphs () const + { + unsigned int ret = num_glyphs.get_relaxed (); + if (unlikely (ret == (unsigned int) -1)) + return load_num_glyphs (); + return ret; + } + + private: + HB_INTERNAL unsigned int load_upem () const; + HB_INTERNAL unsigned int load_num_glyphs () const; +}; +DECLARE_NULL_INSTANCE (hb_face_t); + + +#endif /* HB_FACE_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font-private.hh 2019-02-28 12:04:18.526502638 -0800 +++ /dev/null 2019-02-21 13:14:21.200397537 -0800 @@ -1,565 +0,0 @@ -/* - * 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-object-private.hh" -#include "hb-face-private.hh" -#include "hb-shaper-private.hh" - - - -/* - * hb_font_funcs_t - */ - -#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ - HB_FONT_FUNC_IMPLEMENT (font_h_extents) \ - HB_FONT_FUNC_IMPLEMENT (font_v_extents) \ - HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \ - HB_FONT_FUNC_IMPLEMENT (variation_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; - - 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; - - /* Don't access these directly. Call font->get_*() instead. */ - union get_t { - struct get_funcs_t { -#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT - } f; - void (*array[0 -#define HB_FONT_FUNC_IMPLEMENT(name) +1 - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT - ]) (void); - } get; -}; - - - -/* - * 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; - - float ptem; - - /* Font variation coordinates. */ - unsigned int num_coords; - int *coords; - - 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 int dir_scale (hb_direction_t direction) - { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; } - inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); } - inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); } - inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); } - inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); } - inline float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); } - inline float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); } - inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) - { return em_scale (v, dir_scale (direction)); } - - /* 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 (hb_position_t) (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 (hb_position_t) (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 */ - - HB_INTERNAL bool has_func (unsigned int i); - - /* has_* ... */ -#define HB_FONT_FUNC_IMPLEMENT(name) \ - bool \ - has_##name##_func (void) \ - { \ - hb_font_funcs_t *funcs = this->klass; \ - unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ - return has_func (i); \ - } - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT - - inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents) - { - memset (extents, 0, sizeof (*extents)); - return klass->get.f.font_h_extents (this, user_data, - extents, - klass->user_data.font_h_extents); - } - inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents) - { - memset (extents, 0, sizeof (*extents)); - return klass->get.f.font_v_extents (this, user_data, - extents, - klass->user_data.font_v_extents); - } - - inline bool has_glyph (hb_codepoint_t unicode) - { - hb_codepoint_t glyph; - return get_nominal_glyph (unicode, &glyph); - } - - inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, - hb_codepoint_t *glyph) - { - *glyph = 0; - return klass->get.f.nominal_glyph (this, user_data, - unicode, glyph, - klass->user_data.nominal_glyph); - } - - inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, - hb_codepoint_t *glyph) - { - *glyph = 0; - return klass->get.f.variation_glyph (this, user_data, - unicode, variation_selector, glyph, - klass->user_data.variation_glyph); - } - - inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) - { - return klass->get.f.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.f.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.f.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.f.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.f.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 top_glyph, hb_codepoint_t bottom_glyph) - { - return klass->get.f.glyph_v_kerning (this, user_data, - top_glyph, bottom_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.f.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.f.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.f.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.f.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_h_extents_with_fallback (hb_font_extents_t *extents) - { - if (!get_font_h_extents (extents)) - { - extents->ascender = y_scale * .8; - extents->descender = extents->ascender - y_scale; - extents->line_gap = 0; - } - } - inline void get_v_extents_with_fallback (hb_font_extents_t *extents) - { - if (!get_font_v_extents (extents)) - { - extents->ascender = x_scale / 2; - extents->descender = extents->ascender - x_scale; - extents->line_gap = 0; - } - } - - inline void get_extents_for_direction (hb_direction_t direction, - hb_font_extents_t *extents) - { - if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) - get_h_extents_with_fallback (extents); - else - get_v_extents_with_fallback (extents); - } - - 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); - } - } - - 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 cache this somehow?! */ - hb_font_extents_t extents; - get_h_extents_with_fallback (&extents); - *y = extents.ascender; - } - - inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph, - hb_position_t *x, hb_position_t *y) - { - 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; - } - } - inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph, - hb_position_t *x, hb_position_t *y) - { - 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 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))) - get_glyph_h_origin_with_fallback (glyph, x, y); - else - get_glyph_v_origin_with_fallback (glyph, x, y); - } - - inline void add_glyph_h_origin (hb_codepoint_t glyph, - hb_position_t *x, hb_position_t *y) - { - hb_position_t origin_x, origin_y; - - get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); - - *x += origin_x; - *y += origin_y; - } - inline void add_glyph_v_origin (hb_codepoint_t glyph, - hb_position_t *x, hb_position_t *y) - { - hb_position_t origin_x, origin_y; - - get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); - - *x += origin_x; - *y += origin_y; - } - 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_h_origin (hb_codepoint_t glyph, - hb_position_t *x, hb_position_t *y) - { - hb_position_t origin_x, origin_y; - - get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); - - *x -= origin_x; - *y -= origin_y; - } - inline void subtract_glyph_v_origin (hb_codepoint_t glyph, - hb_position_t *x, hb_position_t *y) - { - hb_position_t origin_x, origin_y; - - get_glyph_v_origin_with_fallback (glyph, &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; - - if (size && snprintf (s, size, "gid%u", glyph) < 0) - *s = '\0'; - } - - /* 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_nominal_glyph (unichar, glyph)) - return true; - } - - return false; - } - - inline hb_position_t em_scale (int16_t v, int scale) - { - int upem = face->get_upem (); - int64_t scaled = v * (int64_t) scale; - scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */ - return (hb_position_t) (scaled / upem); - } - inline hb_position_t em_scalef (float v, int scale) - { - return (hb_position_t) round (v * scale / face->get_upem ()); - } - inline float em_fscale (int16_t v, int scale) - { - return (float) v * scale / face->get_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 */ --- /dev/null 2019-02-21 13:14:21.200397537 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.hh 2019-02-28 12:04:18.366502641 -0800 @@ -0,0 +1,617 @@ +/* + * 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_HH +#define HB_FONT_HH + +#include "hb.hh" + +#include "hb-face.hh" +#include "hb-shaper.hh" + + +/* + * hb_font_funcs_t + */ + +#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ + HB_FONT_FUNC_IMPLEMENT (font_h_extents) \ + HB_FONT_FUNC_IMPLEMENT (font_v_extents) \ + HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \ + HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \ + HB_FONT_FUNC_IMPLEMENT (variation_glyph) \ + HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ + HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ + HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \ + HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \ + 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; + + 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; + + /* Don't access these directly. Call font->get_*() instead. */ + union get_t { + struct get_funcs_t { +#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + } f; + void (*array[0 +#define HB_FONT_FUNC_IMPLEMENT(name) +1 + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + ]) (); + } get; +}; +DECLARE_NULL_INSTANCE (hb_font_funcs_t); + + +/* + * hb_font_t + */ + +#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font); +#include "hb-shaper-list.hh" +#undef HB_SHAPER_IMPLEMENT + +struct hb_font_t +{ + hb_object_header_t header; + + hb_font_t *parent; + hb_face_t *face; + + int x_scale; + int y_scale; + + unsigned int x_ppem; + unsigned int y_ppem; + + float ptem; + + /* Font variation coordinates. */ + unsigned int num_coords; + int *coords; + + hb_font_funcs_t *klass; + void *user_data; + hb_destroy_func_t destroy; + + hb_shaper_object_dataset_t data; /* Various shaper data. */ + + + /* Convert from font-space to user-space */ + int dir_scale (hb_direction_t direction) + { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; } + hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); } + hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); } + hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); } + hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); } + float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); } + float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); } + hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) + { return em_scale (v, dir_scale (direction)); } + + /* Convert from parent-font user-space to our user-space */ + hb_position_t parent_scale_x_distance (hb_position_t v) + { + if (unlikely (parent && parent->x_scale != x_scale)) + return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale); + return v; + } + hb_position_t parent_scale_y_distance (hb_position_t v) + { + if (unlikely (parent && parent->y_scale != y_scale)) + return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale); + return v; + } + hb_position_t parent_scale_x_position (hb_position_t v) + { return parent_scale_x_distance (v); } + hb_position_t parent_scale_y_position (hb_position_t v) + { return parent_scale_y_distance (v); } + + void parent_scale_distance (hb_position_t *x, hb_position_t *y) + { + *x = parent_scale_x_distance (*x); + *y = parent_scale_y_distance (*y); + } + 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 */ + + HB_INTERNAL bool has_func (unsigned int i); + HB_INTERNAL bool has_func_set (unsigned int i); + + /* has_* ... */ +#define HB_FONT_FUNC_IMPLEMENT(name) \ + bool \ + has_##name##_func () \ + { \ + hb_font_funcs_t *funcs = this->klass; \ + unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ + return has_func (i); \ + } \ + bool \ + has_##name##_func_set () \ + { \ + hb_font_funcs_t *funcs = this->klass; \ + unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ + return has_func_set (i); \ + } + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + + hb_bool_t get_font_h_extents (hb_font_extents_t *extents) + { + memset (extents, 0, sizeof (*extents)); + return klass->get.f.font_h_extents (this, user_data, + extents, + klass->user_data.font_h_extents); + } + hb_bool_t get_font_v_extents (hb_font_extents_t *extents) + { + memset (extents, 0, sizeof (*extents)); + return klass->get.f.font_v_extents (this, user_data, + extents, + klass->user_data.font_v_extents); + } + + bool has_glyph (hb_codepoint_t unicode) + { + hb_codepoint_t glyph; + return get_nominal_glyph (unicode, &glyph); + } + + hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, + hb_codepoint_t *glyph) + { + *glyph = 0; + return klass->get.f.nominal_glyph (this, user_data, + unicode, glyph, + klass->user_data.nominal_glyph); + } + unsigned int get_nominal_glyphs (unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride) + { + return klass->get.f.nominal_glyphs (this, user_data, + count, + first_unicode, unicode_stride, + first_glyph, glyph_stride, + klass->user_data.nominal_glyphs); + } + + hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph) + { + *glyph = 0; + return klass->get.f.variation_glyph (this, user_data, + unicode, variation_selector, glyph, + klass->user_data.variation_glyph); + } + + hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) + { + return klass->get.f.glyph_h_advance (this, user_data, + glyph, + klass->user_data.glyph_h_advance); + } + + hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) + { + return klass->get.f.glyph_v_advance (this, user_data, + glyph, + klass->user_data.glyph_v_advance); + } + + void get_glyph_h_advances (unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + hb_position_t *first_advance, + unsigned int advance_stride) + { + return klass->get.f.glyph_h_advances (this, user_data, + count, + first_glyph, glyph_stride, + first_advance, advance_stride, + klass->user_data.glyph_h_advances); + } + + void get_glyph_v_advances (unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned int glyph_stride, + hb_position_t *first_advance, + unsigned int advance_stride) + { + return klass->get.f.glyph_v_advances (this, user_data, + count, + first_glyph, glyph_stride, + first_advance, advance_stride, + klass->user_data.glyph_v_advances); + } + + 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.f.glyph_h_origin (this, user_data, + glyph, x, y, + klass->user_data.glyph_h_origin); + } + + 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.f.glyph_v_origin (this, user_data, + glyph, x, y, + klass->user_data.glyph_v_origin); + } + + hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, + hb_codepoint_t right_glyph) + { + return klass->get.f.glyph_h_kerning (this, user_data, + left_glyph, right_glyph, + klass->user_data.glyph_h_kerning); + } + + hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, + hb_codepoint_t bottom_glyph) + { + return klass->get.f.glyph_v_kerning (this, user_data, + top_glyph, bottom_glyph, + klass->user_data.glyph_v_kerning); + } + + hb_bool_t get_glyph_extents (hb_codepoint_t glyph, + hb_glyph_extents_t *extents) + { + memset (extents, 0, sizeof (*extents)); + return klass->get.f.glyph_extents (this, user_data, + glyph, + extents, + klass->user_data.glyph_extents); + } + + 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.f.glyph_contour_point (this, user_data, + glyph, point_index, + x, y, + klass->user_data.glyph_contour_point); + } + + hb_bool_t get_glyph_name (hb_codepoint_t glyph, + char *name, unsigned int size) + { + if (size) *name = '\0'; + return klass->get.f.glyph_name (this, user_data, + glyph, + name, size, + klass->user_data.glyph_name); + } + + 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.f.glyph_from_name (this, user_data, + name, len, + glyph, + klass->user_data.glyph_from_name); + } + + + /* A bit higher-level, and with fallback */ + + void get_h_extents_with_fallback (hb_font_extents_t *extents) + { + if (!get_font_h_extents (extents)) + { + extents->ascender = y_scale * .8; + extents->descender = extents->ascender - y_scale; + extents->line_gap = 0; + } + } + void get_v_extents_with_fallback (hb_font_extents_t *extents) + { + if (!get_font_v_extents (extents)) + { + extents->ascender = x_scale / 2; + extents->descender = extents->ascender - x_scale; + extents->line_gap = 0; + } + } + + void get_extents_for_direction (hb_direction_t direction, + hb_font_extents_t *extents) + { + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) + get_h_extents_with_fallback (extents); + else + get_v_extents_with_fallback (extents); + } + + void get_glyph_advance_for_direction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) + { + *x = *y = 0; + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) + *x = get_glyph_h_advance (glyph); + else + *y = get_glyph_v_advance (glyph); + } + void get_glyph_advances_for_direction (hb_direction_t direction, + unsigned int count, + const hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride) + { + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) + get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); + else + get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); + } + + 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 cache this somehow?! */ + hb_font_extents_t extents; + get_h_extents_with_fallback (&extents); + *y = extents.ascender; + } + + void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + 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; + } + } + void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + 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; + } + } + + 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))) + get_glyph_h_origin_with_fallback (glyph, x, y); + else + get_glyph_v_origin_with_fallback (glyph, x, y); + } + + void add_glyph_h_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + hb_position_t origin_x, origin_y; + + get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); + + *x += origin_x; + *y += origin_y; + } + void add_glyph_v_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + hb_position_t origin_x, origin_y; + + get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); + + *x += origin_x; + *y += origin_y; + } + 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; + } + + void subtract_glyph_h_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + hb_position_t origin_x, origin_y; + + get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); + + *x -= origin_x; + *y -= origin_y; + } + void subtract_glyph_v_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + hb_position_t origin_x, origin_y; + + get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); + + *x -= origin_x; + *y -= origin_y; + } + 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; + } + + 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))) { + *y = 0; + *x = get_glyph_h_kerning (first_glyph, second_glyph); + } else { + *x = 0; + *y = get_glyph_v_kerning (first_glyph, second_glyph); + } + } + + 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; + } + + 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. */ + void + glyph_to_string (hb_codepoint_t glyph, + char *s, unsigned int size) + { + if (get_glyph_name (glyph, s, size)) return; + + if (size && snprintf (s, size, "gid%u", glyph) < 0) + *s = '\0'; + } + + /* Parses gidDDD and uniUUUU strings automatically. */ + 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_nominal_glyph (unichar, glyph)) + return true; + } + + return false; + } + + hb_position_t em_scale (int16_t v, int scale) + { + int upem = face->get_upem (); + int64_t scaled = v * (int64_t) scale; + scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */ + return (hb_position_t) (scaled / upem); + } + hb_position_t em_scalef (float v, int scale) + { return (hb_position_t) round (v * scale / face->get_upem ()); } + float em_fscale (int16_t v, int scale) + { return (float) v * scale / face->get_upem (); } +}; +DECLARE_NULL_INSTANCE (hb_font_t); + + +#endif /* HB_FONT_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map-private.hh 2019-02-28 12:04:18.910502632 -0800 +++ /dev/null 2019-02-21 13:14:21.200397537 -0800 @@ -1,255 +0,0 @@ -/* - * Copyright © 2018 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_MAP_PRIVATE_HH -#define HB_MAP_PRIVATE_HH - -#include "hb-private.hh" -#include "hb-object-private.hh" - - -template -inline uint32_t Hash (const T &v) -{ - /* Knuth's multiplicative method: */ - return (uint32_t) v * 2654435761u; -} - - -/* - * hb_map_t - */ - -struct hb_map_t -{ - struct item_t - { - hb_codepoint_t key; - hb_codepoint_t value; - - inline bool is_unused (void) const { return key == INVALID; } - inline bool is_tombstone (void) const { return key != INVALID && value == INVALID; } - }; - - hb_object_header_t header; - bool successful; /* Allocations successful */ - unsigned int population; /* Not including tombstones. */ - unsigned int occupancy; /* Including tombstones. */ - unsigned int mask; - unsigned int prime; - item_t *items; - - inline void init_shallow (void) - { - successful = true; - population = occupancy = 0; - mask = 0; - prime = 0; - items = nullptr; - } - inline void init (void) - { - hb_object_init (this); - init_shallow (); - } - inline void fini_shallow (void) - { - free (items); - } - inline void fini (void) - { - hb_object_fini (this); - fini_shallow (); - } - - inline bool resize (void) - { - if (unlikely (!successful)) return false; - - unsigned int power = _hb_bit_storage (population * 2 + 8); - unsigned int new_size = 1u << power; - item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t)); - if (unlikely (!new_items)) - { - successful = false; - return false; - } - memset (new_items, 0xFF, (size_t) new_size * sizeof (item_t)); - - unsigned int old_size = mask + 1; - item_t *old_items = items; - - /* Switch to new, empty, array. */ - population = occupancy = 0; - mask = new_size - 1; - prime = prime_for (power); - items = new_items; - - /* Insert back old items. */ - if (old_items) - for (unsigned int i = 0; i < old_size; i++) - if (old_items[i].key != INVALID && old_items[i].value != INVALID) - set (old_items[i].key, old_items[i].value); - - free (old_items); - - return true; - } - - inline void set (hb_codepoint_t key, hb_codepoint_t value) - { - if (unlikely (!successful)) return; - if (unlikely (key == INVALID)) return; - if ((occupancy + occupancy / 2) >= mask && !resize ()) return; - unsigned int i = bucket_for (key); - - if (value == INVALID && items[i].key != key) - return; /* Trying to delete non-existent key. */ - - if (!items[i].is_unused ()) - { - occupancy--; - if (items[i].is_tombstone ()) - population--; - } - - items[i].key = key; - items[i].value = value; - - occupancy++; - if (!items[i].is_tombstone ()) - population++; - - } - inline hb_codepoint_t get (hb_codepoint_t key) const - { - if (unlikely (!items)) return INVALID; - unsigned int i = bucket_for (key); - return items[i].key == key ? items[i].value : INVALID; - } - - inline void del (hb_codepoint_t key) - { - set (key, INVALID); - } - inline bool has (hb_codepoint_t key) const - { - return get (key) != INVALID; - } - - inline hb_codepoint_t operator [] (unsigned int key) const - { return get (key); } - - static const hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID; - - inline void clear (void) - { - memset (items, 0xFF, ((size_t) mask + 1) * sizeof (item_t)); - population = occupancy = 0; - } - - inline bool is_empty (void) const - { - return population != 0; - } - - inline unsigned int get_population () const - { - return population; - } - - protected: - - inline unsigned int bucket_for (hb_codepoint_t key) const - { - unsigned int i = Hash (key) % prime; - unsigned int step = 0; - unsigned int tombstone = INVALID; - while (!items[i].is_unused ()) - { - if (items[i].key == key) - return i; - if (tombstone == INVALID && items[i].is_tombstone ()) - tombstone = i; - i = (i + ++step) & mask; - } - return tombstone == INVALID ? i : tombstone; - } - - static inline unsigned int prime_for (unsigned int shift) - { - /* Following comment and table copied from glib. */ - /* Each table size has an associated prime modulo (the first prime - * lower than the table size) used to find the initial bucket. Probing - * then works modulo 2^n. The prime modulo is necessary to get a - * good distribution with poor hash functions. - */ - /* Not declaring static to make all kinds of compilers happy... */ - /*static*/ const unsigned int prime_mod [32] = - { - 1, /* For 1 << 0 */ - 2, - 3, - 7, - 13, - 31, - 61, - 127, - 251, - 509, - 1021, - 2039, - 4093, - 8191, - 16381, - 32749, - 65521, /* For 1 << 16 */ - 131071, - 262139, - 524287, - 1048573, - 2097143, - 4194301, - 8388593, - 16777213, - 33554393, - 67108859, - 134217689, - 268435399, - 536870909, - 1073741789, - 2147483647 /* For 1 << 31 */ - }; - - if (unlikely (shift >= ARRAY_LENGTH (prime_mod))) - return prime_mod[ARRAY_LENGTH (prime_mod) - 1]; - - return prime_mod[shift]; - } -}; - - -#endif /* HB_MAP_PRIVATE_HH */ --- /dev/null 2019-02-21 13:14:21.200397537 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map.hh 2019-02-28 12:04:18.758502634 -0800 @@ -0,0 +1,252 @@ +/* + * Copyright © 2018 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_MAP_HH +#define HB_MAP_HH + +#include "hb.hh" + + +template +inline uint32_t Hash (const T &v) +{ + /* Knuth's multiplicative method: */ + return (uint32_t) v * 2654435761u; +} + + +/* + * hb_map_t + */ + +struct hb_map_t +{ + HB_NO_COPY_ASSIGN (hb_map_t); + hb_map_t () { init (); } + ~hb_map_t () { fini (); } + + struct item_t + { + hb_codepoint_t key; + hb_codepoint_t value; + + bool is_unused () const { return key == INVALID; } + bool is_tombstone () const { return key != INVALID && value == INVALID; } + }; + + hb_object_header_t header; + bool successful; /* Allocations successful */ + unsigned int population; /* Not including tombstones. */ + unsigned int occupancy; /* Including tombstones. */ + unsigned int mask; + unsigned int prime; + item_t *items; + + void init_shallow () + { + successful = true; + population = occupancy = 0; + mask = 0; + prime = 0; + items = nullptr; + } + void init () + { + hb_object_init (this); + init_shallow (); + } + void fini_shallow () + { + free (items); + items = nullptr; + } + void fini () + { + population = occupancy = 0; + hb_object_fini (this); + fini_shallow (); + } + + bool in_error () const { return !successful; } + + bool resize () + { + if (unlikely (!successful)) return false; + + unsigned int power = hb_bit_storage (population * 2 + 8); + unsigned int new_size = 1u << power; + item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t)); + if (unlikely (!new_items)) + { + successful = false; + return false; + } + memset (new_items, 0xFF, (size_t) new_size * sizeof (item_t)); + + unsigned int old_size = mask + 1; + item_t *old_items = items; + + /* Switch to new, empty, array. */ + population = occupancy = 0; + mask = new_size - 1; + prime = prime_for (power); + items = new_items; + + /* Insert back old items. */ + if (old_items) + for (unsigned int i = 0; i < old_size; i++) + if (old_items[i].key != INVALID && old_items[i].value != INVALID) + set (old_items[i].key, old_items[i].value); + + free (old_items); + + return true; + } + + void set (hb_codepoint_t key, hb_codepoint_t value) + { + if (unlikely (!successful)) return; + if (unlikely (key == INVALID)) return; + if ((occupancy + occupancy / 2) >= mask && !resize ()) return; + unsigned int i = bucket_for (key); + + if (value == INVALID && items[i].key != key) + return; /* Trying to delete non-existent key. */ + + if (!items[i].is_unused ()) + { + occupancy--; + if (items[i].is_tombstone ()) + population--; + } + + items[i].key = key; + items[i].value = value; + + occupancy++; + if (!items[i].is_tombstone ()) + population++; + + } + hb_codepoint_t get (hb_codepoint_t key) const + { + if (unlikely (!items)) return INVALID; + unsigned int i = bucket_for (key); + return items[i].key == key ? items[i].value : INVALID; + } + + void del (hb_codepoint_t key) { set (key, INVALID); } + + bool has (hb_codepoint_t key) const + { return get (key) != INVALID; } + + hb_codepoint_t operator [] (unsigned int key) const + { return get (key); } + + static constexpr hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID; + + void clear () + { + memset (items, 0xFF, ((size_t) mask + 1) * sizeof (item_t)); + population = occupancy = 0; + } + + bool is_empty () const { return population == 0; } + + unsigned int get_population () const { return population; } + + protected: + + unsigned int bucket_for (hb_codepoint_t key) const + { + unsigned int i = Hash (key) % prime; + unsigned int step = 0; + unsigned int tombstone = INVALID; + while (!items[i].is_unused ()) + { + if (items[i].key == key) + return i; + if (tombstone == INVALID && items[i].is_tombstone ()) + tombstone = i; + i = (i + ++step) & mask; + } + return tombstone == INVALID ? i : tombstone; + } + + static unsigned int prime_for (unsigned int shift) + { + /* Following comment and table copied from glib. */ + /* Each table size has an associated prime modulo (the first prime + * lower than the table size) used to find the initial bucket. Probing + * then works modulo 2^n. The prime modulo is necessary to get a + * good distribution with poor hash functions. + */ + /* Not declaring static to make all kinds of compilers happy... */ + /*static*/ const unsigned int prime_mod [32] = + { + 1, /* For 1 << 0 */ + 2, + 3, + 7, + 13, + 31, + 61, + 127, + 251, + 509, + 1021, + 2039, + 4093, + 8191, + 16381, + 32749, + 65521, /* For 1 << 16 */ + 131071, + 262139, + 524287, + 1048573, + 2097143, + 4194301, + 8388593, + 16777213, + 33554393, + 67108859, + 134217689, + 268435399, + 536870909, + 1073741789, + 2147483647 /* For 1 << 31 */ + }; + + if (unlikely (shift >= ARRAY_LENGTH (prime_mod))) + return prime_mod[ARRAY_LENGTH (prime_mod) - 1]; + + return prime_mod[shift]; + } +}; + + +#endif /* HB_MAP_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-mutex-private.hh 2019-02-28 12:04:19.294502625 -0800 +++ /dev/null 2019-02-21 13:14:21.200397537 -0800 @@ -1,141 +0,0 @@ -/* - * 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 defined(HB_MUTEX_IMPL_INIT) \ - && defined(hb_mutex_impl_init) \ - && defined(hb_mutex_impl_lock) \ - && defined(hb_mutex_impl_unlock) \ - && defined(hb_mutex_impl_finish) - -/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */ - - -#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) - -#include -typedef CRITICAL_SECTION hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT {0} -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0) -#else -#define hb_mutex_impl_init(M) InitializeCriticalSection (M) -#endif -#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, nullptr) -#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 fini (void) { hb_mutex_impl_finish (&m); } -}; - - -#endif /* HB_MUTEX_PRIVATE_HH */ --- /dev/null 2019-02-21 13:14:21.200397537 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-mutex.hh 2019-02-28 12:04:19.134502628 -0800 @@ -0,0 +1,149 @@ +/* + * 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_HH +#define HB_MUTEX_HH + +#include "hb.hh" + + +/* mutex */ + +/* We need external help for these */ + +#if defined(HB_MUTEX_IMPL_INIT) \ + && defined(hb_mutex_impl_init) \ + && defined(hb_mutex_impl_lock) \ + && defined(hb_mutex_impl_unlock) \ + && defined(hb_mutex_impl_finish) + +/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */ + + +#elif !defined(HB_NO_MT) && defined(_WIN32) + +#include +typedef CRITICAL_SECTION hb_mutex_impl_t; +#define HB_MUTEX_IMPL_INIT {0} +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) +#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0) +#else +#define hb_mutex_impl_init(M) InitializeCriticalSection (M) +#endif +#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, nullptr) +#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; + + void init () { hb_mutex_impl_init (&m); } + void lock () { hb_mutex_impl_lock (&m); } + void unlock () { hb_mutex_impl_unlock (&m); } + void fini () { hb_mutex_impl_finish (&m); } +}; + +struct hb_lock_t +{ + hb_lock_t (hb_mutex_t &mutex_) : mutex (mutex_) { mutex.lock (); } + ~hb_lock_t () { mutex.unlock (); } + private: + hb_mutex_t &mutex; +}; + + +#endif /* HB_MUTEX_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-object-private.hh 2019-02-28 12:04:19.662502619 -0800 +++ /dev/null 2019-02-21 13:14:21.200397537 -0800 @@ -1,221 +0,0 @@ -/* - * 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-debug.hh" - -#include "hb-atomic-private.hh" -#include "hb-mutex-private.hh" - - -/* reference_count */ - -#define HB_REFERENCE_COUNT_INERT_VALUE 0 -#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD -#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)} - -struct hb_reference_count_t -{ - hb_atomic_int_t ref_count; - - inline void init (int v) { ref_count.set_unsafe (v); } - inline int get_unsafe (void) const { return ref_count.get_unsafe (); } - inline int inc (void) { return ref_count.inc (); } - inline int dec (void) { return ref_count.dec (); } - inline void fini (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); } - - inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; } - inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; } -}; - - -/* user_data */ - -struct hb_user_data_array_t -{ - 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 fini (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 fini (void) { items.fini (lock); lock.fini (); } -}; - - -/* 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_INIT, nullptr} - - private: - ASSERT_POD (); -}; - - -/* object */ - -template -static inline void hb_object_trace (const Type *obj, const char *function) -{ - DEBUG_MSG (OBJECT, (void *) obj, - "%s refcount=%d", - function, - obj ? obj->header.ref_count.get_unsafe () : 0); -} - -template -static inline Type *hb_object_create (void) -{ - Type *obj = (Type *) calloc (1, sizeof (Type)); - - if (unlikely (!obj)) - return obj; - - hb_object_init (obj); - hb_object_trace (obj, HB_FUNC); - return obj; -} -template -static inline void hb_object_init (Type *obj) -{ - obj->header.ref_count.init (1); - obj->header.user_data = nullptr; -} -template -static inline bool hb_object_is_inert (const Type *obj) -{ - return unlikely (obj->header.ref_count.is_inert ()); -} -template -static inline bool hb_object_is_valid (const Type *obj) -{ - return likely (obj->header.ref_count.is_valid ()); -} -template -static inline Type *hb_object_reference (Type *obj) -{ - hb_object_trace (obj, HB_FUNC); - if (unlikely (!obj || hb_object_is_inert (obj))) - return obj; - assert (hb_object_is_valid (obj)); - obj->header.ref_count.inc (); - return obj; -} -template -static inline bool hb_object_destroy (Type *obj) -{ - hb_object_trace (obj, HB_FUNC); - if (unlikely (!obj || hb_object_is_inert (obj))) - return false; - assert (hb_object_is_valid (obj)); - if (obj->header.ref_count.dec () != 1) - return false; - - hb_object_fini (obj); - return true; -} -template -static inline void hb_object_fini (Type *obj) -{ - obj->header.ref_count.fini (); /* Do this before user_data */ - if (obj->header.user_data) - { - obj->header.user_data->fini (); - free (obj->header.user_data); - } -} -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) -{ - if (unlikely (!obj || hb_object_is_inert (obj))) - return false; - assert (hb_object_is_valid (obj)); - -retry: - hb_user_data_array_t *user_data = (hb_user_data_array_t *) hb_atomic_ptr_get (&obj->header.user_data); - if (unlikely (!user_data)) - { - user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1); - if (unlikely (!user_data)) - return false; - user_data->init (); - if (unlikely (!hb_atomic_ptr_cmpexch (&obj->header.user_data, nullptr, user_data))) - { - user_data->fini (); - free (user_data); - goto retry; - } - } - - return user_data->set (key, data, destroy, replace); -} - -template -static inline void *hb_object_get_user_data (Type *obj, - hb_user_data_key_t *key) -{ - if (unlikely (!obj || hb_object_is_inert (obj) || !obj->header.user_data)) - return nullptr; - assert (hb_object_is_valid (obj)); - return obj->header.user_data->get (key); -} - - -#endif /* HB_OBJECT_PRIVATE_HH */ --- /dev/null 2019-02-21 13:14:21.200397537 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-object.hh 2019-02-28 12:04:19.506502622 -0800 @@ -0,0 +1,342 @@ +/* + * 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_HH +#define HB_OBJECT_HH + +#include "hb.hh" +#include "hb-atomic.hh" +#include "hb-mutex.hh" +#include "hb-vector.hh" + + +/* + * Lockable set + */ + +template +struct hb_lockable_set_t +{ + hb_vector_t items; + + void init () { items.init (); } + + template + item_t *replace_or_insert (T v, lock_t &l, bool replace) + { + l.lock (); + item_t *item = items.find (v); + if (item) { + if (replace) { + item_t old = *item; + *item = v; + l.unlock (); + old.fini (); + } + else { + item = nullptr; + l.unlock (); + } + } else { + item = items.push (v); + l.unlock (); + } + return item; + } + + template + void remove (T v, lock_t &l) + { + l.lock (); + item_t *item = items.find (v); + if (item) + { + item_t old = *item; + *item = items[items.length - 1]; + items.pop (); + l.unlock (); + old.fini (); + } else { + l.unlock (); + } + } + + template + bool find (T v, item_t *i, lock_t &l) + { + l.lock (); + item_t *item = items.find (v); + if (item) + *i = *item; + l.unlock (); + return !!item; + } + + template + item_t *find_or_insert (T v, lock_t &l) + { + l.lock (); + item_t *item = items.find (v); + if (!item) { + item = items.push (v); + } + l.unlock (); + return item; + } + + void fini (lock_t &l) + { + if (!items.length) + { + /* No need to lock. */ + items.fini (); + return; + } + l.lock (); + while (items.length) + { + item_t old = items[items.length - 1]; + items.pop (); + l.unlock (); + old.fini (); + l.lock (); + } + items.fini (); + l.unlock (); + } + +}; + + +/* + * Reference-count. + */ + +#define HB_REFERENCE_COUNT_INERT_VALUE 0 +#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD +#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)} + +struct hb_reference_count_t +{ + mutable hb_atomic_int_t ref_count; + + void init (int v = 1) { ref_count.set_relaxed (v); } + int get_relaxed () const { return ref_count.get_relaxed (); } + int inc () const { return ref_count.inc (); } + int dec () const { return ref_count.dec (); } + void fini () { ref_count.set_relaxed (HB_REFERENCE_COUNT_POISON_VALUE); } + + bool is_inert () const { return ref_count.get_relaxed () == HB_REFERENCE_COUNT_INERT_VALUE; } + bool is_valid () const { return ref_count.get_relaxed () > 0; } +}; + + +/* user_data */ + +struct hb_user_data_array_t +{ + struct hb_user_data_item_t { + hb_user_data_key_t *key; + void *data; + hb_destroy_func_t destroy; + + bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; } + bool operator == (hb_user_data_item_t &other) const { return key == other.key; } + + void fini () { if (destroy) destroy (data); } + }; + + hb_mutex_t lock; + hb_lockable_set_t items; + + void init () { 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); + + void fini () { items.fini (lock); lock.fini (); } +}; + + +/* + * Object header + */ + +struct hb_object_header_t +{ + hb_reference_count_t ref_count; + mutable hb_atomic_int_t writable; + hb_atomic_ptr_t user_data; +}; +#define HB_OBJECT_HEADER_STATIC \ + { \ + HB_REFERENCE_COUNT_INIT, \ + HB_ATOMIC_INT_INIT (false), \ + HB_ATOMIC_PTR_INIT (nullptr) \ + } + + +/* + * Object + */ + +template +static inline void hb_object_trace (const Type *obj, const char *function) +{ + DEBUG_MSG (OBJECT, (void *) obj, + "%s refcount=%d", + function, + obj ? obj->header.ref_count.get_relaxed () : 0); +} + +template +static inline Type *hb_object_create () +{ + Type *obj = (Type *) calloc (1, sizeof (Type)); + + if (unlikely (!obj)) + return obj; + + hb_object_init (obj); + hb_object_trace (obj, HB_FUNC); + return obj; +} +template +static inline void hb_object_init (Type *obj) +{ + obj->header.ref_count.init (); + obj->header.writable.set_relaxed (true); + obj->header.user_data.init (); +} +template +static inline bool hb_object_is_inert (const Type *obj) +{ + return unlikely (obj->header.ref_count.is_inert ()); +} +template +static inline bool hb_object_is_valid (const Type *obj) +{ + return likely (obj->header.ref_count.is_valid ()); +} +template +static inline bool hb_object_is_immutable (const Type *obj) +{ + return !obj->header.writable.get_relaxed (); +} +template +static inline void hb_object_make_immutable (const Type *obj) +{ + obj->header.writable.set_relaxed (false); +} +template +static inline Type *hb_object_reference (Type *obj) +{ + hb_object_trace (obj, HB_FUNC); + if (unlikely (!obj || hb_object_is_inert (obj))) + return obj; + assert (hb_object_is_valid (obj)); + obj->header.ref_count.inc (); + return obj; +} +template +static inline bool hb_object_destroy (Type *obj) +{ + hb_object_trace (obj, HB_FUNC); + if (unlikely (!obj || hb_object_is_inert (obj))) + return false; + assert (hb_object_is_valid (obj)); + if (obj->header.ref_count.dec () != 1) + return false; + + hb_object_fini (obj); + return true; +} +template +static inline void hb_object_fini (Type *obj) +{ + obj->header.ref_count.fini (); /* Do this before user_data */ + hb_user_data_array_t *user_data = obj->header.user_data.get (); + if (user_data) + { + user_data->fini (); + free (user_data); + user_data = nullptr; + } +} +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) +{ + if (unlikely (!obj || hb_object_is_inert (obj))) + return false; + assert (hb_object_is_valid (obj)); + +retry: + hb_user_data_array_t *user_data = obj->header.user_data.get (); + if (unlikely (!user_data)) + { + user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1); + if (unlikely (!user_data)) + return false; + user_data->init (); + if (unlikely (!obj->header.user_data.cmpexch (nullptr, user_data))) + { + user_data->fini (); + free (user_data); + goto retry; + } + } + + return user_data->set (key, data, destroy, replace); +} + +template +static inline void *hb_object_get_user_data (Type *obj, + hb_user_data_key_t *key) +{ + if (unlikely (!obj || hb_object_is_inert (obj))) + return nullptr; + assert (hb_object_is_valid (obj)); + hb_user_data_array_t *user_data = obj->header.user_data.get (); + if (!user_data) + return nullptr; + return user_data->get (key); +} + + +#endif /* HB_OBJECT_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-file-private.hh 2019-02-28 12:04:20.038502613 -0800 +++ /dev/null 2019-02-21 13:14:21.200397537 -0800 @@ -1,570 +0,0 @@ -/* - * 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" -#include "hb-ot-head-table.hh" - - -namespace OT { - - -/* - * - * The OpenType Font File - * - */ - - -/* - * Organization of an OpenType Font - */ - -struct OpenTypeFontFile; -struct OffsetTable; -struct TTCHeader; - - -typedef struct TableRecord -{ - int cmp (Tag t) const - { return -t.cmp (tag); } - - static int cmp (const void *pa, const void *pb) - { - const TableRecord *a = (const TableRecord *) pa; - const TableRecord *b = (const TableRecord *) pb; - return b->cmp (a->tag); - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); - } - - Tag tag; /* 4-byte identifier. */ - CheckSum checkSum; /* CheckSum for this table. */ - Offset32 offset; /* Offset from beginning of TrueType font - * file. */ - HBUINT32 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 tables.len; } - inline const TableRecord& get_table (unsigned int i) const - { - return tables[i]; - } - inline unsigned int get_table_tags (unsigned int start_offset, - unsigned int *table_count, /* IN/OUT */ - hb_tag_t *table_tags /* OUT */) const - { - if (table_count) - { - if (start_offset >= tables.len) - *table_count = 0; - else - *table_count = MIN (*table_count, tables.len - start_offset); - - const TableRecord *sub_tables = tables.arrayZ + start_offset; - unsigned int count = *table_count; - for (unsigned int i = 0; i < count; i++) - table_tags[i] = sub_tables[i].tag; - } - return tables.len; - } - inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const - { - Tag t; - t.set (tag); - /* Linear-search for small tables to work around fonts with unsorted - * table list. */ - int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t); - if (table_index) - *table_index = i == -1 ? Index::NOT_FOUND_INDEX : (unsigned int) i; - return i != -1; - } - 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 serialize (hb_serialize_context_t *c, - hb_tag_t sfnt_tag, - Supplier &tags, - Supplier &blobs, - unsigned int table_count) - { - TRACE_SERIALIZE (this); - /* Alloc 12 for the OTHeader. */ - if (unlikely (!c->extend_min (*this))) return_trace (false); - /* Write sfntVersion (bytes 0..3). */ - sfnt_version.set (sfnt_tag); - /* Take space for numTables, searchRange, entrySelector, RangeShift - * and the TableRecords themselves. */ - if (unlikely (!tables.serialize (c, table_count))) return_trace (false); - - const char *dir_end = (const char *) c->head; - HBUINT32 *checksum_adjustment = nullptr; - - /* Write OffsetTables, alloc for and write actual table blobs. */ - for (unsigned int i = 0; i < table_count; i++) - { - TableRecord &rec = tables.arrayZ[i]; - hb_blob_t *blob = blobs[i]; - rec.tag.set (tags[i]); - rec.length.set (hb_blob_get_length (blob)); - rec.offset.serialize (c, this); - - /* Allocate room for the table and copy it. */ - char *start = (char *) c->allocate_size (rec.length); - if (unlikely (!start)) {return false;} - - memcpy (start, hb_blob_get_data (blob, nullptr), rec.length); - - /* 4-byte allignment. */ - if (rec.length % 4) - c->allocate_size (4 - rec.length % 4); - const char *end = (const char *) c->head; - - if (tags[i] == HB_OT_TAG_head && end - start >= head::static_size) - { - head *h = (head *) start; - checksum_adjustment = &h->checkSumAdjustment; - checksum_adjustment->set (0); - } - - rec.checkSum.set_for_data (start, end - start); - } - tags += table_count; - blobs += table_count; - - tables.qsort (); - - if (checksum_adjustment) - { - CheckSum checksum; - - /* The following line is a slower version of the following block. */ - //checksum.set_for_data (this, (const char *) c->head - (const char *) this); - checksum.set_for_data (this, dir_end - (const char *) this); - for (unsigned int i = 0; i < table_count; i++) - { - TableRecord &rec = tables.arrayZ[i]; - checksum.set (checksum + rec.checkSum); - } - - checksum_adjustment->set (0xB1B0AFBAu - checksum); - } - - return_trace (true); - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && tables.sanitize (c)); - } - - protected: - Tag sfnt_version; /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */ - BinSearchArrayOf - tables; - 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) const - { - TRACE_SANITIZE (this); - return_trace (table.sanitize (c, this)); - } - - protected: - Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ - FixedVersion<>version; /* Version of the TTC Header (1.0), - * 0x00010000u */ - LArrayOf > - 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) const - { - TRACE_SANITIZE (this); - if (unlikely (!u.header.version.sanitize (c))) return_trace (false); - switch (u.header.version.major) { - case 2: /* version 2 is compatible with version 1 */ - case 1: return_trace (u.version1.sanitize (c)); - default:return_trace (true); - } - } - - protected: - union { - struct { - Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ - FixedVersion<>version; /* Version of the TTC Header (1.0 or 2.0), - * 0x00010000u or 0x00020000u */ - } header; - TTCHeaderVersion1 version1; - } u; -}; - -/* - * Mac Resource Fork - */ - -struct ResourceRefItem -{ - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - // actual data sanitization is done on ResourceForkHeader sanitizer - return_trace (likely (c->check_struct (this))); - } - - HBINT16 id; /* Resource ID, is really should be signed? */ - HBINT16 nameOffset; /* Offset from beginning of resource name list - * to resource name, minus means there is no */ - HBUINT8 attr; /* Resource attributes */ - HBUINT24 dataOffset; /* Offset from beginning of resource data to - * data for this resource */ - HBUINT32 reserved; /* Reserved for handle to resource */ - public: - DEFINE_SIZE_STATIC (12); -}; - -struct ResourceTypeItem -{ - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - // RefList sanitization is done on ResourceMap sanitizer - return_trace (likely (c->check_struct (this))); - } - - inline unsigned int get_resource_count () const - { - return numRes + 1; - } - - inline bool is_sfnt () const - { - return type == HB_TAG ('s','f','n','t'); - } - - inline const ResourceRefItem& get_ref_item (const void *base, - unsigned int i) const - { - return (base+refList)[i]; - } - - protected: - Tag type; /* Resource type */ - HBUINT16 numRes; /* Number of resource this type in map minus 1 */ - OffsetTo > - refList; /* Offset from beginning of resource type list - * to reference list for this type */ - public: - DEFINE_SIZE_STATIC (8); -}; - -struct ResourceMap -{ - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) - return_trace (false); - for (unsigned int i = 0; i < get_types_count (); ++i) - { - const ResourceTypeItem& type = get_type (i); - if (unlikely (!type.sanitize (c))) - return_trace (false); - for (unsigned int j = 0; j < type.get_resource_count (); ++j) - if (unlikely (!get_ref_item (type, j).sanitize (c))) - return_trace (false); - } - return_trace (true); - } - - inline const ResourceTypeItem& get_type (unsigned int i) const - { - // Why offset from the second byte of the object? I'm not sure - return ((&reserved[2])+typeList)[i]; - } - - inline unsigned int get_types_count () const - { - return nTypes + 1; - } - - inline const ResourceRefItem &get_ref_item (const ResourceTypeItem &type, - unsigned int i) const - { - return type.get_ref_item (&(this+typeList), i); - } - - inline const PString& get_name (const ResourceRefItem &item, - unsigned int i) const - { - if (item.nameOffset == -1) - return Null (PString); - - return StructAtOffset (this, nameList + item.nameOffset); - } - - protected: - HBUINT8 reserved[16]; /* Reserved for copy of resource header */ - LOffsetTo - reserved1; /* Reserved for handle to next resource map */ - HBUINT16 reserved2; /* Reserved for file reference number */ - HBUINT16 attr; /* Resource fork attribute */ - OffsetTo > - typeList; /* Offset from beginning of map to - * resource type list */ - HBUINT16 nameList; /* Offset from beginning of map to - * resource name list */ - HBUINT16 nTypes; /* Number of types in the map minus 1 */ - public: - DEFINE_SIZE_STATIC (30); -}; - -struct ResourceForkHeader -{ - inline unsigned int get_face_count () const - { - const ResourceMap &resource_map = this+map; - for (unsigned int i = 0; i < resource_map.get_types_count (); ++i) - { - const ResourceTypeItem& type = resource_map.get_type (i); - if (type.is_sfnt ()) - return type.get_resource_count (); - } - return 0; - } - - inline const LArrayOf& get_data (const ResourceTypeItem& type, - unsigned int idx) const - { - const ResourceMap &resource_map = this+map; - unsigned int offset = dataOffset; - offset += resource_map.get_ref_item (type, idx).dataOffset; - return StructAtOffset > (this, offset); - } - - inline const OpenTypeFontFace& get_face (unsigned int idx) const - { - const ResourceMap &resource_map = this+map; - for (unsigned int i = 0; i < resource_map.get_types_count (); ++i) - { - const ResourceTypeItem& type = resource_map.get_type (i); - if (type.is_sfnt () && idx < type.get_resource_count ()) - return (OpenTypeFontFace&) get_data (type, idx).arrayZ; - } - return Null (OpenTypeFontFace); - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) - return_trace (false); - - const ResourceMap &resource_map = this+map; - if (unlikely (!resource_map.sanitize (c))) - return_trace (false); - - for (unsigned int i = 0; i < resource_map.get_types_count (); ++i) - { - const ResourceTypeItem& type = resource_map.get_type (i); - for (unsigned int j = 0; j < type.get_resource_count (); ++j) - { - const LArrayOf& data = get_data (type, j); - if (unlikely (!(data.sanitize (c) && - ((OpenTypeFontFace&) data.arrayZ).sanitize (c)))) - return_trace (false); - } - } - - return_trace (true); - } - - protected: - HBUINT32 dataOffset; /* Offset from beginning of resource fork - * to resource data */ - LOffsetTo - map; /* Offset from beginning of resource fork - * to resource map */ - HBUINT32 dataLen; /* Length of resource data */ - HBUINT32 mapLen; /* Length of resource map */ - public: - DEFINE_SIZE_STATIC (16); -}; - -/* - * OpenType Font File - */ - -struct OpenTypeFontFile -{ - static const hb_tag_t tableTag = HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */ - - enum { - CFFTag = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */ - TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */ - TTCTag = HB_TAG ('t','t','c','f'), /* TrueType Collection */ - DFontTag = HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */ - TrueTag = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */ - 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 (); -// case DFontTag: return u.rfHeader.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); -// case DFontTag: return u.rfHeader.get_face (i); - default: return Null(OpenTypeFontFace); - } - } - - inline bool serialize_single (hb_serialize_context_t *c, - hb_tag_t sfnt_tag, - Supplier &tags, - Supplier &blobs, - unsigned int table_count) - { - TRACE_SERIALIZE (this); - assert (sfnt_tag != TTCTag); - if (unlikely (!c->extend_min (*this))) return_trace (false); - return_trace (u.fontFace.serialize (c, sfnt_tag, tags, blobs, table_count)); - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!u.tag.sanitize (c))) return_trace (false); - switch (u.tag) { - case CFFTag: /* All the non-collection tags */ - case TrueTag: - case Typ1Tag: - case TrueTypeTag: return_trace (u.fontFace.sanitize (c)); - case TTCTag: return_trace (u.ttcHeader.sanitize (c)); -// case DFontTag: return_trace (u.rfHeader.sanitize (c)); - default: return_trace (true); - } - } - - protected: - union { - Tag tag; /* 4-byte identifier. */ - OpenTypeFontFace fontFace; - TTCHeader ttcHeader; - ResourceForkHeader rfHeader; - } u; - public: - DEFINE_SIZE_UNION (4, tag); -}; - - -} /* namespace OT */ - - -#endif /* HB_OPEN_FILE_PRIVATE_HH */ --- /dev/null 2019-02-21 13:14:21.200397537 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-file.hh 2019-02-28 12:04:19.886502615 -0800 @@ -0,0 +1,525 @@ +/* + * 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_HH +#define HB_OPEN_FILE_HH + +#include "hb-open-type.hh" +#include "hb-ot-head-table.hh" + + +namespace OT { + + +/* + * + * The OpenType Font File + * + */ + + +/* + * Organization of an OpenType Font + */ + +struct OpenTypeFontFile; +struct OffsetTable; +struct TTCHeader; + + +typedef struct TableRecord +{ + int cmp (Tag t) const { return -t.cmp (tag); } + + static int cmp (const void *pa, const void *pb) + { + const TableRecord *a = (const TableRecord *) pa; + const TableRecord *b = (const TableRecord *) pb; + return b->cmp (a->tag); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + Tag tag; /* 4-byte identifier. */ + CheckSum checkSum; /* CheckSum for this table. */ + Offset32 offset; /* Offset from beginning of TrueType font + * file. */ + HBUINT32 length; /* Length of this table. */ + public: + DEFINE_SIZE_STATIC (16); +} OpenTypeTable; + +typedef struct OffsetTable +{ + friend struct OpenTypeFontFile; + + unsigned int get_table_count () const { return tables.len; } + const TableRecord& get_table (unsigned int i) const + { return tables[i]; } + unsigned int get_table_tags (unsigned int start_offset, + unsigned int *table_count, /* IN/OUT */ + hb_tag_t *table_tags /* OUT */) const + { + if (table_count) + { + if (start_offset >= tables.len) + *table_count = 0; + else + *table_count = MIN (*table_count, tables.len - start_offset); + + const TableRecord *sub_tables = tables.arrayZ + start_offset; + unsigned int count = *table_count; + for (unsigned int i = 0; i < count; i++) + table_tags[i] = sub_tables[i].tag; + } + return tables.len; + } + bool find_table_index (hb_tag_t tag, unsigned int *table_index) const + { + Tag t; + t.set (tag); + return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); + } + 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: + + template + bool serialize (hb_serialize_context_t *c, + hb_tag_t sfnt_tag, + hb_array_t items) + { + TRACE_SERIALIZE (this); + /* Alloc 12 for the OTHeader. */ + if (unlikely (!c->extend_min (*this))) return_trace (false); + /* Write sfntVersion (bytes 0..3). */ + sfnt_version.set (sfnt_tag); + /* Take space for numTables, searchRange, entrySelector, RangeShift + * and the TableRecords themselves. */ + if (unlikely (!tables.serialize (c, items.length))) return_trace (false); + + const char *dir_end = (const char *) c->head; + HBUINT32 *checksum_adjustment = nullptr; + + /* Write OffsetTables, alloc for and write actual table blobs. */ + for (unsigned int i = 0; i < tables.len; i++) + { + TableRecord &rec = tables.arrayZ[i]; + hb_blob_t *blob = items[i].blob; + rec.tag.set (items[i].tag); + rec.length.set (hb_blob_get_length (blob)); + rec.offset.serialize (c, this); + + /* Allocate room for the table and copy it. */ + char *start = (char *) c->allocate_size (rec.length); + if (unlikely (!start)) {return false;} + + memcpy (start, hb_blob_get_data (blob, nullptr), rec.length); + + /* 4-byte alignment. */ + c->align (4); + const char *end = (const char *) c->head; + + if (items[i].tag == HB_OT_TAG_head && + (unsigned) (end - start) >= head::static_size) + { + head *h = (head *) start; + checksum_adjustment = &h->checkSumAdjustment; + checksum_adjustment->set (0); + } + + rec.checkSum.set_for_data (start, end - start); + } + + tables.qsort (); + + if (checksum_adjustment) + { + CheckSum checksum; + + /* The following line is a slower version of the following block. */ + //checksum.set_for_data (this, (const char *) c->head - (const char *) this); + checksum.set_for_data (this, dir_end - (const char *) this); + for (unsigned int i = 0; i < items.length; i++) + { + TableRecord &rec = tables.arrayZ[i]; + checksum.set (checksum + rec.checkSum); + } + + checksum_adjustment->set (0xB1B0AFBAu - checksum); + } + + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && tables.sanitize (c)); + } + + protected: + Tag sfnt_version; /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */ + BinSearchArrayOf + tables; + public: + DEFINE_SIZE_ARRAY (12, tables); +} OpenTypeFontFace; + + +/* + * TrueType Collections + */ + +struct TTCHeaderVersion1 +{ + friend struct TTCHeader; + + unsigned int get_face_count () const { return table.len; } + const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (table.sanitize (c, this)); + } + + protected: + Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ + FixedVersion<>version; /* Version of the TTC Header (1.0), + * 0x00010000u */ + LArrayOf > + 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: + + unsigned int get_face_count () 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; + } + } + 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); + } + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!u.header.version.sanitize (c))) return_trace (false); + switch (u.header.version.major) { + case 2: /* version 2 is compatible with version 1 */ + case 1: return_trace (u.version1.sanitize (c)); + default:return_trace (true); + } + } + + protected: + union { + struct { + Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ + FixedVersion<>version; /* Version of the TTC Header (1.0 or 2.0), + * 0x00010000u or 0x00020000u */ + } header; + TTCHeaderVersion1 version1; + } u; +}; + +/* + * Mac Resource Fork + * + * http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html + */ + +struct ResourceRecord +{ + const OpenTypeFontFace & get_face (const void *data_base) const + { return CastR ((data_base+offset).arrayZ); } + + bool sanitize (hb_sanitize_context_t *c, + const void *data_base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + offset.sanitize (c, data_base) && + get_face (data_base).sanitize (c)); + } + + protected: + HBUINT16 id; /* Resource ID. */ + HBINT16 nameOffset; /* Offset from beginning of resource name list + * to resource name, -1 means there is none. */ + HBUINT8 attrs; /* Resource attributes */ + NNOffsetTo, HBUINT24> + offset; /* Offset from beginning of data block to + * data for this resource */ + HBUINT32 reserved; /* Reserved for handle to resource */ + public: + DEFINE_SIZE_STATIC (12); +}; + +#define HB_TAG_sfnt HB_TAG ('s','f','n','t') + +struct ResourceTypeRecord +{ + unsigned int get_resource_count () const + { return tag == HB_TAG_sfnt ? resCountM1 + 1 : 0; } + + bool is_sfnt () const { return tag == HB_TAG_sfnt; } + + const ResourceRecord& get_resource_record (unsigned int i, + const void *type_base) const + { return (type_base+resourcesZ).as_array (get_resource_count ())[i]; } + + bool sanitize (hb_sanitize_context_t *c, + const void *type_base, + const void *data_base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + resourcesZ.sanitize (c, type_base, + get_resource_count (), + data_base)); + } + + protected: + Tag tag; /* Resource type. */ + HBUINT16 resCountM1; /* Number of resources minus 1. */ + NNOffsetTo > + resourcesZ; /* Offset from beginning of resource type list + * to reference item list for this type. */ + public: + DEFINE_SIZE_STATIC (8); +}; + +struct ResourceMap +{ + unsigned int get_face_count () const + { + unsigned int count = get_type_count (); + for (unsigned int i = 0; i < count; i++) + { + const ResourceTypeRecord& type = get_type_record (i); + if (type.is_sfnt ()) + return type.get_resource_count (); + } + return 0; + } + + const OpenTypeFontFace& get_face (unsigned int idx, + const void *data_base) const + { + unsigned int count = get_type_count (); + for (unsigned int i = 0; i < count; i++) + { + const ResourceTypeRecord& type = get_type_record (i); + /* The check for idx < count is here because ResourceRecord is NOT null-safe. + * Because an offset of 0 there does NOT mean null. */ + if (type.is_sfnt () && idx < type.get_resource_count ()) + return type.get_resource_record (idx, &(this+typeList)).get_face (data_base); + } + return Null (OpenTypeFontFace); + } + + bool sanitize (hb_sanitize_context_t *c, const void *data_base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + typeList.sanitize (c, this, + &(this+typeList), + data_base)); + } + + private: + unsigned int get_type_count () const { return (this+typeList).lenM1 + 1; } + + const ResourceTypeRecord& get_type_record (unsigned int i) const + { return (this+typeList)[i]; } + + protected: + HBUINT8 reserved0[16]; /* Reserved for copy of resource header */ + HBUINT32 reserved1; /* Reserved for handle to next resource map */ + HBUINT16 resreved2; /* Reserved for file reference number */ + HBUINT16 attrs; /* Resource fork attribute */ + NNOffsetTo > + typeList; /* Offset from beginning of map to + * resource type list */ + Offset16 nameList; /* Offset from beginning of map to + * resource name list */ + public: + DEFINE_SIZE_STATIC (28); +}; + +struct ResourceForkHeader +{ + unsigned int get_face_count () const + { return (this+map).get_face_count (); } + + const OpenTypeFontFace& get_face (unsigned int idx, + unsigned int *base_offset = nullptr) const + { + const OpenTypeFontFace &face = (this+map).get_face (idx, &(this+data)); + if (base_offset) + *base_offset = (const char *) &face - (const char *) this; + return face; + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + data.sanitize (c, this, dataLen) && + map.sanitize (c, this, &(this+data))); + } + + protected: + LNNOffsetTo > + data; /* Offset from beginning of resource fork + * to resource data */ + LNNOffsetTo + map; /* Offset from beginning of resource fork + * to resource map */ + HBUINT32 dataLen; /* Length of resource data */ + HBUINT32 mapLen; /* Length of resource map */ + public: + DEFINE_SIZE_STATIC (16); +}; + +/* + * OpenType Font File + */ + +struct OpenTypeFontFile +{ + enum { + CFFTag = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */ + TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */ + TTCTag = HB_TAG ('t','t','c','f'), /* TrueType Collection */ + DFontTag = HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */ + TrueTag = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */ + Typ1Tag = HB_TAG ('t','y','p','1') /* Obsolete Apple Type1 font in SFNT container */ + }; + + hb_tag_t get_tag () const { return u.tag; } + + unsigned int get_face_count () 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 (); + case DFontTag: return u.rfHeader.get_face_count (); + default: return 0; + } + } + const OpenTypeFontFace& get_face (unsigned int i, unsigned int *base_offset = nullptr) const + { + if (base_offset) + *base_offset = 0; + 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); + case DFontTag: return u.rfHeader.get_face (i, base_offset); + default: return Null(OpenTypeFontFace); + } + } + + template + bool serialize_single (hb_serialize_context_t *c, + hb_tag_t sfnt_tag, + hb_array_t items) + { + TRACE_SERIALIZE (this); + assert (sfnt_tag != TTCTag); + if (unlikely (!c->extend_min (*this))) return_trace (false); + return_trace (u.fontFace.serialize (c, sfnt_tag, items)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!u.tag.sanitize (c))) return_trace (false); + switch (u.tag) { + case CFFTag: /* All the non-collection tags */ + case TrueTag: + case Typ1Tag: + case TrueTypeTag: return_trace (u.fontFace.sanitize (c)); + case TTCTag: return_trace (u.ttcHeader.sanitize (c)); + case DFontTag: return_trace (u.rfHeader.sanitize (c)); + default: return_trace (true); + } + } + + protected: + union { + Tag tag; /* 4-byte identifier. */ + OpenTypeFontFace fontFace; + TTCHeader ttcHeader; + ResourceForkHeader rfHeader; + } u; + public: + DEFINE_SIZE_UNION (4, tag); +}; + + +} /* namespace OT */ + + +#endif /* HB_OPEN_FILE_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type-private.hh 2019-02-28 12:04:20.430502607 -0800 +++ /dev/null 2019-02-21 13:14:21.200397537 -0800 @@ -1,1300 +0,0 @@ -/* - * 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-debug.hh" -#include "hb-blob-private.hh" -#include "hb-face-private.hh" - - -namespace OT { - - - -/* - * Casts - */ - -/* Cast to struct T, reference to reference */ -template -static inline const Type& CastR(const TObject &X) -{ return reinterpret_cast (X); } -template -static inline Type& CastR(TObject &X) -{ return reinterpret_cast (X); } - -/* Cast to struct T, pointer to pointer */ -template -static inline const Type* CastP(const TObject *X) -{ return reinterpret_cast (X); } -template -static 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 -static inline const Type& StructAtOffset(const void *P, unsigned int offset) -{ return * reinterpret_cast ((const char *) P + offset); } -template -static 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 -static inline const Type& StructAfter(const TObject &X) -{ return StructAtOffset(&X, X.get_size()); } -template -static 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 \ - { \ - static_assert ((_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); \ - inline unsigned int get_size (void) const { return (size); } - -#define DEFINE_SIZE_UNION(size, _member) \ - DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (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) - - - -/* - * Dispatch - */ - -template -struct hb_dispatch_context_t -{ - static const unsigned int max_debug_depth = MaxDebugDepth; - typedef Return return_t; - template - inline bool may_dispatch (const T *obj, const F *format) { return true; } - static return_t no_dispatch_return_value (void) { return Context::default_return_value (); } -}; - - -/* - * Sanitize - */ - -/* This limits sanitizing time on really broken fonts. */ -#ifndef HB_SANITIZE_MAX_EDITS -#define HB_SANITIZE_MAX_EDITS 32 -#endif -#ifndef HB_SANITIZE_MAX_OPS_FACTOR -#define HB_SANITIZE_MAX_OPS_FACTOR 8 -#endif -#ifndef HB_SANITIZE_MAX_OPS_MIN -#define HB_SANITIZE_MAX_OPS_MIN 16384 -#endif - -struct hb_sanitize_context_t : - hb_dispatch_context_t -{ - inline hb_sanitize_context_t (void) : - debug_depth (0), - start (nullptr), end (nullptr), - writable (false), edit_count (0), max_ops (0), - blob (nullptr), - num_glyphs (0) {} - - inline const char *get_name (void) { return "SANITIZE"; } - template - inline bool may_dispatch (const T *obj, const F *format) - { return format->sanitize (this); } - template - inline return_t dispatch (const T &obj) { return obj.sanitize (this); } - static return_t default_return_value (void) { return true; } - static return_t no_dispatch_return_value (void) { return false; } - bool stop_sublookup_iteration (const return_t r) const { return !r; } - - 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, nullptr); - this->end = this->start + this->blob->length; - assert (this->start <= this->end); /* Must not overflow. */ - this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR, - (unsigned) HB_SANITIZE_MAX_OPS_MIN); - this->edit_count = 0; - this->debug_depth = 0; - - DEBUG_MSG_LEVEL (SANITIZE, start, 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->start, 0, -1, - "end [%p..%p] %u edit requests", - this->start, this->end, this->edit_count); - - hb_blob_destroy (this->blob); - this->blob = nullptr; - this->start = this->end = nullptr; - } - - inline bool check_range (const void *base, unsigned int len) const - { - const char *p = (const char *) base; - bool ok = this->max_ops-- > 0 && - this->start <= p && - p <= this->end && - (unsigned int) (this->end - p) >= len; - - DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, - "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s", - p, p + len, len, - this->start, this->end, - ok ? "OK" : "OUT-OF-RANGE"); - - return likely (ok); - } - - 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); - unsigned int array_size = record_size * len; - bool ok = !overflows && this->check_range (base, array_size); - - DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, - "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s", - p, p + (record_size * len), record_size, len, (unsigned int) array_size, - this->start, this->end, - overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE"); - - return likely (ok); - } - - 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, unsigned int len) - { - if (this->edit_count >= HB_SANITIZE_MAX_EDITS) - return false; - - const char *p = (const char *) base; - this->edit_count++; - - DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, - "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 this->writable; - } - - template - inline bool try_set (const Type *obj, const ValueType &v) { - if (this->may_edit (obj, obj->static_size)) { - const_cast (obj)->set (v); - return true; - } - return false; - } - - mutable unsigned int debug_depth; - const char *start, *end; - bool writable; - unsigned int edit_count; - mutable int max_ops; - hb_blob_t *blob; - unsigned int num_glyphs; -}; - - - -/* Template to sanitize an object. */ -template -struct Sanitizer -{ - inline Sanitizer (void) {} - - inline hb_blob_t *sanitize (hb_blob_t *blob) { - bool sane; - - /* TODO is_sane() stuff */ - - c->init (blob); - - retry: - DEBUG_MSG_FUNC (SANITIZE, c->start, "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, c->start, "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, c->start, "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, nullptr); - c->end = c->start + blob->length; - - if (c->start) { - c->writable = true; - /* ok, we made it writable by relocating. try again */ - DEBUG_MSG_FUNC (SANITIZE, c->start, "retry"); - goto retry; - } - } - } - - c->end_processing (); - - DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED"); - if (sane) - { - blob->lock (); - return blob; - } - else - { - hb_blob_destroy (blob); - return hb_blob_get_empty (); - } - } - - inline void set_num_glyphs (unsigned int num_glyphs) { c->num_glyphs = num_glyphs; } - - private: - hb_sanitize_context_t c[1]; -}; - - - -/* - * Serialize - */ - - -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 nullptr; - } - 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 nullptr; - 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 nullptr; - 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 nullptr; - return reinterpret_cast (&obj); - } - - inline void truncate (void *new_head) - { - assert (this->start < new_head && new_head <= this->head); - this->head = (char *) new_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_, unsigned int stride_=sizeof(Type)) - { - head = array; - len = len_; - stride = stride_; - } - inline const Type operator [] (unsigned int i) const - { - if (unlikely (i >= len)) return Type (); - return * (const Type *) (const void *) ((const char *) head + stride * i); - } - - inline Supplier & operator += (unsigned int count) - { - if (unlikely (count > len)) - count = len; - len -= count; - head = (const Type *) (const void *) ((const char *) head + stride * count); - return *this; - } - - private: - inline Supplier (const Supplier &); /* Disallow copy */ - inline Supplier& operator= (const Supplier &); /* Disallow copy */ - - unsigned int len; - unsigned int stride; - 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 V) - { - v = V; - } - inline operator Type (void) const - { - return v; - } - private: uint8_t v; -}; -template -struct BEInt -{ - public: - inline void set (Type V) - { - v[0] = (V >> 8) & 0xFF; - v[1] = (V ) & 0xFF; - } - inline operator Type (void) const - { - return (v[0] << 8) - + (v[1] ); - } - private: uint8_t v[2]; -}; -template -struct BEInt -{ - public: - inline void set (Type V) - { - v[0] = (V >> 16) & 0xFF; - v[1] = (V >> 8) & 0xFF; - v[2] = (V ) & 0xFF; - } - inline operator Type (void) const - { - return (v[0] << 16) - + (v[1] << 8) - + (v[2] ); - } - private: uint8_t v[3]; -}; -template -struct BEInt -{ - public: - inline void set (Type V) - { - v[0] = (V >> 24) & 0xFF; - v[1] = (V >> 16) & 0xFF; - v[2] = (V >> 8) & 0xFF; - v[3] = (V ) & 0xFF; - } - inline operator Type (void) const - { - return (v[0] << 24) - + (v[1] << 16) - + (v[2] << 8) - + (v[3] ); - } - private: uint8_t v[4]; -}; - -/* 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 (Type) v == (Type) o.v; } - inline bool operator != (const IntType &o) const { return !(*this == o); } - static inline int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } - template - inline int cmp (Type2 a) const - { - Type b = v; - if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int)) - return (int) a - (int) b; - else - return a < b ? -1 : a == b ? 0 : +1; - } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); - } - protected: - BEInt v; - public: - DEFINE_SIZE_STATIC (Size); -}; - -typedef IntType HBUINT8; /* 8-bit unsigned integer. */ -typedef IntType HBINT8; /* 8-bit signed integer. */ -typedef IntType HBUINT16; /* 16-bit unsigned integer. */ -typedef IntType HBINT16; /* 16-bit signed integer. */ -typedef IntType HBUINT32; /* 32-bit unsigned integer. */ -typedef IntType HBINT32; /* 32-bit signed integer. */ -typedef IntType HBUINT24; /* 24-bit unsigned integer. */ - -/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */ -typedef HBINT16 FWORD; - -/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */ -typedef HBUINT16 UFWORD; - -/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */ -struct F2DOT14 : HBINT16 -{ - // 16384 means 1<<14 - inline float to_float (void) const { return ((int32_t) v) / 16384.f; } - inline void set_float (float f) { v.set (round (f * 16384.f)); } - public: - DEFINE_SIZE_STATIC (2); -}; - -/* 32-bit signed fixed-point number (16.16). */ -struct Fixed : HBINT32 -{ - // 65536 means 1<<16 - inline float to_float (void) const { return ((int32_t) v) / 65536.f; } - inline void set_float (float f) { v.set (round (f * 65536.f)); } - public: - DEFINE_SIZE_STATIC (4); -}; - -/* 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) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); - } - protected: - HBINT32 major; - HBUINT32 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 : HBUINT32 -{ - /* 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 (OT, Tag, " "); - -/* Glyph index number, same as uint16 (length = 16 bits) */ -typedef HBUINT16 GlyphID; - -/* Name-table index, same as uint16 (length = 16 bits) */ -typedef HBUINT16 NameID; - -/* Script/language-system/feature index */ -struct Index : HBUINT16 { - static const unsigned int NOT_FOUND_INDEX = 0xFFFFu; -}; -DEFINE_NULL_DATA (OT, Index, "\xff\xff"); - -/* Offset, Null offset = 0 */ -template -struct Offset : Type -{ - inline bool is_null (void) const { return 0 == *this; } - - inline void *serialize (hb_serialize_context_t *c, const void *base) - { - void *t = c->start_embed (); - this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ - return t; - } - - public: - DEFINE_SIZE_STATIC (sizeof(Type)); -}; - -typedef Offset Offset16; -typedef Offset Offset32; - - -/* CheckSum */ -struct CheckSum : HBUINT32 -{ - /* This is reference implementation from the spec. */ - static inline uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length) - { - uint32_t Sum = 0L; - assert (0 == (Length & 3)); - const HBUINT32 *EndPtr = Table + Length / HBUINT32::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 HBUINT32 *) data, length)); } - - public: - DEFINE_SIZE_STATIC (4); -}; - - -/* - * Version Numbers - */ - -template -struct FixedVersion -{ - inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); - } - - FixedType major; - FixedType minor; - public: - DEFINE_SIZE_STATIC (2 * sizeof(FixedType)); -}; - - - -/* - * Template subclasses of Offset that do the dereferencing. - * Use: (base+offset) - */ - -template -struct OffsetTo : Offset -{ - inline const Type& operator () (const void *base) const - { - unsigned int offset = *this; - if (unlikely (!offset)) return Null(Type); - return StructAtOffset (base, offset); - } - inline Type& operator () (void *base) const - { - unsigned int offset = *this; - if (unlikely (!offset)) return Crap(Type); - return StructAtOffset (base, offset); - } - - inline Type& serialize (hb_serialize_context_t *c, const void *base) - { - return * (Type *) Offset::serialize (c, base); - } - - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const - { - TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) return_trace (false); - unsigned int offset = *this; - if (unlikely (!offset)) return_trace (true); - if (unlikely (!c->check_range (base, offset))) return_trace (false); - const Type &obj = StructAtOffset (base, offset); - return_trace (likely (obj.sanitize (c)) || neuter (c)); - } - template - inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const - { - TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) return_trace (false); - unsigned int offset = *this; - if (unlikely (!offset)) return_trace (true); - if (unlikely (!c->check_range (base, offset))) return_trace (false); - const Type &obj = StructAtOffset (base, offset); - return_trace (likely (obj.sanitize (c, user_data)) || neuter (c)); - } - - /* Set the offset to Null */ - inline bool neuter (hb_sanitize_context_t *c) const { - return c->try_set (this, 0); - } - DEFINE_SIZE_STATIC (sizeof(OffsetType)); -}; -template struct LOffsetTo : OffsetTo {}; -template -static inline const Type& operator + (const Base &base, const OffsetTo &offset) { return offset (base); } -template -static inline Type& operator + (Base &base, OffsetTo &offset) { return offset (base); } - - -/* - * Array Types - */ - - -/* TODO Use it in ArrayOf, HeadlessArrayOf, and other places around the code base?? */ -template -struct UnsizedArrayOf -{ - inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; } - inline Type& operator [] (unsigned int i) { return arrayZ[i]; } - - inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const - { - TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c, count))) return_trace (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 && arrayZ[0].sanitize (c)); - - return_trace (true); - } - inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const - { - TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c, count))) return_trace (false); - for (unsigned int i = 0; i < count; i++) - if (unlikely (!arrayZ[i].sanitize (c, base))) - return_trace (false); - return_trace (true); - } - template - inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const - { - TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c, count))) return_trace (false); - for (unsigned int i = 0; i < count; i++) - if (unlikely (!arrayZ[i].sanitize (c, base, user_data))) - return_trace (false); - return_trace (true); - } - - inline bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const - { - TRACE_SANITIZE (this); - return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count)); - } - - public: - Type arrayZ[VAR]; - public: - DEFINE_SIZE_ARRAY (0, arrayZ); -}; - -/* Unsized array of offset's */ -template -struct UnsizedOffsetArrayOf : UnsizedArrayOf > {}; - -/* Unsized array of offsets relative to the beginning of the array itself. */ -template -struct UnsizedOffsetListOf : UnsizedOffsetArrayOf -{ - inline const Type& operator [] (unsigned int i) const - { - return this+this->arrayZ[i]; - } - - inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const - { - TRACE_SANITIZE (this); - return_trace ((UnsizedOffsetArrayOf::sanitize (c, count, this))); - } - template - inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const - { - TRACE_SANITIZE (this); - return_trace ((UnsizedOffsetArrayOf::sanitize (c, count, this, user_data))); - } -}; - - -/* An array with a number of elements. */ -template -struct ArrayOf -{ - 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 arrayZ + start_offset; - } - - inline const Type& operator [] (unsigned int i) const - { - if (unlikely (i >= len)) return Null(Type); - return arrayZ[i]; - } - inline Type& operator [] (unsigned int i) - { - if (unlikely (i >= len)) return Crap(Type); - return arrayZ[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 (false); - len.set (items_len); /* TODO(serialize) Overflow? */ - if (unlikely (!c->extend (*this))) return_trace (false); - return_trace (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 (false); - for (unsigned int i = 0; i < items_len; i++) - arrayZ[i] = items[i]; - items += items_len; - return_trace (true); - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c))) return_trace (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 && arrayZ[0].sanitize (c)); - - return_trace (true); - } - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const - { - TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c))) return_trace (false); - unsigned int count = len; - for (unsigned int i = 0; i < count; i++) - if (unlikely (!arrayZ[i].sanitize (c, base))) - return_trace (false); - return_trace (true); - } - template - inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const - { - TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c))) return_trace (false); - unsigned int count = len; - for (unsigned int i = 0; i < count; i++) - if (unlikely (!arrayZ[i].sanitize (c, base, user_data))) - return_trace (false); - return_trace (true); - } - - template - inline int lsearch (const SearchType &x) const - { - unsigned int count = len; - for (unsigned int i = 0; i < count; i++) - if (!this->arrayZ[i].cmp (x)) - return i; - return -1; - } - - inline void qsort (void) - { - ::qsort (arrayZ, len, sizeof (Type), Type::cmp); - } - - private: - inline bool sanitize_shallow (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (len.sanitize (c) && c->check_array (arrayZ, Type::static_size, len)); - } - - public: - LenType len; - Type arrayZ[VAR]; - public: - DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); -}; -template struct LArrayOf : ArrayOf {}; -typedef ArrayOf PString; - -/* Array of Offset's */ -template -struct OffsetArrayOf : ArrayOf > {}; - -/* 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->arrayZ[i]; - } - inline const Type& operator [] (unsigned int i) - { - if (unlikely (i >= this->len)) return Crap(Type); - return this+this->arrayZ[i]; - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (OffsetArrayOf::sanitize (c, this)); - } - template - inline bool sanitize (hb_sanitize_context_t *c, T user_data) const - { - TRACE_SANITIZE (this); - return_trace (OffsetArrayOf::sanitize (c, this, user_data)); - } -}; - - -/* An array starting at second element. */ -template -struct HeadlessArrayOf -{ - inline const Type& operator [] (unsigned int i) const - { - if (unlikely (i >= len || !i)) return Null(Type); - return arrayZ[i-1]; - } - inline Type& operator [] (unsigned int i) - { - if (unlikely (i >= len || !i)) return Crap(Type); - return arrayZ[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 (false); - len.set (items_len); /* TODO(serialize) Overflow? */ - if (unlikely (!items_len)) return_trace (true); - if (unlikely (!c->extend (*this))) return_trace (false); - for (unsigned int i = 0; i < items_len - 1; i++) - arrayZ[i] = items[i]; - items += items_len - 1; - return_trace (true); - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c))) return_trace (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 && arrayZ[0].sanitize (c)); - - return_trace (true); - } - - private: - inline bool sanitize_shallow (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (len.sanitize (c) && - (!len || c->check_array (arrayZ, Type::static_size, len - 1))); - } - - public: - LenType len; - Type arrayZ[VAR]; - public: - DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); -}; - - -/* - * An array with sorted elements. Supports binary searching. - */ -template -struct SortedArrayOf : ArrayOf -{ - template - inline int bsearch (const SearchType &x) const - { - /* Hand-coded bsearch here since this is in the hot inner loop. */ - const Type *arr = this->arrayZ; - int min = 0, max = (int) this->len - 1; - while (min <= max) - { - int mid = (min + max) / 2; - int c = arr[mid].cmp (x); - if (c < 0) - max = mid - 1; - else if (c > 0) - min = mid + 1; - else - return mid; - } - return -1; - } -}; - -/* - * Binary-search arrays - */ - -struct BinSearchHeader -{ - inline operator uint32_t (void) const { return len; } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); - } - - inline void set (unsigned int v) - { - len.set (v); - assert (len == v); - entrySelector.set (MAX (1u, _hb_bit_storage (v)) - 1); - searchRange.set (16 * (1u << entrySelector)); - rangeShift.set (v * 16 > searchRange - ? 16 * v - searchRange - : 0); - } - - protected: - HBUINT16 len; - HBUINT16 searchRange; - HBUINT16 entrySelector; - HBUINT16 rangeShift; - - public: - DEFINE_SIZE_STATIC (8); -}; - -template -struct BinSearchArrayOf : SortedArrayOf {}; - - -/* Lazy struct and blob loaders. */ - -/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */ -template -struct hb_lazy_loader_t -{ - inline void init (hb_face_t *face_) - { - face = face_; - instance = nullptr; - } - - inline void fini (void) - { - if (instance && instance != &Null(T)) - { - instance->fini(); - free (instance); - } - } - - inline const T* get (void) const - { - retry: - T *p = (T *) hb_atomic_ptr_get (&instance); - if (unlikely (!p)) - { - p = (T *) calloc (1, sizeof (T)); - if (unlikely (!p)) - p = const_cast (&Null(T)); - else - p->init (face); - if (unlikely (!hb_atomic_ptr_cmpexch (const_cast(&instance), nullptr, p))) - { - if (p != &Null(T)) - p->fini (); - goto retry; - } - } - return p; - } - - inline const T* operator-> (void) const - { - return get (); - } - - private: - hb_face_t *face; - T *instance; -}; - -/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */ -template -struct hb_table_lazy_loader_t -{ - inline void init (hb_face_t *face_) - { - face = face_; - blob = nullptr; - } - - inline void fini (void) - { - hb_blob_destroy (blob); - } - - inline const T* get (void) const - { - retry: - hb_blob_t *blob_ = (hb_blob_t *) hb_atomic_ptr_get (&blob); - if (unlikely (!blob_)) - { - blob_ = OT::Sanitizer().sanitize (face->reference_table (T::tableTag)); - if (!hb_atomic_ptr_cmpexch (&blob, nullptr, blob_)) - { - hb_blob_destroy (blob_); - goto retry; - } - blob = blob_; - } - return blob_->as (); - } - - inline const T* operator-> (void) const - { - return get(); - } - - private: - hb_face_t *face; - mutable hb_blob_t *blob; -}; - - -} /* namespace OT */ - - -#endif /* HB_OPEN_TYPE_PRIVATE_HH */ --- /dev/null 2019-02-21 13:14:21.200397537 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type.hh 2019-02-28 12:04:20.278502609 -0800 @@ -0,0 +1,1008 @@ +/* + * 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_HH +#define HB_OPEN_TYPE_HH + +#include "hb.hh" +#include "hb-blob.hh" +#include "hb-face.hh" +#include "hb-machinery.hh" +#include "hb-subset.hh" + + +namespace OT { + + +/* + * + * 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 hb_signedness_int; +template <> struct hb_signedness_int { typedef unsigned int value; }; +template <> struct hb_signedness_int { typedef signed int value; }; + +/* Integer types in big-endian order and no alignment requirement */ +template +struct IntType +{ + typedef Type type; + typedef typename hb_signedness_int::value>::value wide_type; + + void set (wide_type i) { v.set (i); } + operator wide_type () const { return v; } + bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } + bool operator != (const IntType &o) const { return !(*this == o); } + static int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } + template + int cmp (Type2 a) const + { + Type b = v; + if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int)) + return (int) a - (int) b; + else + return a < b ? -1 : a == b ? 0 : +1; + } + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + protected: + BEInt v; + public: + DEFINE_SIZE_STATIC (Size); +}; + +typedef IntType HBUINT8; /* 8-bit unsigned integer. */ +typedef IntType HBINT8; /* 8-bit signed integer. */ +typedef IntType HBUINT16; /* 16-bit unsigned integer. */ +typedef IntType HBINT16; /* 16-bit signed integer. */ +typedef IntType HBUINT32; /* 32-bit unsigned integer. */ +typedef IntType HBINT32; /* 32-bit signed integer. */ +/* Note: we cannot defined a signed HBINT24 because there's no corresponding C type. + * Works for unsigned, but not signed, since we rely on compiler for sign-extension. */ +typedef IntType HBUINT24; /* 24-bit unsigned integer. */ + +/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */ +typedef HBINT16 FWORD; + +/* 32-bit signed integer (HBINT32) that describes a quantity in FUnits. */ +typedef HBINT32 FWORD32; + +/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */ +typedef HBUINT16 UFWORD; + +/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */ +struct F2DOT14 : HBINT16 +{ + // 16384 means 1<<14 + float to_float () const { return ((int32_t) v) / 16384.f; } + void set_float (float f) { v.set (round (f * 16384.f)); } + public: + DEFINE_SIZE_STATIC (2); +}; + +/* 32-bit signed fixed-point number (16.16). */ +struct Fixed : HBINT32 +{ + // 65536 means 1<<16 + float to_float () const { return ((int32_t) v) / 65536.f; } + void set_float (float f) { v.set (round (f * 65536.f)); } + public: + DEFINE_SIZE_STATIC (4); +}; + +/* 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 +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + protected: + HBINT32 major; + HBUINT32 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 : HBUINT32 +{ + /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ + operator const char* () const { return reinterpret_cast (&this->v); } + operator char* () { return reinterpret_cast (&this->v); } + public: + DEFINE_SIZE_STATIC (4); +}; + +/* Glyph index number, same as uint16 (length = 16 bits) */ +typedef HBUINT16 GlyphID; + +/* Script/language-system/feature index */ +struct Index : HBUINT16 { + static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFu; +}; +DECLARE_NULL_NAMESPACE_BYTES (OT, Index); + +typedef Index NameID; + +/* Offset, Null offset = 0 */ +template +struct Offset : Type +{ + typedef Type type; + + bool is_null () const { return has_null && 0 == *this; } + + void *serialize (hb_serialize_context_t *c, const void *base) + { + void *t = c->start_embed (); + this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ + return t; + } + + public: + DEFINE_SIZE_STATIC (sizeof (Type)); +}; + +typedef Offset Offset16; +typedef Offset Offset32; + + +/* CheckSum */ +struct CheckSum : HBUINT32 +{ + /* This is reference implementation from the spec. */ + static uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length) + { + uint32_t Sum = 0L; + assert (0 == (Length & 3)); + const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size; + + while (Table < EndPtr) + Sum += *Table++; + return Sum; + } + + /* Note: data should be 4byte aligned and have 4byte padding at the end. */ + void set_for_data (const void *data, unsigned int length) + { set (CalcTableChecksum ((const HBUINT32 *) data, length)); } + + public: + DEFINE_SIZE_STATIC (4); +}; + + +/* + * Version Numbers + */ + +template +struct FixedVersion +{ + uint32_t to_int () const { return (major << (sizeof (FixedType) * 8)) + minor; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + FixedType major; + FixedType minor; + public: + DEFINE_SIZE_STATIC (2 * sizeof (FixedType)); +}; + + +/* + * Template subclasses of Offset that do the dereferencing. + * Use: (base+offset) + */ + +template +struct _hb_has_null +{ + static const Type *get_null () { return nullptr; } + static Type *get_crap () { return nullptr; } +}; +template +struct _hb_has_null +{ + static const Type *get_null () { return &Null(Type); } + static Type *get_crap () { return &Crap(Type); } +}; + +template +struct OffsetTo : Offset +{ + const Type& operator () (const void *base) const + { + if (unlikely (this->is_null ())) return *_hb_has_null::get_null (); + return StructAtOffset (base, *this); + } + Type& operator () (void *base) const + { + if (unlikely (this->is_null ())) return *_hb_has_null::get_crap (); + return StructAtOffset (base, *this); + } + + Type& serialize (hb_serialize_context_t *c, const void *base) + { + return * (Type *) Offset::serialize (c, base); + } + + template + void serialize_subset (hb_subset_context_t *c, const T &src, const void *base) + { + if (&src == &Null (T)) + { + this->set (0); + return; + } + serialize (c->serializer, base); + if (!src.subset (c)) + this->set (0); + } + + bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + if (unlikely (!c->check_struct (this))) return_trace (false); + if (unlikely (this->is_null ())) return_trace (true); + if (unlikely (!c->check_range (base, *this))) return_trace (false); + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (sanitize_shallow (c, base) && + (this->is_null () || + StructAtOffset (base, *this).sanitize (c) || + neuter (c))); + } + template + bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1) const + { + TRACE_SANITIZE (this); + return_trace (sanitize_shallow (c, base) && + (this->is_null () || + StructAtOffset (base, *this).sanitize (c, d1) || + neuter (c))); + } + template + bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2) const + { + TRACE_SANITIZE (this); + return_trace (sanitize_shallow (c, base) && + (this->is_null () || + StructAtOffset (base, *this).sanitize (c, d1, d2) || + neuter (c))); + } + template + bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2, T3 d3) const + { + TRACE_SANITIZE (this); + return_trace (sanitize_shallow (c, base) && + (this->is_null () || + StructAtOffset (base, *this).sanitize (c, d1, d2, d3) || + neuter (c))); + } + + /* Set the offset to Null */ + bool neuter (hb_sanitize_context_t *c) const + { + if (!has_null) return false; + return c->try_set (this, 0); + } + DEFINE_SIZE_STATIC (sizeof (OffsetType)); +}; +/* Partial specializations. */ +template struct LOffsetTo : OffsetTo {}; +template struct NNOffsetTo : OffsetTo {}; +template struct LNNOffsetTo : OffsetTo {}; + +template +static inline const Type& operator + (const Base &base, const OffsetTo &offset) { return offset (base); } +template +static inline Type& operator + (Base &base, OffsetTo &offset) { return offset (base); } + + +/* + * Array Types + */ + +template +struct UnsizedArrayOf +{ + typedef Type item_t; + static constexpr unsigned item_size = hb_static_size (Type); + + HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type); + + const Type& operator [] (int i_) const + { + unsigned int i = (unsigned int) i_; + const Type *p = &arrayZ[i]; + if (unlikely (p < arrayZ)) return Null (Type); /* Overflowed. */ + return *p; + } + Type& operator [] (int i_) + { + unsigned int i = (unsigned int) i_; + Type *p = &arrayZ[i]; + if (unlikely (p < arrayZ)) return Crap (Type); /* Overflowed. */ + return *p; + } + + unsigned int get_size (unsigned int len) const + { return len * Type::static_size; } + + template operator T * () { return arrayZ; } + template operator const T * () const { return arrayZ; } + hb_array_t as_array (unsigned int len) + { return hb_array (arrayZ, len); } + hb_array_t as_array (unsigned int len) const + { return hb_array (arrayZ, len); } + operator hb_array_t () { return as_array (); } + operator hb_array_t () const { return as_array (); } + + template + Type &lsearch (unsigned int len, const T &x, Type ¬_found = Crap (Type)) + { return *as_array (len).lsearch (x, ¬_found); } + template + const Type &lsearch (unsigned int len, const T &x, const Type ¬_found = Null (Type)) const + { return *as_array (len).lsearch (x, ¬_found); } + + void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1) + { as_array (len).qsort (start, end); } + + bool sanitize (hb_sanitize_context_t *c, unsigned int count) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c, count))) return_trace (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 && arrayZ[0].sanitize (c)); + + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c, count))) return_trace (false); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!arrayZ[i].sanitize (c, base))) + return_trace (false); + return_trace (true); + } + template + bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c, count))) return_trace (false); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!arrayZ[i].sanitize (c, base, user_data))) + return_trace (false); + return_trace (true); + } + + bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const + { + TRACE_SANITIZE (this); + return_trace (c->check_array (arrayZ, count)); + } + + public: + Type arrayZ[VAR]; + public: + DEFINE_SIZE_UNBOUNDED (0); +}; + +/* Unsized array of offset's */ +template +struct UnsizedOffsetArrayOf : UnsizedArrayOf > {}; + +/* Unsized array of offsets relative to the beginning of the array itself. */ +template +struct UnsizedOffsetListOf : UnsizedOffsetArrayOf +{ + const Type& operator [] (int i_) const + { + unsigned int i = (unsigned int) i_; + const OffsetTo *p = &this->arrayZ[i]; + if (unlikely (p < this->arrayZ)) return Null (Type); /* Overflowed. */ + return this+*p; + } + Type& operator [] (int i_) + { + unsigned int i = (unsigned int) i_; + const OffsetTo *p = &this->arrayZ[i]; + if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */ + return this+*p; + } + + + bool sanitize (hb_sanitize_context_t *c, unsigned int count) const + { + TRACE_SANITIZE (this); + return_trace ((UnsizedOffsetArrayOf::sanitize (c, count, this))); + } + template + bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const + { + TRACE_SANITIZE (this); + return_trace ((UnsizedOffsetArrayOf::sanitize (c, count, this, user_data))); + } +}; + +/* An array with sorted elements. Supports binary searching. */ +template +struct SortedUnsizedArrayOf : UnsizedArrayOf +{ + hb_sorted_array_t as_array (unsigned int len) + { return hb_sorted_array (this->arrayZ, len); } + hb_sorted_array_t as_array (unsigned int len) const + { return hb_sorted_array (this->arrayZ, len); } + operator hb_sorted_array_t () { return as_array (); } + operator hb_sorted_array_t () const { return as_array (); } + + template + Type &bsearch (unsigned int len, const T &x, Type ¬_found = Crap (Type)) + { return *as_array (len).bsearch (x, ¬_found); } + template + const Type &bsearch (unsigned int len, const T &x, const Type ¬_found = Null (Type)) const + { return *as_array (len).bsearch (x, ¬_found); } + template + bool bfind (unsigned int len, const T &x, unsigned int *i = nullptr, + hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) const + { return as_array (len).bfind (x, i, not_found, to_store); } +}; + + +/* An array with a number of elements. */ +template +struct ArrayOf +{ + typedef Type item_t; + static constexpr unsigned item_size = hb_static_size (Type); + + HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOf, Type, LenType); + + const Type& operator [] (int i_) const + { + unsigned int i = (unsigned int) i_; + if (unlikely (i >= len)) return Null (Type); + return arrayZ[i]; + } + Type& operator [] (int i_) + { + unsigned int i = (unsigned int) i_; + if (unlikely (i >= len)) return Crap (Type); + return arrayZ[i]; + } + + unsigned int get_size () const + { return len.static_size + len * Type::static_size; } + + hb_array_t as_array () + { return hb_array (arrayZ, len); } + hb_array_t as_array () const + { return hb_array (arrayZ, len); } + operator hb_array_t (void) { return as_array (); } + operator hb_array_t (void) const { return as_array (); } + + hb_array_t sub_array (unsigned int start_offset, unsigned int count) const + { return as_array ().sub_array (start_offset, count);} + hb_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const + { return as_array ().sub_array (start_offset, count);} + hb_array_t sub_array (unsigned int start_offset, unsigned int count) + { return as_array ().sub_array (start_offset, count);} + hb_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) + { return as_array ().sub_array (start_offset, count);} + + bool serialize (hb_serialize_context_t *c, unsigned int items_len) + { + TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return_trace (false); + len.set (items_len); /* TODO(serialize) Overflow? */ + if (unlikely (!c->extend (*this))) return_trace (false); + return_trace (true); + } + template + bool serialize (hb_serialize_context_t *c, hb_array_t items) + { + TRACE_SERIALIZE (this); + if (unlikely (!serialize (c, items.length))) return_trace (false); + for (unsigned int i = 0; i < items.length; i++) + hb_assign (arrayZ[i], items[i]); + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return_trace (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 && arrayZ[0].sanitize (c)); + + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return_trace (false); + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + if (unlikely (!arrayZ[i].sanitize (c, base))) + return_trace (false); + return_trace (true); + } + template + bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return_trace (false); + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + if (unlikely (!arrayZ[i].sanitize (c, base, user_data))) + return_trace (false); + return_trace (true); + } + + template + Type &lsearch (const T &x, Type ¬_found = Crap (Type)) + { return *as_array ().lsearch (x, ¬_found); } + template + const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const + { return *as_array ().lsearch (x, ¬_found); } + + void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1) + { as_array ().qsort (start, end); } + + bool sanitize_shallow (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (len.sanitize (c) && c->check_array (arrayZ, len)); + } + + public: + LenType len; + Type arrayZ[VAR]; + public: + DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); +}; +template struct LArrayOf : ArrayOf {}; +typedef ArrayOf PString; + +/* Array of Offset's */ +template +struct OffsetArrayOf : ArrayOf > {}; +template +struct LOffsetArrayOf : ArrayOf > {}; +template +struct LOffsetLArrayOf : ArrayOf, HBUINT32> {}; + +/* Array of offsets relative to the beginning of the array itself. */ +template +struct OffsetListOf : OffsetArrayOf +{ + const Type& operator [] (int i_) const + { + unsigned int i = (unsigned int) i_; + if (unlikely (i >= this->len)) return Null (Type); + return this+this->arrayZ[i]; + } + const Type& operator [] (int i_) + { + unsigned int i = (unsigned int) i_; + if (unlikely (i >= this->len)) return Crap (Type); + return this+this->arrayZ[i]; + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + struct OffsetListOf *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + unsigned int count = this->len; + for (unsigned int i = 0; i < count; i++) + out->arrayZ[i].serialize_subset (c, (*this)[i], out); + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (OffsetArrayOf::sanitize (c, this)); + } + template + bool sanitize (hb_sanitize_context_t *c, T user_data) const + { + TRACE_SANITIZE (this); + return_trace (OffsetArrayOf::sanitize (c, this, user_data)); + } +}; + +/* An array starting at second element. */ +template +struct HeadlessArrayOf +{ + static constexpr unsigned item_size = Type::static_size; + + HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (HeadlessArrayOf, Type, LenType); + + const Type& operator [] (int i_) const + { + unsigned int i = (unsigned int) i_; + if (unlikely (i >= lenP1 || !i)) return Null (Type); + return arrayZ[i-1]; + } + Type& operator [] (int i_) + { + unsigned int i = (unsigned int) i_; + if (unlikely (i >= lenP1 || !i)) return Crap (Type); + return arrayZ[i-1]; + } + unsigned int get_size () const + { return lenP1.static_size + (lenP1 ? lenP1 - 1 : 0) * Type::static_size; } + + bool serialize (hb_serialize_context_t *c, + hb_array_t items) + { + TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return_trace (false); + lenP1.set (items.length + 1); /* TODO(serialize) Overflow? */ + if (unlikely (!c->extend (*this))) return_trace (false); + for (unsigned int i = 0; i < items.length; i++) + arrayZ[i] = items[i]; + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return_trace (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 && arrayZ[0].sanitize (c)); + + return_trace (true); + } + + private: + bool sanitize_shallow (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (lenP1.sanitize (c) && + (!lenP1 || c->check_array (arrayZ, lenP1 - 1))); + } + + public: + LenType lenP1; + Type arrayZ[VAR]; + public: + DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); +}; + +/* An array storing length-1. */ +template +struct ArrayOfM1 +{ + HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOfM1, Type, LenType); + + const Type& operator [] (int i_) const + { + unsigned int i = (unsigned int) i_; + if (unlikely (i > lenM1)) return Null (Type); + return arrayZ[i]; + } + Type& operator [] (int i_) + { + unsigned int i = (unsigned int) i_; + if (unlikely (i > lenM1)) return Crap (Type); + return arrayZ[i]; + } + unsigned int get_size () const + { return lenM1.static_size + (lenM1 + 1) * Type::static_size; } + + template + bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return_trace (false); + unsigned int count = lenM1 + 1; + for (unsigned int i = 0; i < count; i++) + if (unlikely (!arrayZ[i].sanitize (c, base, user_data))) + return_trace (false); + return_trace (true); + } + + private: + bool sanitize_shallow (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (lenM1.sanitize (c) && + (c->check_array (arrayZ, lenM1 + 1))); + } + + public: + LenType lenM1; + Type arrayZ[VAR]; + public: + DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); +}; + +/* An array with sorted elements. Supports binary searching. */ +template +struct SortedArrayOf : ArrayOf +{ + hb_sorted_array_t as_array () + { return hb_sorted_array (this->arrayZ, this->len); } + hb_sorted_array_t as_array () const + { return hb_sorted_array (this->arrayZ, this->len); } + operator hb_sorted_array_t () { return as_array (); } + operator hb_sorted_array_t () const { return as_array (); } + + hb_array_t sub_array (unsigned int start_offset, unsigned int count) const + { return as_array ().sub_array (start_offset, count);} + hb_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const + { return as_array ().sub_array (start_offset, count);} + hb_array_t sub_array (unsigned int start_offset, unsigned int count) + { return as_array ().sub_array (start_offset, count);} + hb_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) + { return as_array ().sub_array (start_offset, count);} + + template + Type &bsearch (const T &x, Type ¬_found = Crap (Type)) + { return *as_array ().bsearch (x, ¬_found); } + template + const Type &bsearch (const T &x, const Type ¬_found = Null (Type)) const + { return *as_array ().bsearch (x, ¬_found); } + template + bool bfind (const T &x, unsigned int *i = nullptr, + hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) const + { return as_array ().bfind (x, i, not_found, to_store); } +}; + +/* + * Binary-search arrays + */ + +template +struct BinSearchHeader +{ + operator uint32_t () const { return len; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + void set (unsigned int v) + { + len.set (v); + assert (len == v); + entrySelector.set (MAX (1u, hb_bit_storage (v)) - 1); + searchRange.set (16 * (1u << entrySelector)); + rangeShift.set (v * 16 > searchRange + ? 16 * v - searchRange + : 0); + } + + protected: + LenType len; + LenType searchRange; + LenType entrySelector; + LenType rangeShift; + + public: + DEFINE_SIZE_STATIC (8); +}; + +template +struct BinSearchArrayOf : SortedArrayOf > {}; + + +struct VarSizedBinSearchHeader +{ + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT16 unitSize; /* Size of a lookup unit for this search in bytes. */ + HBUINT16 nUnits; /* Number of units of the preceding size to be searched. */ + HBUINT16 searchRange; /* The value of unitSize times the largest power of 2 + * that is less than or equal to the value of nUnits. */ + HBUINT16 entrySelector; /* The log base 2 of the largest power of 2 less than + * or equal to the value of nUnits. */ + HBUINT16 rangeShift; /* The value of unitSize times the difference of the + * value of nUnits minus the largest power of 2 less + * than or equal to the value of nUnits. */ + public: + DEFINE_SIZE_STATIC (10); +}; + +template +struct VarSizedBinSearchArrayOf +{ + static constexpr unsigned item_size = Type::static_size; + + HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type); + + bool last_is_terminator () const + { + if (unlikely (!header.nUnits)) return false; + + /* Gah. + * + * "The number of termination values that need to be included is table-specific. + * The value that indicates binary search termination is 0xFFFF." */ + const HBUINT16 *words = &StructAtOffset (&bytesZ, (header.nUnits - 1) * header.unitSize); + unsigned int count = Type::TerminationWordCount; + for (unsigned int i = 0; i < count; i++) + if (words[i] != 0xFFFFu) + return false; + return true; + } + + const Type& operator [] (int i_) const + { + unsigned int i = (unsigned int) i_; + if (unlikely (i >= get_length ())) return Null (Type); + return StructAtOffset (&bytesZ, i * header.unitSize); + } + Type& operator [] (int i_) + { + unsigned int i = (unsigned int) i_; + if (unlikely (i >= get_length ())) return Crap (Type); + return StructAtOffset (&bytesZ, i * header.unitSize); + } + unsigned int get_length () const + { return header.nUnits - last_is_terminator (); } + unsigned int get_size () const + { return header.static_size + header.nUnits * header.unitSize; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return_trace (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 && StructAtOffset (&bytesZ, 0).sanitize (c)); + + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return_trace (false); + unsigned int count = get_length (); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!(*this)[i].sanitize (c, base))) + return_trace (false); + return_trace (true); + } + template + bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return_trace (false); + unsigned int count = get_length (); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!(*this)[i].sanitize (c, base, user_data))) + return_trace (false); + return_trace (true); + } + + template + const Type *bsearch (const T &key) const + { + unsigned int size = header.unitSize; + int min = 0, max = (int) get_length () - 1; + while (min <= max) + { + int mid = ((unsigned int) min + (unsigned int) max) / 2; + const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size)); + int c = p->cmp (key); + if (c < 0) max = mid - 1; + else if (c > 0) min = mid + 1; + else return p; + } + return nullptr; + } + + private: + bool sanitize_shallow (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (header.sanitize (c) && + Type::static_size <= header.unitSize && + c->check_range (bytesZ.arrayZ, + header.nUnits, + header.unitSize)); + } + + protected: + VarSizedBinSearchHeader header; + UnsizedArrayOf bytesZ; + public: + DEFINE_SIZE_ARRAY (10, bytesZ); +}; + + +} /* namespace OT */ + + +#endif /* HB_OPEN_TYPE_HH */ --- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common-private.hh 2019-02-28 12:04:20.830502600 -0800 +++ /dev/null 2019-02-21 13:14:21.200397537 -0800 @@ -1,1786 +0,0 @@ -/* - * 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-private.hh" -#include "hb-debug.hh" -#include "hb-ot-layout-private.hh" -#include "hb-open-type-private.hh" -#include "hb-set-private.hh" - - -#ifndef HB_MAX_NESTING_LEVEL -#define HB_MAX_NESTING_LEVEL 6 -#endif -#ifndef HB_MAX_CONTEXT_LENGTH -#define HB_MAX_CONTEXT_LENGTH 64 -#endif - - -namespace OT { - - -#define NOT_COVERED ((unsigned int) -1) - - - -/* - * - * 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; - const void *list_base; - }; - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const - { - TRACE_SANITIZE (this); - const sanitize_closure_t closure = {tag, base}; - return_trace (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 - { - /* If we want to allow non-sorted data, we can lsearch(). */ - int i = this->/*lsearch*/bsearch (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) const - { - TRACE_SANITIZE (this); - return_trace (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) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); - } - - inline bool intersects (const hb_set_t *glyphs) const { - return glyphs->intersects (start, end); - } - - template - inline bool add_coverage (set_t *glyphs) const { - return glyphs->add_range (start, end); - } - - GlyphID start; /* First GlyphID in the range */ - GlyphID end; /* Last GlyphID in the range */ - HBUINT16 value; /* Value */ - public: - DEFINE_SIZE_STATIC (6); -}; -DEFINE_NULL_DATA (OT, 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 HBUINT16 *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 != 0xFFFFu; } - inline unsigned int get_required_feature_index (void) const - { - if (reqFeatureIndex == 0xFFFFu) - return Index::NOT_FOUND_INDEX; - return reqFeatureIndex;; - } - - inline bool sanitize (hb_sanitize_context_t *c, - const Record::sanitize_closure_t * = nullptr) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && featureIndex.sanitize (c)); - } - - Offset16 lookupOrderZ; /* = Null (reserved for an offset to a - * reordering table) */ - HBUINT16 reqFeatureIndex;/* Index of a feature required for this - * language system--if no required features - * = 0xFFFFu */ - IndexArray featureIndex; /* Array of indices into the FeatureList */ - public: - DEFINE_SIZE_ARRAY (6, featureIndex); -}; -DEFINE_NULL_DATA (OT, 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