diff --git a/gfx/harfbuzz/src/Makefile.am b/gfx/harfbuzz/src/Makefile.am index 5894b205b1a9..9f7c7f8486e4 100644 --- a/gfx/harfbuzz/src/Makefile.am +++ b/gfx/harfbuzz/src/Makefile.am @@ -51,6 +51,7 @@ HBSOURCES = \ hb-tt-font.cc \ hb-unicode-private.hh \ hb-unicode.cc \ + hb-utf-private.hh \ hb-warning.cc \ $(NULL) HBHEADERS = \ @@ -78,6 +79,7 @@ HBSOURCES += \ hb-ot-map-private.hh \ hb-ot-shape.cc \ hb-ot-shape-complex-arabic.cc \ + hb-ot-shape-complex-arabic-fallback.hh \ hb-ot-shape-complex-arabic-table.hh \ hb-ot-shape-complex-indic.cc \ hb-ot-shape-complex-indic-machine.hh \ @@ -98,6 +100,11 @@ HBHEADERS += \ $(NULL) endif +if HAVE_PTHREAD +HBCFLAGS += $(PTHREAD_CFLAGS) +HBLIBS += $(PTHREAD_LIBS) +endif + if HAVE_GLIB HBCFLAGS += $(GLIB_CFLAGS) HBLIBS += $(GLIB_LIBS) @@ -163,6 +170,21 @@ HBSOURCES += hb-old.cc endif DIST_SUBDIRS += hb-old +if HAVE_ICU_LE +SUBDIRS += hb-icu-le +HBCFLAGS += -I$(srcdir)/hb-icu-le +HBLIBS += hb-icu-le/libhb-icu-le.la +HBSOURCES += hb-icu-le.cc +endif +DIST_SUBDIRS += hb-icu-le + +if HAVE_UCDN +SUBDIRS += hb-ucdn +HBCFLAGS += -I$(srcdir)/hb-ucdn +HBLIBS += hb-ucdn/libhb-ucdn.la +HBSOURCES += hb-ucdn.cc +endif +DIST_SUBDIRS += hb-ucdn # Put the library together @@ -170,16 +192,18 @@ DIST_SUBDIRS += hb-old if OS_WIN32 export_symbols = -export-symbols harfbuzz.def harfbuzz_def_dependency = harfbuzz.def -endif - +libharfbuzz_la_LINK = $(CXXLINK) $(libharfbuzz_la_LDFLAGS) +else # Use a C linker, not C++; Don't link to libstdc++ libharfbuzz_la_LINK = $(LINK) $(libharfbuzz_la_LDFLAGS) +endif + libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS) nodist_libharfbuzz_la_SOURCES = $(nodist_HBSOURCES) libharfbuzz_la_CPPFLAGS = $(HBCFLAGS) libharfbuzz_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) $(export_symbols) -no-undefined libharfbuzz_la_LIBADD = $(HBLIBS) -libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency) +EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency) pkginclude_HEADERS = $(HBHEADERS) nodist_pkginclude_HEADERS = hb-version.h @@ -217,23 +241,18 @@ arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt .PHONY: unicode-tables arabic-table indic-table -BUILT_SOURCES += hb-ot-shape-complex-indic-machine.hh EXTRA_DIST += hb-ot-shape-complex-indic-machine.rl hb-ot-shape-complex-indic-machine.hh: hb-ot-shape-complex-indic-machine.rl $(AM_V_GEN)$(top_srcdir)/missing --run ragel -e -F1 -o "$@.tmp" "$<" && \ mv "$@.tmp" "$@" || ( $(RM) "$@.tmp" && false ) -noinst_PROGRAMS = main indic test-would-substitute +noinst_PROGRAMS = main test-would-substitute bin_PROGRAMS = main_SOURCES = main.cc main_CPPFLAGS = $(HBCFLAGS) main_LDADD = libharfbuzz.la $(HBLIBS) -indic_SOURCES = indic.cc -indic_CPPFLAGS = $(HBCFLAGS) -indic_LDADD = libharfbuzz.la $(HBLIBS) - test_would_substitute_SOURCES = test-would-substitute.cc test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) @@ -244,7 +263,6 @@ dist_check_SCRIPTS = \ check-exported-symbols.sh \ check-includes.sh \ check-internal-symbols.sh \ - check-static-inits.sh \ $(NULL) if HAVE_ICU @@ -252,6 +270,11 @@ else dist_check_SCRIPTS += check-libstdc++.sh endif +if HAVE_ICU_LE +else +dist_check_SCRIPTS += check-static-inits.sh +endif + TESTS = $(dist_check_SCRIPTS) TESTS_ENVIRONMENT = \ srcdir="$(srcdir)" \ diff --git a/gfx/harfbuzz/src/check-libstdc++.sh b/gfx/harfbuzz/src/check-libstdc++.sh index 05215324b166..e7e0e295e1ab 100755 --- a/gfx/harfbuzz/src/check-libstdc++.sh +++ b/gfx/harfbuzz/src/check-libstdc++.sh @@ -27,7 +27,7 @@ for suffix in so dylib; do fi done if ! $tested; then - echo "check-internal-symbols.sh: libharfbuzz shared library not found; skipping test" + echo "check-libstdc++.sh: libharfbuzz shared library not found; skipping test" exit 77 fi diff --git a/gfx/harfbuzz/src/check-static-inits.sh b/gfx/harfbuzz/src/check-static-inits.sh index 1eceb1bade23..bb0a7ff630d7 100755 --- a/gfx/harfbuzz/src/check-static-inits.sh +++ b/gfx/harfbuzz/src/check-static-inits.sh @@ -28,10 +28,10 @@ for obj in $OBJS; do fi done -echo "Checking that no object file has lazy static C++ constructors/destructors" +echo "Checking that no object file has lazy static C++ constructors/destructors or other such stuff" for obj in $OBJS; do if objdump -t "$obj" | grep '__c'; then - echo "Ouch, $obj has lazy static C++ constructors/destructors" + echo "Ouch, $obj has lazy static C++ constructors/destructors or other such stuff" stat=1 fi done diff --git a/gfx/harfbuzz/src/gen-arabic-table.py b/gfx/harfbuzz/src/gen-arabic-table.py index 2d3c88193647..da5a4fcbf5c2 100755 --- a/gfx/harfbuzz/src/gen-arabic-table.py +++ b/gfx/harfbuzz/src/gen-arabic-table.py @@ -122,7 +122,7 @@ def print_shaping_table(f): keys = shapes.keys () min_u, max_u = min (keys), max (keys) for u in range (min_u, max_u + 1): - s = [shapes[u][shape] if u in shapes and shape in shapes[u] else u + s = [shapes[u][shape] if u in shapes and shape in shapes[u] else 0 for shape in ['initial', 'medial', 'final', 'isolated']] value = ', '.join ("0x%04X" % c for c in s) print " {%s}, /* U+%04X %s */" % (value, u, names[u] if u in names else "") @@ -148,9 +148,9 @@ def print_shaping_table(f): ligas[liga[0]].append ((liga[1], c)) max_i = max (len (ligas[l]) for l in ligas) print - print "static const struct {" + print "static const struct ligature_set_t {" print " uint16_t first;" - print " struct {" + print " struct ligature_pairs_t {" print " uint16_t second;" print " uint16_t ligature;" print " } ligatures[%d];" % max_i diff --git a/gfx/harfbuzz/src/hb-atomic-private.hh b/gfx/harfbuzz/src/hb-atomic-private.hh index 0f70641f490e..5861a7124b3d 100644 --- a/gfx/harfbuzz/src/hb-atomic-private.hh +++ b/gfx/harfbuzz/src/hb-atomic-private.hh @@ -42,17 +42,28 @@ #if 0 -#elif !defined(HB_NO_MT) && defined(_MSC_VER) && _MSC_VER >= 1600 +#elif !defined(HB_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__) -#include -/* On x86, _InterlockedCompareExchangePointer is a macro defined in concrt.h */ -#include +#define WIN32_LEAN_AND_MEAN +#include + +/* mingw32 does not have MemoryBarrier. + * MemoryBarrier may be defined as a macro or a function. + * Just make a failsafe version for ourselves. */ +#ifdef MemoryBarrier +#define HBMemoryBarrier MemoryBarrier +#else +static inline void HBMemoryBarrier (void) { + long dummy = 0; + InterlockedExchange (&dummy, 1); +} +#endif typedef long hb_atomic_int_t; -#define hb_atomic_int_add(AI, V) _InterlockedExchangeAdd (&(AI), (V)) +#define hb_atomic_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V)) -#define hb_atomic_ptr_get(P) (MemoryBarrier (), (void *) *(P)) -#define hb_atomic_ptr_cmpexch(P,O,N) (_InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O)) +#define hb_atomic_ptr_get(P) (HBMemoryBarrier (), (void *) *(P)) +#define hb_atomic_ptr_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O)) #elif !defined(HB_NO_MT) && defined(__APPLE__) @@ -74,19 +85,6 @@ typedef int hb_atomic_int_t; #define hb_atomic_ptr_get(P) (void *) (__sync_synchronize (), *(P)) #define hb_atomic_ptr_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N)) -#elif !defined(HB_NO_MT) && defined(HAVE_GLIB) - -#include -typedef int hb_atomic_int_t; -#if GLIB_CHECK_VERSION(2,29,5) -#define hb_atomic_int_add(AI, V) g_atomic_int_add (&(AI), (V)) -#else -#define hb_atomic_int_add(AI, V) g_atomic_int_exchange_and_add (&(AI), (V)) -#endif - -#define hb_atomic_ptr_get(P) g_atomic_pointer_get (P) -#define hb_atomic_ptr_cmpexch(P,O,N) g_atomic_pointer_compare_and_exchange ((void **) (P), (void *) (O), (void *) (N)) - #elif !defined(HB_NO_MT) diff --git a/gfx/harfbuzz/src/hb-buffer-private.hh b/gfx/harfbuzz/src/hb-buffer-private.hh index 9864ca2c8bbc..67a2752c0686 100644 --- a/gfx/harfbuzz/src/hb-buffer-private.hh +++ b/gfx/harfbuzz/src/hb-buffer-private.hh @@ -1,7 +1,7 @@ /* * Copyright © 1998-2004 David Turner and Werner Lemberg * Copyright © 2004,2007,2009,2010 Red Hat, Inc. - * Copyright © 2011 Google, Inc. + * Copyright © 2011,2012 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -92,6 +92,8 @@ struct hb_buffer_t { /* Buffer contents */ + hb_buffer_content_type_t content_type; + bool in_error; /* Allocation failed */ bool have_output; /* Whether we have an output buffer going on */ bool have_positions; /* Whether we have positions */ @@ -115,9 +117,18 @@ struct hb_buffer_t { inline hb_glyph_info_t prev (void) const { return info[out_len - 1]; } unsigned int serial; + + /* These reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ uint8_t allocated_var_bytes[8]; const char *allocated_var_owner[8]; + /* Text before / after the main buffer contents. + * Always in Unicode, and ordered outward. + * Index 0 is for "pre-context", 1 for "post-context". */ + static const unsigned int CONTEXT_LENGTH = 5; + hb_codepoint_t context[2][CONTEXT_LENGTH]; + unsigned int context_len[2]; + /* Methods */ @@ -129,6 +140,7 @@ struct hb_buffer_t { HB_INTERNAL void allocate_var (unsigned int byte_i, unsigned int count, const char *owner); HB_INTERNAL void deallocate_var (unsigned int byte_i, unsigned int count, const char *owner); + HB_INTERNAL void assert_var (unsigned int byte_i, unsigned int count, const char *owner); HB_INTERNAL void deallocate_var_all (void); HB_INTERNAL void add (hb_codepoint_t codepoint, @@ -151,11 +163,26 @@ struct hb_buffer_t { HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index); /* Makes a copy of the glyph at idx to output and replace glyph_index */ HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index); + HB_INTERNAL void output_info (hb_glyph_info_t &glyph_info); /* Copies glyph at idx to output but doesn't advance idx */ HB_INTERNAL void copy_glyph (void); /* Copies glyph at idx to output and advance idx. * If there's no output, just advance idx. */ - HB_INTERNAL void next_glyph (void); + inline void + next_glyph (void) + { + if (have_output) + { + if (unlikely (out_info != info || out_len != idx)) { + if (unlikely (!make_room_for (1, 1))) return; + out_info[out_len] = info[idx]; + } + out_len++; + } + + idx++; + } + /* Advance idx without copying to output. */ inline void skip_glyph (void) { idx++; } @@ -188,6 +215,8 @@ struct hb_buffer_t { HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out); HB_INTERNAL void *get_scratch_buffer (unsigned int *size); + + inline void clear_context (unsigned int side) { context_len[side] = 0; } }; @@ -198,6 +227,8 @@ struct hb_buffer_t { HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var (), #var) #define HB_BUFFER_DEALLOCATE_VAR(b, var) \ HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var (), #var) +#define HB_BUFFER_ASSERT_VAR(b, var) \ + HB_BUFFER_XALLOCATE_VAR (b, assert_var, var (), #var) #endif /* HB_BUFFER_PRIVATE_HH */ diff --git a/gfx/harfbuzz/src/hb-buffer.cc b/gfx/harfbuzz/src/hb-buffer.cc index eddd5d0ba43e..2f8f511b0090 100644 --- a/gfx/harfbuzz/src/hb-buffer.cc +++ b/gfx/harfbuzz/src/hb-buffer.cc @@ -1,7 +1,7 @@ /* * Copyright © 1998-2004 David Turner and Werner Lemberg * Copyright © 2004,2007,2009,2010 Red Hat, Inc. - * Copyright © 2011 Google, Inc. + * Copyright © 2011,2012 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -28,9 +28,7 @@ */ #include "hb-buffer-private.hh" - -#include - +#include "hb-utf-private.hh" #ifndef HB_DEBUG_BUFFER @@ -147,6 +145,7 @@ hb_buffer_t::reset (void) hb_segment_properties_t default_props = _HB_BUFFER_PROPS_DEFAULT; props = default_props; + content_type = HB_BUFFER_CONTENT_TYPE_INVALID; in_error = false; have_output = false; have_positions = false; @@ -159,6 +158,9 @@ hb_buffer_t::reset (void) serial = 0; memset (allocated_var_bytes, 0, sizeof allocated_var_bytes); memset (allocated_var_owner, 0, sizeof allocated_var_owner); + + memset (context, 0, sizeof context); + memset (context_len, 0, sizeof context_len); } void @@ -267,6 +269,16 @@ hb_buffer_t::output_glyph (hb_codepoint_t glyph_index) out_len++; } +void +hb_buffer_t::output_info (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) { @@ -290,21 +302,6 @@ hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index) out_len++; } -void -hb_buffer_t::next_glyph (void) -{ - if (have_output) - { - if (unlikely (out_info != info || out_len != idx)) { - if (unlikely (!make_room_for (1, 1))) return; - out_info[out_len] = info[idx]; - } - out_len++; - } - - idx++; -} - void hb_buffer_t::set_masks (hb_mask_t value, @@ -451,6 +448,9 @@ hb_buffer_t::merge_out_clusters (unsigned int start, void hb_buffer_t::guess_properties (void) { + if (unlikely (!len)) return; + assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE); + /* If script is set to INVALID, guess from buffer contents */ if (props.script == HB_SCRIPT_INVALID) { for (unsigned int i = 0; i < len; i++) { @@ -523,6 +523,22 @@ void hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const } } +void hb_buffer_t::assert_var (unsigned int byte_i, unsigned int count, const char *owner) +{ + if (DEBUG (BUFFER)) + dump_var_allocation (this); + + DEBUG_MSG (BUFFER, this, + "Asserting var bytes %d..%d for %s", + byte_i, byte_i + count - 1, owner); + + assert (byte_i < 8 && byte_i + count <= 8); + for (unsigned int i = byte_i; i < byte_i + count; i++) { + assert (allocated_var_bytes[i]); + assert (0 == strcmp (allocated_var_owner[i], owner)); + } +} + void hb_buffer_t::deallocate_var_all (void) { memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes)); @@ -553,9 +569,12 @@ hb_buffer_get_empty (void) const_cast (&_hb_unicode_funcs_nil), _HB_BUFFER_PROPS_DEFAULT, + HB_BUFFER_CONTENT_TYPE_INVALID, true, /* in_error */ true, /* have_output */ true /* have_positions */ + + /* Zero is good enough for everything else. */ }; return const_cast (&_hb_buffer_nil); @@ -598,6 +617,20 @@ hb_buffer_get_user_data (hb_buffer_t *buffer, } +void +hb_buffer_set_content_type (hb_buffer_t *buffer, + hb_buffer_content_type_t content_type) +{ + buffer->content_type = content_type; +} + +hb_buffer_content_type_t +hb_buffer_get_content_type (hb_buffer_t *buffer) +{ + return buffer->content_type; +} + + void hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, hb_unicode_funcs_t *unicode) @@ -695,6 +728,7 @@ hb_buffer_add (hb_buffer_t *buffer, unsigned int cluster) { buffer->add (codepoint, mask, cluster); + buffer->clear_context (1); } hb_bool_t @@ -715,6 +749,11 @@ hb_buffer_set_length (hb_buffer_t *buffer, } buffer->len = length; + + if (!length) + buffer->clear_context (0); + buffer->clear_context (1); + return true; } @@ -767,68 +806,63 @@ hb_buffer_guess_properties (hb_buffer_t *buffer) buffer->guess_properties (); } -#define ADD_UTF(T) \ - HB_STMT_START { \ - if (text_length == -1) { \ - text_length = 0; \ - const T *p = (const T *) text; \ - while (*p) { \ - text_length++; \ - p++; \ - } \ - } \ - if (item_length == -1) \ - item_length = text_length - item_offset; \ - buffer->ensure (buffer->len + item_length * sizeof (T) / 4); \ - const T *next = (const T *) text + item_offset; \ - const T *end = next + item_length; \ - while (next < end) { \ - hb_codepoint_t u; \ - const T *old_next = next; \ - next = UTF_NEXT (next, end, u); \ - hb_buffer_add (buffer, u, 1, old_next - (const T *) text); \ - } \ - } HB_STMT_END - - -#define UTF8_COMPUTE(Char, Mask, Len) \ - if (Char < 128) { Len = 1; Mask = 0x7f; } \ - else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \ - else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \ - else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \ - else Len = 0; - -static inline const uint8_t * -hb_utf8_next (const uint8_t *text, - const uint8_t *end, - hb_codepoint_t *unicode) +template +static inline void +hb_buffer_add_utf (hb_buffer_t *buffer, + const T *text, + int text_length, + unsigned int item_offset, + int item_length) { - uint8_t c = *text; - unsigned int mask, len; + assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || + (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID)); - /* TODO check for overlong sequences? */ + if (unlikely (hb_object_is_inert (buffer))) + return; - UTF8_COMPUTE (c, mask, len); - if (unlikely (!len || (unsigned int) (end - text) < len)) { - *unicode = -1; - return text + 1; - } else { - hb_codepoint_t result; - unsigned int i; - result = c & mask; - for (i = 1; i < len; i++) - { - if (unlikely ((text[i] & 0xc0) != 0x80)) - { - *unicode = -1; - return text + 1; - } - result <<= 6; - result |= (text[i] & 0x3f); - } - *unicode = result; - return text + len; + if (text_length == -1) + text_length = hb_utf_strlen (text); + + if (item_length == -1) + item_length = text_length - item_offset; + + buffer->ensure (buffer->len + item_length * sizeof (T) / 4); + + if (!buffer->len) + { + /* Add pre-context */ + buffer->clear_context (0); + const T *prev = text + item_offset; + const T *start = text; + while (start < prev && buffer->context_len[0] < buffer->CONTEXT_LENGTH) + { + hb_codepoint_t u; + prev = hb_utf_prev (prev, start, &u); + buffer->context[0][buffer->context_len[0]++] = u; + } } + + const T *next = text + item_offset; + const T *end = next + item_length; + while (next < end) + { + hb_codepoint_t u; + const T *old_next = next; + next = hb_utf_next (next, end, &u); + buffer->add (u, 1, old_next - (const T *) text); + } + + /* Add post-context */ + buffer->clear_context (1); + end = text + text_length; + while (next < end && buffer->context_len[1] < buffer->CONTEXT_LENGTH) + { + hb_codepoint_t u; + next = hb_utf_next (next, end, &u); + buffer->context[1][buffer->context_len[1]++] = u; + } + + buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; } void @@ -838,31 +872,7 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer, unsigned int item_offset, int item_length) { -#define UTF_NEXT(S, E, U) hb_utf8_next (S, E, &(U)) - ADD_UTF (uint8_t); -#undef UTF_NEXT -} - -static inline const uint16_t * -hb_utf16_next (const uint16_t *text, - const uint16_t *end, - hb_codepoint_t *unicode) -{ - uint16_t c = *text++; - - if (unlikely (c >= 0xd800 && c < 0xdc00)) { - /* high surrogate */ - uint16_t l; - if (text < end && ((l = *text), likely (l >= 0xdc00 && l < 0xe000))) { - /* low surrogate */ - *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000); - text++; - } else - *unicode = -1; - } else - *unicode = c; - - return text; + hb_buffer_add_utf (buffer, (const uint8_t *) text, text_length, item_offset, item_length); } void @@ -872,9 +882,7 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer, unsigned int item_offset, int item_length) { -#define UTF_NEXT(S, E, U) hb_utf16_next (S, E, &(U)) - ADD_UTF (uint16_t); -#undef UTF_NEXT + hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); } void @@ -884,9 +892,7 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer, unsigned int item_offset, int item_length) { -#define UTF_NEXT(S, E, U) ((U) = *(S), (S)+1) - ADD_UTF (uint32_t); -#undef UTF_NEXT + hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); } @@ -949,7 +955,7 @@ void hb_buffer_normalize_glyphs (hb_buffer_t *buffer) { assert (buffer->have_positions); - /* XXX assert (buffer->have_glyphs); */ + assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); diff --git a/gfx/harfbuzz/src/hb-buffer.h b/gfx/harfbuzz/src/hb-buffer.h index aebf4821a098..dc63d1bf6640 100644 --- a/gfx/harfbuzz/src/hb-buffer.h +++ b/gfx/harfbuzz/src/hb-buffer.h @@ -1,7 +1,7 @@ /* * Copyright © 1998-2004 David Turner and Werner Lemberg * Copyright © 2004,2007,2009 Red Hat, Inc. - * Copyright © 2011 Google, Inc. + * Copyright © 2011,2012 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -62,6 +62,12 @@ typedef struct hb_glyph_position_t { hb_var_int_t var; } hb_glyph_position_t; +typedef enum { + HB_BUFFER_CONTENT_TYPE_INVALID = 0, + HB_BUFFER_CONTENT_TYPE_UNICODE, + HB_BUFFER_CONTENT_TYPE_GLYPHS +} hb_buffer_content_type_t; + hb_buffer_t * hb_buffer_create (void); @@ -87,6 +93,14 @@ hb_buffer_get_user_data (hb_buffer_t *buffer, hb_user_data_key_t *key); +void +hb_buffer_set_content_type (hb_buffer_t *buffer, + hb_buffer_content_type_t content_type); + +hb_buffer_content_type_t +hb_buffer_get_content_type (hb_buffer_t *buffer); + + void hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, hb_unicode_funcs_t *unicode_funcs); diff --git a/gfx/harfbuzz/src/hb-common.cc b/gfx/harfbuzz/src/hb-common.cc index 1301ab2b2023..33a514dbfda8 100644 --- a/gfx/harfbuzz/src/hb-common.cc +++ b/gfx/harfbuzz/src/hb-common.cc @@ -58,6 +58,15 @@ hb_tag_from_string (const char *s, int len) return HB_TAG_CHAR4 (tag); } +void +hb_tag_to_string (hb_tag_t tag, char *buf) +{ + buf[0] = (char) (uint8_t) (tag >> 24); + buf[1] = (char) (uint8_t) (tag >> 16); + buf[2] = (char) (uint8_t) (tag >> 8); + buf[3] = (char) (uint8_t) (tag >> 0); +} + /* hb_direction_t */ diff --git a/gfx/harfbuzz/src/hb-common.h b/gfx/harfbuzz/src/hb-common.h index 920bd327808d..cc221d33be9d 100644 --- a/gfx/harfbuzz/src/hb-common.h +++ b/gfx/harfbuzz/src/hb-common.h @@ -95,10 +95,14 @@ typedef uint32_t hb_tag_t; #define HB_TAG_NONE HB_TAG(0,0,0,0) -/* len=-1 means str is NUL-terminated */ +/* len=-1 means str is NUL-terminated. */ hb_tag_t hb_tag_from_string (const char *str, int len); +/* buf should have 4 bytes. */ +void +hb_tag_to_string (hb_tag_t tag, char *buf); + /* hb_direction_t */ diff --git a/gfx/harfbuzz/src/hb-font.cc b/gfx/harfbuzz/src/hb-font.cc index 922dee334048..062703256985 100644 --- a/gfx/harfbuzz/src/hb-font.cc +++ b/gfx/harfbuzz/src/hb-font.cc @@ -589,10 +589,10 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void if (tag == HB_TAG_NONE) return hb_blob_reference (data->blob); - const OpenTypeFontFile &ot_file = *Sanitizer::lock_instance (data->blob); - const OpenTypeFontFace &ot_face = ot_file.get_face (data->index); + const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer::lock_instance (data->blob); + const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); - const OpenTypeTable &table = ot_face.get_table_by_tag (tag); + 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); @@ -608,7 +608,7 @@ hb_face_create (hb_blob_t *blob, if (unlikely (!blob || !hb_blob_get_length (blob))) return hb_face_get_empty (); - hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (Sanitizer::sanitize (hb_blob_reference (blob)), index); + hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer::sanitize (hb_blob_reference (blob)), index); if (unlikely (!closure)) return hb_face_get_empty (); @@ -740,8 +740,8 @@ hb_face_get_upem (hb_face_t *face) void hb_face_t::load_upem (void) const { - hb_blob_t *head_blob = Sanitizer::sanitize (reference_table (HB_OT_TAG_head)); - const head *head_table = Sanitizer::lock_instance (head_blob); + hb_blob_t *head_blob = OT::Sanitizer::sanitize (reference_table (HB_OT_TAG_head)); + const OT::head *head_table = OT::Sanitizer::lock_instance (head_blob); upem = head_table->get_upem (); hb_blob_destroy (head_blob); } diff --git a/gfx/harfbuzz/src/hb-graphite2.cc b/gfx/harfbuzz/src/hb-graphite2.cc index a30c42efb2ca..6c890d42c638 100644 --- a/gfx/harfbuzz/src/hb-graphite2.cc +++ b/gfx/harfbuzz/src/hb-graphite2.cc @@ -211,11 +211,6 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, gr_face *grface = HB_SHAPER_DATA_GET (face)->grface; gr_font *grfont = HB_SHAPER_DATA_GET (font); - unsigned int charlen; - hb_glyph_info_t *bufferi = hb_buffer_get_glyph_infos (buffer, &charlen); - - int success = 0; - const char *lang = hb_language_to_string (hb_buffer_get_language (buffer)); const char *lang_end = strchr (lang, '-'); int lang_len = lang_end ? lang_end - lang : -1; @@ -229,24 +224,23 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, features++; } - /* TODO Use scratch buffer for these. */ - hb_codepoint_t *gids = NULL, *pg; - hb_graphite2_cluster_t *clusters = NULL; gr_segment *seg = NULL; - uint32_t *text = NULL; const gr_slot *is; unsigned int ci = 0, ic = 0; float curradvx = 0., curradvy = 0.; - unsigned int glyphlen = 0; - unsigned int *p; - text = (uint32_t *) malloc ((charlen + 1) * sizeof (uint32_t)); - if (!text) goto dieout; + unsigned int scratch_size; + char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size); - p = text; - for (unsigned int i = 0; i < charlen; ++i) - *p++ = bufferi++->codepoint; - *p = 0; +#define ALLOCATE_ARRAY(Type, name, len) \ + Type *name = (Type *) scratch; \ + scratch += (len) * sizeof ((name)[0]); \ + scratch_size -= (len) * sizeof ((name)[0]); + + ALLOCATE_ARRAY (uint32_t, chars, buffer->len); + + for (unsigned int i = 0; i < buffer->len; ++i) + chars[i] = buffer->info[i].codepoint; hb_tag_t script_tag[2]; hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]); @@ -254,18 +248,40 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, seg = gr_make_seg (grfont, grface, script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1], feats, - gr_utf32, text, charlen, + gr_utf32, chars, buffer->len, 2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0)); - if (!seg) goto dieout; - glyphlen = gr_seg_n_slots (seg); - clusters = (hb_graphite2_cluster_t *) calloc (charlen, sizeof (hb_graphite2_cluster_t)); - if (!glyphlen || !clusters) goto dieout; + if (unlikely (!seg)) { + if (feats) gr_featureval_destroy (feats); + return false; + } - gids = (hb_codepoint_t *) malloc (glyphlen * sizeof (hb_codepoint_t)); - if (!gids) goto dieout; + unsigned int glyph_count = gr_seg_n_slots (seg); + if (unlikely (!glyph_count)) { + if (feats) gr_featureval_destroy (feats); + gr_seg_destroy (seg); + return false; + } - pg = gids; + scratch = (char *) buffer->get_scratch_buffer (&scratch_size); + while ((sizeof (hb_graphite2_cluster_t) * buffer->len + + sizeof (hb_codepoint_t) * glyph_count) > scratch_size) + { + buffer->ensure (buffer->allocated * 2); + if (unlikely (buffer->in_error)) { + if (feats) gr_featureval_destroy (feats); + gr_seg_destroy (seg); + return false; + } + scratch = (char *) buffer->get_scratch_buffer (&scratch_size); + } + + ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len); + ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count); + + memset (clusters, 0, sizeof (clusters[0]) * buffer->len); + + hb_codepoint_t *pg = gids; for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (is), ic++) { unsigned int before = gr_slot_before (is); @@ -325,13 +341,8 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) hb_buffer_reverse_clusters (buffer); - success = 1; - -dieout: if (feats) gr_featureval_destroy (feats); - if (gids) free (gids); - if (clusters) free (clusters); - if (seg) gr_seg_destroy (seg); - if (text) free (text); - return success; + gr_seg_destroy (seg); + + return true; } diff --git a/gfx/harfbuzz/src/hb-icu-le.cc b/gfx/harfbuzz/src/hb-icu-le.cc new file mode 100644 index 000000000000..68c9c428a967 --- /dev/null +++ b/gfx/harfbuzz/src/hb-icu-le.cc @@ -0,0 +1,213 @@ +/* + * Copyright © 2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#define HB_SHAPER icu_le +#define hb_icu_le_shaper_font_data_t PortableFontInstance +#include "hb-shaper-impl-private.hh" + +#include "hb-icu-le/PortableFontInstance.h" + +#include "layout/LayoutEngine.h" +#include "unicode/unistr.h" + +#include "hb-icu.h" + + +/* + * shaper face data + */ + +struct hb_icu_le_shaper_face_data_t {}; + +hb_icu_le_shaper_face_data_t * +_hb_icu_le_shaper_face_data_create (hb_face_t *face) +{ + return (hb_icu_le_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED; +} + +void +_hb_icu_le_shaper_face_data_destroy (hb_icu_le_shaper_face_data_t *data) +{ +} + + +/* + * shaper font data + */ + +hb_icu_le_shaper_font_data_t * +_hb_icu_le_shaper_font_data_create (hb_font_t *font) +{ + LEErrorCode status = LE_NO_ERROR; + hb_icu_le_shaper_font_data_t *data = new PortableFontInstance (font->face, + font->x_scale, + font->y_scale, + status); + if (status != LE_NO_ERROR) { + delete (data); + return NULL; + } + + return data; +} + +void +_hb_icu_le_shaper_font_data_destroy (hb_icu_le_shaper_font_data_t *data) +{ + delete (data); +} + + +/* + * shaper shape_plan data + */ + +struct hb_icu_le_shaper_shape_plan_data_t {}; + +hb_icu_le_shaper_shape_plan_data_t * +_hb_icu_le_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, + const hb_feature_t *user_features, + unsigned int num_user_features) +{ + return (hb_icu_le_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; +} + +void +_hb_icu_le_shaper_shape_plan_data_destroy (hb_icu_le_shaper_shape_plan_data_t *data) +{ +} + + +/* + * shaper + */ + +hb_bool_t +_hb_icu_le_shape (hb_shape_plan_t *shape_plan, + hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features) +{ + LEFontInstance *font_instance = HB_SHAPER_DATA_GET (font); + le_int32 script_code = hb_icu_script_from_script (shape_plan->props.script); + le_int32 language_code = -1 /* TODO */; + le_int32 typography_flags = 3; // essential for ligatures and kerning + LEErrorCode status = LE_NO_ERROR; + LayoutEngine *le = LayoutEngine::layoutEngineFactory (font_instance, + script_code, + language_code, + typography_flags, + status); + if (status != LE_NO_ERROR) + { delete (le); return false; } + +retry: + + unsigned int scratch_size; + char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size); + +#define ALLOCATE_ARRAY(Type, name, len) \ + Type *name = (Type *) scratch; \ + scratch += (len) * sizeof ((name)[0]); \ + scratch_size -= (len) * sizeof ((name)[0]); + + ALLOCATE_ARRAY (LEUnicode, chars, buffer->len); + ALLOCATE_ARRAY (unsigned int, clusters, buffer->len); + + for (unsigned int i = 0; i < buffer->len; i++) { + chars[i] = buffer->info[i].codepoint; + clusters[i] = buffer->info[i].cluster; + } + + unsigned int glyph_count = le->layoutChars(chars, + 0, + buffer->len, + buffer->len, + HB_DIRECTION_IS_BACKWARD (buffer->props.direction), + 0., 0., + status); + if (status != LE_NO_ERROR) + { delete (le); return false; } + + unsigned int num_glyphs = scratch_size / (sizeof (LEGlyphID) + + sizeof (le_int32) + + sizeof (float) * 2); + + if (unlikely (glyph_count >= num_glyphs || glyph_count > buffer->allocated)) { + buffer->ensure (buffer->allocated * 2); + if (buffer->in_error) + { delete (le); return false; } + goto retry; + } + + ALLOCATE_ARRAY (LEGlyphID, glyphs, glyph_count); + ALLOCATE_ARRAY (le_int32, indices, glyph_count); + ALLOCATE_ARRAY (float, positions, glyph_count * 2 + 2); + + le->getGlyphs(glyphs, status); + le->getCharIndices(indices, status); + le->getGlyphPositions(positions, status); + +#undef ALLOCATE_ARRAY + + /* Ok, we've got everything we need, now compose output buffer, + * very, *very*, carefully! */ + + unsigned int j = 0; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < glyph_count; i++) + { + if (glyphs[i] >= 0xFFFE) + continue; + + info[j].codepoint = glyphs[i]; + info[j].cluster = clusters[indices[i]]; + + /* icu-le doesn't seem to have separapte advance values. */ + info[j].mask = positions[2 * i + 2] - positions[2 * i]; + info[j].var1.u32 = 0; + info[j].var2.u32 = -positions[2 * i + 1]; + + j++; + } + buffer->len = j; + + buffer->clear_positions (); + + for (unsigned int i = 0; i < buffer->len; i++) { + hb_glyph_info_t *info = &buffer->info[i]; + hb_glyph_position_t *pos = &buffer->pos[i]; + + /* TODO vertical */ + pos->x_advance = info->mask; + pos->x_offset = info->var1.u32; + pos->y_offset = info->var2.u32; + } + + delete (le); + return true; +} diff --git a/gfx/harfbuzz/src/hb-mutex-private.hh b/gfx/harfbuzz/src/hb-mutex-private.hh index fc8ef4959951..5b3a17e91748 100644 --- a/gfx/harfbuzz/src/hb-mutex-private.hh +++ b/gfx/harfbuzz/src/hb-mutex-private.hh @@ -65,26 +65,6 @@ typedef pthread_mutex_t hb_mutex_impl_t; #define hb_mutex_impl_finish(M) pthread_mutex_destroy (M) -#elif !defined(HB_NO_MT) && defined(HAVE_GLIB) - -#include -#if !GLIB_CHECK_VERSION(2,32,0) -typedef GStaticMutex hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT G_STATIC_MUTEX_INIT -#define hb_mutex_impl_init(M) g_static_mutex_init (M) -#define hb_mutex_impl_lock(M) g_static_mutex_lock (M) -#define hb_mutex_impl_unlock(M) g_static_mutex_unlock (M) -#define hb_mutex_impl_finish(M) g_static_mutex_free (M) -#else -typedef GMutex hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT {0} -#define hb_mutex_impl_init(M) g_mutex_init (M) -#define hb_mutex_impl_lock(M) g_mutex_lock (M) -#define hb_mutex_impl_unlock(M) g_mutex_unlock (M) -#define hb_mutex_impl_finish(M) g_mutex_clear (M) -#endif - - #elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) #if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD) diff --git a/gfx/harfbuzz/src/hb-old.cc b/gfx/harfbuzz/src/hb-old.cc index 197e6209366a..529bffa0c946 100644 --- a/gfx/harfbuzz/src/hb-old.cc +++ b/gfx/harfbuzz/src/hb-old.cc @@ -337,6 +337,9 @@ retry: ALLOCATE_ARRAY (HB_GlyphAttributes, item.attributes, num_glyphs); ALLOCATE_ARRAY (HB_Fixed, item.advances, num_glyphs); ALLOCATE_ARRAY (HB_FixedPoint, item.offsets, num_glyphs); + /* Apparently in some cases the offsets array will not be fully assigned to. + * Clear it. */ + memset (item.offsets, 0, num_glyphs * sizeof (item.offsets[0])); uint32_t *vis_clusters; ALLOCATE_ARRAY (uint32_t, vis_clusters, num_glyphs); diff --git a/gfx/harfbuzz/src/hb-open-file-private.hh b/gfx/harfbuzz/src/hb-open-file-private.hh index e2d4a2c237f9..31fedfbbceab 100644 --- a/gfx/harfbuzz/src/hb-open-file-private.hh +++ b/gfx/harfbuzz/src/hb-open-file-private.hh @@ -32,6 +32,8 @@ #include "hb-open-type-private.hh" +namespace OT { + /* * @@ -253,5 +255,7 @@ struct OpenTypeFontFile }; +} // namespace OT + #endif /* HB_OPEN_FILE_PRIVATE_HH */ diff --git a/gfx/harfbuzz/src/hb-open-type-private.hh b/gfx/harfbuzz/src/hb-open-type-private.hh index 4d8c507fbc94..3067b900ada7 100644 --- a/gfx/harfbuzz/src/hb-open-type-private.hh +++ b/gfx/harfbuzz/src/hb-open-type-private.hh @@ -34,6 +34,8 @@ #include "hb-blob.h" +namespace OT { + /* * Casts @@ -325,6 +327,160 @@ struct Sanitizer +/* + * Serialize + */ + +#ifndef HB_DEBUG_SERIALIZE +#define HB_DEBUG_SERIALIZE (HB_DEBUG+0) +#endif + + +#define TRACE_SERIALIZE() \ + hb_auto_trace_t trace (&c->debug_depth, "SERIALIZE", c, HB_FUNC, ""); + + +struct hb_serialize_context_t +{ + inline hb_serialize_context_t (void *start, unsigned int size) + { + this->start = (char *) start; + this->end = this->start + size; + + this->ran_out_of_room = false; + this->head = this->start; + this->debug_depth = 0; + } + + template + inline Type *start_serialize (void) + { + DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1, + "start [%p..%p] (%lu bytes)", + this->start, this->end, + (unsigned long) (this->end - this->start)); + + return start_embed (); + } + + inline void end_serialize (void) + { + DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1, + "end [%p..%p] serialized %d bytes; %s", + this->start, this->end, + (int) (this->head - this->start), + this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room"); + + } + + template + inline Type *copy (void) + { + assert (!this->ran_out_of_room); + unsigned int len = this->head - this->start; + void *p = malloc (len); + if (p) + memcpy (p, this->start, len); + return reinterpret_cast (p); + } + + template + inline Type *allocate_size (unsigned int size) + { + if (unlikely (this->ran_out_of_room || this->end - this->head < size)) { + this->ran_out_of_room = true; + return NULL; + } + memset (this->head, 0, size); + char *ret = this->head; + this->head += size; + return reinterpret_cast (ret); + } + + template + inline Type *allocate_min (void) + { + return this->allocate_size (Type::min_size); + } + + template + inline Type *start_embed (void) + { + Type *ret = reinterpret_cast (this->head); + return ret; + } + + template + inline Type *embed (const Type &obj) + { + unsigned int size = obj.get_size (); + Type *ret = this->allocate_size (size); + if (unlikely (!ret)) return NULL; + memcpy (ret, obj, size); + return ret; + } + + template + inline Type *extend_min (Type &obj) + { + unsigned int size = obj.min_size; + assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); + if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return NULL; + return reinterpret_cast (&obj); + } + + template + inline Type *extend (Type &obj) + { + unsigned int size = obj.get_size (); + assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); + if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return NULL; + return reinterpret_cast (&obj); + } + + inline void truncate (void *head) + { + assert (this->start < head && head <= this->head); + this->head = (char *) head; + } + + unsigned int debug_depth; + char *start, *end, *head; + bool ran_out_of_room; +}; + +template +struct Supplier +{ + inline Supplier (const Type *array, unsigned int len_) + { + head = array; + len = len_; + } + inline const Type operator [] (unsigned int i) const + { + if (unlikely (i >= len)) return Type (); + return head[i]; + } + + inline void advance (unsigned int count) + { + if (unlikely (count > len)) + count = len; + len -= count; + head += count; + } + + private: + inline Supplier (const Supplier &); /* Disallow copy */ + inline Supplier& operator= (const Supplier &); /* Disallow copy */ + + unsigned int len; + const Type *head; +}; + + + /* * @@ -371,6 +527,8 @@ struct IntType inline operator Type(void) const { return v; } inline bool operator == (const IntType &o) const { return v == o.v; } inline bool operator != (const IntType &o) const { return v != o.v; } + static inline int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } + inline int cmp (IntType va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; } inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); @@ -382,11 +540,6 @@ struct IntType DEFINE_SIZE_STATIC (sizeof (Type)); }; -/* Typedef these to avoid clash with windows.h */ -#define USHORT HB_USHORT -#define SHORT HB_SHORT -#define ULONG HB_ULONG -#define LONG HB_LONG typedef IntType USHORT; /* 16-bit unsigned integer. */ typedef IntType SHORT; /* 16-bit signed integer. */ typedef IntType ULONG; /* 32-bit unsigned integer. */ @@ -493,6 +646,18 @@ struct GenericOffsetTo : OffsetType if (unlikely (!offset)) return Null(Type); return StructAtOffset (base, offset); } + inline Type& operator () (void *base) + { + unsigned int offset = *this; + return StructAtOffset (base, offset); + } + + inline Type& serialize (hb_serialize_context_t *c, void *base) + { + Type *t = c->start_embed (); + this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ + return *t; + } inline bool sanitize (hb_sanitize_context_t *c, void *base) { TRACE_SANITIZE (); @@ -523,7 +688,9 @@ struct GenericOffsetTo : OffsetType } }; template -inline const Type& operator + (const Base &base, GenericOffsetTo offset) { return offset (base); } +inline const Type& operator + (const Base &base, const GenericOffsetTo &offset) { return offset (base); } +template +inline Type& operator + (Base &base, GenericOffsetTo &offset) { return offset (base); } template struct OffsetTo : GenericOffsetTo {}; @@ -556,9 +723,35 @@ struct GenericArrayOf if (unlikely (i >= len)) return Null(Type); return array[i]; } + inline Type& operator [] (unsigned int i) + { + return array[i]; + } inline unsigned int get_size (void) const { return len.static_size + len * Type::static_size; } + inline bool serialize (hb_serialize_context_t *c, + unsigned int items_len) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + len.set (items_len); /* TODO(serialize) Overflow? */ + if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + + inline bool serialize (hb_serialize_context_t *c, + Supplier &items, + unsigned int items_len) + { + TRACE_SERIALIZE (); + if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < items_len; i++) + array[i] = items[i]; + items.advance (items_len); + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); @@ -662,6 +855,21 @@ struct HeadlessArrayOf 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 (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + len.set (items_len); /* TODO(serialize) Overflow? */ + if (unlikely (!items_len)) return TRACE_RETURN (true); + if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < items_len - 1; i++) + array[i] = items[i]; + items.advance (items_len - 1); + return TRACE_RETURN (true); + } + inline bool sanitize_shallow (hb_sanitize_context_t *c) { return c->check_struct (this) && c->check_array (this, Type::static_size, len); @@ -714,5 +922,7 @@ struct SortedArrayOf : ArrayOf { }; +} // namespace OT + #endif /* HB_OPEN_TYPE_PRIVATE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-head-table.hh b/gfx/harfbuzz/src/hb-ot-head-table.hh index bf2d2452b905..0934168f58f6 100644 --- a/gfx/harfbuzz/src/hb-ot-head-table.hh +++ b/gfx/harfbuzz/src/hb-ot-head-table.hh @@ -32,6 +32,8 @@ #include "hb-open-type-private.hh" +namespace OT { + /* * head -- Font Header @@ -141,5 +143,7 @@ struct head }; +} // namespace OT + #endif /* HB_OT_HEAD_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-hhea-table.hh b/gfx/harfbuzz/src/hb-ot-hhea-table.hh index 24f8bdcfd27c..5009e6b6a2df 100644 --- a/gfx/harfbuzz/src/hb-ot-hhea-table.hh +++ b/gfx/harfbuzz/src/hb-ot-hhea-table.hh @@ -30,6 +30,8 @@ #include "hb-open-type-private.hh" +namespace OT { + /* * hhea -- The Horizontal Header Table @@ -89,4 +91,7 @@ struct hhea }; +} // namespace OT + + #endif /* HB_OT_HHEA_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh index cc7cfbb96cdd..feb601680083 100644 --- a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh +++ b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh @@ -30,6 +30,8 @@ #include "hb-open-type-private.hh" +namespace OT { + /* * hmtx -- The Horizontal Metrics Table @@ -83,4 +85,8 @@ struct hmtx DEFINE_SIZE_ARRAY2 (0, longHorMetric, leftSideBearingX); }; + +} // namespace OT + + #endif /* HB_OT_HMTX_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh index cea5b75da770..f5a067aec9d2 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh @@ -34,6 +34,9 @@ #include "hb-set-private.hh" +namespace OT { + + #define NOT_COVERED ((unsigned int) -1) #define MAX_NESTING_LEVEL 8 @@ -310,11 +313,29 @@ struct Lookup return flag; } + inline bool serialize (hb_serialize_context_t *c, + unsigned int lookup_type, + uint32_t lookup_props, + unsigned int num_subtables) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + lookupType.set (lookup_type); + lookupFlag.set (lookup_props & 0xFFFF); + if (unlikely (!subTable.serialize (c, num_subtables))) return TRACE_RETURN (false); + if (lookupFlag & LookupFlag::UseMarkFilteringSet) + { + USHORT &markFilteringSet = StructAfter (subTable); + markFilteringSet.set (lookup_props >> 16); + } + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); /* Real sanitize of the subtables is done by GSUB/GPOS/... */ if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false); - if (unlikely (lookupFlag & LookupFlag::UseMarkFilteringSet)) + if (lookupFlag & LookupFlag::UseMarkFilteringSet) { USHORT &markFilteringSet = StructAfter (subTable); if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false); @@ -352,6 +373,20 @@ struct CoverageFormat1 return i; } + inline bool serialize (hb_serialize_context_t *c, + Supplier &glyphs, + unsigned int num_glyphs) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + glyphArray.len.set (num_glyphs); + if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < num_glyphs; i++) + glyphArray[i] = glyphs[i]; + glyphs.advance (num_glyphs); + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); return TRACE_RETURN (glyphArray.sanitize (c)); @@ -403,6 +438,38 @@ struct CoverageFormat2 return NOT_COVERED; } + inline bool serialize (hb_serialize_context_t *c, + Supplier &glyphs, + unsigned int num_glyphs) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + + if (unlikely (!num_glyphs)) return TRACE_RETURN (true); + + unsigned int num_ranges = 1; + for (unsigned int i = 1; i < num_glyphs; i++) + if (glyphs[i - 1] + 1 != glyphs[i]) + num_ranges++; + rangeRecord.len.set (num_ranges); + if (unlikely (!c->extend (rangeRecord))) return TRACE_RETURN (false); + + unsigned int range = 0; + rangeRecord[range].start = glyphs[0]; + rangeRecord[range].value.set (0); + for (unsigned int i = 1; i < num_glyphs; i++) + if (glyphs[i - 1] + 1 != glyphs[i]) { + range++; + rangeRecord[range].start = glyphs[i]; + rangeRecord[range].value.set (i); + rangeRecord[range].end = glyphs[i]; + } else { + rangeRecord[range].end = glyphs[i]; + } + glyphs.advance (num_glyphs); + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); return TRACE_RETURN (rangeRecord.sanitize (c)); @@ -479,6 +546,24 @@ struct Coverage } } + inline bool serialize (hb_serialize_context_t *c, + Supplier &glyphs, + unsigned int num_glyphs) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + unsigned int num_ranges = 1; + for (unsigned int i = 1; i < num_glyphs; i++) + if (glyphs[i - 1] + 1 != glyphs[i]) + num_ranges++; + u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs)); + case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, num_glyphs)); + default:return TRACE_RETURN (false); + } + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); if (!u.format.sanitize (c)) return TRACE_RETURN (false); @@ -763,5 +848,7 @@ struct Device }; +} // namespace OT + #endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh index cebbe68b0984..92ae1cf581b8 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh @@ -34,6 +34,8 @@ #include "hb-font-private.hh" +namespace OT { + /* * Attachment List Table @@ -421,5 +423,7 @@ struct GDEF }; +} // namespace OT + #endif /* HB_OT_LAYOUT_GDEF_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh index 41168b2e0aa6..41cb93d02492 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh @@ -32,6 +32,8 @@ #include "hb-ot-layout-gsubgpos-private.hh" +namespace OT { + /* buffer **position** var allocations */ #define attach_lookback() var.u16[0] /* number of glyphs to go back to attach this glyph to its base */ @@ -1529,11 +1531,11 @@ struct PosLookup : Lookup return false; } - inline bool apply_string (hb_apply_context_t *c) const + inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest) const { bool ret = false; - if (unlikely (!c->buffer->len)) + if (unlikely (!c->buffer->len || !c->lookup_mask)) return false; c->set_lookup (*this); @@ -1543,7 +1545,7 @@ struct PosLookup : Lookup while (c->buffer->idx < c->buffer->len) { if ((c->buffer->cur().mask & c->lookup_mask) && - c->digest.may_have (c->buffer->cur().codepoint) && + digest->may_have (c->buffer->cur().codepoint) && apply_once (c)) ret = true; else @@ -1578,9 +1580,6 @@ struct GPOS : GSUBGPOS inline void add_coverage (set_t *glyphs, unsigned int lookup_index) const { get_lookup (lookup_index).add_coverage (glyphs); } - inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index) const - { return get_lookup (lookup_index).apply_string (c); } - static inline void position_start (hb_font_t *font, hb_buffer_t *buffer); static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer, hb_bool_t zero_width_attahced_marks); @@ -1598,20 +1597,20 @@ struct GPOS : GSUBGPOS static void fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) { - unsigned int j = pos[i].cursive_chain(); - if (likely (!j)) - return; + unsigned int j = pos[i].cursive_chain(); + if (likely (!j)) + return; - j += i; + j += i; - pos[i].cursive_chain() = 0; + pos[i].cursive_chain() = 0; - fix_cursive_minor_offset (pos, j, direction); + fix_cursive_minor_offset (pos, j, direction); - if (HB_DIRECTION_IS_HORIZONTAL (direction)) - pos[i].y_offset += pos[j].y_offset; - else - pos[i].x_offset += pos[j].x_offset; + if (HB_DIRECTION_IS_HORIZONTAL (direction)) + pos[i].y_offset += pos[j].y_offset; + else + pos[i].x_offset += pos[j].x_offset; } static void @@ -1713,5 +1712,7 @@ static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i #undef cursive_chain +} // namespace OT + #endif /* HB_OT_LAYOUT_GPOS_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh index 111441882cfc..90faa79c6452 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh @@ -32,6 +32,8 @@ #include "hb-ot-layout-gsubgpos-private.hh" +namespace OT { + struct SingleSubstFormat1 { @@ -70,6 +72,18 @@ struct SingleSubstFormat1 return TRACE_RETURN (true); } + inline bool serialize (hb_serialize_context_t *c, + Supplier &glyphs, + unsigned int num_glyphs, + int delta) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); + deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */ + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c)); @@ -122,6 +136,18 @@ struct SingleSubstFormat2 return TRACE_RETURN (true); } + inline bool serialize (hb_serialize_context_t *c, + Supplier &glyphs, + Supplier &substitutes, + unsigned int num_glyphs) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return TRACE_RETURN (false); + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c)); @@ -142,6 +168,7 @@ struct SingleSubstFormat2 struct SingleSubst { friend struct SubstLookupSubTable; + friend struct SubstLookup; private: @@ -174,6 +201,33 @@ struct SingleSubst } } + inline bool serialize (hb_serialize_context_t *c, + Supplier &glyphs, + Supplier &substitutes, + unsigned int num_glyphs) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); + unsigned int format = 2; + int delta; + if (num_glyphs) { + 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]) { + format = 2; + break; + } + } + u.format.set (format); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs, delta)); + case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, substitutes, num_glyphs)); + default:return TRACE_RETURN (false); + } + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); if (!u.format.sanitize (c)) return TRACE_RETURN (false); @@ -223,6 +277,16 @@ struct Sequence return TRACE_RETURN (true); } + inline bool serialize (hb_serialize_context_t *c, + Supplier &glyphs, + unsigned int num_glyphs) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + public: inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); @@ -267,6 +331,24 @@ struct MultipleSubstFormat1 return TRACE_RETURN ((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) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!sequence.serialize (c, num_glyphs))) return TRACE_RETURN (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_RETURN (false); + substitute_len_list.advance (num_glyphs); + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, this)); @@ -287,6 +369,7 @@ struct MultipleSubstFormat1 struct MultipleSubst { friend struct SubstLookupSubTable; + friend struct SubstLookup; private: @@ -316,6 +399,22 @@ struct MultipleSubst } } + inline bool serialize (hb_serialize_context_t *c, + Supplier &glyphs, + Supplier &substitute_len_list, + unsigned int num_glyphs, + Supplier &substitute_glyphs_list) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); + unsigned int format = 1; + u.format.set (format); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list)); + default:return TRACE_RETURN (false); + } + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); if (!u.format.sanitize (c)) return TRACE_RETURN (false); @@ -389,6 +488,24 @@ struct AlternateSubstFormat1 return TRACE_RETURN (true); } + inline bool serialize (hb_serialize_context_t *c, + Supplier &glyphs, + Supplier &alternate_len_list, + unsigned int num_glyphs, + Supplier &alternate_glyphs_list) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!alternateSet.serialize (c, num_glyphs))) return TRACE_RETURN (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_RETURN (false); + alternate_len_list.advance (num_glyphs); + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c, this)); @@ -409,6 +526,7 @@ struct AlternateSubstFormat1 struct AlternateSubst { friend struct SubstLookupSubTable; + friend struct SubstLookup; private: @@ -438,6 +556,22 @@ struct AlternateSubst } } + inline bool serialize (hb_serialize_context_t *c, + Supplier &glyphs, + Supplier &alternate_len_list, + unsigned int num_glyphs, + Supplier &alternate_glyphs_list) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); + unsigned int format = 1; + u.format.set (format); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list)); + default:return TRACE_RETURN (false); + } + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); if (!u.format.sanitize (c)) return TRACE_RETURN (false); @@ -489,135 +623,43 @@ struct Ligature unsigned int count = component.len; if (unlikely (count < 1)) return TRACE_RETURN (false); - hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); - if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); + unsigned int end_offset; + bool is_mark_ligature; + unsigned int total_component_count; - /* - * This is perhaps the trickiest part of GSUB... Remarks: - * - * - If all components of the ligature were marks, we call this a mark ligature. - * - * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize - * it as a ligature glyph. Though, really, this will not really be used... - * - * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave - * the ligature to keep its old ligature id. This will allow it to attach to - * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH, - * and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a - * ligature id and component value of 2. Then if SHADDA,FATHA form a ligature - * later, we don't want them to lose their ligature id/component, otherwise - * GPOS will fail to correctly position the mark ligature on top of the - * LAM,LAM,HEH ligature. See: - * https://bugzilla.gnome.org/show_bug.cgi?id=676343 - * - * - If a ligature is formed of components that some of which are also ligatures - * themselves, and those ligature components had marks attached to *their* - * components, we have to attach the marks to the new ligature component - * positions! Now *that*'s tricky! And these marks may be following the - * last component of the whole sequence, so we should loop forward looking - * for them and update them. - * - * Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a - * 'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature - * id and component == 1. Now, during 'liga', the LAM and the LAM-HEH ligature - * form a LAM-LAM-HEH ligature. We need to reassign the SHADDA and FATHA to - * the new ligature with a component value of 2. - * - * This in fact happened to a font... See: - * https://bugzilla.gnome.org/show_bug.cgi?id=437633 - * - * - Ligatures cannot be formed across glyphs attached to different components - * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and - * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother. - * However, it would be wrong to ligate that SHADDA,FATHA sequence.o - * There is an exception to this: If a ligature tries ligating with marks that - * belong to it itself, go ahead, assuming that the font designer knows what - * they are doing (otherwise it can break Indic stuff when a matra wants to - * ligate with a conjunct...) - */ - - bool is_mark_ligature = !!(c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); - - unsigned int total_component_count = 0; - total_component_count += get_lig_num_comps (c->buffer->cur()); - - unsigned int first_lig_id = get_lig_id (c->buffer->cur()); - unsigned int first_lig_comp = get_lig_comp (c->buffer->cur()); - - for (unsigned int i = 1; i < count; i++) - { - unsigned int property; - - if (!skippy_iter.next (&property)) return TRACE_RETURN (false); - - if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i])) return TRACE_RETURN (false); - - unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]); - unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx]); - - if (first_lig_id && first_lig_comp) { - /* If first component was attached to a previous ligature component, - * all subsequent components should be attached to the same ligature - * component, otherwise we shouldn't ligate them. */ - if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) - return TRACE_RETURN (false); - } else { - /* If first component was NOT attached to a previous ligature component, - * all subsequent components should also NOT be attached to any ligature - * component, unless they are attached to the first component itself! */ - if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id)) - return TRACE_RETURN (false); - } - - is_mark_ligature = is_mark_ligature && (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); - total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]); - } + if (likely (!match_input (c, count, + &component[1], + match_glyph, + NULL, + &end_offset, + &is_mark_ligature, + &total_component_count))) + return TRACE_RETURN (false); /* Deal, we are forming the ligature. */ - c->buffer->merge_clusters (c->buffer->idx, skippy_iter.idx + 1); + c->buffer->merge_clusters (c->buffer->idx, c->buffer->idx + end_offset); - unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE; - unsigned int lig_id = is_mark_ligature ? 0 : allocate_lig_id (c->buffer); - unsigned int last_lig_id = get_lig_id (c->buffer->cur()); - unsigned int last_num_components = get_lig_num_comps (c->buffer->cur()); - unsigned int components_so_far = last_num_components; + ligate_input (c, + count, + &component[1], + ligGlyph, + match_glyph, + NULL, + is_mark_ligature, + total_component_count); - if (!is_mark_ligature) - set_lig_props_for_ligature (c->buffer->cur(), lig_id, total_component_count); - c->replace_glyph (ligGlyph, klass); - - for (unsigned int i = 1; i < count; i++) - { - while (c->should_mark_skip_current_glyph ()) - { - if (!is_mark_ligature) { - unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (MAX (get_lig_comp (c->buffer->cur()), 1u), last_num_components); - set_lig_props_for_mark (c->buffer->cur(), lig_id, new_lig_comp); - } - c->buffer->next_glyph (); - } - - last_lig_id = get_lig_id (c->buffer->cur()); - last_num_components = get_lig_num_comps (c->buffer->cur()); - components_so_far += last_num_components; - - /* Skip the base glyph */ - c->buffer->idx++; - } - - if (!is_mark_ligature && last_lig_id) { - /* Re-adjust components for any marks following. */ - for (unsigned int i = c->buffer->idx; i < c->buffer->len; i++) { - if (last_lig_id == get_lig_id (c->buffer->info[i])) { - unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (MAX (get_lig_comp (c->buffer->info[i]), 1u), last_num_components); - set_lig_props_for_mark (c->buffer->info[i], lig_id, new_lig_comp); - } else - break; - } - } + return TRACE_RETURN (true); + } + inline bool serialize (hb_serialize_context_t *c, + GlyphID ligature, + Supplier &components, /* Starting from second */ + unsigned int num_components /* Including first component */) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + ligGlyph = ligature; + if (unlikely (!component.serialize (c, components, num_components))) return TRACE_RETURN (false); return TRACE_RETURN (true); } @@ -676,6 +718,25 @@ struct LigatureSet return TRACE_RETURN (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 */) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!ligature.serialize (c, num_ligatures))) return TRACE_RETURN (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_RETURN (false); + ligatures.advance (num_ligatures); + component_count_list.advance (num_ligatures); + return TRACE_RETURN (true); + } + public: inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); @@ -728,6 +789,28 @@ struct LigatureSubstFormat1 return TRACE_RETURN (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 */) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return TRACE_RETURN (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_RETURN (false); + ligature_per_first_glyph_count_list.advance (num_first_glyphs); + if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); @@ -748,6 +831,7 @@ struct LigatureSubstFormat1 struct LigatureSubst { friend struct SubstLookupSubTable; + friend struct SubstLookup; private: @@ -785,6 +869,25 @@ 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 */) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); + unsigned int format = 1; + u.format.set (format); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs, + ligatures_list, component_count_list, component_list)); + default:return TRACE_RETURN (false); + } + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); if (!u.format.sanitize (c)) return TRACE_RETURN (false); @@ -1183,10 +1286,10 @@ struct SubstLookup : Lookup } } - inline bool would_apply (hb_would_apply_context_t *c) const + inline bool would_apply (hb_would_apply_context_t *c, const hb_set_digest_t *digest) const { if (unlikely (!c->len)) return false; - if (!c->digest.may_have (c->glyphs[0])) return false; + if (!digest->may_have (c->glyphs[0])) return false; unsigned int lookup_type = get_type (); unsigned int count = get_subtable_count (); for (unsigned int i = 0; i < count; i++) @@ -1210,11 +1313,11 @@ struct SubstLookup : Lookup return false; } - inline bool apply_string (hb_apply_context_t *c) const + inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest) const { bool ret = false; - if (unlikely (!c->buffer->len)) + if (unlikely (!c->buffer->len || !c->lookup_mask)) return false; c->set_lookup (*this); @@ -1228,7 +1331,7 @@ struct SubstLookup : Lookup while (c->buffer->idx < c->buffer->len) { if ((c->buffer->cur().mask & c->lookup_mask) && - c->digest.may_have (c->buffer->cur().codepoint) && + digest->may_have (c->buffer->cur().codepoint) && apply_once (c)) ret = true; else @@ -1244,7 +1347,7 @@ struct SubstLookup : Lookup do { if ((c->buffer->cur().mask & c->lookup_mask) && - c->digest.may_have (c->buffer->cur().codepoint) && + digest->may_have (c->buffer->cur().codepoint) && apply_once (c)) ret = true; else @@ -1257,7 +1360,66 @@ struct SubstLookup : Lookup return ret; } - inline bool sanitize (hb_sanitize_context_t *c) { + private: + inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c, + unsigned int i) + { return CastR > (subTable)[i].serialize (c, this); } + public: + + inline bool serialize_single (hb_serialize_context_t *c, + uint32_t lookup_props, + Supplier &glyphs, + Supplier &substitutes, + unsigned int num_glyphs) + { + TRACE_SERIALIZE (); + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return TRACE_RETURN (false); + return TRACE_RETURN (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs)); + } + + 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) + { + TRACE_SERIALIZE (); + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return TRACE_RETURN (false); + return TRACE_RETURN (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) + { + TRACE_SERIALIZE (); + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return TRACE_RETURN (false); + return TRACE_RETURN (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 */) + { + TRACE_SERIALIZE (); + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return TRACE_RETURN (false); + return TRACE_RETURN (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)); + } + + inline bool sanitize (hb_sanitize_context_t *c) + { TRACE_SANITIZE (); if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); OffsetArrayOf &list = CastR > (subTable); @@ -1297,12 +1459,6 @@ struct GSUB : GSUBGPOS inline void add_coverage (set_t *glyphs, unsigned int lookup_index) const { get_lookup (lookup_index).add_coverage (glyphs); } - inline bool would_substitute_lookup (hb_would_apply_context_t *c, unsigned int lookup_index) const - { return get_lookup (lookup_index).would_apply (c); } - - inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index) const - { return get_lookup (lookup_index).apply_string (c); } - static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer); static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer); @@ -1410,5 +1566,7 @@ static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup } +} // namespace OT + #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh index ba2a7e0e1ba8..da31bdfe13ba 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh @@ -34,6 +34,8 @@ #include "hb-set-private.hh" +namespace OT { + #ifndef HB_DEBUG_CLOSURE #define HB_DEBUG_CLOSURE (HB_DEBUG+0) @@ -76,18 +78,17 @@ struct hb_would_apply_context_t hb_face_t *face; const hb_codepoint_t *glyphs; unsigned int len; - const hb_set_digest_t digest; + bool zero_context; unsigned int debug_depth; hb_would_apply_context_t (hb_face_t *face_, const hb_codepoint_t *glyphs_, unsigned int len_, - const hb_set_digest_t *digest_ - ) : + bool zero_context_) : face (face_), glyphs (glyphs_), len (len_), - digest (*digest_), + zero_context (zero_context_), debug_depth (0) {}; }; @@ -113,21 +114,22 @@ struct hb_apply_context_t unsigned int debug_depth; const GDEF &gdef; bool has_glyph_classes; - const hb_set_digest_t digest; hb_apply_context_t (hb_font_t *font_, hb_buffer_t *buffer_, - hb_mask_t lookup_mask_, - const hb_set_digest_t *digest_) : + hb_mask_t lookup_mask_) : font (font_), face (font->face), buffer (buffer_), direction (buffer_->props.direction), lookup_mask (lookup_mask_), nesting_level_left (MAX_NESTING_LEVEL), lookup_props (0), property (0), debug_depth (0), gdef (*hb_ot_layout_from_face (face)->gdef), - has_glyph_classes (gdef.has_glyph_classes ()), - digest (*digest_) {} + has_glyph_classes (gdef.has_glyph_classes ()) {} + + void set_lookup_props (unsigned int lookup_props_) { + lookup_props = lookup_props_; + } void set_lookup (const Lookup &l) { lookup_props = l.get_props (); @@ -416,26 +418,160 @@ static inline bool match_input (hb_apply_context_t *c, const USHORT input[], /* Array of input values--start with second glyph */ match_func_t match_func, const void *match_data, - unsigned int *end_offset = NULL) + unsigned int *end_offset = NULL, + bool *p_is_mark_ligature = NULL, + unsigned int *p_total_component_count = NULL) { + hb_auto_trace_t trace (&c->debug_depth, "APPLY", NULL, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); - if (skippy_iter.has_no_chance ()) - return false; + if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); + + /* + * This is perhaps the trickiest part of OpenType... Remarks: + * + * - If all components of the ligature were marks, we call this a mark ligature. + * + * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize + * it as a ligature glyph. + * + * - Ligatures cannot be formed across glyphs attached to different components + * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and + * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother. + * However, it would be wrong to ligate that SHADDA,FATHA sequence.o + * There is an exception to this: If a ligature tries ligating with marks that + * belong to it itself, go ahead, assuming that the font designer knows what + * they are doing (otherwise it can break Indic stuff when a matra wants to + * ligate with a conjunct...) + */ + + bool is_mark_ligature = !!(c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); + + unsigned int total_component_count = 0; + total_component_count += get_lig_num_comps (c->buffer->cur()); + + unsigned int first_lig_id = get_lig_id (c->buffer->cur()); + unsigned int first_lig_comp = get_lig_comp (c->buffer->cur()); for (unsigned int i = 1; i < count; i++) { - if (!skippy_iter.next ()) - return false; + unsigned int property; - if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, input[i - 1], match_data))) - return false; + if (!skippy_iter.next (&property)) return TRACE_RETURN (false); + + if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, input[i - 1], match_data))) return false; + + unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]); + unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx]); + + if (first_lig_id && first_lig_comp) { + /* If first component was attached to a previous ligature component, + * all subsequent components should be attached to the same ligature + * component, otherwise we shouldn't ligate them. */ + if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) + return TRACE_RETURN (false); + } else { + /* If first component was NOT attached to a previous ligature component, + * all subsequent components should also NOT be attached to any ligature + * component, unless they are attached to the first component itself! */ + if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id)) + return TRACE_RETURN (false); + } + + is_mark_ligature = is_mark_ligature && (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); + total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]); } if (end_offset) *end_offset = skippy_iter.idx - c->buffer->idx + 1; + if (p_is_mark_ligature) + *p_is_mark_ligature = is_mark_ligature; + + if (p_total_component_count) + *p_total_component_count = total_component_count; + return true; } +static inline void ligate_input (hb_apply_context_t *c, + unsigned int count, /* Including the first glyph (not matched) */ + const USHORT input[], /* Array of input values--start with second glyph */ + hb_codepoint_t lig_glyph, + match_func_t match_func, + const void *match_data, + bool is_mark_ligature, + unsigned int total_component_count) +{ + /* + * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave + * the ligature to keep its old ligature id. This will allow it to attach to + * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH, + * and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a + * ligature id and component value of 2. Then if SHADDA,FATHA form a ligature + * later, we don't want them to lose their ligature id/component, otherwise + * GPOS will fail to correctly position the mark ligature on top of the + * LAM,LAM,HEH ligature. See: + * https://bugzilla.gnome.org/show_bug.cgi?id=676343 + * + * - If a ligature is formed of components that some of which are also ligatures + * themselves, and those ligature components had marks attached to *their* + * components, we have to attach the marks to the new ligature component + * positions! Now *that*'s tricky! And these marks may be following the + * last component of the whole sequence, so we should loop forward looking + * for them and update them. + * + * Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a + * 'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature + * id and component == 1. Now, during 'liga', the LAM and the LAM-HEH ligature + * form a LAM-LAM-HEH ligature. We need to reassign the SHADDA and FATHA to + * the new ligature with a component value of 2. + * + * This in fact happened to a font... See: + * https://bugzilla.gnome.org/show_bug.cgi?id=437633 + */ + + unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE; + unsigned int lig_id = is_mark_ligature ? 0 : allocate_lig_id (c->buffer); + unsigned int last_lig_id = get_lig_id (c->buffer->cur()); + unsigned int last_num_components = get_lig_num_comps (c->buffer->cur()); + unsigned int components_so_far = last_num_components; + + if (!is_mark_ligature) + set_lig_props_for_ligature (c->buffer->cur(), lig_id, total_component_count); + c->replace_glyph (lig_glyph, klass); + + for (unsigned int i = 1; i < count; i++) + { + while (c->should_mark_skip_current_glyph ()) + { + if (!is_mark_ligature) { + unsigned int new_lig_comp = components_so_far - last_num_components + + MIN (MAX (get_lig_comp (c->buffer->cur()), 1u), last_num_components); + set_lig_props_for_mark (c->buffer->cur(), lig_id, new_lig_comp); + } + c->buffer->next_glyph (); + } + + last_lig_id = get_lig_id (c->buffer->cur()); + last_num_components = get_lig_num_comps (c->buffer->cur()); + components_so_far += last_num_components; + + /* Skip the base glyph */ + c->buffer->idx++; + } + + if (!is_mark_ligature && last_lig_id) { + /* Re-adjust components for any marks following. */ + for (unsigned int i = c->buffer->idx; i < c->buffer->len; i++) { + if (last_lig_id == get_lig_id (c->buffer->info[i])) { + unsigned int new_lig_comp = components_so_far - last_num_components + + MIN (MAX (get_lig_comp (c->buffer->info[i]), 1u), last_num_components); + set_lig_props_for_mark (c->buffer->info[i], lig_id, new_lig_comp); + } else + break; + } + } +} static inline bool match_backtrack (hb_apply_context_t *c, unsigned int count, @@ -443,20 +579,22 @@ static inline bool match_backtrack (hb_apply_context_t *c, match_func_t match_func, const void *match_data) { + hb_auto_trace_t trace (&c->debug_depth, "APPLY", NULL, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); + hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true); if (skippy_iter.has_no_chance ()) - return false; + return TRACE_RETURN (false); for (unsigned int i = 0; i < count; i++) { if (!skippy_iter.prev ()) - return false; + return TRACE_RETURN (false); if (likely (!match_func (c->buffer->out_info[skippy_iter.idx].codepoint, backtrack[i], match_data))) - return false; + return TRACE_RETURN (false); } - return true; + return TRACE_RETURN (true); } static inline bool match_lookahead (hb_apply_context_t *c, @@ -466,20 +604,22 @@ static inline bool match_lookahead (hb_apply_context_t *c, const void *match_data, unsigned int offset) { + hb_auto_trace_t trace (&c->debug_depth, "APPLY", NULL, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true); if (skippy_iter.has_no_chance ()) - return false; + return TRACE_RETURN (false); for (unsigned int i = 0; i < count; i++) { if (!skippy_iter.next ()) - return false; + return TRACE_RETURN (false); if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, lookahead[i], match_data))) - return false; + return TRACE_RETURN (false); } - return true; + return TRACE_RETURN (true); } @@ -1066,8 +1206,7 @@ static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c const LookupRecord lookupRecord[], ChainContextApplyLookupContext &lookup_context) { - return !backtrackCount - && !lookaheadCount + return (c->zero_context ? !backtrackCount && !lookaheadCount : true) && would_match_input (c, inputCount, input, lookup_context.funcs.match, lookup_context.match_data[1]); @@ -1680,5 +1819,7 @@ struct GSUBGPOS }; +} // namespace OT + #endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-layout-private.hh b/gfx/harfbuzz/src/hb-ot-layout-private.hh index e10178202af5..70fda8ead8e4 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-private.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-private.hh @@ -139,9 +139,10 @@ static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) { HB_INTERNAL hb_bool_t hb_ot_layout_would_substitute_lookup_fast (hb_face_t *face, + unsigned int lookup_index, const hb_codepoint_t *glyphs, unsigned int glyphs_length, - unsigned int lookup_index); + hb_bool_t zero_context); /* Should be called before all the substitute_lookup's are done. */ @@ -184,15 +185,21 @@ hb_ot_layout_position_finish (hb_font_t *font, * hb_ot_layout_t */ +namespace OT { + struct GDEF; + struct GSUB; + struct GPOS; +} + struct hb_ot_layout_t { hb_blob_t *gdef_blob; hb_blob_t *gsub_blob; hb_blob_t *gpos_blob; - const struct GDEF *gdef; - const struct GSUB *gsub; - const struct GPOS *gpos; + const struct OT::GDEF *gdef; + const struct OT::GSUB *gsub; + const struct OT::GPOS *gpos; unsigned int gsub_lookup_count; unsigned int gpos_lookup_count; diff --git a/gfx/harfbuzz/src/hb-ot-layout.cc b/gfx/harfbuzz/src/hb-ot-layout.cc index e4d84e82adf1..e241e3326978 100644 --- a/gfx/harfbuzz/src/hb-ot-layout.cc +++ b/gfx/harfbuzz/src/hb-ot-layout.cc @@ -35,7 +35,6 @@ #include "hb-ot-layout-gpos-table.hh" #include "hb-ot-maxp-table.hh" - #include #include @@ -49,14 +48,14 @@ _hb_ot_layout_create (hb_face_t *face) if (unlikely (!layout)) return NULL; - layout->gdef_blob = Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GDEF)); - layout->gdef = Sanitizer::lock_instance (layout->gdef_blob); + layout->gdef_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GDEF)); + layout->gdef = OT::Sanitizer::lock_instance (layout->gdef_blob); - layout->gsub_blob = Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GSUB)); - layout->gsub = Sanitizer::lock_instance (layout->gsub_blob); + layout->gsub_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GSUB)); + layout->gsub = OT::Sanitizer::lock_instance (layout->gsub_blob); - layout->gpos_blob = Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GPOS)); - layout->gpos = Sanitizer::lock_instance (layout->gpos_blob); + layout->gpos_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GPOS)); + layout->gpos = OT::Sanitizer::lock_instance (layout->gpos_blob); layout->gsub_lookup_count = layout->gsub->get_lookup_count (); layout->gpos_lookup_count = layout->gpos->get_lookup_count (); @@ -92,22 +91,22 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) free (layout); } -static inline const GDEF& +static inline const OT::GDEF& _get_gdef (hb_face_t *face) { - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(GDEF); + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF); return *hb_ot_layout_from_face (face)->gdef; } -static inline const GSUB& +static inline const OT::GSUB& _get_gsub (hb_face_t *face) { - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(GSUB); + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB); return *hb_ot_layout_from_face (face)->gsub; } -static inline const GPOS& +static inline const OT::GPOS& _get_gpos (hb_face_t *face) { - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(GPOS); + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS); return *hb_ot_layout_from_face (face)->gpos; } @@ -149,14 +148,14 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, * GSUB/GPOS */ -static const GSUBGPOS& +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); - default: return Null(GSUBGPOS); + default: return OT::Null(OT::GSUBGPOS); } } @@ -168,7 +167,7 @@ hb_ot_layout_table_get_script_tags (hb_face_t *face, unsigned int *script_count /* IN/OUT */, hb_tag_t *script_tags /* OUT */) { - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); return g.get_script_tags (start_offset, script_count, script_tags); } @@ -179,8 +178,8 @@ hb_ot_layout_table_find_script (hb_face_t *face, hb_tag_t script_tag, unsigned int *script_index) { - ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); if (g.find_script_index (script_tag, script_index)) return true; @@ -205,8 +204,8 @@ hb_ot_layout_table_choose_script (hb_face_t *face, unsigned int *script_index, hb_tag_t *chosen_script) { - ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); while (*script_tags) { @@ -254,7 +253,7 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face, unsigned int *feature_count /* IN/OUT */, hb_tag_t *feature_tags /* OUT */) { - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); return g.get_feature_tags (start_offset, feature_count, feature_tags); } @@ -268,7 +267,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face, unsigned int *language_count /* IN/OUT */, hb_tag_t *language_tags /* OUT */) { - const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); + const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); return s.get_lang_sys_tags (start_offset, language_count, language_tags); } @@ -280,8 +279,8 @@ hb_ot_layout_script_find_language (hb_face_t *face, hb_tag_t language_tag, unsigned int *language_index) { - ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX); - const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); + ASSERT_STATIC (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); if (s.find_lang_sys_index (language_tag, language_index)) return true; @@ -301,7 +300,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face, unsigned int language_index, unsigned int *feature_index) { - const LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index); + const OT::LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index); if (feature_index) *feature_index = l.get_required_feature_index (); @@ -317,8 +316,8 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t *face, unsigned int *feature_count /* IN/OUT */, unsigned int *feature_indexes /* OUT */) { - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index); return l.get_feature_indexes (start_offset, feature_count, feature_indexes); } @@ -332,8 +331,8 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face, unsigned int *feature_count /* IN/OUT */, hb_tag_t *feature_tags /* OUT */) { - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index); ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t)); unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags); @@ -356,9 +355,9 @@ hb_ot_layout_language_find_feature (hb_face_t *face, hb_tag_t feature_tag, unsigned int *feature_index) { - ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); + ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index); unsigned int num_features = l.get_feature_count (); for (unsigned int i = 0; i < num_features; i++) { @@ -382,48 +381,53 @@ hb_ot_layout_feature_get_lookup_indexes (hb_face_t *face, unsigned int *lookup_count /* IN/OUT */, unsigned int *lookup_indexes /* OUT */) { - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - const Feature &f = g.get_feature (feature_index); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + const OT::Feature &f = g.get_feature (feature_index); return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); } /* - * GSUB + * OT::GSUB */ hb_bool_t hb_ot_layout_has_substitution (hb_face_t *face) { - return &_get_gsub (face) != &Null(GSUB); + return &_get_gsub (face) != &OT::Null(OT::GSUB); } hb_bool_t hb_ot_layout_would_substitute_lookup (hb_face_t *face, + unsigned int lookup_index, const hb_codepoint_t *glyphs, unsigned int glyphs_length, - unsigned int lookup_index) + hb_bool_t zero_context) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false; - return hb_ot_layout_would_substitute_lookup_fast (face, glyphs, glyphs_length, lookup_index); + return hb_ot_layout_would_substitute_lookup_fast (face, lookup_index, glyphs, glyphs_length, zero_context); } hb_bool_t hb_ot_layout_would_substitute_lookup_fast (hb_face_t *face, + unsigned int lookup_index, const hb_codepoint_t *glyphs, unsigned int glyphs_length, - unsigned int lookup_index) + hb_bool_t zero_context) { if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false; - hb_would_apply_context_t c (face, glyphs, glyphs_length, &hb_ot_layout_from_face (face)->gsub_digests[lookup_index]); - return hb_ot_layout_from_face (face)->gsub->would_substitute_lookup (&c, lookup_index); + OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context); + + const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); + + return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_digests[lookup_index]); } void hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer) { - GSUB::substitute_start (font, buffer); + OT::GSUB::substitute_start (font, buffer); } hb_bool_t @@ -433,39 +437,43 @@ hb_ot_layout_substitute_lookup (hb_font_t *font, hb_mask_t mask) { if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gsub_lookup_count)) return false; - hb_apply_context_t c (font, buffer, mask, &hb_ot_layout_from_face (font->face)->gsub_digests[lookup_index]); - return hb_ot_layout_from_face (font->face)->gsub->substitute_lookup (&c, lookup_index); + + OT::hb_apply_context_t c (font, buffer, mask); + + const OT::SubstLookup& l = hb_ot_layout_from_face (font->face)->gsub->get_lookup (lookup_index); + + return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gsub_digests[lookup_index]); } void hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer) { - GSUB::substitute_finish (font, buffer); + OT::GSUB::substitute_finish (font, buffer); } void hb_ot_layout_substitute_closure_lookup (hb_face_t *face, - hb_set_t *glyphs, - unsigned int lookup_index) + unsigned int lookup_index, + hb_set_t *glyphs) { - hb_closure_context_t c (face, glyphs); + OT::hb_closure_context_t c (face, glyphs); _get_gsub (face).closure_lookup (&c, lookup_index); } /* - * GPOS + * OT::GPOS */ hb_bool_t hb_ot_layout_has_positioning (hb_face_t *face) { - return &_get_gpos (face) != &Null(GPOS); + return &_get_gpos (face) != &OT::Null(OT::GPOS); } void hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer) { - GPOS::position_start (font, buffer); + OT::GPOS::position_start (font, buffer); } hb_bool_t @@ -475,12 +483,16 @@ hb_ot_layout_position_lookup (hb_font_t *font, hb_mask_t mask) { if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gpos_lookup_count)) return false; - hb_apply_context_t c (font, buffer, mask, &hb_ot_layout_from_face (font->face)->gpos_digests[lookup_index]); - return hb_ot_layout_from_face (font->face)->gpos->position_lookup (&c, lookup_index); + + OT::hb_apply_context_t c (font, buffer, mask); + + const OT::PosLookup& l = hb_ot_layout_from_face (font->face)->gpos->get_lookup (lookup_index); + + return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gpos_digests[lookup_index]); } void hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer, hb_bool_t zero_width_attached_marks) { - GPOS::position_finish (font, buffer, zero_width_attached_marks); + OT::GPOS::position_finish (font, buffer, zero_width_attached_marks); } diff --git a/gfx/harfbuzz/src/hb-ot-layout.h b/gfx/harfbuzz/src/hb-ot-layout.h index 2ad4ff4d0137..d431a380175f 100644 --- a/gfx/harfbuzz/src/hb-ot-layout.h +++ b/gfx/harfbuzz/src/hb-ot-layout.h @@ -171,14 +171,15 @@ hb_ot_layout_has_substitution (hb_face_t *face); hb_bool_t hb_ot_layout_would_substitute_lookup (hb_face_t *face, + unsigned int lookup_index, const hb_codepoint_t *glyphs, unsigned int glyphs_length, - unsigned int lookup_index); + hb_bool_t zero_context); void hb_ot_layout_substitute_closure_lookup (hb_face_t *face, - hb_set_t *glyphs, - unsigned int lookup_index); + unsigned int lookup_index, + hb_set_t *glyphs); /* * GPOS diff --git a/gfx/harfbuzz/src/hb-ot-map-private.hh b/gfx/harfbuzz/src/hb-ot-map-private.hh index b9c67362ab0a..7eb85c89e8e0 100644 --- a/gfx/harfbuzz/src/hb-ot-map-private.hh +++ b/gfx/harfbuzz/src/hb-ot-map-private.hh @@ -49,6 +49,7 @@ struct hb_ot_map_t unsigned int shift; hb_mask_t mask; hb_mask_t _1_mask; /* mask for value=1, for quick access */ + hb_bool_t needs_fallback; static int cmp (const feature_map_t *a, const feature_map_t *b) { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; } @@ -80,6 +81,11 @@ struct hb_ot_map_t return map ? map->mask : 0; } + inline bool needs_fallback (hb_tag_t feature_tag) const { + const feature_map_t *map = features.bsearch (&feature_tag); + return map ? map->needs_fallback : false; + } + inline hb_mask_t get_1_mask (hb_tag_t feature_tag) const { const feature_map_t *map = features.bsearch (&feature_tag); return map ? map->_1_mask : 0; @@ -147,10 +153,10 @@ struct hb_ot_map_builder_t hb_ot_map_builder_t (void) { memset (this, 0, sizeof (*this)); } - HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value, bool global); + HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value, bool global, bool has_fallback = false); - inline void add_bool_feature (hb_tag_t tag, bool global = true) - { add_feature (tag, 1, global); } + inline void add_bool_feature (hb_tag_t tag, bool global = true, bool has_fallback = false) + { add_feature (tag, 1, global, has_fallback); } inline void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func) { add_pause (0, pause_func); } @@ -174,6 +180,7 @@ struct hb_ot_map_builder_t unsigned int seq; /* sequence#, used for stable sorting only */ unsigned int max_value; bool global; /* whether the feature applies value to every glyph in the buffer */ + bool has_fallback; /* whether to allocate bits even if feature not found */ unsigned int default_value; /* for non-global features, what should the unset glyphs take */ unsigned int stage[2]; /* GSUB/GPOS */ diff --git a/gfx/harfbuzz/src/hb-ot-map.cc b/gfx/harfbuzz/src/hb-ot-map.cc index 7eed624c4464..f290c98a8798 100644 --- a/gfx/harfbuzz/src/hb-ot-map.cc +++ b/gfx/harfbuzz/src/hb-ot-map.cc @@ -60,7 +60,7 @@ hb_ot_map_t::add_lookups (hb_face_t *face, } -void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, bool global) +void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, bool global, bool has_fallback) { feature_info_t *info = feature_infos.push(); if (unlikely (!info)) return; @@ -68,6 +68,7 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, bool gl info->seq = feature_infos.len; info->max_value = value; info->global = global; + info->has_fallback = has_fallback; info->default_value = global ? value : 0; info->stage[0] = current_stage[0]; info->stage[1] = current_stage[1]; @@ -116,16 +117,8 @@ void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_ void hb_ot_map_t::substitute_closure (const hb_ot_shape_plan_t *plan, hb_face_t *face, hb_set_t *glyphs) const { unsigned int table_index = 0; - unsigned int i = 0; - - for (unsigned int pause_index = 0; pause_index < pauses[table_index].len; pause_index++) { - const pause_map_t *pause = &pauses[table_index][pause_index]; - for (; i < pause->num_lookups; i++) - hb_ot_layout_substitute_closure_lookup (face, glyphs, lookups[table_index][i].index); - } - - for (; i < lookups[table_index].len; i++) - hb_ot_layout_substitute_closure_lookup (face, glyphs, lookups[table_index][i].index); + for (unsigned int i = 0; i < lookups[table_index].len; i++) + hb_ot_layout_substitute_closure_lookup (face, lookups[table_index][i].index, glyphs); } void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func) @@ -183,6 +176,7 @@ hb_ot_map_builder_t::compile (hb_face_t *face, feature_infos[j].global = false; feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_infos[i].max_value); } + feature_infos[j].has_fallback = feature_infos[j].has_fallback || feature_infos[i].has_fallback; feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_infos[i].stage[0]); feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_infos[i].stage[1]); /* Inherit default_value from j */ @@ -217,7 +211,7 @@ hb_ot_map_builder_t::compile (hb_face_t *face, language_index[table_index], info->tag, &feature_index[table_index]); - if (!found) + if (!found && !info->has_fallback) continue; @@ -242,6 +236,7 @@ hb_ot_map_builder_t::compile (hb_face_t *face, m.global_mask |= (info->default_value << map->shift) & map->mask; } map->_1_mask = (1 << map->shift) & map->mask; + map->needs_fallback = !found; } feature_infos.shrink (0); /* Done with these */ diff --git a/gfx/harfbuzz/src/hb-ot-maxp-table.hh b/gfx/harfbuzz/src/hb-ot-maxp-table.hh index c2c90d1ff0d9..9e113c73ad6a 100644 --- a/gfx/harfbuzz/src/hb-ot-maxp-table.hh +++ b/gfx/harfbuzz/src/hb-ot-maxp-table.hh @@ -30,6 +30,8 @@ #include "hb-open-type-private.hh" +namespace OT { + /* * maxp -- The Maximum Profile Table @@ -61,5 +63,7 @@ struct maxp }; +} // namespace OT + #endif /* HB_OT_MAXP_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-name-table.hh b/gfx/harfbuzz/src/hb-ot-name-table.hh index e0d2e89971cb..6cc7a5ea2fd3 100644 --- a/gfx/harfbuzz/src/hb-ot-name-table.hh +++ b/gfx/harfbuzz/src/hb-ot-name-table.hh @@ -30,6 +30,8 @@ #include "hb-open-type-private.hh" +namespace OT { + /* * name -- The Naming Table @@ -124,5 +126,7 @@ struct name }; +} // namespace OT + #endif /* HB_OT_NAME_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh new file mode 100644 index 000000000000..bf68561e1619 --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh @@ -0,0 +1,253 @@ +/* + * Copyright © 2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH +#define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH + +#include "hb-private.hh" + +#include "hb-ot-shape-private.hh" +#include "hb-ot-layout-gsub-table.hh" + + +static const hb_tag_t arabic_fallback_features[] = +{ + HB_TAG('i','n','i','t'), + HB_TAG('m','e','d','i'), + HB_TAG('f','i','n','a'), + HB_TAG('i','s','o','l'), + HB_TAG('r','l','i','g'), +}; + +/* Same order as the fallback feature array */ +enum { + FALLBACK_INIT, + FALLBACK_MEDI, + FALLBACK_FINA, + FALLBACK_ISOL, + FALLBACK_RLIG, + ARABIC_NUM_FALLBACK_FEATURES +}; + +static OT::SubstLookup * +arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + unsigned int feature_index) +{ + OT::GlyphID glyphs[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1]; + OT::GlyphID substitutes[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1]; + unsigned int num_glyphs = 0; + + /* Populate arrays */ + for (hb_codepoint_t u = SHAPING_TABLE_FIRST; u < SHAPING_TABLE_LAST + 1; u++) + { + hb_codepoint_t s = shaping_table[u - SHAPING_TABLE_FIRST][feature_index]; + hb_codepoint_t u_glyph, s_glyph; + + if (!s || + !hb_font_get_glyph (font, u, 0, &u_glyph) || + !hb_font_get_glyph (font, s, 0, &s_glyph) || + u_glyph == s_glyph || + u_glyph > 0xFFFF || s_glyph > 0xFFFF) + continue; + + glyphs[num_glyphs].set (u_glyph); + substitutes[num_glyphs].set (s_glyph); + + num_glyphs++; + } + + /* Bubble-sort! + * May not be good-enough for presidential candidate interviews, but good-enough for us... */ + hb_bubble_sort (&glyphs[0], num_glyphs, 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)); + OT::SubstLookup *lookup = c.start_serialize (); + bool ret = lookup->serialize_single (&c, + OT::LookupFlag::IgnoreMarks, + glyphs_supplier, + substitutes_supplier, + num_glyphs); + c.end_serialize (); + /* TODO sanitize the results? */ + + return ret ? c.copy () : NULL; +} + +static OT::SubstLookup * +arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan, + hb_font_t *font) +{ + OT::GlyphID first_glyphs[ARRAY_LENGTH_CONST (ligature_table)]; + unsigned int first_glyphs_indirection[ARRAY_LENGTH_CONST (ligature_table)]; + unsigned int ligature_per_first_glyph_count_list[ARRAY_LENGTH_CONST (first_glyphs)]; + unsigned int num_first_glyphs = 0; + + /* We know that all our ligatures are 2-component */ + OT::GlyphID ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)]; + unsigned int component_count_list[ARRAY_LENGTH_CONST (ligature_list)]; + OT::GlyphID component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */]; + unsigned int num_ligatures = 0; + + /* Populate arrays */ + + /* Sort out the first-glyphs */ + for (unsigned int first_glyph_idx = 0; first_glyph_idx < ARRAY_LENGTH (first_glyphs); first_glyph_idx++) + { + hb_codepoint_t first_u = ligature_table[first_glyph_idx].first; + hb_codepoint_t first_glyph; + if (!hb_font_get_glyph (font, first_u, 0, &first_glyph)) + continue; + first_glyphs[num_first_glyphs].set (first_glyph); + ligature_per_first_glyph_count_list[num_first_glyphs] = 0; + first_glyphs_indirection[num_first_glyphs] = first_glyph_idx; + num_first_glyphs++; + } + hb_bubble_sort (&first_glyphs[0], num_first_glyphs, OT::GlyphID::cmp, &first_glyphs_indirection[0]); + + /* Now that the first-glyphs are sorted, walk again, populate ligatures. */ + for (unsigned int i = 0; i < num_first_glyphs; i++) + { + unsigned int first_glyph_idx = first_glyphs_indirection[i]; + + for (unsigned int second_glyph_idx = 0; second_glyph_idx < ARRAY_LENGTH (ligature_table[0].ligatures); second_glyph_idx++) + { + hb_codepoint_t second_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].second; + hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].ligature; + hb_codepoint_t second_glyph, ligature_glyph; + if (!second_u || + !hb_font_get_glyph (font, second_u, 0, &second_glyph) || + !hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph)) + continue; + + ligature_per_first_glyph_count_list[i]++; + + ligature_list[num_ligatures].set (ligature_glyph); + component_count_list[num_ligatures] = 2; + component_list[num_ligatures].set (second_glyph); + num_ligatures++; + } + } + + 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)); + 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); + + c.end_serialize (); + /* TODO sanitize the results? */ + + return ret ? c.copy () : NULL; +} + +static OT::SubstLookup * +arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + unsigned int feature_index) +{ + if (feature_index < 4) + return arabic_fallback_synthesize_lookup_single (plan, font, feature_index); + else + return arabic_fallback_synthesize_lookup_ligature (plan, font); +} + +struct arabic_fallback_plan_t +{ + ASSERT_POD (); + + hb_mask_t mask_array[ARABIC_NUM_FALLBACK_FEATURES]; + OT::SubstLookup *lookup_array[ARABIC_NUM_FALLBACK_FEATURES]; + hb_set_digest_t digest_array[ARABIC_NUM_FALLBACK_FEATURES]; +}; + +static const arabic_fallback_plan_t arabic_fallback_plan_nil = {}; + +static arabic_fallback_plan_t * +arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan, + hb_font_t *font) +{ + 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); + + for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) { + fallback_plan->mask_array[i] = plan->map.get_1_mask (arabic_fallback_features[i]); + if (fallback_plan->mask_array[i]) { + fallback_plan->lookup_array[i] = arabic_fallback_synthesize_lookup (plan, font, i); + if (fallback_plan->lookup_array[i]) + fallback_plan->lookup_array[i]->add_coverage (&fallback_plan->digest_array[i]); + } + } + + return fallback_plan; +} + +static void +arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan) +{ + if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil) + return; + + for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) + if (fallback_plan->lookup_array[i]) + free (fallback_plan->lookup_array[i]); + + free (fallback_plan); +} + +static void +arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan, + hb_font_t *font, + hb_buffer_t *buffer) +{ + for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) + if (fallback_plan->lookup_array[i]) { + OT::hb_apply_context_t c (font, buffer, fallback_plan->mask_array[i]); + fallback_plan->lookup_array[i]->apply_string (&c, &fallback_plan->digest_array[i]); + } +} + + +#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh index c66111b69725..5e29167ad742 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh @@ -729,24 +729,24 @@ static const uint8_t joining_table[] = static const uint16_t shaping_table[][4] = { - {0x0621, 0x0621, 0x0621, 0xFE80}, /* U+0621 ARABIC LETTER HAMZA ISOLATED FORM */ - {0x0622, 0x0622, 0xFE82, 0xFE81}, /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */ - {0x0623, 0x0623, 0xFE84, 0xFE83}, /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */ - {0x0624, 0x0624, 0xFE86, 0xFE85}, /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */ - {0x0625, 0x0625, 0xFE88, 0xFE87}, /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */ + {0x0000, 0x0000, 0x0000, 0xFE80}, /* U+0621 ARABIC LETTER HAMZA ISOLATED FORM */ + {0x0000, 0x0000, 0xFE82, 0xFE81}, /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */ + {0x0000, 0x0000, 0xFE84, 0xFE83}, /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */ + {0x0000, 0x0000, 0xFE86, 0xFE85}, /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */ + {0x0000, 0x0000, 0xFE88, 0xFE87}, /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */ {0xFE8B, 0xFE8C, 0xFE8A, 0xFE89}, /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */ - {0x0627, 0x0627, 0xFE8E, 0xFE8D}, /* U+0627 ARABIC LETTER ALEF */ + {0x0000, 0x0000, 0xFE8E, 0xFE8D}, /* U+0627 ARABIC LETTER ALEF */ {0xFE91, 0xFE92, 0xFE90, 0xFE8F}, /* U+0628 ARABIC LETTER BEH */ - {0x0629, 0x0629, 0xFE94, 0xFE93}, /* U+0629 ARABIC LETTER TEH MARBUTA */ + {0x0000, 0x0000, 0xFE94, 0xFE93}, /* U+0629 ARABIC LETTER TEH MARBUTA */ {0xFE97, 0xFE98, 0xFE96, 0xFE95}, /* U+062A ARABIC LETTER TEH */ {0xFE9B, 0xFE9C, 0xFE9A, 0xFE99}, /* U+062B ARABIC LETTER THEH */ {0xFE9F, 0xFEA0, 0xFE9E, 0xFE9D}, /* U+062C ARABIC LETTER JEEM */ {0xFEA3, 0xFEA4, 0xFEA2, 0xFEA1}, /* U+062D ARABIC LETTER HAH */ {0xFEA7, 0xFEA8, 0xFEA6, 0xFEA5}, /* U+062E ARABIC LETTER KHAH */ - {0x062F, 0x062F, 0xFEAA, 0xFEA9}, /* U+062F ARABIC LETTER DAL */ - {0x0630, 0x0630, 0xFEAC, 0xFEAB}, /* U+0630 ARABIC LETTER THAL */ - {0x0631, 0x0631, 0xFEAE, 0xFEAD}, /* U+0631 ARABIC LETTER REH */ - {0x0632, 0x0632, 0xFEB0, 0xFEAF}, /* U+0632 ARABIC LETTER ZAIN */ + {0x0000, 0x0000, 0xFEAA, 0xFEA9}, /* U+062F ARABIC LETTER DAL */ + {0x0000, 0x0000, 0xFEAC, 0xFEAB}, /* U+0630 ARABIC LETTER THAL */ + {0x0000, 0x0000, 0xFEAE, 0xFEAD}, /* U+0631 ARABIC LETTER REH */ + {0x0000, 0x0000, 0xFEB0, 0xFEAF}, /* U+0632 ARABIC LETTER ZAIN */ {0xFEB3, 0xFEB4, 0xFEB2, 0xFEB1}, /* U+0633 ARABIC LETTER SEEN */ {0xFEB7, 0xFEB8, 0xFEB6, 0xFEB5}, /* U+0634 ARABIC LETTER SHEEN */ {0xFEBB, 0xFEBC, 0xFEBA, 0xFEB9}, /* U+0635 ARABIC LETTER SAD */ @@ -755,12 +755,12 @@ static const uint16_t shaping_table[][4] = {0xFEC7, 0xFEC8, 0xFEC6, 0xFEC5}, /* U+0638 ARABIC LETTER ZAH */ {0xFECB, 0xFECC, 0xFECA, 0xFEC9}, /* U+0639 ARABIC LETTER AIN */ {0xFECF, 0xFED0, 0xFECE, 0xFECD}, /* U+063A ARABIC LETTER GHAIN */ - {0x063B, 0x063B, 0x063B, 0x063B}, /* U+063B */ - {0x063C, 0x063C, 0x063C, 0x063C}, /* U+063C */ - {0x063D, 0x063D, 0x063D, 0x063D}, /* U+063D */ - {0x063E, 0x063E, 0x063E, 0x063E}, /* U+063E */ - {0x063F, 0x063F, 0x063F, 0x063F}, /* U+063F */ - {0x0640, 0x0640, 0x0640, 0x0640}, /* U+0640 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063B */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063C */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063D */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063E */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+063F */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0640 */ {0xFED3, 0xFED4, 0xFED2, 0xFED1}, /* U+0641 ARABIC LETTER FEH */ {0xFED7, 0xFED8, 0xFED6, 0xFED5}, /* U+0642 ARABIC LETTER QAF */ {0xFEDB, 0xFEDC, 0xFEDA, 0xFED9}, /* U+0643 ARABIC LETTER KAF */ @@ -768,146 +768,146 @@ static const uint16_t shaping_table[][4] = {0xFEE3, 0xFEE4, 0xFEE2, 0xFEE1}, /* U+0645 ARABIC LETTER MEEM */ {0xFEE7, 0xFEE8, 0xFEE6, 0xFEE5}, /* U+0646 ARABIC LETTER NOON */ {0xFEEB, 0xFEEC, 0xFEEA, 0xFEE9}, /* U+0647 ARABIC LETTER HEH */ - {0x0648, 0x0648, 0xFEEE, 0xFEED}, /* U+0648 ARABIC LETTER WAW */ + {0x0000, 0x0000, 0xFEEE, 0xFEED}, /* U+0648 ARABIC LETTER WAW */ {0xFBE8, 0xFBE9, 0xFEF0, 0xFEEF}, /* U+0649 ARABIC LETTER */ {0xFEF3, 0xFEF4, 0xFEF2, 0xFEF1}, /* U+064A ARABIC LETTER YEH */ - {0x064B, 0x064B, 0x064B, 0x064B}, /* U+064B */ - {0x064C, 0x064C, 0x064C, 0x064C}, /* U+064C */ - {0x064D, 0x064D, 0x064D, 0x064D}, /* U+064D */ - {0x064E, 0x064E, 0x064E, 0x064E}, /* U+064E */ - {0x064F, 0x064F, 0x064F, 0x064F}, /* U+064F */ - {0x0650, 0x0650, 0x0650, 0x0650}, /* U+0650 */ - {0x0651, 0x0651, 0x0651, 0x0651}, /* U+0651 */ - {0x0652, 0x0652, 0x0652, 0x0652}, /* U+0652 */ - {0x0653, 0x0653, 0x0653, 0x0653}, /* U+0653 */ - {0x0654, 0x0654, 0x0654, 0x0654}, /* U+0654 */ - {0x0655, 0x0655, 0x0655, 0x0655}, /* U+0655 */ - {0x0656, 0x0656, 0x0656, 0x0656}, /* U+0656 */ - {0x0657, 0x0657, 0x0657, 0x0657}, /* U+0657 */ - {0x0658, 0x0658, 0x0658, 0x0658}, /* U+0658 */ - {0x0659, 0x0659, 0x0659, 0x0659}, /* U+0659 */ - {0x065A, 0x065A, 0x065A, 0x065A}, /* U+065A */ - {0x065B, 0x065B, 0x065B, 0x065B}, /* U+065B */ - {0x065C, 0x065C, 0x065C, 0x065C}, /* U+065C */ - {0x065D, 0x065D, 0x065D, 0x065D}, /* U+065D */ - {0x065E, 0x065E, 0x065E, 0x065E}, /* U+065E */ - {0x065F, 0x065F, 0x065F, 0x065F}, /* U+065F */ - {0x0660, 0x0660, 0x0660, 0x0660}, /* U+0660 */ - {0x0661, 0x0661, 0x0661, 0x0661}, /* U+0661 */ - {0x0662, 0x0662, 0x0662, 0x0662}, /* U+0662 */ - {0x0663, 0x0663, 0x0663, 0x0663}, /* U+0663 */ - {0x0664, 0x0664, 0x0664, 0x0664}, /* U+0664 */ - {0x0665, 0x0665, 0x0665, 0x0665}, /* U+0665 */ - {0x0666, 0x0666, 0x0666, 0x0666}, /* U+0666 */ - {0x0667, 0x0667, 0x0667, 0x0667}, /* U+0667 */ - {0x0668, 0x0668, 0x0668, 0x0668}, /* U+0668 */ - {0x0669, 0x0669, 0x0669, 0x0669}, /* U+0669 */ - {0x066A, 0x066A, 0x066A, 0x066A}, /* U+066A */ - {0x066B, 0x066B, 0x066B, 0x066B}, /* U+066B */ - {0x066C, 0x066C, 0x066C, 0x066C}, /* U+066C */ - {0x066D, 0x066D, 0x066D, 0x066D}, /* U+066D */ - {0x066E, 0x066E, 0x066E, 0x066E}, /* U+066E */ - {0x066F, 0x066F, 0x066F, 0x066F}, /* U+066F */ - {0x0670, 0x0670, 0x0670, 0x0670}, /* U+0670 */ - {0x0671, 0x0671, 0xFB51, 0xFB50}, /* U+0671 ARABIC LETTER ALEF WASLA */ - {0x0672, 0x0672, 0x0672, 0x0672}, /* U+0672 */ - {0x0673, 0x0673, 0x0673, 0x0673}, /* U+0673 */ - {0x0674, 0x0674, 0x0674, 0x0674}, /* U+0674 */ - {0x0675, 0x0675, 0x0675, 0x0675}, /* U+0675 */ - {0x0676, 0x0676, 0x0676, 0x0676}, /* U+0676 */ - {0x0677, 0x0677, 0x0677, 0xFBDD}, /* U+0677 ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM */ - {0x0678, 0x0678, 0x0678, 0x0678}, /* U+0678 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064B */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064C */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064D */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064E */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+064F */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0650 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0651 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0652 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0653 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0654 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0655 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0656 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0657 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0658 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0659 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065A */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065B */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065C */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065D */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065E */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+065F */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0660 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0661 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0662 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0663 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0664 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0665 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0666 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0667 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0668 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0669 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066A */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066B */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066C */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066D */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066E */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+066F */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0670 */ + {0x0000, 0x0000, 0xFB51, 0xFB50}, /* U+0671 ARABIC LETTER ALEF WASLA */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0672 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0673 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0674 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0675 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0676 */ + {0x0000, 0x0000, 0x0000, 0xFBDD}, /* U+0677 ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0678 */ {0xFB68, 0xFB69, 0xFB67, 0xFB66}, /* U+0679 ARABIC LETTER TTEH */ {0xFB60, 0xFB61, 0xFB5F, 0xFB5E}, /* U+067A ARABIC LETTER TTEHEH */ {0xFB54, 0xFB55, 0xFB53, 0xFB52}, /* U+067B ARABIC LETTER BEEH */ - {0x067C, 0x067C, 0x067C, 0x067C}, /* U+067C */ - {0x067D, 0x067D, 0x067D, 0x067D}, /* U+067D */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+067C */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+067D */ {0xFB58, 0xFB59, 0xFB57, 0xFB56}, /* U+067E ARABIC LETTER PEH */ {0xFB64, 0xFB65, 0xFB63, 0xFB62}, /* U+067F ARABIC LETTER TEHEH */ {0xFB5C, 0xFB5D, 0xFB5B, 0xFB5A}, /* U+0680 ARABIC LETTER BEHEH */ - {0x0681, 0x0681, 0x0681, 0x0681}, /* U+0681 */ - {0x0682, 0x0682, 0x0682, 0x0682}, /* U+0682 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0681 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0682 */ {0xFB78, 0xFB79, 0xFB77, 0xFB76}, /* U+0683 ARABIC LETTER NYEH */ {0xFB74, 0xFB75, 0xFB73, 0xFB72}, /* U+0684 ARABIC LETTER DYEH */ - {0x0685, 0x0685, 0x0685, 0x0685}, /* U+0685 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0685 */ {0xFB7C, 0xFB7D, 0xFB7B, 0xFB7A}, /* U+0686 ARABIC LETTER TCHEH */ {0xFB80, 0xFB81, 0xFB7F, 0xFB7E}, /* U+0687 ARABIC LETTER TCHEHEH */ - {0x0688, 0x0688, 0xFB89, 0xFB88}, /* U+0688 ARABIC LETTER DDAL */ - {0x0689, 0x0689, 0x0689, 0x0689}, /* U+0689 */ - {0x068A, 0x068A, 0x068A, 0x068A}, /* U+068A */ - {0x068B, 0x068B, 0x068B, 0x068B}, /* U+068B */ - {0x068C, 0x068C, 0xFB85, 0xFB84}, /* U+068C ARABIC LETTER DAHAL */ - {0x068D, 0x068D, 0xFB83, 0xFB82}, /* U+068D ARABIC LETTER DDAHAL */ - {0x068E, 0x068E, 0xFB87, 0xFB86}, /* U+068E ARABIC LETTER DUL */ - {0x068F, 0x068F, 0x068F, 0x068F}, /* U+068F */ - {0x0690, 0x0690, 0x0690, 0x0690}, /* U+0690 */ - {0x0691, 0x0691, 0xFB8D, 0xFB8C}, /* U+0691 ARABIC LETTER RREH */ - {0x0692, 0x0692, 0x0692, 0x0692}, /* U+0692 */ - {0x0693, 0x0693, 0x0693, 0x0693}, /* U+0693 */ - {0x0694, 0x0694, 0x0694, 0x0694}, /* U+0694 */ - {0x0695, 0x0695, 0x0695, 0x0695}, /* U+0695 */ - {0x0696, 0x0696, 0x0696, 0x0696}, /* U+0696 */ - {0x0697, 0x0697, 0x0697, 0x0697}, /* U+0697 */ - {0x0698, 0x0698, 0xFB8B, 0xFB8A}, /* U+0698 ARABIC LETTER JEH */ - {0x0699, 0x0699, 0x0699, 0x0699}, /* U+0699 */ - {0x069A, 0x069A, 0x069A, 0x069A}, /* U+069A */ - {0x069B, 0x069B, 0x069B, 0x069B}, /* U+069B */ - {0x069C, 0x069C, 0x069C, 0x069C}, /* U+069C */ - {0x069D, 0x069D, 0x069D, 0x069D}, /* U+069D */ - {0x069E, 0x069E, 0x069E, 0x069E}, /* U+069E */ - {0x069F, 0x069F, 0x069F, 0x069F}, /* U+069F */ - {0x06A0, 0x06A0, 0x06A0, 0x06A0}, /* U+06A0 */ - {0x06A1, 0x06A1, 0x06A1, 0x06A1}, /* U+06A1 */ - {0x06A2, 0x06A2, 0x06A2, 0x06A2}, /* U+06A2 */ - {0x06A3, 0x06A3, 0x06A3, 0x06A3}, /* U+06A3 */ + {0x0000, 0x0000, 0xFB89, 0xFB88}, /* U+0688 ARABIC LETTER DDAL */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0689 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+068A */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+068B */ + {0x0000, 0x0000, 0xFB85, 0xFB84}, /* U+068C ARABIC LETTER DAHAL */ + {0x0000, 0x0000, 0xFB83, 0xFB82}, /* U+068D ARABIC LETTER DDAHAL */ + {0x0000, 0x0000, 0xFB87, 0xFB86}, /* U+068E ARABIC LETTER DUL */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+068F */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0690 */ + {0x0000, 0x0000, 0xFB8D, 0xFB8C}, /* U+0691 ARABIC LETTER RREH */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0692 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0693 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0694 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0695 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0696 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0697 */ + {0x0000, 0x0000, 0xFB8B, 0xFB8A}, /* U+0698 ARABIC LETTER JEH */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+0699 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069A */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069B */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069C */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069D */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069E */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+069F */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A0 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A1 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A2 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A3 */ {0xFB6C, 0xFB6D, 0xFB6B, 0xFB6A}, /* U+06A4 ARABIC LETTER VEH */ - {0x06A5, 0x06A5, 0x06A5, 0x06A5}, /* U+06A5 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A5 */ {0xFB70, 0xFB71, 0xFB6F, 0xFB6E}, /* U+06A6 ARABIC LETTER PEHEH */ - {0x06A7, 0x06A7, 0x06A7, 0x06A7}, /* U+06A7 */ - {0x06A8, 0x06A8, 0x06A8, 0x06A8}, /* U+06A8 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A7 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06A8 */ {0xFB90, 0xFB91, 0xFB8F, 0xFB8E}, /* U+06A9 ARABIC LETTER KEHEH */ - {0x06AA, 0x06AA, 0x06AA, 0x06AA}, /* U+06AA */ - {0x06AB, 0x06AB, 0x06AB, 0x06AB}, /* U+06AB */ - {0x06AC, 0x06AC, 0x06AC, 0x06AC}, /* U+06AC */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AA */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AB */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AC */ {0xFBD5, 0xFBD6, 0xFBD4, 0xFBD3}, /* U+06AD ARABIC LETTER NG */ - {0x06AE, 0x06AE, 0x06AE, 0x06AE}, /* U+06AE */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06AE */ {0xFB94, 0xFB95, 0xFB93, 0xFB92}, /* U+06AF ARABIC LETTER GAF */ - {0x06B0, 0x06B0, 0x06B0, 0x06B0}, /* U+06B0 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B0 */ {0xFB9C, 0xFB9D, 0xFB9B, 0xFB9A}, /* U+06B1 ARABIC LETTER NGOEH */ - {0x06B2, 0x06B2, 0x06B2, 0x06B2}, /* U+06B2 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B2 */ {0xFB98, 0xFB99, 0xFB97, 0xFB96}, /* U+06B3 ARABIC LETTER GUEH */ - {0x06B4, 0x06B4, 0x06B4, 0x06B4}, /* U+06B4 */ - {0x06B5, 0x06B5, 0x06B5, 0x06B5}, /* U+06B5 */ - {0x06B6, 0x06B6, 0x06B6, 0x06B6}, /* U+06B6 */ - {0x06B7, 0x06B7, 0x06B7, 0x06B7}, /* U+06B7 */ - {0x06B8, 0x06B8, 0x06B8, 0x06B8}, /* U+06B8 */ - {0x06B9, 0x06B9, 0x06B9, 0x06B9}, /* U+06B9 */ - {0x06BA, 0x06BA, 0xFB9F, 0xFB9E}, /* U+06BA ARABIC LETTER NOON GHUNNA */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B4 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B5 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B6 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B7 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B8 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06B9 */ + {0x0000, 0x0000, 0xFB9F, 0xFB9E}, /* U+06BA ARABIC LETTER NOON GHUNNA */ {0xFBA2, 0xFBA3, 0xFBA1, 0xFBA0}, /* U+06BB ARABIC LETTER RNOON */ - {0x06BC, 0x06BC, 0x06BC, 0x06BC}, /* U+06BC */ - {0x06BD, 0x06BD, 0x06BD, 0x06BD}, /* U+06BD */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06BC */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06BD */ {0xFBAC, 0xFBAD, 0xFBAB, 0xFBAA}, /* U+06BE ARABIC LETTER HEH DOACHASHMEE */ - {0x06BF, 0x06BF, 0x06BF, 0x06BF}, /* U+06BF */ - {0x06C0, 0x06C0, 0xFBA5, 0xFBA4}, /* U+06C0 ARABIC LETTER HEH WITH YEH ABOVE */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06BF */ + {0x0000, 0x0000, 0xFBA5, 0xFBA4}, /* U+06C0 ARABIC LETTER HEH WITH YEH ABOVE */ {0xFBA8, 0xFBA9, 0xFBA7, 0xFBA6}, /* U+06C1 ARABIC LETTER HEH GOAL */ - {0x06C2, 0x06C2, 0x06C2, 0x06C2}, /* U+06C2 */ - {0x06C3, 0x06C3, 0x06C3, 0x06C3}, /* U+06C3 */ - {0x06C4, 0x06C4, 0x06C4, 0x06C4}, /* U+06C4 */ - {0x06C5, 0x06C5, 0xFBE1, 0xFBE0}, /* U+06C5 ARABIC LETTER KIRGHIZ OE */ - {0x06C6, 0x06C6, 0xFBDA, 0xFBD9}, /* U+06C6 ARABIC LETTER OE */ - {0x06C7, 0x06C7, 0xFBD8, 0xFBD7}, /* U+06C7 ARABIC LETTER U */ - {0x06C8, 0x06C8, 0xFBDC, 0xFBDB}, /* U+06C8 ARABIC LETTER YU */ - {0x06C9, 0x06C9, 0xFBE3, 0xFBE2}, /* U+06C9 ARABIC LETTER KIRGHIZ YU */ - {0x06CA, 0x06CA, 0x06CA, 0x06CA}, /* U+06CA */ - {0x06CB, 0x06CB, 0xFBDF, 0xFBDE}, /* U+06CB ARABIC LETTER VE */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06C2 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06C3 */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06C4 */ + {0x0000, 0x0000, 0xFBE1, 0xFBE0}, /* U+06C5 ARABIC LETTER KIRGHIZ OE */ + {0x0000, 0x0000, 0xFBDA, 0xFBD9}, /* U+06C6 ARABIC LETTER OE */ + {0x0000, 0x0000, 0xFBD8, 0xFBD7}, /* U+06C7 ARABIC LETTER U */ + {0x0000, 0x0000, 0xFBDC, 0xFBDB}, /* U+06C8 ARABIC LETTER YU */ + {0x0000, 0x0000, 0xFBE3, 0xFBE2}, /* U+06C9 ARABIC LETTER KIRGHIZ YU */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CA */ + {0x0000, 0x0000, 0xFBDF, 0xFBDE}, /* U+06CB ARABIC LETTER VE */ {0xFBFE, 0xFBFF, 0xFBFD, 0xFBFC}, /* U+06CC ARABIC LETTER FARSI YEH */ - {0x06CD, 0x06CD, 0x06CD, 0x06CD}, /* U+06CD */ - {0x06CE, 0x06CE, 0x06CE, 0x06CE}, /* U+06CE */ - {0x06CF, 0x06CF, 0x06CF, 0x06CF}, /* U+06CF */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CD */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CE */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06CF */ {0xFBE6, 0xFBE7, 0xFBE5, 0xFBE4}, /* U+06D0 ARABIC LETTER E */ - {0x06D1, 0x06D1, 0x06D1, 0x06D1}, /* U+06D1 */ - {0x06D2, 0x06D2, 0xFBAF, 0xFBAE}, /* U+06D2 ARABIC LETTER YEH BARREE */ - {0x06D3, 0x06D3, 0xFBB1, 0xFBB0}, /* U+06D3 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */ + {0x0000, 0x0000, 0x0000, 0x0000}, /* U+06D1 */ + {0x0000, 0x0000, 0xFBAF, 0xFBAE}, /* U+06D2 ARABIC LETTER YEH BARREE */ + {0x0000, 0x0000, 0xFBB1, 0xFBB0}, /* U+06D3 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */ }; #define SHAPING_TABLE_FIRST 0x0621 diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc index 857bf559c89b..572089186283 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc @@ -28,7 +28,6 @@ #include "hb-ot-shape-private.hh" - /* buffer var allocations */ #define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */ @@ -81,24 +80,6 @@ static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_categ JOINING_TYPE_T : JOINING_TYPE_U; } -static hb_codepoint_t get_arabic_shape (hb_codepoint_t u, unsigned int shape) -{ - if (likely (hb_in_range (u, SHAPING_TABLE_FIRST, SHAPING_TABLE_LAST)) && shape < 4) - return shaping_table[u - SHAPING_TABLE_FIRST][shape]; - return u; -} - -static uint16_t get_ligature (hb_codepoint_t first, hb_codepoint_t second) -{ - if (unlikely (!second)) return 0; - for (unsigned i = 0; i < ARRAY_LENGTH (ligature_table); i++) - if (ligature_table[i].first == first) - for (unsigned j = 0; j < ARRAY_LENGTH (ligature_table[i].ligatures); j++) - if (ligature_table[i].ligatures[j].second == second) - return ligature_table[i].ligatures[j].ligature; - return 0; -} - static const hb_tag_t arabic_features[] = { HB_TAG('i','n','i','t'), @@ -161,6 +142,10 @@ static const struct arabic_state_table_entry { }; +static void +arabic_fallback_shape (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void collect_features_arabic (hb_ot_shape_planner_t *plan) @@ -183,12 +168,12 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) map->add_gsub_pause (NULL); for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) - map->add_bool_feature (arabic_features[i], false); + map->add_bool_feature (arabic_features[i], false, i < 4); /* The first four features have fallback. */ map->add_gsub_pause (NULL); - map->add_bool_feature (HB_TAG('r','l','i','g')); - map->add_gsub_pause (NULL); + map->add_bool_feature (HB_TAG('r','l','i','g'), true, true); + map->add_gsub_pause (arabic_fallback_shape); map->add_bool_feature (HB_TAG('c','a','l','t')); map->add_gsub_pause (NULL); @@ -197,16 +182,20 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) map->add_bool_feature (HB_TAG('c','s','w','h')); } +#include "hb-ot-shape-complex-arabic-fallback.hh" + struct arabic_shape_plan_t { ASSERT_POD (); - bool do_fallback; /* 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]; + + bool do_fallback; + arabic_fallback_plan_t *fallback_plan; }; static void * @@ -216,75 +205,47 @@ data_create_arabic (const hb_ot_shape_plan_t *plan) if (unlikely (!arabic_plan)) return NULL; - hb_mask_t total_masks = 0; + arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC; for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) { arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]); - total_masks |= arabic_plan->mask_array[i]; + if (i < 4) + arabic_plan->do_fallback = arabic_plan->do_fallback && plan->map.needs_fallback (arabic_features[i]); } - /* Pitfalls: - * - This path fires if user force-set init/medi/fina/isol off, - * - If font does not declare script 'arab', well, what to do? - * Most probably it's safe to assume that init/medi/fina/isol - * still mean Arabic shaping, although they do not have to. - */ - arabic_plan->do_fallback = 0 == total_masks; - return arabic_plan; } static void data_destroy_arabic (void *data) { + arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) data; + + arabic_fallback_plan_destroy (arabic_plan->fallback_plan); + free (data); } -static void -arabic_fallback_shape (hb_font_t *font, hb_buffer_t *buffer) -{ - /* Only Arabic has presentation forms encoded in Unicode. */ - if (buffer->props.script != HB_SCRIPT_ARABIC) - return; - - unsigned int count = buffer->len; - hb_codepoint_t glyph; - - /* Shape to presentation forms */ - for (unsigned int i = 0; i < count; i++) { - hb_codepoint_t u = buffer->info[i].codepoint; - hb_codepoint_t shaped = get_arabic_shape (u, buffer->info[i].arabic_shaping_action()); - if (shaped != u && font->get_glyph (shaped, 0, &glyph)) - buffer->info[i].codepoint = shaped; - } - - /* Mandatory ligatures */ - buffer->clear_output (); - for (buffer->idx = 0; buffer->idx + 1 < count;) { - hb_codepoint_t ligature = get_ligature (buffer->cur().codepoint, - buffer->cur(+1).codepoint); - if (likely (!ligature) || !(font->get_glyph (ligature, 0, &glyph))) { - buffer->next_glyph (); - continue; - } - - buffer->replace_glyphs (2, 1, &ligature); - - /* Technically speaking we can skip marks and stuff, like the GSUB path does. - * But who cares, we're in fallback! */ - } - for (; buffer->idx < count;) - buffer->next_glyph (); - buffer->swap_buffers (); -} - static void arabic_joining (hb_buffer_t *buffer) { unsigned int count = buffer->len; - unsigned int prev = 0, state = 0; + unsigned int prev = (unsigned int) -1, state = 0; HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action); + /* Check pre-context */ + for (unsigned int i = 0; i < buffer->context_len[0]; i++) + { + unsigned int this_type = get_joining_type (buffer->context[0][i], buffer->unicode->general_category (buffer->context[0][i])); + + if (unlikely (this_type == JOINING_TYPE_T)) + continue; + + const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; + state = entry->next_state; + break; + } + for (unsigned int i = 0; i < count; i++) { unsigned int this_type = get_joining_type (buffer->info[i].codepoint, _hb_glyph_info_get_general_category (&buffer->info[i])); @@ -296,7 +257,7 @@ arabic_joining (hb_buffer_t *buffer) const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; - if (entry->prev_action != NONE) + if (entry->prev_action != NONE && prev != (unsigned int) -1) buffer->info[prev].arabic_shaping_action() = entry->prev_action; buffer->info[i].arabic_shaping_action() = entry->curr_action; @@ -305,21 +266,21 @@ arabic_joining (hb_buffer_t *buffer) state = entry->next_state; } - HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); -} - -static void -preprocess_text_arabic (const hb_ot_shape_plan_t *plan, - hb_buffer_t *buffer, - hb_font_t *font) -{ - const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; - - if (unlikely (arabic_plan->do_fallback)) + for (unsigned int i = 0; i < buffer->context_len[1]; i++) { - arabic_joining (buffer); - arabic_fallback_shape (font, buffer); + unsigned int this_type = get_joining_type (buffer->context[1][i], buffer->unicode->general_category (buffer->context[0][i])); + + if (unlikely (this_type == JOINING_TYPE_T)) + continue; + + const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; + if (entry->prev_action != NONE && prev != (unsigned int) -1) + buffer->info[prev].arabic_shaping_action() = entry->prev_action; + break; } + + + HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); } static void @@ -329,15 +290,39 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan, { const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; - if (likely (!arabic_plan->do_fallback)) - { - arabic_joining (buffer); - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - buffer->info[i].mask |= arabic_plan->mask_array[buffer->info[i].arabic_shaping_action()]; - } + arabic_joining (buffer); + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + buffer->info[i].mask |= arabic_plan->mask_array[buffer->info[i].arabic_shaping_action()]; } + +static void +arabic_fallback_shape (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) +{ + const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; + + if (!arabic_plan->do_fallback) + return; + +retry: + arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) hb_atomic_ptr_get (&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, NULL, fallback_plan))) { + arabic_fallback_plan_destroy (fallback_plan); + goto retry; + } + } + + arabic_fallback_plan_shape (fallback_plan, font, buffer); +} + + const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = { "arabic", @@ -345,7 +330,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = NULL, /* override_features */ data_create_arabic, data_destroy_arabic, - preprocess_text_arabic, + NULL, /* preprocess_text_arabic */ NULL, /* normalization_preference */ setup_masks_arabic, true, /* zero_width_attached_marks */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh index 736a2d2800d4..53f22e306f0d 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh @@ -32,182 +32,242 @@ #include "hb-private.hh" -#line 36 "hb-ot-shape-complex-indic-machine.hh.tmp" +#line 36 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" static const unsigned char _indic_syllable_machine_trans_keys[] = { - 1u, 16u, 13u, 13u, 4u, 14u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, + 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, - 4u, 14u, 4u, 14u, 4u, 14u, 1u, 16u, 13u, 13u, 4u, 14u, 5u, 7u, 7u, 7u, + 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, + 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, + 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, + 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, + 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, + 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, + 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, + 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, + 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, + 4u, 14u, 4u, 14u, 4u, 14u, 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, - 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 1u, 16u, 13u, 13u, - 4u, 14u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, - 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, 16u, 16u, 4u, 7u, - 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, 4u, 7u, 6u, 6u, 16u, 16u, - 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, - 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, - 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, - 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 8u, 14u, 5u, 14u, - 9u, 14u, 9u, 9u, 3u, 13u, 3u, 9u, 9u, 9u, 3u, 9u, 6u, 14u, 3u, 14u, - 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, - 3u, 14u, 4u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, - 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, - 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 3u, 14u, 3u, 14u, 4u, 14u, - 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, - 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, - 5u, 14u, 8u, 14u, 5u, 14u, 9u, 14u, 9u, 9u, 3u, 13u, 3u, 9u, 9u, 9u, - 3u, 9u, 6u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, - 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 1u, 16u, - 1u, 16u, 1u, 16u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 1u, 16u, - 1u, 16u, 1u, 16u, 3u, 14u, 1u, 16u, 1u, 16u, 4u, 14u, 1u, 16u, 3u, 14u, + 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, - 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 8u, 14u, 5u, 14u, 9u, 14u, 9u, 9u, - 3u, 13u, 3u, 9u, 9u, 9u, 3u, 9u, 6u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, + 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 8u, 14u, 5u, 9u, 9u, 9u, 9u, 9u, + 3u, 13u, 3u, 9u, 8u, 9u, 3u, 9u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, + 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, + 4u, 14u, 6u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 3u, 14u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 3u, 14u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 3u, 14u, 3u, 14u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, + 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, + 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 8u, 14u, + 5u, 9u, 9u, 9u, 9u, 9u, 3u, 13u, 3u, 9u, 8u, 9u, 3u, 9u, 3u, 13u, + 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, + 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 6u, 14u, 3u, 14u, 1u, 16u, 3u, 14u, + 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 3u, 14u, + 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 3u, 14u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 3u, 14u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, + 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, + 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, + 8u, 14u, 5u, 9u, 9u, 9u, 9u, 9u, 3u, 13u, 3u, 9u, 8u, 9u, 3u, 9u, + 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, + 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 6u, 14u, 3u, 14u, 1u, 16u, + 3u, 14u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, + 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 3u, 14u, + 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 3u, 14u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 14u, 3u, 14u, 4u, 14u, 3u, 14u, + 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, + 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 4u, 14u, 1u, 16u, 3u, 14u, + 3u, 14u, 4u, 14u, 5u, 14u, 8u, 14u, 5u, 9u, 9u, 9u, 9u, 9u, 3u, 13u, + 3u, 9u, 8u, 9u, 3u, 9u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, - 1u, 16u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 1u, 16u, 1u, 16u, - 1u, 16u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, 1u, 16u, 1u, 16u, - 1u, 16u, 3u, 14u, 1u, 16u, 3u, 14u, 1u, 16u, 0 + 6u, 14u, 3u, 14u, 1u, 16u, 3u, 14u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 3u, 14u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 3u, 14u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 3u, 14u, 3u, 14u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 14u, + 1u, 16u, 3u, 14u, 1u, 16u, 0 }; static const char _indic_syllable_machine_key_spans[] = { - 16, 1, 11, 3, 1, 3, 3, 1, + 16, 1, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 1, 1, 1, 1, 4, 1, 1, 4, 1, 1, 4, 1, 1, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 16, 1, 11, 3, 1, + 11, 11, 11, 11, 16, 1, 3, 3, + 1, 3, 3, 1, 3, 3, 1, 3, + 3, 1, 1, 1, 1, 4, 1, 1, + 4, 1, 1, 4, 1, 1, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 16, 1, 3, 3, 1, 3, 3, 1, + 3, 3, 1, 3, 3, 1, 1, 1, + 1, 4, 1, 1, 4, 1, 1, 4, + 1, 1, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 16, 1, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 1, 1, 1, 1, 4, 1, 1, 4, 1, 1, 4, 1, 1, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 16, 1, - 11, 3, 1, 3, 3, 1, 3, 3, - 1, 3, 3, 1, 1, 1, 1, 4, - 1, 1, 4, 1, 1, 4, 1, 1, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 16, 12, 12, 11, 16, 12, 12, - 11, 16, 12, 12, 11, 16, 12, 12, - 11, 16, 12, 12, 11, 10, 7, 10, - 6, 1, 11, 7, 1, 7, 9, 12, - 11, 10, 12, 11, 10, 12, 11, 10, - 12, 11, 11, 16, 12, 16, 16, 16, - 12, 16, 16, 16, 12, 16, 16, 16, - 12, 16, 16, 16, 12, 12, 12, 11, - 16, 12, 12, 11, 16, 12, 12, 11, - 16, 12, 12, 11, 16, 12, 12, 11, - 10, 7, 10, 6, 1, 11, 7, 1, - 7, 9, 12, 11, 10, 12, 11, 10, - 12, 11, 10, 12, 11, 16, 12, 16, - 16, 16, 12, 16, 16, 16, 12, 16, - 16, 16, 12, 16, 16, 11, 16, 12, + 11, 11, 11, 11, 11, 11, 11, 16, 12, 12, 11, 16, 12, 12, 11, 16, 12, 12, 11, 16, 12, 12, 11, 16, - 12, 12, 11, 10, 7, 10, 6, 1, - 11, 7, 1, 7, 9, 12, 11, 10, + 12, 12, 11, 10, 7, 5, 1, 1, + 11, 7, 2, 7, 11, 12, 12, 11, + 10, 12, 11, 10, 12, 11, 10, 12, + 11, 9, 12, 11, 16, 12, 12, 16, + 16, 16, 16, 16, 12, 12, 16, 16, + 16, 16, 16, 12, 12, 16, 16, 16, + 16, 16, 12, 12, 16, 16, 16, 16, + 16, 12, 12, 12, 12, 11, 16, 12, + 12, 11, 16, 12, 12, 11, 16, 12, + 12, 11, 16, 12, 12, 11, 10, 7, + 5, 1, 1, 11, 7, 2, 7, 11, + 12, 12, 11, 10, 12, 11, 10, 12, + 11, 10, 12, 11, 9, 12, 16, 12, + 12, 16, 16, 16, 16, 16, 12, 12, + 16, 16, 16, 16, 16, 12, 12, 16, + 16, 16, 16, 16, 12, 12, 16, 16, + 16, 16, 11, 16, 12, 12, 11, 16, + 12, 12, 11, 16, 12, 12, 11, 16, + 12, 12, 11, 16, 12, 12, 11, 10, + 7, 5, 1, 1, 11, 7, 2, 7, + 11, 12, 12, 11, 10, 12, 11, 10, + 12, 11, 10, 12, 11, 9, 12, 16, + 12, 12, 16, 16, 16, 16, 16, 12, + 12, 16, 16, 16, 16, 16, 12, 12, + 16, 16, 16, 16, 16, 12, 12, 16, + 16, 16, 16, 16, 11, 12, 11, 12, + 12, 11, 16, 12, 12, 11, 16, 12, + 12, 11, 16, 12, 12, 11, 16, 12, + 12, 11, 10, 7, 5, 1, 1, 11, + 7, 2, 7, 11, 12, 12, 11, 10, 12, 11, 10, 12, 11, 10, 12, 11, - 16, 12, 16, 16, 16, 12, 16, 16, - 16, 12, 16, 16, 16, 12, 16, 16, - 16, 12, 16, 12, 16 + 9, 12, 16, 12, 12, 16, 16, 16, + 16, 16, 12, 12, 16, 16, 16, 16, + 16, 12, 12, 16, 16, 16, 16, 16, + 12, 12, 16, 16, 16, 16, 16, 12, + 16, 12, 16 }; static const short _indic_syllable_machine_index_offsets[] = { - 0, 17, 19, 31, 35, 37, 41, 45, - 47, 51, 55, 57, 61, 65, 67, 69, - 71, 73, 78, 80, 82, 87, 89, 91, - 96, 98, 100, 112, 124, 136, 148, 160, - 172, 184, 196, 208, 225, 227, 239, 243, - 245, 249, 253, 255, 259, 263, 265, 269, - 273, 275, 277, 279, 281, 286, 288, 290, - 295, 297, 299, 304, 306, 308, 320, 332, - 344, 356, 368, 380, 392, 404, 416, 433, - 435, 447, 451, 453, 457, 461, 463, 467, - 471, 473, 477, 481, 483, 485, 487, 489, - 494, 496, 498, 503, 505, 507, 512, 514, - 516, 528, 540, 552, 564, 576, 588, 600, - 612, 624, 641, 654, 667, 679, 696, 709, - 722, 734, 751, 764, 777, 789, 806, 819, - 832, 844, 861, 874, 887, 899, 910, 918, - 929, 936, 938, 950, 958, 960, 968, 978, - 991, 1003, 1014, 1027, 1039, 1050, 1063, 1075, - 1086, 1099, 1111, 1123, 1140, 1153, 1170, 1187, - 1204, 1217, 1234, 1251, 1268, 1281, 1298, 1315, - 1332, 1345, 1362, 1379, 1396, 1409, 1422, 1435, - 1447, 1464, 1477, 1490, 1502, 1519, 1532, 1545, - 1557, 1574, 1587, 1600, 1612, 1629, 1642, 1655, - 1667, 1678, 1686, 1697, 1704, 1706, 1718, 1726, - 1728, 1736, 1746, 1759, 1771, 1782, 1795, 1807, - 1818, 1831, 1843, 1854, 1867, 1879, 1896, 1909, - 1926, 1943, 1960, 1973, 1990, 2007, 2024, 2037, - 2054, 2071, 2088, 2101, 2118, 2135, 2147, 2164, - 2177, 2190, 2203, 2215, 2232, 2245, 2258, 2270, - 2287, 2300, 2313, 2325, 2342, 2355, 2368, 2380, - 2397, 2410, 2423, 2435, 2446, 2454, 2465, 2472, - 2474, 2486, 2494, 2496, 2504, 2514, 2527, 2539, - 2550, 2563, 2575, 2586, 2599, 2611, 2622, 2635, - 2647, 2664, 2677, 2694, 2711, 2728, 2741, 2758, - 2775, 2792, 2805, 2822, 2839, 2856, 2869, 2886, - 2903, 2920, 2933, 2950, 2963 + 0, 17, 19, 23, 27, 29, 33, 37, + 39, 43, 47, 49, 53, 57, 59, 61, + 63, 65, 70, 72, 74, 79, 81, 83, + 88, 90, 92, 104, 116, 128, 140, 152, + 164, 176, 188, 200, 212, 229, 231, 235, + 239, 241, 245, 249, 251, 255, 259, 261, + 265, 269, 271, 273, 275, 277, 282, 284, + 286, 291, 293, 295, 300, 302, 304, 316, + 328, 340, 352, 364, 376, 388, 400, 412, + 424, 441, 443, 447, 451, 453, 457, 461, + 463, 467, 471, 473, 477, 481, 483, 485, + 487, 489, 494, 496, 498, 503, 505, 507, + 512, 514, 516, 528, 540, 552, 564, 576, + 588, 600, 612, 624, 641, 643, 647, 651, + 653, 657, 661, 663, 667, 671, 673, 677, + 681, 683, 685, 687, 689, 694, 696, 698, + 703, 705, 707, 712, 714, 716, 728, 740, + 752, 764, 776, 788, 800, 812, 824, 836, + 853, 866, 879, 891, 908, 921, 934, 946, + 963, 976, 989, 1001, 1018, 1031, 1044, 1056, + 1073, 1086, 1099, 1111, 1122, 1130, 1136, 1138, + 1140, 1152, 1160, 1163, 1171, 1183, 1196, 1209, + 1221, 1232, 1245, 1257, 1268, 1281, 1293, 1304, + 1317, 1329, 1339, 1352, 1364, 1381, 1394, 1407, + 1424, 1441, 1458, 1475, 1492, 1505, 1518, 1535, + 1552, 1569, 1586, 1603, 1616, 1629, 1646, 1663, + 1680, 1697, 1714, 1727, 1740, 1757, 1774, 1791, + 1808, 1825, 1838, 1851, 1864, 1877, 1889, 1906, + 1919, 1932, 1944, 1961, 1974, 1987, 1999, 2016, + 2029, 2042, 2054, 2071, 2084, 2097, 2109, 2120, + 2128, 2134, 2136, 2138, 2150, 2158, 2161, 2169, + 2181, 2194, 2207, 2219, 2230, 2243, 2255, 2266, + 2279, 2291, 2302, 2315, 2327, 2337, 2350, 2367, + 2380, 2393, 2410, 2427, 2444, 2461, 2478, 2491, + 2504, 2521, 2538, 2555, 2572, 2589, 2602, 2615, + 2632, 2649, 2666, 2683, 2700, 2713, 2726, 2743, + 2760, 2777, 2794, 2806, 2823, 2836, 2849, 2861, + 2878, 2891, 2904, 2916, 2933, 2946, 2959, 2971, + 2988, 3001, 3014, 3026, 3043, 3056, 3069, 3081, + 3092, 3100, 3106, 3108, 3110, 3122, 3130, 3133, + 3141, 3153, 3166, 3179, 3191, 3202, 3215, 3227, + 3238, 3251, 3263, 3274, 3287, 3299, 3309, 3322, + 3339, 3352, 3365, 3382, 3399, 3416, 3433, 3450, + 3463, 3476, 3493, 3510, 3527, 3544, 3561, 3574, + 3587, 3604, 3621, 3638, 3655, 3672, 3685, 3698, + 3715, 3732, 3749, 3766, 3783, 3795, 3808, 3820, + 3833, 3846, 3858, 3875, 3888, 3901, 3913, 3930, + 3943, 3956, 3968, 3985, 3998, 4011, 4023, 4040, + 4053, 4066, 4078, 4089, 4097, 4103, 4105, 4107, + 4119, 4127, 4130, 4138, 4150, 4163, 4176, 4188, + 4199, 4212, 4224, 4235, 4248, 4260, 4271, 4284, + 4296, 4306, 4319, 4336, 4349, 4362, 4379, 4396, + 4413, 4430, 4447, 4460, 4473, 4490, 4507, 4524, + 4541, 4558, 4571, 4584, 4601, 4618, 4635, 4652, + 4669, 4682, 4695, 4712, 4729, 4746, 4763, 4780, + 4793, 4810, 4823 }; static const short _indic_syllable_machine_indicies[] = { 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 0, 3, 0, 4, 5, 5, 6, 0, - 0, 0, 0, 0, 0, 4, 0, 7, - 7, 6, 0, 6, 0, 8, 8, 9, - 0, 10, 10, 9, 0, 9, 0, 11, - 11, 12, 0, 13, 13, 12, 0, 12, - 0, 14, 14, 15, 0, 16, 16, 15, - 0, 15, 0, 17, 0, 18, 0, 19, - 0, 20, 14, 14, 15, 0, 21, 0, - 22, 0, 23, 11, 11, 12, 0, 24, - 0, 25, 0, 26, 8, 8, 9, 0, - 27, 0, 28, 0, 4, 5, 5, 6, - 0, 0, 0, 0, 0, 29, 4, 0, - 30, 5, 5, 6, 0, 0, 0, 0, - 0, 0, 30, 0, 30, 5, 5, 6, - 0, 0, 0, 0, 0, 31, 30, 0, - 32, 5, 5, 6, 0, 0, 0, 0, - 0, 0, 32, 0, 32, 5, 5, 6, - 0, 0, 0, 0, 0, 33, 32, 0, - 34, 5, 5, 6, 0, 0, 0, 0, - 0, 0, 34, 0, 34, 5, 5, 6, - 0, 0, 0, 0, 0, 35, 34, 0, - 36, 5, 5, 6, 0, 0, 0, 0, - 0, 0, 36, 0, 36, 5, 5, 6, - 0, 0, 0, 0, 0, 37, 36, 0, - 39, 40, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 39, - 38, 41, 38, 42, 43, 43, 44, 38, - 38, 38, 38, 38, 38, 42, 38, 45, - 45, 44, 38, 44, 38, 46, 46, 47, - 38, 48, 48, 47, 38, 47, 38, 49, - 49, 50, 38, 51, 51, 50, 38, 50, - 38, 52, 52, 53, 38, 54, 54, 53, - 38, 53, 38, 55, 38, 56, 38, 57, - 38, 58, 52, 52, 53, 38, 59, 38, - 60, 38, 61, 49, 49, 50, 38, 62, - 38, 63, 38, 64, 46, 46, 47, 38, - 65, 38, 66, 38, 42, 43, 43, 44, - 38, 38, 38, 38, 38, 67, 42, 38, - 68, 43, 43, 44, 38, 38, 38, 38, - 38, 38, 68, 38, 68, 43, 43, 44, + 0, 3, 0, 4, 4, 5, 0, 6, + 6, 5, 0, 5, 0, 7, 7, 8, + 0, 9, 9, 8, 0, 8, 0, 10, + 10, 11, 0, 12, 12, 11, 0, 11, + 0, 13, 13, 14, 0, 15, 15, 14, + 0, 14, 0, 16, 0, 17, 0, 18, + 0, 19, 13, 13, 14, 0, 20, 0, + 21, 0, 22, 10, 10, 11, 0, 23, + 0, 24, 0, 25, 7, 7, 8, 0, + 26, 0, 27, 0, 28, 4, 4, 5, + 0, 0, 0, 0, 0, 0, 28, 0, + 28, 4, 4, 5, 0, 0, 0, 0, + 0, 29, 28, 0, 30, 4, 4, 5, + 0, 0, 0, 0, 0, 0, 30, 0, + 30, 4, 4, 5, 0, 0, 0, 0, + 0, 31, 30, 0, 32, 4, 4, 5, + 0, 0, 0, 0, 0, 0, 32, 0, + 32, 4, 4, 5, 0, 0, 0, 0, + 0, 33, 32, 0, 34, 4, 4, 5, + 0, 0, 0, 0, 0, 0, 34, 0, + 34, 4, 4, 5, 0, 0, 0, 0, + 0, 35, 34, 0, 36, 4, 4, 5, + 0, 0, 0, 0, 0, 0, 36, 0, + 36, 4, 4, 5, 0, 0, 0, 0, + 0, 37, 36, 0, 39, 40, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 39, 38, 41, 38, 42, + 42, 43, 38, 44, 44, 43, 38, 43, + 38, 45, 45, 46, 38, 47, 47, 46, + 38, 46, 38, 48, 48, 49, 38, 50, + 50, 49, 38, 49, 38, 51, 51, 52, + 38, 53, 53, 52, 38, 52, 38, 54, + 38, 55, 38, 56, 38, 57, 51, 51, + 52, 38, 58, 38, 59, 38, 60, 48, + 48, 49, 38, 61, 38, 62, 38, 63, + 45, 45, 46, 38, 64, 38, 65, 38, + 66, 42, 42, 43, 38, 38, 38, 38, + 38, 38, 66, 38, 66, 42, 42, 43, + 38, 38, 38, 38, 38, 67, 66, 38, + 68, 42, 42, 43, 38, 38, 38, 38, + 38, 38, 68, 38, 68, 42, 42, 43, 38, 38, 38, 38, 38, 69, 68, 38, - 70, 43, 43, 44, 38, 38, 38, 38, - 38, 38, 70, 38, 70, 43, 43, 44, + 70, 42, 42, 43, 38, 38, 38, 38, + 38, 38, 70, 38, 70, 42, 42, 43, 38, 38, 38, 38, 38, 71, 70, 38, - 72, 43, 43, 44, 38, 38, 38, 38, - 38, 38, 72, 38, 72, 43, 43, 44, + 72, 42, 42, 43, 38, 38, 38, 38, + 38, 38, 72, 38, 72, 42, 42, 43, 38, 38, 38, 38, 38, 73, 72, 38, - 74, 43, 43, 44, 38, 38, 38, 38, - 38, 38, 74, 38, 74, 43, 43, 44, + 74, 42, 42, 43, 38, 38, 38, 38, + 38, 38, 74, 38, 74, 42, 42, 43, 38, 38, 38, 38, 38, 75, 74, 38, 77, 78, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, - 76, 79, 76, 80, 81, 81, 82, 76, - 76, 76, 76, 76, 76, 80, 76, 83, - 83, 82, 76, 82, 76, 84, 84, 85, + 76, 79, 76, 80, 80, 81, 76, 83, + 83, 81, 82, 81, 82, 84, 84, 85, 76, 86, 86, 85, 76, 85, 76, 87, 87, 88, 76, 89, 89, 88, 76, 88, 76, 90, 90, 91, 76, 92, 92, 91, @@ -215,395 +275,670 @@ static const short _indic_syllable_machine_indicies[] = { 76, 96, 90, 90, 91, 76, 97, 76, 98, 76, 99, 87, 87, 88, 76, 100, 76, 101, 76, 102, 84, 84, 85, 76, - 103, 76, 104, 76, 80, 81, 81, 82, - 76, 76, 76, 76, 76, 105, 80, 76, - 106, 81, 81, 82, 76, 76, 76, 76, - 76, 76, 106, 76, 106, 81, 81, 82, - 76, 76, 76, 76, 76, 107, 106, 76, - 108, 81, 81, 82, 76, 76, 76, 76, - 76, 76, 108, 76, 108, 81, 81, 82, - 76, 76, 76, 76, 76, 109, 108, 76, - 110, 81, 81, 82, 76, 76, 76, 76, - 76, 76, 110, 76, 110, 81, 81, 82, - 76, 76, 76, 76, 76, 111, 110, 76, - 112, 81, 81, 82, 76, 76, 76, 76, - 76, 76, 112, 76, 112, 81, 81, 82, - 76, 76, 76, 76, 76, 113, 112, 76, + 103, 76, 104, 76, 105, 80, 80, 81, + 76, 76, 76, 76, 76, 76, 105, 76, + 105, 80, 80, 81, 76, 76, 76, 76, + 76, 106, 105, 76, 107, 80, 80, 81, + 76, 76, 76, 76, 76, 76, 107, 76, + 107, 80, 80, 81, 76, 76, 76, 76, + 76, 108, 107, 76, 109, 80, 80, 81, + 76, 76, 76, 76, 76, 76, 109, 76, + 109, 80, 80, 81, 76, 76, 76, 76, + 76, 110, 109, 76, 111, 80, 80, 81, + 76, 76, 76, 76, 76, 76, 111, 76, + 111, 80, 80, 81, 76, 76, 76, 76, + 76, 112, 111, 76, 113, 80, 80, 81, + 76, 76, 76, 76, 76, 76, 113, 76, 115, 116, 114, 114, 114, 114, 114, 114, - 114, 114, 117, 117, 114, 114, 118, 119, - 114, 121, 122, 123, 124, 6, 125, 126, - 127, 120, 120, 37, 128, 120, 129, 122, - 124, 124, 6, 125, 126, 127, 120, 120, - 120, 128, 120, 122, 124, 124, 6, 125, - 126, 127, 120, 120, 120, 128, 120, 130, - 120, 120, 120, 19, 131, 120, 125, 126, - 120, 120, 120, 120, 132, 120, 130, 120, - 133, 134, 135, 136, 6, 125, 126, 127, - 120, 120, 35, 137, 120, 138, 134, 136, - 136, 6, 125, 126, 127, 120, 120, 120, - 137, 120, 134, 136, 136, 6, 125, 126, - 127, 120, 120, 120, 137, 120, 139, 120, - 120, 120, 19, 140, 120, 125, 126, 120, - 120, 120, 120, 132, 120, 139, 120, 141, - 142, 143, 144, 6, 125, 126, 127, 120, - 120, 33, 145, 120, 146, 142, 144, 144, - 6, 125, 126, 127, 120, 120, 120, 145, - 120, 142, 144, 144, 6, 125, 126, 127, - 120, 120, 120, 145, 120, 147, 120, 120, - 120, 19, 148, 120, 125, 126, 120, 120, - 120, 120, 132, 120, 147, 120, 149, 150, - 151, 152, 6, 125, 126, 127, 120, 120, - 31, 153, 120, 154, 150, 152, 152, 6, - 125, 126, 127, 120, 120, 120, 153, 120, - 150, 152, 152, 6, 125, 126, 127, 120, - 120, 120, 153, 120, 155, 120, 120, 120, - 19, 156, 120, 125, 126, 120, 120, 120, - 120, 132, 120, 155, 120, 157, 158, 159, - 160, 6, 125, 126, 127, 120, 120, 29, - 161, 120, 162, 158, 160, 160, 6, 125, - 126, 127, 120, 120, 120, 161, 120, 158, - 160, 160, 6, 125, 126, 127, 120, 120, - 120, 161, 120, 19, 19, 120, 125, 126, - 120, 120, 120, 120, 132, 120, 125, 126, - 120, 120, 120, 120, 132, 120, 163, 120, - 120, 120, 126, 120, 120, 120, 120, 132, - 120, 126, 120, 120, 120, 120, 132, 120, - 164, 120, 165, 120, 166, 120, 120, 120, - 126, 120, 120, 120, 3, 120, 2, 120, - 120, 120, 120, 120, 126, 120, 126, 120, - 165, 120, 120, 120, 120, 120, 126, 120, - 19, 120, 125, 126, 120, 120, 120, 120, - 132, 120, 167, 28, 168, 169, 9, 125, - 126, 120, 120, 120, 120, 132, 120, 28, - 168, 169, 9, 125, 126, 120, 120, 120, - 120, 132, 120, 168, 168, 9, 125, 126, - 120, 120, 120, 120, 132, 120, 170, 25, - 171, 172, 12, 125, 126, 120, 120, 120, - 120, 132, 120, 25, 171, 172, 12, 125, - 126, 120, 120, 120, 120, 132, 120, 171, - 171, 12, 125, 126, 120, 120, 120, 120, - 132, 120, 173, 22, 174, 175, 15, 125, - 126, 120, 120, 120, 120, 132, 120, 22, - 174, 175, 15, 125, 126, 120, 120, 120, - 120, 132, 120, 174, 174, 15, 125, 126, - 120, 120, 120, 120, 132, 120, 176, 19, - 120, 177, 120, 125, 126, 120, 120, 120, - 120, 132, 120, 19, 120, 177, 120, 125, - 126, 120, 120, 120, 120, 132, 120, 158, - 160, 160, 6, 125, 126, 120, 120, 120, - 120, 161, 120, 1, 2, 120, 120, 19, - 19, 120, 125, 126, 120, 120, 120, 120, - 132, 120, 1, 120, 157, 158, 160, 160, - 6, 125, 126, 127, 120, 120, 120, 161, - 120, 155, 120, 120, 120, 120, 120, 120, - 125, 126, 120, 120, 120, 120, 132, 120, - 155, 120, 155, 120, 120, 120, 120, 156, - 120, 125, 126, 120, 120, 120, 120, 132, - 120, 155, 120, 155, 2, 120, 120, 19, - 156, 120, 125, 126, 120, 120, 120, 120, - 132, 120, 155, 120, 149, 150, 152, 152, - 6, 125, 126, 127, 120, 120, 120, 153, - 120, 147, 120, 120, 120, 120, 120, 120, - 125, 126, 120, 120, 120, 120, 132, 120, - 147, 120, 147, 120, 120, 120, 120, 148, - 120, 125, 126, 120, 120, 120, 120, 132, - 120, 147, 120, 147, 2, 120, 120, 19, - 148, 120, 125, 126, 120, 120, 120, 120, - 132, 120, 147, 120, 141, 142, 144, 144, - 6, 125, 126, 127, 120, 120, 120, 145, - 120, 139, 120, 120, 120, 120, 120, 120, - 125, 126, 120, 120, 120, 120, 132, 120, - 139, 120, 139, 120, 120, 120, 120, 140, - 120, 125, 126, 120, 120, 120, 120, 132, - 120, 139, 120, 139, 2, 120, 120, 19, - 140, 120, 125, 126, 120, 120, 120, 120, - 132, 120, 139, 120, 133, 134, 136, 136, - 6, 125, 126, 127, 120, 120, 120, 137, - 120, 130, 120, 120, 120, 120, 120, 120, - 125, 126, 120, 120, 120, 120, 132, 120, - 130, 120, 130, 120, 120, 120, 120, 131, - 120, 125, 126, 120, 120, 120, 120, 132, - 120, 130, 120, 130, 2, 120, 120, 19, - 131, 120, 125, 126, 120, 120, 120, 120, - 132, 120, 130, 120, 121, 122, 124, 124, - 6, 125, 126, 127, 120, 120, 120, 128, - 120, 179, 180, 181, 182, 44, 183, 184, - 178, 178, 178, 75, 185, 178, 186, 180, - 187, 182, 44, 183, 184, 178, 178, 178, - 178, 185, 178, 180, 187, 182, 44, 183, - 184, 178, 178, 178, 178, 185, 178, 188, - 178, 178, 178, 57, 189, 178, 183, 184, - 178, 178, 178, 178, 190, 178, 188, 178, - 191, 192, 193, 194, 44, 183, 184, 178, - 178, 178, 73, 195, 178, 196, 192, 194, - 194, 44, 183, 184, 178, 178, 178, 178, - 195, 178, 192, 194, 194, 44, 183, 184, - 178, 178, 178, 178, 195, 178, 197, 178, - 178, 178, 57, 198, 178, 183, 184, 178, - 178, 178, 178, 190, 178, 197, 178, 199, - 200, 201, 202, 44, 183, 184, 178, 178, - 178, 71, 203, 178, 204, 200, 202, 202, - 44, 183, 184, 178, 178, 178, 178, 203, - 178, 200, 202, 202, 44, 183, 184, 178, - 178, 178, 178, 203, 178, 205, 178, 178, - 178, 57, 206, 178, 183, 184, 178, 178, - 178, 178, 190, 178, 205, 178, 207, 208, - 209, 210, 44, 183, 184, 178, 178, 178, - 69, 211, 178, 212, 208, 210, 210, 44, - 183, 184, 178, 178, 178, 178, 211, 178, - 208, 210, 210, 44, 183, 184, 178, 178, - 178, 178, 211, 178, 213, 178, 178, 178, - 57, 214, 178, 183, 184, 178, 178, 178, - 178, 190, 178, 213, 178, 215, 216, 217, - 218, 44, 183, 184, 178, 178, 178, 67, - 219, 178, 220, 216, 218, 218, 44, 183, - 184, 178, 178, 178, 178, 219, 178, 216, - 218, 218, 44, 183, 184, 178, 178, 178, - 178, 219, 178, 57, 57, 178, 183, 184, - 178, 178, 178, 178, 190, 178, 183, 184, - 178, 178, 178, 178, 190, 178, 221, 178, - 178, 178, 184, 178, 178, 178, 178, 190, - 178, 184, 178, 178, 178, 178, 190, 178, - 222, 178, 223, 178, 224, 178, 178, 178, - 184, 178, 178, 178, 41, 178, 40, 178, - 178, 178, 178, 178, 184, 178, 184, 178, - 223, 178, 178, 178, 178, 178, 184, 178, - 57, 178, 183, 184, 178, 178, 178, 178, - 190, 178, 225, 66, 226, 227, 47, 183, - 184, 178, 178, 178, 178, 190, 178, 66, - 226, 227, 47, 183, 184, 178, 178, 178, - 178, 190, 178, 226, 226, 47, 183, 184, - 178, 178, 178, 178, 190, 178, 228, 63, - 229, 230, 50, 183, 184, 178, 178, 178, - 178, 190, 178, 63, 229, 230, 50, 183, - 184, 178, 178, 178, 178, 190, 178, 229, - 229, 50, 183, 184, 178, 178, 178, 178, - 190, 178, 231, 60, 232, 233, 53, 183, - 184, 178, 178, 178, 178, 190, 178, 60, - 232, 233, 53, 183, 184, 178, 178, 178, - 178, 190, 178, 232, 232, 53, 183, 184, - 178, 178, 178, 178, 190, 178, 234, 57, - 178, 235, 178, 183, 184, 178, 178, 178, - 178, 190, 178, 57, 178, 235, 178, 183, - 184, 178, 178, 178, 178, 190, 178, 39, - 40, 178, 178, 57, 57, 178, 183, 184, - 178, 178, 178, 178, 190, 178, 39, 178, - 215, 216, 218, 218, 44, 183, 184, 178, - 178, 178, 178, 219, 178, 213, 178, 178, - 178, 178, 178, 178, 183, 184, 178, 178, - 178, 178, 190, 178, 213, 178, 213, 178, - 178, 178, 178, 214, 178, 183, 184, 178, - 178, 178, 178, 190, 178, 213, 178, 213, - 40, 178, 178, 57, 214, 178, 183, 184, - 178, 178, 178, 178, 190, 178, 213, 178, - 207, 208, 210, 210, 44, 183, 184, 178, - 178, 178, 178, 211, 178, 205, 178, 178, - 178, 178, 178, 178, 183, 184, 178, 178, - 178, 178, 190, 178, 205, 178, 205, 178, - 178, 178, 178, 206, 178, 183, 184, 178, - 178, 178, 178, 190, 178, 205, 178, 205, - 40, 178, 178, 57, 206, 178, 183, 184, - 178, 178, 178, 178, 190, 178, 205, 178, - 199, 200, 202, 202, 44, 183, 184, 178, - 178, 178, 178, 203, 178, 197, 178, 178, - 178, 178, 178, 178, 183, 184, 178, 178, - 178, 178, 190, 178, 197, 178, 197, 178, - 178, 178, 178, 198, 178, 183, 184, 178, - 178, 178, 178, 190, 178, 197, 178, 197, - 40, 178, 178, 57, 198, 178, 183, 184, - 178, 178, 178, 178, 190, 178, 197, 178, - 191, 192, 194, 194, 44, 183, 184, 178, - 178, 178, 178, 195, 178, 188, 178, 178, - 178, 178, 178, 178, 183, 184, 178, 178, - 178, 178, 190, 178, 188, 178, 188, 178, - 178, 178, 178, 189, 178, 183, 184, 178, - 178, 178, 178, 190, 178, 188, 178, 74, - 43, 43, 44, 178, 178, 178, 178, 178, - 178, 74, 178, 188, 40, 178, 178, 57, - 189, 178, 183, 184, 178, 178, 178, 178, - 190, 178, 188, 178, 179, 180, 187, 182, - 44, 183, 184, 178, 178, 178, 178, 185, - 178, 237, 238, 239, 240, 82, 241, 242, - 236, 236, 236, 113, 243, 236, 244, 238, - 240, 240, 82, 241, 242, 236, 236, 236, - 236, 243, 236, 238, 240, 240, 82, 241, - 242, 236, 236, 236, 236, 243, 236, 245, - 236, 236, 236, 95, 246, 236, 241, 242, - 236, 236, 236, 236, 247, 236, 245, 236, - 248, 249, 250, 251, 82, 241, 242, 236, - 236, 236, 111, 252, 236, 253, 249, 251, - 251, 82, 241, 242, 236, 236, 236, 236, - 252, 236, 249, 251, 251, 82, 241, 242, - 236, 236, 236, 236, 252, 236, 254, 236, - 236, 236, 95, 255, 236, 241, 242, 236, - 236, 236, 236, 247, 236, 254, 236, 256, - 257, 258, 259, 82, 241, 242, 236, 236, - 236, 109, 260, 236, 261, 257, 259, 259, - 82, 241, 242, 236, 236, 236, 236, 260, - 236, 257, 259, 259, 82, 241, 242, 236, - 236, 236, 236, 260, 236, 262, 236, 236, - 236, 95, 263, 236, 241, 242, 236, 236, - 236, 236, 247, 236, 262, 236, 264, 265, - 266, 267, 82, 241, 242, 236, 236, 236, - 107, 268, 236, 269, 265, 267, 267, 82, - 241, 242, 236, 236, 236, 236, 268, 236, - 265, 267, 267, 82, 241, 242, 236, 236, - 236, 236, 268, 236, 270, 236, 236, 236, - 95, 271, 236, 241, 242, 236, 236, 236, - 236, 247, 236, 270, 236, 272, 273, 274, - 275, 82, 241, 242, 236, 236, 236, 105, - 276, 236, 277, 273, 275, 275, 82, 241, - 242, 236, 236, 236, 236, 276, 236, 273, - 275, 275, 82, 241, 242, 236, 236, 236, - 236, 276, 236, 95, 95, 236, 241, 242, - 236, 236, 236, 236, 247, 236, 241, 242, - 236, 236, 236, 236, 247, 236, 278, 236, - 236, 236, 242, 236, 236, 236, 236, 247, - 236, 242, 236, 236, 236, 236, 247, 236, - 279, 236, 280, 236, 281, 236, 236, 236, - 242, 236, 236, 236, 79, 236, 78, 236, - 236, 236, 236, 236, 242, 236, 242, 236, - 280, 236, 236, 236, 236, 236, 242, 236, - 95, 236, 241, 242, 236, 236, 236, 236, - 247, 236, 282, 104, 283, 284, 85, 241, - 242, 236, 236, 236, 236, 247, 236, 104, - 283, 284, 85, 241, 242, 236, 236, 236, - 236, 247, 236, 283, 283, 85, 241, 242, - 236, 236, 236, 236, 247, 236, 285, 101, - 286, 287, 88, 241, 242, 236, 236, 236, - 236, 247, 236, 101, 286, 287, 88, 241, - 242, 236, 236, 236, 236, 247, 236, 286, - 286, 88, 241, 242, 236, 236, 236, 236, - 247, 236, 288, 98, 289, 290, 91, 241, - 242, 236, 236, 236, 236, 247, 236, 98, - 289, 290, 91, 241, 242, 236, 236, 236, - 236, 247, 236, 289, 289, 91, 241, 242, - 236, 236, 236, 236, 247, 236, 291, 95, - 236, 292, 236, 241, 242, 236, 236, 236, - 236, 247, 236, 95, 236, 292, 236, 241, - 242, 236, 236, 236, 236, 247, 236, 77, - 78, 236, 236, 95, 95, 236, 241, 242, - 236, 236, 236, 236, 247, 236, 77, 236, - 272, 273, 275, 275, 82, 241, 242, 236, - 236, 236, 236, 276, 236, 270, 236, 236, - 236, 236, 236, 236, 241, 242, 236, 236, - 236, 236, 247, 236, 270, 236, 270, 236, - 236, 236, 236, 271, 236, 241, 242, 236, - 236, 236, 236, 247, 236, 270, 236, 270, - 78, 236, 236, 95, 271, 236, 241, 242, - 236, 236, 236, 236, 247, 236, 270, 236, - 264, 265, 267, 267, 82, 241, 242, 236, - 236, 236, 236, 268, 236, 262, 236, 236, - 236, 236, 236, 236, 241, 242, 236, 236, - 236, 236, 247, 236, 262, 236, 262, 236, - 236, 236, 236, 263, 236, 241, 242, 236, - 236, 236, 236, 247, 236, 262, 236, 262, - 78, 236, 236, 95, 263, 236, 241, 242, - 236, 236, 236, 236, 247, 236, 262, 236, - 256, 257, 259, 259, 82, 241, 242, 236, - 236, 236, 236, 260, 236, 254, 236, 236, - 236, 236, 236, 236, 241, 242, 236, 236, - 236, 236, 247, 236, 254, 236, 254, 236, - 236, 236, 236, 255, 236, 241, 242, 236, - 236, 236, 236, 247, 236, 254, 236, 254, - 78, 236, 236, 95, 255, 236, 241, 242, - 236, 236, 236, 236, 247, 236, 254, 236, - 248, 249, 251, 251, 82, 241, 242, 236, - 236, 236, 236, 252, 236, 245, 236, 236, - 236, 236, 236, 236, 241, 242, 236, 236, - 236, 236, 247, 236, 245, 236, 245, 236, - 236, 236, 236, 246, 236, 241, 242, 236, - 236, 236, 236, 247, 236, 245, 236, 245, - 78, 236, 236, 95, 246, 236, 241, 242, - 236, 236, 236, 236, 247, 236, 245, 236, - 237, 238, 240, 240, 82, 241, 242, 236, - 236, 236, 236, 243, 236, 115, 116, 293, - 293, 293, 293, 293, 293, 293, 293, 117, - 117, 293, 293, 293, 115, 293, 121, 294, - 123, 124, 6, 125, 126, 127, 120, 120, - 37, 128, 120, 130, 116, 120, 120, 19, - 131, 120, 125, 126, 120, 117, 117, 120, - 132, 120, 130, 120, 0 + 114, 114, 114, 114, 114, 114, 114, 115, + 114, 117, 114, 118, 118, 119, 114, 120, + 120, 119, 114, 119, 114, 121, 121, 122, + 114, 123, 123, 122, 114, 122, 114, 124, + 124, 125, 114, 126, 126, 125, 114, 125, + 114, 127, 127, 128, 114, 129, 129, 128, + 114, 128, 114, 130, 114, 131, 114, 132, + 114, 133, 127, 127, 128, 114, 134, 114, + 135, 114, 136, 124, 124, 125, 114, 137, + 114, 138, 114, 139, 121, 121, 122, 114, + 140, 114, 141, 114, 142, 118, 118, 119, + 114, 114, 114, 114, 114, 114, 142, 114, + 142, 118, 118, 119, 114, 114, 114, 114, + 114, 143, 142, 114, 144, 118, 118, 119, + 114, 114, 114, 114, 114, 114, 144, 114, + 144, 118, 118, 119, 114, 114, 114, 114, + 114, 145, 144, 114, 146, 118, 118, 119, + 114, 114, 114, 114, 114, 114, 146, 114, + 146, 118, 118, 119, 114, 114, 114, 114, + 114, 147, 146, 114, 148, 118, 118, 119, + 114, 114, 114, 114, 114, 114, 148, 114, + 148, 118, 118, 119, 114, 114, 114, 114, + 114, 149, 148, 114, 150, 118, 118, 119, + 114, 114, 114, 114, 114, 114, 150, 114, + 150, 118, 118, 119, 114, 114, 114, 114, + 114, 151, 150, 114, 153, 154, 155, 156, + 157, 158, 81, 159, 160, 152, 161, 161, + 162, 163, 164, 165, 152, 167, 168, 169, + 170, 5, 171, 172, 173, 166, 166, 37, + 174, 166, 175, 168, 176, 176, 5, 171, + 172, 173, 166, 166, 166, 174, 166, 168, + 176, 176, 5, 171, 172, 173, 166, 166, + 166, 174, 166, 177, 166, 166, 166, 18, + 178, 166, 171, 172, 166, 166, 166, 166, + 179, 166, 177, 166, 180, 181, 182, 183, + 5, 171, 172, 173, 166, 166, 35, 184, + 166, 185, 181, 186, 186, 5, 171, 172, + 173, 166, 166, 166, 184, 166, 181, 186, + 186, 5, 171, 172, 173, 166, 166, 166, + 184, 166, 187, 166, 166, 166, 18, 188, + 166, 171, 172, 166, 166, 166, 166, 179, + 166, 187, 166, 189, 190, 191, 192, 5, + 171, 172, 173, 166, 166, 33, 193, 166, + 194, 190, 195, 195, 5, 171, 172, 173, + 166, 166, 166, 193, 166, 190, 195, 195, + 5, 171, 172, 173, 166, 166, 166, 193, + 166, 196, 166, 166, 166, 18, 197, 166, + 171, 172, 166, 166, 166, 166, 179, 166, + 196, 166, 198, 199, 200, 201, 5, 171, + 172, 173, 166, 166, 31, 202, 166, 203, + 199, 204, 204, 5, 171, 172, 173, 166, + 166, 166, 202, 166, 199, 204, 204, 5, + 171, 172, 173, 166, 166, 166, 202, 166, + 205, 166, 166, 166, 18, 206, 166, 171, + 172, 166, 166, 166, 166, 179, 166, 205, + 166, 207, 208, 209, 210, 5, 171, 172, + 173, 166, 166, 29, 211, 166, 212, 208, + 213, 213, 5, 171, 172, 173, 166, 166, + 166, 211, 166, 208, 213, 213, 5, 171, + 172, 173, 166, 166, 166, 211, 166, 18, + 214, 166, 171, 172, 166, 166, 166, 166, + 179, 166, 171, 172, 166, 166, 166, 166, + 179, 166, 215, 166, 166, 166, 172, 166, + 172, 166, 216, 166, 217, 166, 218, 219, + 166, 171, 172, 166, 166, 166, 3, 166, + 2, 166, 166, 166, 166, 171, 172, 166, + 171, 172, 166, 217, 166, 166, 166, 166, + 171, 172, 166, 217, 166, 218, 166, 166, + 171, 172, 166, 166, 166, 3, 166, 18, + 166, 220, 220, 5, 171, 172, 166, 166, + 166, 166, 179, 166, 221, 27, 222, 223, + 8, 171, 172, 166, 166, 166, 166, 179, + 166, 27, 222, 223, 8, 171, 172, 166, + 166, 166, 166, 179, 166, 222, 222, 8, + 171, 172, 166, 166, 166, 166, 179, 166, + 224, 24, 225, 226, 11, 171, 172, 166, + 166, 166, 166, 179, 166, 24, 225, 226, + 11, 171, 172, 166, 166, 166, 166, 179, + 166, 225, 225, 11, 171, 172, 166, 166, + 166, 166, 179, 166, 227, 21, 228, 229, + 14, 171, 172, 166, 166, 166, 166, 179, + 166, 21, 228, 229, 14, 171, 172, 166, + 166, 166, 166, 179, 166, 228, 228, 14, + 171, 172, 166, 166, 166, 166, 179, 166, + 230, 18, 166, 231, 166, 171, 172, 166, + 166, 166, 166, 179, 166, 18, 166, 231, + 166, 171, 172, 166, 166, 166, 166, 179, + 166, 232, 166, 171, 172, 166, 166, 166, + 166, 179, 166, 18, 166, 166, 166, 166, + 171, 172, 166, 166, 166, 166, 179, 166, + 208, 213, 213, 5, 171, 172, 166, 166, + 166, 166, 211, 166, 1, 2, 166, 166, + 18, 214, 166, 171, 172, 166, 166, 166, + 166, 179, 166, 1, 166, 207, 208, 213, + 213, 5, 171, 172, 173, 166, 166, 166, + 211, 166, 207, 208, 209, 213, 5, 171, + 172, 173, 166, 166, 29, 211, 166, 205, + 166, 233, 166, 220, 220, 5, 171, 172, + 166, 166, 166, 166, 179, 166, 205, 166, + 205, 166, 166, 166, 166, 166, 166, 171, + 172, 166, 166, 166, 166, 179, 166, 205, + 166, 205, 166, 166, 166, 166, 234, 166, + 171, 172, 166, 166, 166, 166, 179, 166, + 205, 166, 205, 166, 233, 166, 166, 166, + 166, 171, 172, 166, 166, 166, 166, 179, + 166, 205, 166, 205, 2, 166, 166, 18, + 206, 166, 171, 172, 166, 166, 166, 166, + 179, 166, 205, 166, 198, 199, 204, 204, + 5, 171, 172, 173, 166, 166, 166, 202, + 166, 198, 199, 200, 204, 5, 171, 172, + 173, 166, 166, 31, 202, 166, 196, 166, + 235, 166, 220, 220, 5, 171, 172, 166, + 166, 166, 166, 179, 166, 196, 166, 196, + 166, 166, 166, 166, 166, 166, 171, 172, + 166, 166, 166, 166, 179, 166, 196, 166, + 196, 166, 166, 166, 166, 236, 166, 171, + 172, 166, 166, 166, 166, 179, 166, 196, + 166, 196, 166, 235, 166, 166, 166, 166, + 171, 172, 166, 166, 166, 166, 179, 166, + 196, 166, 196, 2, 166, 166, 18, 197, + 166, 171, 172, 166, 166, 166, 166, 179, + 166, 196, 166, 189, 190, 195, 195, 5, + 171, 172, 173, 166, 166, 166, 193, 166, + 189, 190, 191, 195, 5, 171, 172, 173, + 166, 166, 33, 193, 166, 187, 166, 237, + 166, 220, 220, 5, 171, 172, 166, 166, + 166, 166, 179, 166, 187, 166, 187, 166, + 166, 166, 166, 166, 166, 171, 172, 166, + 166, 166, 166, 179, 166, 187, 166, 187, + 166, 166, 166, 166, 238, 166, 171, 172, + 166, 166, 166, 166, 179, 166, 187, 166, + 187, 166, 237, 166, 166, 166, 166, 171, + 172, 166, 166, 166, 166, 179, 166, 187, + 166, 187, 2, 166, 166, 18, 188, 166, + 171, 172, 166, 166, 166, 166, 179, 166, + 187, 166, 180, 181, 186, 186, 5, 171, + 172, 173, 166, 166, 166, 184, 166, 180, + 181, 182, 186, 5, 171, 172, 173, 166, + 166, 35, 184, 166, 177, 166, 239, 166, + 220, 220, 5, 171, 172, 166, 166, 166, + 166, 179, 166, 177, 166, 177, 166, 166, + 166, 166, 166, 166, 171, 172, 166, 166, + 166, 166, 179, 166, 177, 166, 177, 166, + 166, 166, 166, 240, 166, 171, 172, 166, + 166, 166, 166, 179, 166, 177, 166, 177, + 166, 239, 166, 166, 166, 166, 171, 172, + 166, 166, 166, 166, 179, 166, 177, 166, + 177, 2, 166, 166, 18, 178, 166, 171, + 172, 166, 166, 166, 166, 179, 166, 177, + 166, 167, 168, 176, 176, 5, 171, 172, + 173, 166, 166, 166, 174, 166, 167, 168, + 169, 176, 5, 171, 172, 173, 166, 166, + 37, 174, 166, 242, 243, 244, 245, 43, + 246, 247, 241, 241, 241, 75, 248, 241, + 249, 243, 250, 245, 43, 246, 247, 241, + 241, 241, 241, 248, 241, 243, 250, 245, + 43, 246, 247, 241, 241, 241, 241, 248, + 241, 251, 241, 241, 241, 56, 252, 241, + 246, 247, 241, 241, 241, 241, 253, 241, + 251, 241, 254, 255, 256, 257, 43, 246, + 247, 241, 241, 241, 73, 258, 241, 259, + 255, 260, 260, 43, 246, 247, 241, 241, + 241, 241, 258, 241, 255, 260, 260, 43, + 246, 247, 241, 241, 241, 241, 258, 241, + 261, 241, 241, 241, 56, 262, 241, 246, + 247, 241, 241, 241, 241, 253, 241, 261, + 241, 263, 264, 265, 266, 43, 246, 247, + 241, 241, 241, 71, 267, 241, 268, 264, + 269, 269, 43, 246, 247, 241, 241, 241, + 241, 267, 241, 264, 269, 269, 43, 246, + 247, 241, 241, 241, 241, 267, 241, 270, + 241, 241, 241, 56, 271, 241, 246, 247, + 241, 241, 241, 241, 253, 241, 270, 241, + 272, 273, 274, 275, 43, 246, 247, 241, + 241, 241, 69, 276, 241, 277, 273, 278, + 278, 43, 246, 247, 241, 241, 241, 241, + 276, 241, 273, 278, 278, 43, 246, 247, + 241, 241, 241, 241, 276, 241, 279, 241, + 241, 241, 56, 280, 241, 246, 247, 241, + 241, 241, 241, 253, 241, 279, 241, 281, + 282, 283, 284, 43, 246, 247, 241, 241, + 241, 67, 285, 241, 286, 282, 287, 287, + 43, 246, 247, 241, 241, 241, 241, 285, + 241, 282, 287, 287, 43, 246, 247, 241, + 241, 241, 241, 285, 241, 56, 288, 241, + 246, 247, 241, 241, 241, 241, 253, 241, + 246, 247, 241, 241, 241, 241, 253, 241, + 289, 241, 241, 241, 247, 241, 247, 241, + 290, 241, 291, 241, 292, 293, 241, 246, + 247, 241, 241, 241, 41, 241, 40, 241, + 241, 241, 241, 246, 247, 241, 246, 247, + 241, 291, 241, 241, 241, 241, 246, 247, + 241, 291, 241, 292, 241, 241, 246, 247, + 241, 241, 241, 41, 241, 56, 241, 294, + 294, 43, 246, 247, 241, 241, 241, 241, + 253, 241, 295, 65, 296, 297, 46, 246, + 247, 241, 241, 241, 241, 253, 241, 65, + 296, 297, 46, 246, 247, 241, 241, 241, + 241, 253, 241, 296, 296, 46, 246, 247, + 241, 241, 241, 241, 253, 241, 298, 62, + 299, 300, 49, 246, 247, 241, 241, 241, + 241, 253, 241, 62, 299, 300, 49, 246, + 247, 241, 241, 241, 241, 253, 241, 299, + 299, 49, 246, 247, 241, 241, 241, 241, + 253, 241, 301, 59, 302, 303, 52, 246, + 247, 241, 241, 241, 241, 253, 241, 59, + 302, 303, 52, 246, 247, 241, 241, 241, + 241, 253, 241, 302, 302, 52, 246, 247, + 241, 241, 241, 241, 253, 241, 304, 56, + 241, 305, 241, 246, 247, 241, 241, 241, + 241, 253, 241, 56, 241, 305, 241, 246, + 247, 241, 241, 241, 241, 253, 241, 306, + 241, 246, 247, 241, 241, 241, 241, 253, + 241, 56, 241, 241, 241, 241, 246, 247, + 241, 241, 241, 241, 253, 241, 39, 40, + 241, 241, 56, 288, 241, 246, 247, 241, + 241, 241, 241, 253, 241, 39, 241, 281, + 282, 287, 287, 43, 246, 247, 241, 241, + 241, 241, 285, 241, 281, 282, 283, 287, + 43, 246, 247, 241, 241, 241, 67, 285, + 241, 279, 241, 307, 241, 294, 294, 43, + 246, 247, 241, 241, 241, 241, 253, 241, + 279, 241, 279, 241, 241, 241, 241, 241, + 241, 246, 247, 241, 241, 241, 241, 253, + 241, 279, 241, 279, 241, 241, 241, 241, + 308, 241, 246, 247, 241, 241, 241, 241, + 253, 241, 279, 241, 279, 241, 307, 241, + 241, 241, 241, 246, 247, 241, 241, 241, + 241, 253, 241, 279, 241, 279, 40, 241, + 241, 56, 280, 241, 246, 247, 241, 241, + 241, 241, 253, 241, 279, 241, 272, 273, + 278, 278, 43, 246, 247, 241, 241, 241, + 241, 276, 241, 272, 273, 274, 278, 43, + 246, 247, 241, 241, 241, 69, 276, 241, + 270, 241, 309, 241, 294, 294, 43, 246, + 247, 241, 241, 241, 241, 253, 241, 270, + 241, 270, 241, 241, 241, 241, 241, 241, + 246, 247, 241, 241, 241, 241, 253, 241, + 270, 241, 270, 241, 241, 241, 241, 310, + 241, 246, 247, 241, 241, 241, 241, 253, + 241, 270, 241, 270, 241, 309, 241, 241, + 241, 241, 246, 247, 241, 241, 241, 241, + 253, 241, 270, 241, 270, 40, 241, 241, + 56, 271, 241, 246, 247, 241, 241, 241, + 241, 253, 241, 270, 241, 263, 264, 269, + 269, 43, 246, 247, 241, 241, 241, 241, + 267, 241, 263, 264, 265, 269, 43, 246, + 247, 241, 241, 241, 71, 267, 241, 261, + 241, 311, 241, 294, 294, 43, 246, 247, + 241, 241, 241, 241, 253, 241, 261, 241, + 261, 241, 241, 241, 241, 241, 241, 246, + 247, 241, 241, 241, 241, 253, 241, 261, + 241, 261, 241, 241, 241, 241, 312, 241, + 246, 247, 241, 241, 241, 241, 253, 241, + 261, 241, 261, 241, 311, 241, 241, 241, + 241, 246, 247, 241, 241, 241, 241, 253, + 241, 261, 241, 261, 40, 241, 241, 56, + 262, 241, 246, 247, 241, 241, 241, 241, + 253, 241, 261, 241, 254, 255, 260, 260, + 43, 246, 247, 241, 241, 241, 241, 258, + 241, 254, 255, 256, 260, 43, 246, 247, + 241, 241, 241, 73, 258, 241, 251, 241, + 313, 241, 294, 294, 43, 246, 247, 241, + 241, 241, 241, 253, 241, 251, 241, 251, + 241, 241, 241, 241, 241, 241, 246, 247, + 241, 241, 241, 241, 253, 241, 251, 241, + 251, 241, 241, 241, 241, 314, 241, 246, + 247, 241, 241, 241, 241, 253, 241, 251, + 241, 251, 241, 313, 241, 241, 241, 241, + 246, 247, 241, 241, 241, 241, 253, 241, + 251, 241, 74, 42, 42, 43, 241, 241, + 241, 241, 241, 241, 74, 241, 251, 40, + 241, 241, 56, 252, 241, 246, 247, 241, + 241, 241, 241, 253, 241, 251, 241, 242, + 243, 250, 245, 43, 246, 247, 241, 241, + 241, 241, 248, 241, 316, 156, 317, 317, + 81, 159, 160, 315, 315, 315, 315, 163, + 315, 156, 317, 317, 81, 159, 160, 315, + 315, 315, 315, 163, 315, 318, 315, 315, + 315, 95, 319, 315, 159, 160, 315, 315, + 315, 315, 320, 315, 318, 315, 321, 322, + 323, 324, 81, 159, 160, 315, 315, 315, + 112, 325, 315, 326, 322, 327, 327, 81, + 159, 160, 315, 315, 315, 315, 325, 315, + 322, 327, 327, 81, 159, 160, 315, 315, + 315, 315, 325, 315, 328, 315, 315, 315, + 95, 329, 315, 159, 160, 315, 315, 315, + 315, 320, 315, 328, 315, 330, 331, 332, + 333, 81, 159, 160, 315, 315, 315, 110, + 334, 315, 335, 331, 336, 336, 81, 159, + 160, 315, 315, 315, 315, 334, 315, 331, + 336, 336, 81, 159, 160, 315, 315, 315, + 315, 334, 315, 337, 315, 315, 315, 95, + 338, 315, 159, 160, 315, 315, 315, 315, + 320, 315, 337, 315, 339, 340, 341, 342, + 81, 159, 160, 315, 315, 315, 108, 343, + 315, 344, 340, 345, 345, 81, 159, 160, + 315, 315, 315, 315, 343, 315, 340, 345, + 345, 81, 159, 160, 315, 315, 315, 315, + 343, 315, 346, 315, 315, 315, 95, 347, + 315, 159, 160, 315, 315, 315, 315, 320, + 315, 346, 315, 348, 349, 350, 351, 81, + 159, 160, 315, 315, 315, 106, 352, 315, + 353, 349, 354, 354, 81, 159, 160, 315, + 315, 315, 315, 352, 315, 349, 354, 354, + 81, 159, 160, 315, 315, 315, 315, 352, + 315, 95, 355, 315, 159, 160, 315, 315, + 315, 315, 320, 315, 159, 160, 315, 315, + 315, 315, 320, 315, 356, 315, 315, 315, + 160, 315, 160, 315, 357, 315, 358, 315, + 359, 360, 315, 159, 160, 315, 315, 315, + 79, 315, 78, 315, 315, 315, 315, 159, + 160, 315, 159, 160, 315, 358, 315, 315, + 315, 315, 159, 160, 315, 358, 315, 359, + 315, 315, 159, 160, 315, 315, 315, 79, + 315, 95, 315, 361, 361, 81, 159, 160, + 315, 315, 315, 315, 320, 315, 362, 104, + 363, 364, 85, 159, 160, 315, 315, 315, + 315, 320, 315, 104, 363, 364, 85, 159, + 160, 315, 315, 315, 315, 320, 315, 363, + 363, 85, 159, 160, 315, 315, 315, 315, + 320, 315, 365, 101, 366, 367, 88, 159, + 160, 315, 315, 315, 315, 320, 315, 101, + 366, 367, 88, 159, 160, 315, 315, 315, + 315, 320, 315, 366, 366, 88, 159, 160, + 315, 315, 315, 315, 320, 315, 368, 98, + 369, 370, 91, 159, 160, 315, 315, 315, + 315, 320, 315, 98, 369, 370, 91, 159, + 160, 315, 315, 315, 315, 320, 315, 369, + 369, 91, 159, 160, 315, 315, 315, 315, + 320, 315, 371, 95, 315, 372, 315, 159, + 160, 315, 315, 315, 315, 320, 315, 95, + 315, 372, 315, 159, 160, 315, 315, 315, + 315, 320, 315, 373, 315, 159, 160, 315, + 315, 315, 315, 320, 315, 95, 315, 315, + 315, 315, 159, 160, 315, 315, 315, 315, + 320, 315, 77, 78, 315, 315, 95, 355, + 315, 159, 160, 315, 315, 315, 315, 320, + 315, 77, 315, 348, 349, 354, 354, 81, + 159, 160, 315, 315, 315, 315, 352, 315, + 348, 349, 350, 354, 81, 159, 160, 315, + 315, 315, 106, 352, 315, 346, 315, 374, + 315, 361, 361, 81, 159, 160, 315, 315, + 315, 315, 320, 315, 346, 315, 346, 315, + 315, 315, 315, 315, 315, 159, 160, 315, + 315, 315, 315, 320, 315, 346, 315, 346, + 315, 315, 315, 315, 375, 315, 159, 160, + 315, 315, 315, 315, 320, 315, 346, 315, + 346, 315, 374, 315, 315, 315, 315, 159, + 160, 315, 315, 315, 315, 320, 315, 346, + 315, 346, 78, 315, 315, 95, 347, 315, + 159, 160, 315, 315, 315, 315, 320, 315, + 346, 315, 339, 340, 345, 345, 81, 159, + 160, 315, 315, 315, 315, 343, 315, 339, + 340, 341, 345, 81, 159, 160, 315, 315, + 315, 108, 343, 315, 337, 315, 376, 315, + 361, 361, 81, 159, 160, 315, 315, 315, + 315, 320, 315, 337, 315, 337, 315, 315, + 315, 315, 315, 315, 159, 160, 315, 315, + 315, 315, 320, 315, 337, 315, 337, 315, + 315, 315, 315, 377, 315, 159, 160, 315, + 315, 315, 315, 320, 315, 337, 315, 337, + 315, 376, 315, 315, 315, 315, 159, 160, + 315, 315, 315, 315, 320, 315, 337, 315, + 337, 78, 315, 315, 95, 338, 315, 159, + 160, 315, 315, 315, 315, 320, 315, 337, + 315, 330, 331, 336, 336, 81, 159, 160, + 315, 315, 315, 315, 334, 315, 330, 331, + 332, 336, 81, 159, 160, 315, 315, 315, + 110, 334, 315, 328, 315, 378, 315, 361, + 361, 81, 159, 160, 315, 315, 315, 315, + 320, 315, 328, 315, 328, 315, 315, 315, + 315, 315, 315, 159, 160, 315, 315, 315, + 315, 320, 315, 328, 315, 328, 315, 315, + 315, 315, 379, 315, 159, 160, 315, 315, + 315, 315, 320, 315, 328, 315, 328, 315, + 378, 315, 315, 315, 315, 159, 160, 315, + 315, 315, 315, 320, 315, 328, 315, 328, + 78, 315, 315, 95, 329, 315, 159, 160, + 315, 315, 315, 315, 320, 315, 328, 315, + 321, 322, 327, 327, 81, 159, 160, 315, + 315, 315, 315, 325, 315, 321, 322, 323, + 327, 81, 159, 160, 315, 315, 315, 112, + 325, 315, 318, 315, 380, 315, 361, 361, + 81, 159, 160, 315, 315, 315, 315, 320, + 315, 318, 315, 318, 315, 315, 315, 315, + 315, 315, 159, 160, 315, 315, 315, 315, + 320, 315, 318, 315, 318, 315, 315, 315, + 315, 381, 315, 159, 160, 315, 315, 315, + 315, 320, 315, 318, 315, 318, 315, 380, + 315, 315, 315, 315, 159, 160, 315, 315, + 315, 315, 320, 315, 318, 315, 318, 78, + 315, 315, 95, 319, 315, 159, 160, 315, + 315, 315, 315, 320, 315, 318, 315, 113, + 80, 80, 81, 382, 382, 382, 382, 382, + 162, 113, 382, 155, 156, 317, 317, 81, + 159, 160, 315, 315, 315, 315, 163, 315, + 113, 80, 80, 81, 382, 382, 382, 382, + 382, 382, 113, 382, 384, 385, 386, 387, + 119, 388, 389, 383, 383, 383, 151, 390, + 383, 391, 385, 387, 387, 119, 388, 389, + 383, 383, 383, 383, 390, 383, 385, 387, + 387, 119, 388, 389, 383, 383, 383, 383, + 390, 383, 392, 383, 383, 383, 132, 393, + 383, 388, 389, 383, 383, 383, 383, 394, + 383, 392, 383, 395, 396, 397, 398, 119, + 388, 389, 383, 383, 383, 149, 399, 383, + 400, 396, 401, 401, 119, 388, 389, 383, + 383, 383, 383, 399, 383, 396, 401, 401, + 119, 388, 389, 383, 383, 383, 383, 399, + 383, 402, 383, 383, 383, 132, 403, 383, + 388, 389, 383, 383, 383, 383, 394, 383, + 402, 383, 404, 405, 406, 407, 119, 388, + 389, 383, 383, 383, 147, 408, 383, 409, + 405, 410, 410, 119, 388, 389, 383, 383, + 383, 383, 408, 383, 405, 410, 410, 119, + 388, 389, 383, 383, 383, 383, 408, 383, + 411, 383, 383, 383, 132, 412, 383, 388, + 389, 383, 383, 383, 383, 394, 383, 411, + 383, 413, 414, 415, 416, 119, 388, 389, + 383, 383, 383, 145, 417, 383, 418, 414, + 419, 419, 119, 388, 389, 383, 383, 383, + 383, 417, 383, 414, 419, 419, 119, 388, + 389, 383, 383, 383, 383, 417, 383, 420, + 383, 383, 383, 132, 421, 383, 388, 389, + 383, 383, 383, 383, 394, 383, 420, 383, + 422, 423, 424, 425, 119, 388, 389, 383, + 383, 383, 143, 426, 383, 427, 423, 428, + 428, 119, 388, 389, 383, 383, 383, 383, + 426, 383, 423, 428, 428, 119, 388, 389, + 383, 383, 383, 383, 426, 383, 132, 429, + 383, 388, 389, 383, 383, 383, 383, 394, + 383, 388, 389, 383, 383, 383, 383, 394, + 383, 430, 383, 383, 383, 389, 383, 389, + 383, 431, 383, 432, 383, 433, 434, 383, + 388, 389, 383, 383, 383, 117, 383, 116, + 383, 383, 383, 383, 388, 389, 383, 388, + 389, 383, 432, 383, 383, 383, 383, 388, + 389, 383, 432, 383, 433, 383, 383, 388, + 389, 383, 383, 383, 117, 383, 132, 383, + 435, 435, 119, 388, 389, 383, 383, 383, + 383, 394, 383, 436, 141, 437, 438, 122, + 388, 389, 383, 383, 383, 383, 394, 383, + 141, 437, 438, 122, 388, 389, 383, 383, + 383, 383, 394, 383, 437, 437, 122, 388, + 389, 383, 383, 383, 383, 394, 383, 439, + 138, 440, 441, 125, 388, 389, 383, 383, + 383, 383, 394, 383, 138, 440, 441, 125, + 388, 389, 383, 383, 383, 383, 394, 383, + 440, 440, 125, 388, 389, 383, 383, 383, + 383, 394, 383, 442, 135, 443, 444, 128, + 388, 389, 383, 383, 383, 383, 394, 383, + 135, 443, 444, 128, 388, 389, 383, 383, + 383, 383, 394, 383, 443, 443, 128, 388, + 389, 383, 383, 383, 383, 394, 383, 445, + 132, 383, 446, 383, 388, 389, 383, 383, + 383, 383, 394, 383, 132, 383, 446, 383, + 388, 389, 383, 383, 383, 383, 394, 383, + 447, 383, 388, 389, 383, 383, 383, 383, + 394, 383, 132, 383, 383, 383, 383, 388, + 389, 383, 383, 383, 383, 394, 383, 115, + 116, 383, 383, 132, 429, 383, 388, 389, + 383, 383, 383, 383, 394, 383, 115, 383, + 422, 423, 428, 428, 119, 388, 389, 383, + 383, 383, 383, 426, 383, 422, 423, 424, + 428, 119, 388, 389, 383, 383, 383, 143, + 426, 383, 420, 383, 448, 383, 435, 435, + 119, 388, 389, 383, 383, 383, 383, 394, + 383, 420, 383, 420, 383, 383, 383, 383, + 383, 383, 388, 389, 383, 383, 383, 383, + 394, 383, 420, 383, 420, 383, 383, 383, + 383, 449, 383, 388, 389, 383, 383, 383, + 383, 394, 383, 420, 383, 420, 383, 448, + 383, 383, 383, 383, 388, 389, 383, 383, + 383, 383, 394, 383, 420, 383, 420, 116, + 383, 383, 132, 421, 383, 388, 389, 383, + 383, 383, 383, 394, 383, 420, 383, 413, + 414, 419, 419, 119, 388, 389, 383, 383, + 383, 383, 417, 383, 413, 414, 415, 419, + 119, 388, 389, 383, 383, 383, 145, 417, + 383, 411, 383, 450, 383, 435, 435, 119, + 388, 389, 383, 383, 383, 383, 394, 383, + 411, 383, 411, 383, 383, 383, 383, 383, + 383, 388, 389, 383, 383, 383, 383, 394, + 383, 411, 383, 411, 383, 383, 383, 383, + 451, 383, 388, 389, 383, 383, 383, 383, + 394, 383, 411, 383, 411, 383, 450, 383, + 383, 383, 383, 388, 389, 383, 383, 383, + 383, 394, 383, 411, 383, 411, 116, 383, + 383, 132, 412, 383, 388, 389, 383, 383, + 383, 383, 394, 383, 411, 383, 404, 405, + 410, 410, 119, 388, 389, 383, 383, 383, + 383, 408, 383, 404, 405, 406, 410, 119, + 388, 389, 383, 383, 383, 147, 408, 383, + 402, 383, 452, 383, 435, 435, 119, 388, + 389, 383, 383, 383, 383, 394, 383, 402, + 383, 402, 383, 383, 383, 383, 383, 383, + 388, 389, 383, 383, 383, 383, 394, 383, + 402, 383, 402, 383, 383, 383, 383, 453, + 383, 388, 389, 383, 383, 383, 383, 394, + 383, 402, 383, 402, 383, 452, 383, 383, + 383, 383, 388, 389, 383, 383, 383, 383, + 394, 383, 402, 383, 402, 116, 383, 383, + 132, 403, 383, 388, 389, 383, 383, 383, + 383, 394, 383, 402, 383, 395, 396, 401, + 401, 119, 388, 389, 383, 383, 383, 383, + 399, 383, 395, 396, 397, 401, 119, 388, + 389, 383, 383, 383, 149, 399, 383, 392, + 383, 454, 383, 435, 435, 119, 388, 389, + 383, 383, 383, 383, 394, 383, 392, 383, + 392, 383, 383, 383, 383, 383, 383, 388, + 389, 383, 383, 383, 383, 394, 383, 392, + 383, 392, 383, 383, 383, 383, 455, 383, + 388, 389, 383, 383, 383, 383, 394, 383, + 392, 383, 392, 383, 454, 383, 383, 383, + 383, 388, 389, 383, 383, 383, 383, 394, + 383, 392, 383, 392, 116, 383, 383, 132, + 393, 383, 388, 389, 383, 383, 383, 383, + 394, 383, 392, 383, 384, 385, 387, 387, + 119, 388, 389, 383, 383, 383, 383, 390, + 383, 153, 154, 382, 382, 382, 382, 382, + 382, 382, 382, 161, 161, 382, 382, 382, + 153, 382, 167, 456, 169, 170, 5, 171, + 172, 173, 166, 166, 37, 174, 166, 177, + 154, 166, 166, 18, 178, 166, 171, 172, + 166, 161, 161, 166, 179, 166, 177, 166, + 0 }; static const short _indic_syllable_machine_trans_targs[] = { - 105, 130, 132, 133, 134, 3, 135, 4, - 6, 138, 7, 9, 141, 10, 12, 144, - 13, 15, 16, 126, 18, 19, 143, 21, - 22, 140, 24, 25, 137, 148, 150, 152, - 154, 156, 158, 160, 162, 164, 105, 189, - 191, 192, 193, 38, 194, 39, 41, 197, - 42, 44, 200, 45, 47, 203, 48, 50, - 51, 185, 53, 54, 202, 56, 57, 199, - 59, 60, 196, 206, 208, 210, 212, 214, - 216, 218, 220, 223, 105, 248, 250, 251, - 252, 73, 253, 74, 76, 256, 77, 79, - 259, 80, 82, 262, 83, 85, 86, 244, - 88, 89, 261, 91, 92, 258, 94, 95, - 255, 265, 267, 269, 271, 273, 275, 277, - 279, 281, 105, 106, 165, 224, 282, 283, - 105, 107, 109, 34, 33, 127, 129, 146, - 163, 108, 110, 161, 0, 111, 113, 32, - 31, 159, 112, 114, 157, 115, 117, 30, - 29, 155, 116, 118, 153, 119, 121, 28, - 27, 151, 120, 122, 149, 123, 125, 26, - 2, 147, 124, 128, 105, 131, 1, 136, - 5, 23, 139, 8, 20, 142, 11, 17, - 145, 14, 105, 166, 168, 69, 221, 186, - 188, 222, 167, 68, 169, 219, 35, 170, - 172, 67, 66, 217, 171, 173, 215, 174, - 176, 65, 64, 213, 175, 177, 211, 178, - 180, 63, 62, 209, 179, 181, 207, 182, - 184, 61, 37, 205, 183, 187, 105, 190, - 36, 195, 40, 58, 198, 43, 55, 201, - 46, 52, 204, 49, 105, 225, 227, 104, - 103, 245, 247, 280, 226, 228, 278, 70, - 229, 231, 102, 101, 276, 230, 232, 274, - 233, 235, 100, 99, 272, 234, 236, 270, - 237, 239, 98, 97, 268, 238, 240, 266, - 241, 243, 96, 72, 264, 242, 246, 105, - 249, 71, 254, 75, 93, 257, 78, 90, - 260, 81, 87, 263, 84, 105, 284 + 143, 168, 170, 171, 3, 174, 4, 6, + 177, 7, 9, 180, 10, 12, 183, 13, + 15, 16, 164, 18, 19, 182, 21, 22, + 179, 24, 25, 176, 185, 189, 193, 196, + 200, 203, 207, 210, 214, 217, 143, 243, + 245, 246, 39, 249, 40, 42, 252, 43, + 45, 255, 46, 48, 258, 49, 51, 52, + 239, 54, 55, 257, 57, 58, 254, 60, + 61, 251, 260, 263, 267, 270, 274, 277, + 281, 284, 288, 292, 143, 316, 318, 319, + 75, 322, 143, 76, 78, 325, 79, 81, + 328, 82, 84, 331, 85, 87, 88, 312, + 90, 91, 330, 93, 94, 327, 96, 97, + 324, 333, 336, 340, 343, 347, 350, 354, + 357, 361, 143, 391, 393, 394, 110, 397, + 111, 113, 400, 114, 116, 403, 117, 119, + 406, 120, 122, 123, 387, 125, 126, 405, + 128, 129, 402, 131, 132, 399, 408, 411, + 415, 418, 422, 425, 429, 432, 436, 439, + 143, 144, 219, 293, 295, 364, 366, 313, + 315, 367, 365, 363, 440, 441, 143, 145, + 147, 35, 218, 165, 167, 187, 216, 146, + 34, 148, 212, 0, 149, 151, 33, 211, + 209, 150, 32, 152, 205, 153, 155, 31, + 204, 202, 154, 30, 156, 198, 157, 159, + 29, 197, 195, 158, 28, 160, 191, 161, + 163, 27, 190, 188, 162, 26, 173, 166, + 143, 169, 1, 172, 2, 175, 5, 23, + 178, 8, 20, 181, 11, 17, 184, 14, + 186, 192, 194, 199, 201, 206, 208, 213, + 215, 143, 220, 222, 71, 290, 240, 242, + 291, 221, 70, 223, 286, 36, 224, 226, + 69, 285, 283, 225, 68, 227, 279, 228, + 230, 67, 278, 276, 229, 66, 231, 272, + 232, 234, 65, 271, 269, 233, 64, 235, + 265, 236, 238, 63, 264, 262, 237, 62, + 248, 241, 143, 244, 37, 247, 38, 250, + 41, 59, 253, 44, 56, 256, 47, 53, + 259, 50, 261, 266, 268, 273, 275, 280, + 282, 287, 289, 143, 294, 106, 296, 359, + 72, 297, 299, 105, 358, 356, 298, 104, + 300, 352, 301, 303, 103, 351, 349, 302, + 102, 304, 345, 305, 307, 101, 344, 342, + 306, 100, 308, 338, 309, 311, 99, 337, + 335, 310, 98, 321, 314, 143, 317, 73, + 320, 74, 323, 77, 95, 326, 80, 92, + 329, 83, 89, 332, 86, 334, 339, 341, + 346, 348, 353, 355, 360, 362, 143, 143, + 368, 370, 142, 141, 388, 390, 438, 369, + 371, 434, 107, 372, 374, 140, 433, 431, + 373, 139, 375, 427, 376, 378, 138, 426, + 424, 377, 137, 379, 420, 380, 382, 136, + 419, 417, 381, 135, 383, 413, 384, 386, + 134, 412, 410, 385, 133, 396, 389, 143, + 392, 108, 395, 109, 398, 112, 130, 401, + 115, 127, 404, 118, 124, 407, 121, 409, + 414, 416, 421, 423, 428, 430, 435, 437, + 442 }; static const char _indic_syllable_machine_trans_actions[] = { - 1, 2, 0, 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, 3, 2, - 0, 0, 2, 0, 2, 0, 0, 2, + 1, 2, 0, 0, 0, 2, 0, 0, + 2, 0, 0, 2, 0, 0, 2, 0, 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, 0, 0, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 2, + 0, 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, 2, 0, 0, - 2, 0, 2, 0, 0, 2, 0, 0, + 0, 2, 5, 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, 2, 0, 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, - 2, 2, 7, 2, 2, 2, 0, 2, - 8, 2, 2, 0, 0, 2, 0, 2, - 2, 2, 2, 2, 0, 2, 2, 0, - 0, 2, 2, 2, 2, 2, 2, 0, - 0, 2, 2, 2, 2, 2, 2, 0, - 0, 2, 2, 2, 2, 2, 2, 0, - 0, 2, 2, 2, 9, 0, 0, 2, - 0, 0, 2, 0, 0, 2, 0, 0, - 2, 0, 10, 2, 2, 0, 2, 2, + 10, 2, 2, 6, 2, 11, 11, 0, + 0, 2, 6, 2, 0, 2, 12, 2, + 2, 0, 2, 0, 0, 2, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, - 2, 0, 0, 2, 2, 2, 2, 2, - 2, 0, 0, 2, 2, 2, 2, 2, - 2, 0, 0, 2, 2, 2, 2, 2, - 2, 0, 0, 2, 2, 2, 11, 0, - 0, 2, 0, 0, 2, 0, 0, 2, - 0, 0, 2, 0, 12, 2, 2, 0, - 0, 2, 0, 2, 2, 2, 2, 0, - 2, 2, 0, 0, 2, 2, 2, 2, - 2, 2, 0, 0, 2, 2, 2, 2, - 2, 2, 0, 0, 2, 2, 2, 2, - 2, 2, 0, 0, 2, 2, 2, 13, + 2, 2, 0, 2, 2, 2, 2, 0, + 2, 2, 2, 0, 2, 2, 2, 2, + 0, 2, 2, 2, 0, 2, 2, 2, + 2, 0, 2, 2, 2, 0, 2, 0, + 13, 0, 0, 2, 0, 2, 0, 0, + 2, 0, 0, 2, 0, 0, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 14, 2, 2, 0, 2, 0, 0, + 2, 2, 0, 2, 2, 0, 2, 2, + 0, 2, 2, 2, 0, 2, 2, 2, + 2, 0, 2, 2, 2, 0, 2, 2, + 2, 2, 0, 2, 2, 2, 0, 2, + 2, 2, 2, 0, 2, 2, 2, 0, + 2, 0, 15, 0, 0, 2, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, - 2, 0, 0, 2, 0, 14, 2 + 2, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 16, 6, 0, 6, 6, + 0, 6, 2, 0, 6, 2, 6, 0, + 6, 6, 6, 2, 0, 6, 2, 6, + 0, 6, 6, 6, 2, 0, 6, 2, + 6, 0, 6, 6, 6, 2, 0, 6, + 2, 6, 0, 6, 0, 17, 0, 0, + 2, 0, 2, 0, 0, 2, 0, 0, + 2, 0, 0, 2, 0, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 18, 19, + 2, 2, 0, 0, 0, 0, 2, 2, + 2, 2, 0, 2, 2, 0, 2, 2, + 2, 0, 2, 2, 2, 2, 0, 2, + 2, 2, 0, 2, 2, 2, 2, 0, + 2, 2, 2, 0, 2, 2, 2, 2, + 0, 2, 2, 2, 0, 2, 0, 20, + 0, 0, 2, 0, 2, 0, 0, 2, + 0, 0, 2, 0, 0, 2, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2 }; static const char _indic_syllable_machine_to_state_actions[] = { @@ -620,7 +955,11 @@ static const char _indic_syllable_machine_to_state_actions[] = { 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, 5, 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, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -642,7 +981,23 @@ static const char _indic_syllable_machine_to_state_actions[] = { 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, 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, 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 }; static const char _indic_syllable_machine_from_state_actions[] = { @@ -659,7 +1014,11 @@ static const char _indic_syllable_machine_from_state_actions[] = { 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, 6, 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, @@ -681,7 +1040,23 @@ static const char _indic_syllable_machine_from_state_actions[] = { 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, 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, 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 }; static const short _indic_syllable_machine_eof_trans[] = { @@ -689,73 +1064,92 @@ static const short _indic_syllable_machine_eof_trans[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 39, 39, 39, 39, 39, + 1, 1, 1, 1, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 77, 77, + 39, 39, 39, 39, 39, 39, 39, 39, + 77, 77, 77, 83, 83, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 0, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, - 237, 237, 237, 237, 237, 237, 237, 237, - 237, 237, 237, 237, 237, 237, 237, 237, - 237, 237, 237, 237, 237, 237, 237, 237, - 237, 237, 237, 237, 237, 237, 237, 237, - 237, 237, 237, 237, 237, 237, 237, 237, - 237, 237, 237, 237, 237, 237, 237, 237, - 237, 237, 237, 237, 237, 237, 237, 237, - 237, 237, 294, 121, 121 + 77, 77, 77, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 0, + 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 383, 316, 383, 384, + 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, + 383, 167, 167 }; -static const int indic_syllable_machine_start = 105; -static const int indic_syllable_machine_first_final = 105; +static const int indic_syllable_machine_start = 143; +static const int indic_syllable_machine_first_final = 143; static const int indic_syllable_machine_error = -1; -static const int indic_syllable_machine_en_main = 105; +static const int indic_syllable_machine_en_main = 143; #line 36 "../../src/hb-ot-shape-complex-indic-machine.rl" -#line 88 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 90 "../../src/hb-ot-shape-complex-indic-machine.rl" -#define process_syllable(func) \ +#define found_syllable(syllable_type) \ HB_STMT_START { \ - if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #func); \ + if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ for (unsigned int i = last; i < p+1; i++) \ - info[i].syllable() = syllable_serial; \ - PASTE (initial_reordering_, func) (plan, buffer, last, p+1); \ + info[i].syllable() = (syllable_serial << 4) | syllable_type; \ last = p+1; \ syllable_serial++; \ - if (unlikely (!syllable_serial)) syllable_serial++; \ + if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END static void -find_syllables (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer) +find_syllables (hb_buffer_t *buffer) { unsigned int p, pe, eof, ts, te, act; int cs; hb_glyph_info_t *info = buffer->info; -#line 759 "hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1153 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" { cs = indic_syllable_machine_start; ts = 0; @@ -763,16 +1157,16 @@ find_syllables (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer) act = 0; } -#line 110 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 111 "../../src/hb-ot-shape-complex-indic-machine.rl" p = 0; pe = eof = buffer->len; unsigned int last = 0; - uint8_t syllable_serial = 1; + unsigned int syllable_serial = 1; -#line 776 "hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1170 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" { int _slen; int _trans; @@ -782,11 +1176,11 @@ find_syllables (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer) goto _test_eof; _resume: switch ( _indic_syllable_machine_from_state_actions[cs] ) { - case 6: -#line 1 "NONE" + case 9: +#line 1 "../../src/hb-ot-shape-complex-indic-machine.rl" {ts = p;} break; -#line 790 "hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1184 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -805,63 +1199,99 @@ _eof_trans: switch ( _indic_syllable_machine_trans_actions[_trans] ) { case 2: -#line 1 "NONE" +#line 1 "../../src/hb-ot-shape-complex-indic-machine.rl" {te = p+1;} break; - case 9: -#line 81 "../../src/hb-ot-shape-complex-indic-machine.rl" - {te = p+1;{ process_syllable (consonant_syllable); }} - break; - case 11: -#line 82 "../../src/hb-ot-shape-complex-indic-machine.rl" - {te = p+1;{ process_syllable (vowel_syllable); }} - break; case 13: +#line 82 "../../src/hb-ot-shape-complex-indic-machine.rl" + {te = p+1;{ found_syllable (consonant_syllable); }} + break; + case 15: #line 83 "../../src/hb-ot-shape-complex-indic-machine.rl" - {te = p+1;{ process_syllable (standalone_cluster); }} + {te = p+1;{ found_syllable (vowel_syllable); }} + break; + case 20: +#line 84 "../../src/hb-ot-shape-complex-indic-machine.rl" + {te = p+1;{ found_syllable (standalone_cluster); }} + break; + case 17: +#line 85 "../../src/hb-ot-shape-complex-indic-machine.rl" + {te = p+1;{ found_syllable (broken_cluster); }} + break; + case 10: +#line 86 "../../src/hb-ot-shape-complex-indic-machine.rl" + {te = p+1;{ found_syllable (non_indic_cluster); }} + break; + case 12: +#line 82 "../../src/hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (consonant_syllable); }} + break; + case 14: +#line 83 "../../src/hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (vowel_syllable); }} + break; + case 19: +#line 84 "../../src/hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (standalone_cluster); }} + break; + case 16: +#line 85 "../../src/hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (broken_cluster); }} + break; + case 18: +#line 86 "../../src/hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (non_indic_cluster); }} + break; + case 1: +#line 82 "../../src/hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (consonant_syllable); }} + break; + case 3: +#line 83 "../../src/hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (vowel_syllable); }} break; case 7: #line 84 "../../src/hb-ot-shape-complex-indic-machine.rl" - {te = p+1;{ process_syllable (non_indic); }} - break; - case 8: -#line 81 "../../src/hb-ot-shape-complex-indic-machine.rl" - {te = p;p--;{ process_syllable (consonant_syllable); }} - break; - case 10: -#line 82 "../../src/hb-ot-shape-complex-indic-machine.rl" - {te = p;p--;{ process_syllable (vowel_syllable); }} - break; - case 12: -#line 83 "../../src/hb-ot-shape-complex-indic-machine.rl" - {te = p;p--;{ process_syllable (standalone_cluster); }} - break; - case 14: -#line 84 "../../src/hb-ot-shape-complex-indic-machine.rl" - {te = p;p--;{ process_syllable (non_indic); }} - break; - case 1: -#line 81 "../../src/hb-ot-shape-complex-indic-machine.rl" - {{p = ((te))-1;}{ process_syllable (consonant_syllable); }} - break; - case 3: -#line 82 "../../src/hb-ot-shape-complex-indic-machine.rl" - {{p = ((te))-1;}{ process_syllable (vowel_syllable); }} + {{p = ((te))-1;}{ found_syllable (standalone_cluster); }} break; case 4: -#line 83 "../../src/hb-ot-shape-complex-indic-machine.rl" - {{p = ((te))-1;}{ process_syllable (standalone_cluster); }} +#line 85 "../../src/hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (broken_cluster); }} break; -#line 856 "hb-ot-shape-complex-indic-machine.hh.tmp" + case 5: +#line 1 "../../src/hb-ot-shape-complex-indic-machine.rl" + { switch( act ) { + case 4: + {{p = ((te))-1;} found_syllable (broken_cluster); } + break; + case 5: + {{p = ((te))-1;} found_syllable (non_indic_cluster); } + break; + } + } + break; + case 6: +#line 1 "../../src/hb-ot-shape-complex-indic-machine.rl" + {te = p+1;} +#line 85 "../../src/hb-ot-shape-complex-indic-machine.rl" + {act = 4;} + break; + case 11: +#line 1 "../../src/hb-ot-shape-complex-indic-machine.rl" + {te = p+1;} +#line 86 "../../src/hb-ot-shape-complex-indic-machine.rl" + {act = 5;} + break; +#line 1286 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" } _again: switch ( _indic_syllable_machine_to_state_actions[cs] ) { - case 5: -#line 1 "NONE" + case 8: +#line 1 "../../src/hb-ot-shape-complex-indic-machine.rl" {ts = 0;} break; -#line 865 "hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1295 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" } if ( ++p != pe ) @@ -877,7 +1307,7 @@ _again: } -#line 119 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 120 "../../src/hb-ot-shape-complex-indic-machine.rl" } diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl index b6a372e4ab6c..b74546650a05 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl @@ -62,44 +62,45 @@ z = ZWJ|ZWNJ; # is_joiner h = H | Coeng; # is_halant_or_coeng reph = (Ra H | Repha); # possible reph -cn = c.n?; +cn = c.ZWJ?.n?; forced_rakar = ZWJ H ZWJ Ra; matra_group = z{0,3}.M.N?.(H | forced_rakar)?; -syllable_tail = (SM.ZWNJ?)? (Coeng (cn|V))? (VD VD?)?; +syllable_tail = (Coeng (cn|V))? (SM.ZWNJ?)? (VD VD?)?; place_holder = NBSP | DOTTEDCIRCLE; -halant_group = (z?.h.ZWJ?); +halant_group = (z?.h.(ZWJ.N?)?); final_halant_group = halant_group | h.ZWNJ; -halant_or_matra_group = (final_halant_group | matra_group{0,4}); +halant_or_matra_group = (final_halant_group | (h.ZWJ)? matra_group{0,4}); consonant_syllable = Repha? (cn.halant_group){0,4} cn A? halant_or_matra_group? syllable_tail; vowel_syllable = reph? V.n? (ZWJ | (halant_group.cn){0,4} halant_or_matra_group? syllable_tail); standalone_cluster = reph? place_holder.n? (halant_group.cn){0,4} halant_or_matra_group? syllable_tail; +broken_cluster = n? (halant_group.cn){0,4} halant_or_matra_group syllable_tail; other = any; main := |* - consonant_syllable => { process_syllable (consonant_syllable); }; - vowel_syllable => { process_syllable (vowel_syllable); }; - standalone_cluster => { process_syllable (standalone_cluster); }; - other => { process_syllable (non_indic); }; + consonant_syllable => { found_syllable (consonant_syllable); }; + vowel_syllable => { found_syllable (vowel_syllable); }; + standalone_cluster => { found_syllable (standalone_cluster); }; + broken_cluster => { found_syllable (broken_cluster); }; + other => { found_syllable (non_indic_cluster); }; *|; }%% -#define process_syllable(func) \ +#define found_syllable(syllable_type) \ HB_STMT_START { \ - if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #func); \ + if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ for (unsigned int i = last; i < p+1; i++) \ - info[i].syllable() = syllable_serial; \ - PASTE (initial_reordering_, func) (plan, buffer, last, p+1); \ + info[i].syllable() = (syllable_serial << 4) | syllable_type; \ last = p+1; \ syllable_serial++; \ - if (unlikely (!syllable_serial)) syllable_serial++; \ + if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END static void -find_syllables (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer) +find_syllables (hb_buffer_t *buffer) { unsigned int p, pe, eof, ts, te, act; int cs; @@ -113,7 +114,7 @@ find_syllables (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer) pe = eof = buffer->len; unsigned int last = 0; - uint8_t syllable_serial = 1; + unsigned int syllable_serial = 1; %%{ write exec; }%% diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh index 79daba593843..91b0be5c32b1 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh @@ -300,7 +300,7 @@ is_halant_or_coeng (const hb_glyph_info_t &info) } static inline void -set_indic_properties (hb_glyph_info_t &info) +set_indic_properties (hb_glyph_info_t &info) { hb_codepoint_t u = info.codepoint; unsigned int type = get_indic_categories (u); diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc index 6fbd5c8129e5..6a87c1e3ff5e 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc @@ -202,6 +202,10 @@ enum { INDIC_BASIC_FEATURES = INIT /* Don't forget to update this! */ }; +static void +setup_syllables (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void initial_reordering (const hb_ot_shape_plan_t *plan, hb_font_t *font, @@ -216,6 +220,9 @@ collect_features_indic (hb_ot_shape_planner_t *plan) { hb_ot_map_builder_t *map = &plan->map; + /* Do this before any lookups have been applied. */ + map->add_gsub_pause (setup_syllables); + map->add_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. */ @@ -254,10 +261,11 @@ struct would_substitute_feature_t inline bool would_substitute (hb_codepoint_t *glyphs, unsigned int glyphs_count, + bool zero_context, hb_face_t *face) const { for (unsigned int i = 0; i < count; i++) - if (hb_ot_layout_would_substitute_lookup_fast (face, glyphs, glyphs_count, lookups[i].index)) + if (hb_ot_layout_would_substitute_lookup_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context)) return true; return false; } @@ -340,13 +348,25 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan, hb_codepoint_t *glyphs, unsigned int glyphs_len, hb_face_t *face) { - if (indic_plan->pref.would_substitute (glyphs, glyphs_len, face)) return POS_BELOW_C; - if (indic_plan->blwf.would_substitute (glyphs, glyphs_len, face)) return POS_BELOW_C; - if (indic_plan->pstf.would_substitute (glyphs, glyphs_len, face)) return POS_POST_C; + bool zero_context = indic_plan->is_old_spec ? false : true; + if (indic_plan->pref.would_substitute (glyphs, glyphs_len, zero_context, face)) return POS_BELOW_C; + if (indic_plan->blwf.would_substitute (glyphs, glyphs_len, zero_context, face)) return POS_BELOW_C; + if (indic_plan->pstf.would_substitute (glyphs, glyphs_len, zero_context, face)) return POS_POST_C; return POS_BASE_C; } +enum syllable_type_t { + consonant_syllable, + vowel_syllable, + standalone_cluster, + broken_cluster, + non_indic_cluster, +}; + +#include "hb-ot-shape-complex-indic-machine.hh" + + static void setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, @@ -363,6 +383,14 @@ setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, set_indic_properties (buffer->info[i]); } +static void +setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) +{ + find_syllables (buffer); +} + static int compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) { @@ -445,7 +473,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, hb_buffer has_reph = true; }; - switch (indic_plan->config->base_pos == BASE_POS_LAST) + switch (indic_plan->config->base_pos) { case BASE_POS_LAST: { @@ -694,13 +722,12 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, hb_buffer info[i].mask |= mask; } - /* XXX This will not match for old-Indic spec since the Halant-Ra order is reversed already. */ if (indic_plan->mask_array[PREF] && base + 2 < end) { /* Find a Halant,Ra sequence and mark it for pre-base reordering processing. */ for (unsigned int i = base + 1; i + 1 < end; i++) - if (is_halant_or_coeng (info[i]) && - info[i + 1].indic_category() == OT_Ra) + if (is_halant_or_coeng (info[i + (indic_plan->is_old_spec ? 1 : 0)]) && + info[i + (indic_plan->is_old_spec ? 0 : 1)].indic_category() == OT_Ra) { info[i++].mask |= indic_plan->mask_array[PREF]; info[i++].mask |= indic_plan->mask_array[PREF]; @@ -769,15 +796,87 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan, } static void -initial_reordering_non_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_buffer_t *buffer HB_UNUSED, - unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) +{ + /* We already inserted dotted-circles, so just call the standalone_cluster. */ + initial_reordering_standalone_cluster (plan, buffer, start, end); +} + +static void +initial_reordering_non_indic_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_buffer_t *buffer HB_UNUSED, + unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) { /* Nothing to do right now. If we ever switch to using the output * buffer in the reordering process, we'd need to next_glyph() here. */ } -#include "hb-ot-shape-complex-indic-machine.hh" + +static void +initial_reordering_syllable (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) +{ + syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); + switch (syllable_type) { + case consonant_syllable: initial_reordering_consonant_syllable (plan, buffer, start, end); return; + case vowel_syllable: initial_reordering_vowel_syllable (plan, buffer, start, end); return; + case standalone_cluster: initial_reordering_standalone_cluster (plan, buffer, start, end); return; + case broken_cluster: initial_reordering_broken_cluster (plan, buffer, start, end); return; + case non_indic_cluster: initial_reordering_non_indic_cluster (plan, buffer, start, end); return; + } +} + +static inline void +insert_dotted_circles (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) +{ + /* Note: This loop is extra overhead, but should not be measurable. */ + bool has_broken_syllables = false; + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) { + has_broken_syllables = true; + break; + } + if (likely (!has_broken_syllables)) + return; + + + hb_codepoint_t dottedcircle_glyph; + if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph)) + return; + + hb_glyph_info_t dottedcircle; + dottedcircle.codepoint = 0x25CC; + set_indic_properties (dottedcircle); + dottedcircle.codepoint = dottedcircle_glyph; + + buffer->clear_output (); + + buffer->idx = 0; + unsigned int last_syllable = 0; + while (buffer->idx < buffer->len) + { + unsigned int syllable = buffer->cur().syllable(); + syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F); + if (unlikely (last_syllable != syllable && syllable_type == broken_cluster)) + { + hb_glyph_info_t info = dottedcircle; + info.cluster = buffer->cur().cluster; + info.mask = buffer->cur().mask; + info.syllable() = buffer->cur().syllable(); + buffer->output_info (info); + last_syllable = syllable; + } + buffer->next_glyph (); + } + + buffer->swap_buffers (); +} static void initial_reordering (const hb_ot_shape_plan_t *plan, @@ -785,7 +884,20 @@ initial_reordering (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer) { update_consonant_positions (plan, font, buffer); - find_syllables (plan, buffer); + insert_dotted_circles (plan, font, buffer); + + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + if (unlikely (!count)) return; + unsigned int last = 0; + unsigned int last_syllable = info[0].syllable(); + for (unsigned int i = 1; i < count; i++) + if (last_syllable != info[i].syllable()) { + initial_reordering_syllable (plan, buffer, last, i); + last = i; + last_syllable = info[last].syllable(); + } + initial_reordering_syllable (plan, buffer, last, count); } static void @@ -829,11 +941,11 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, /* If we lost track of base, alas, position before last thingy. */ unsigned int new_pos = base == end ? base - 2 : base - 1; - /* Malayalam does not have "half" forms or explicit virama forms. - * The glyphs formed by 'half' are Chillus. We want to position - * matra after them all. + /* Malayalam / Tamil do not have "half" forms or explicit virama forms. + * The glyphs formed by 'half' are Chillus or ligated explicit viramas. + * We want to position matra after them. */ - if (buffer->props.script != HB_SCRIPT_MALAYALAM) + if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL) { while (new_pos > start && !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H) | FLAG (OT_Coeng))))) @@ -853,7 +965,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, new_pos = start; /* No move. */ } - if (start < new_pos) + if (start < new_pos && info[new_pos].indic_position () != POS_PRE_M) { /* Now go see if there's actually any matras... */ for (unsigned int i = new_pos; i > start; i--) @@ -1109,7 +1221,7 @@ final_reordering (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer) { unsigned int count = buffer->len; - if (!count) return; + if (unlikely (!count)) return; hb_glyph_info_t *info = buffer->info; unsigned int last = 0; @@ -1122,11 +1234,21 @@ final_reordering (const hb_ot_shape_plan_t *plan, } final_reordering_syllable (plan, buffer, last, count); + /* Zero syllables now... */ + for (unsigned int i = 0; i < count; i++) + info[i].syllable() = 0; + HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category); HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position); } +static hb_ot_shape_normalization_mode_t +normalization_preference_indic (const hb_ot_shape_plan_t *plan) +{ + return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; +} + const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = { "indic", @@ -1135,7 +1257,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = data_create_indic, data_destroy_indic, NULL, /* preprocess_text */ - NULL, /* normalization_preference */ + normalization_preference_indic, setup_masks_indic, false, /* zero_width_attached_marks */ }; diff --git a/gfx/harfbuzz/src/hb-ot-shape-fallback-private.hh b/gfx/harfbuzz/src/hb-ot-shape-fallback-private.hh index be96c4f195a8..5e9cb061780e 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-fallback-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-fallback-private.hh @@ -36,4 +36,9 @@ HB_INTERNAL void _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); +HB_INTERNAL void _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); + + #endif /* HB_OT_SHAPE_FALLBACK_PRIVATE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc index 56a3e7ae11e8..eb7777e213c7 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc @@ -26,28 +26,55 @@ #include "hb-ot-shape-fallback-private.hh" -static void -zero_mark_advances (hb_buffer_t *buffer, - unsigned int start, - unsigned int end) -{ - for (unsigned int i = start; i < end; i++) - if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) - { - buffer->pos[i].x_advance = 0; - buffer->pos[i].y_advance = 0; - } -} - static unsigned int -recategorize_combining_class (unsigned int modified_combining_class) +recategorize_combining_class (hb_codepoint_t u, + unsigned int klass) { - if (modified_combining_class >= 200) - return modified_combining_class; + if (klass >= 200) + return klass; - /* This should be kept in sync with modified combining class mapping - * from hb-unicode.cc. */ - switch (modified_combining_class) + /* Thai / Lao need some per-character work. */ + if ((u & ~0xFF) == 0x0E00) + { + if (unlikely (klass == 0)) + { + switch (u) + { + case 0x0E31: + case 0x0E34: + case 0x0E35: + case 0x0E36: + case 0x0E37: + case 0x0E47: + case 0x0E4C: + case 0x0E4D: + case 0x0E4E: + klass = HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT; + break; + + case 0x0EB1: + case 0x0EB4: + case 0x0EB5: + case 0x0EB6: + case 0x0EB7: + case 0x0EBB: + case 0x0ECC: + case 0x0ECD: + klass = HB_UNICODE_COMBINING_CLASS_ABOVE; + break; + + case 0x0EBC: + klass = HB_UNICODE_COMBINING_CLASS_BELOW; + break; + } + } else { + /* Thai virama is below-right */ + if (u == 0x0E3A) + klass = HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT; + } + } + + switch (klass) { /* Hebrew */ @@ -101,23 +128,20 @@ recategorize_combining_class (unsigned int modified_combining_class) /* Thai */ - /* Note: to be useful we also need to position U+0E3A that has ccc=9 (virama). - * But viramas can be both above and below based on the codepoint / script. */ - case HB_MODIFIED_COMBINING_CLASS_CCC103: /* sara u / sara uu */ - return HB_UNICODE_COMBINING_CLASS_BELOW; + return HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT; case HB_MODIFIED_COMBINING_CLASS_CCC107: /* mai */ - return HB_UNICODE_COMBINING_CLASS_ABOVE; + return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT; /* Lao */ case HB_MODIFIED_COMBINING_CLASS_CCC118: /* sign u / sign uu */ - return HB_UNICODE_COMBINING_CLASS_BELOW; + return HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT; case HB_MODIFIED_COMBINING_CLASS_CCC122: /* mai */ - return HB_UNICODE_COMBINING_CLASS_ABOVE; + return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT; /* Tibetan */ @@ -133,7 +157,35 @@ recategorize_combining_class (unsigned int modified_combining_class) } - return modified_combining_class; + return klass; +} + +void +_hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) +{ + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { + unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&buffer->info[i]); + combining_class = recategorize_combining_class (buffer->info[i].codepoint, combining_class); + _hb_glyph_info_set_modified_combining_class (&buffer->info[i], combining_class); + } +} + + +static void +zero_mark_advances (hb_buffer_t *buffer, + unsigned int start, + unsigned int end) +{ + for (unsigned int i = start; i < end; i++) + if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + { + buffer->pos[i].x_advance = 0; + buffer->pos[i].y_advance = 0; + } } static inline void @@ -171,6 +223,7 @@ position_mark (const hb_ot_shape_plan_t *plan, } /* Fall through */ + default: case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW: case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE: case HB_UNICODE_COMBINING_CLASS_BELOW: @@ -234,6 +287,7 @@ position_around_base (const hb_ot_shape_plan_t *plan, unsigned int base, unsigned int end) { + hb_direction_t horiz_dir = HB_DIRECTION_INVALID; hb_glyph_extents_t base_extents; if (!font->get_glyph_extents (buffer->info[base].codepoint, &base_extents)) @@ -245,33 +299,61 @@ position_around_base (const hb_ot_shape_plan_t *plan, base_extents.x_bearing += buffer->pos[base].x_offset; base_extents.y_bearing += buffer->pos[base].y_offset; - /* XXX Handle ligature component positioning... */ - HB_UNUSED bool is_ligature = is_a_ligature (buffer->info[base]); + unsigned int lig_id = get_lig_id (buffer->info[base]); + unsigned int num_lig_components = get_lig_num_comps (buffer->info[base]); hb_position_t x_offset = 0, y_offset = 0; if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) { x_offset -= buffer->pos[base].x_advance; y_offset -= buffer->pos[base].y_advance; } + + hb_glyph_extents_t component_extents = base_extents; + unsigned int last_lig_component = (unsigned int) -1; unsigned int last_combining_class = 255; hb_glyph_extents_t cluster_extents; for (unsigned int i = base + 1; i < end; i++) - if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i])) { - unsigned int this_combining_class = recategorize_combining_class (_hb_glyph_info_get_modified_combining_class (&buffer->info[i])); - if (this_combining_class != last_combining_class) - cluster_extents = base_extents; + if (num_lig_components > 1) { + unsigned int this_lig_id = get_lig_id (buffer->info[i]); + unsigned int this_lig_component = get_lig_comp (buffer->info[i]) - 1; + /* Conditions for attaching to the last component. */ + if (!lig_id || lig_id != this_lig_id || this_lig_component >= num_lig_components) + this_lig_component = num_lig_components - 1; + if (last_lig_component != this_lig_component) + { + last_lig_component = this_lig_component; + last_combining_class = 255; + component_extents = base_extents; + if (unlikely (horiz_dir == HB_DIRECTION_INVALID)) { + if (HB_DIRECTION_IS_HORIZONTAL (plan->props.direction)) + horiz_dir = plan->props.direction; + else + horiz_dir = hb_script_get_horizontal_direction (plan->props.script); + } + if (horiz_dir == HB_DIRECTION_LTR) + component_extents.x_bearing += (this_lig_component * component_extents.width) / num_lig_components; + else + component_extents.x_bearing += ((num_lig_components - 1 - this_lig_component) * component_extents.width) / num_lig_components; + component_extents.width /= num_lig_components; + } + } - position_mark (plan, font, buffer, base_extents, i, this_combining_class); + unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&buffer->info[i]); + if (last_combining_class != this_combining_class) + { + last_combining_class = this_combining_class; + cluster_extents = component_extents; + } + + position_mark (plan, font, buffer, cluster_extents, i, this_combining_class); buffer->pos[i].x_advance = 0; buffer->pos[i].y_advance = 0; buffer->pos[i].x_offset += x_offset; buffer->pos[i].y_offset += y_offset; - /* combine cluster extents. */ - - last_combining_class = this_combining_class; } else { if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) { x_offset -= buffer->pos[i].x_advance; @@ -281,8 +363,6 @@ position_around_base (const hb_ot_shape_plan_t *plan, y_offset += buffer->pos[i].y_advance; } } - - } static inline void @@ -297,14 +377,17 @@ position_cluster (const hb_ot_shape_plan_t *plan, /* Find the base glyph */ for (unsigned int i = start; i < end; i++) - if (is_a_ligature (buffer->info[i]) || - !(FLAG (_hb_glyph_info_get_general_category (&buffer->info[i])) & - (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | - FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | - FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))) + if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[i]))) { - position_around_base (plan, font, buffer, i, end); - break; + /* Find mark glyphs */ + unsigned int j; + for (j = i + 1; j < end; j++) + if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[j]))) + break; + + position_around_base (plan, font, buffer, i, j); + + i = j - 1; } } diff --git a/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh b/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh index 462b87dd92cc..c5fcbea6c2e0 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh @@ -38,6 +38,7 @@ enum hb_ot_shape_normalization_mode_t { HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED, HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */ + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* always fully decomposes and then recompose back */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL, /* including base-to-base composition */ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS diff --git a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc index 93dd00cd14f9..18a3f3f441cf 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc @@ -130,10 +130,7 @@ compose_func (hb_unicode_funcs_t *unicode, hb_codepoint_t *ab) { /* XXX, this belongs to indic normalizer. */ - if ((FLAG (unicode->general_category (a)) & - (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | - FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | - FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))) + if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (unicode->general_category (a))) return false; /* XXX, add composition-exclusion exceptions to Indic shaper. */ if (a == 0x09AF && b == 0x09BC) { *ab = 0x09DF; return true; } @@ -414,10 +411,10 @@ decompose_multi_char_cluster (hb_font_t *font, hb_buffer_t *buffer, unsigned int } static inline bool -decompose_cluster (hb_font_t *font, hb_buffer_t *buffer, bool recompose, unsigned int end) +decompose_cluster (hb_font_t *font, hb_buffer_t *buffer, bool short_circuit, unsigned int end) { if (likely (buffer->idx + 1 == end)) - return decompose_current_character (font, buffer, recompose); + return decompose_current_character (font, buffer, short_circuit); else return decompose_multi_char_cluster (font, buffer, end); } @@ -437,7 +434,8 @@ void _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer, hb_ot_shape_normalization_mode_t mode) { - bool recompose = mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED; + bool short_circuit = mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED && + mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; bool can_use_recompose = false; unsigned int count; @@ -459,7 +457,7 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer, if (buffer->cur().cluster != buffer->info[end].cluster) break; - can_use_recompose = decompose_cluster (font, buffer, recompose, end) || can_use_recompose; + can_use_recompose = decompose_cluster (font, buffer, short_circuit, end) || can_use_recompose; } buffer->swap_buffers (); @@ -495,7 +493,7 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer, } - if (!recompose) + if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED) return; /* Third round, recompose */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-private.hh b/gfx/harfbuzz/src/hb-ot-shape-private.hh index f85604554a9a..c4c368db7c61 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-private.hh @@ -95,6 +95,12 @@ _hb_glyph_info_get_general_category (const hb_glyph_info_t *info) return (hb_unicode_general_category_t) (info->unicode_props0() & 0x7F); } +inline void +_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info, unsigned int modified_class) +{ + info->unicode_props1() = modified_class; +} + inline unsigned int _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info) { diff --git a/gfx/harfbuzz/src/hb-ot-shape.cc b/gfx/harfbuzz/src/hb-ot-shape.cc index 29076cf4ddee..313766af3c2f 100644 --- a/gfx/harfbuzz/src/hb-ot-shape.cc +++ b/gfx/harfbuzz/src/hb-ot-shape.cc @@ -234,15 +234,41 @@ hb_set_unicode_props (hb_buffer_t *buffer) _hb_glyph_info_set_unicode_props (&buffer->info[i], buffer->unicode); } +static void +hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) +{ + if (buffer->context_len[0] || + _hb_glyph_info_get_general_category (&buffer->info[0]) != + HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + return; + + hb_codepoint_t dottedcircle_glyph; + if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph)) + return; + + hb_glyph_info_t dottedcircle; + dottedcircle.codepoint = 0x25CC; + _hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode); + + buffer->clear_output (); + + buffer->idx = 0; + hb_glyph_info_t info = dottedcircle; + info.cluster = buffer->cur().cluster; + info.mask = buffer->cur().mask; + buffer->output_info (info); + while (buffer->idx < buffer->len) + buffer->next_glyph (); + + buffer->swap_buffers (); +} + static void hb_form_clusters (hb_buffer_t *buffer) { unsigned int count = buffer->len; for (unsigned int i = 1; i < count; i++) - if (FLAG (_hb_glyph_info_get_general_category (&buffer->info[i])) & - (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | - FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | - FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))) + if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[i]))) buffer->merge_clusters (i - 1, i + 1); } @@ -316,6 +342,16 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer) buffer->info[i].codepoint = buffer->info[i].glyph_index(); } +static inline void +hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) +{ + unsigned int count = c->buffer->len; + for (unsigned int i = 0; i < count; i++) + c->buffer->info[i].glyph_props() = _hb_glyph_info_get_general_category (&c->buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ? + HB_OT_LAYOUT_GLYPH_CLASS_MARK : + HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH; +} + static inline void hb_ot_substitute_default (hb_ot_shape_context_t *c) { @@ -333,22 +369,15 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c) hb_ot_shape_setup_masks (c); + /* This is unfortunate to go here, but necessary... */ + if (!hb_ot_layout_has_positioning (c->face)) + _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, c->buffer); + hb_ot_map_glyphs_fast (c->buffer); HB_BUFFER_DEALLOCATE_VAR (c->buffer, glyph_index); } -static inline void -hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) -{ - unsigned int count = c->buffer->len; - for (unsigned int i = 0; i < count; i++) - c->buffer->info[i].glyph_props() = _hb_glyph_info_get_general_category (&c->buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ? - HB_OT_LAYOUT_GLYPH_CLASS_MARK : - HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH; -} - - static inline void hb_ot_substitute_complex (hb_ot_shape_context_t *c) { @@ -357,8 +386,7 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c) if (!hb_ot_layout_has_glyph_classes (c->face)) hb_synthesize_glyph_classes (c); - if (hb_ot_layout_has_substitution (c->face)) - c->plan->substitute (c->font, c->buffer); + c->plan->substitute (c->font, c->buffer); hb_ot_layout_substitute_finish (c->font, c->buffer); @@ -486,14 +514,18 @@ hb_ot_position (hb_ot_shape_context_t *c) static void hb_ot_hide_zerowidth (hb_ot_shape_context_t *c) { - hb_codepoint_t space; - if (!c->font->get_glyph (' ', 0, &space)) - return; /* No point! */ + hb_codepoint_t space = 0; unsigned int count = c->buffer->len; for (unsigned int i = 0; i < count; i++) if (unlikely (!is_a_ligature (c->buffer->info[i]) && - _hb_glyph_info_is_zero_width (&c->buffer->info[i]))) { + _hb_glyph_info_is_zero_width (&c->buffer->info[i]))) + { + if (!space) { + /* We assume that the space glyph is not gid0. */ + if (unlikely (!c->font->get_glyph (' ', 0, &space)) || !space) + return; /* No point! */ + } c->buffer->info[i].codepoint = space; c->buffer->pos[i].x_advance = 0; c->buffer->pos[i].y_advance = 0; @@ -517,6 +549,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) c->buffer->clear_output (); hb_set_unicode_props (c->buffer); + hb_insert_dotted_circle (c->buffer, c->font); hb_form_clusters (c->buffer); hb_ensure_native_direction (c->buffer); @@ -556,7 +589,7 @@ hb_ot_map_glyphs_dumb (hb_font_t *font, { unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) - font->get_glyph (buffer->cur().codepoint, 0, &buffer->cur().codepoint); + font->get_glyph (buffer->info[i].codepoint, 0, &buffer->info[i].codepoint); } void diff --git a/gfx/harfbuzz/src/hb-private.hh b/gfx/harfbuzz/src/hb-private.hh index 8655020517b6..42c025909ae9 100644 --- a/gfx/harfbuzz/src/hb-private.hh +++ b/gfx/harfbuzz/src/hb-private.hh @@ -77,6 +77,8 @@ static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; } #undef ARRAY_LENGTH template static inline unsigned int ARRAY_LENGTH (const Type (&a)[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]))) #define HB_STMT_START do #define HB_STMT_END while (0) @@ -544,7 +546,7 @@ _hb_debug (unsigned int level, #define DEBUG_LEVEL(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT)) #define DEBUG(WHAT) (DEBUG_LEVEL (WHAT, 0)) -template inline void +template static inline void _hb_debug_msg_va (const char *what, const void *obj, const char *func, @@ -581,12 +583,13 @@ _hb_debug_msg_va (const char *what, fprintf (stderr, " " VRBAR LBAR); if (func) { - /* If there's a class name, just write that. */ - const char *dotdot = strstr (func, "::"); + /* Skip return type */ const char *space = strchr (func, ' '); - if (space && dotdot && space < dotdot) + if (space) func = space + 1; - unsigned int func_len = dotdot ? dotdot - func : strlen (func); + /* Skip parameter list */ + const char *paren = strchr (func, '('); + unsigned int func_len = paren ? paren - func : strlen (func); fprintf (stderr, "%.*s: ", func_len, func); } @@ -605,7 +608,7 @@ _hb_debug_msg_va<0> (const char *what HB_UNUSED, const char *message HB_UNUSED, va_list ap HB_UNUSED) {} -template inline void +template static inline void _hb_debug_msg (const char *what, const void *obj, const char *func, @@ -614,7 +617,7 @@ _hb_debug_msg (const char *what, int level_dir, const char *message, ...) HB_PRINTF_FUNC(7, 8); -template inline void +template static inline void _hb_debug_msg (const char *what, const void *obj, const char *func, diff --git a/gfx/harfbuzz/src/hb-shape.cc b/gfx/harfbuzz/src/hb-shape.cc index 5aa587bc35f3..4d6482362e2e 100644 --- a/gfx/harfbuzz/src/hb-shape.cc +++ b/gfx/harfbuzz/src/hb-shape.cc @@ -1,5 +1,6 @@ /* * Copyright © 2009 Red Hat, Inc. + * Copyright © 2012 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -22,6 +23,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod */ #include "hb-private.hh" @@ -32,6 +34,172 @@ #include "hb-font-private.hh" +static void +parse_space (const char **pp, const char *end) +{ + char c; +#define ISSPACE(c) ((c)==' '||(c)=='\f'||(c)=='\n'||(c)=='\r'||(c)=='\t'||(c)=='\v') + while (*pp < end && (c = **pp, ISSPACE (c))) + (*pp)++; +#undef ISSPACE +} + +static hb_bool_t +parse_char (const char **pp, const char *end, char c) +{ + parse_space (pp, end); + + if (*pp == end || **pp != c) + return false; + + (*pp)++; + return true; +} + +static hb_bool_t +parse_uint (const char **pp, const char *end, unsigned int *pv) +{ + char buf[32]; + strncpy (buf, *pp, end - *pp); + buf[ARRAY_LENGTH (buf) - 1] = '\0'; + + char *p = buf; + char *pend = p; + unsigned int v; + + v = strtol (p, &pend, 0); + + if (p == pend) + return false; + + *pv = v; + *pp += pend - p; + return true; +} + +static hb_bool_t +parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) +{ + if (parse_char (pp, end, '-')) + feature->value = 0; + else { + parse_char (pp, end, '+'); + feature->value = 1; + } + + return true; +} + +static hb_bool_t +parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature) +{ + const char *p = *pp; + char c; + + parse_space (pp, end); + +#define ISALNUM(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z') || ('0' <= (c) && (c) <= '9')) + while (*pp < end && (c = **pp, ISALNUM(c))) + (*pp)++; +#undef ISALNUM + + if (p == *pp) + return false; + + feature->tag = hb_tag_from_string (p, *pp - p); + return true; +} + +static hb_bool_t +parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) +{ + parse_space (pp, end); + + hb_bool_t has_start; + + feature->start = 0; + feature->end = (unsigned int) -1; + + if (!parse_char (pp, end, '[')) + return true; + + has_start = parse_uint (pp, end, &feature->start); + + if (parse_char (pp, end, ':')) { + parse_uint (pp, end, &feature->end); + } else { + if (has_start) + feature->end = feature->start + 1; + } + + return parse_char (pp, end, ']'); +} + +static hb_bool_t +parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature) +{ + return !parse_char (pp, end, '=') || parse_uint (pp, end, &feature->value); +} + + +static hb_bool_t +parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) +{ + return parse_feature_value_prefix (pp, end, feature) && + parse_feature_tag (pp, end, feature) && + parse_feature_indices (pp, end, feature) && + parse_feature_value_postfix (pp, end, feature) && + *pp == end; +} + +hb_bool_t +hb_feature_from_string (const char *str, int len, + hb_feature_t *feature) +{ + if (len < 0) + len = strlen (str); + + return parse_one_feature (&str, str + len, feature); +} + +void +hb_feature_to_string (hb_feature_t *feature, + char *buf, unsigned int size) +{ + if (unlikely (!size)) return; + + char s[128]; + unsigned int len = 0; + if (feature->value == 0) + s[len++] = '-'; + hb_tag_to_string (feature->tag, s + len); + len += 4; + while (len && s[len - 1] == ' ') + len--; + if (feature->start != 0 || feature->start != (unsigned int) -1) + { + s[len++] = '['; + if (feature->start) + len += snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->start); + if (feature->end != feature->start + 1) { + s[len++] = ':'; + if (feature->end != (unsigned int) -1) + len += snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->end); + } + s[len++] = ']'; + } + if (feature->value > 1) + { + s[len++] = '='; + len += snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->value); + } + assert (len < ARRAY_LENGTH (s)); + len = MIN (len, size - 1); + memcpy (buf, s, len); + s[len] = '\0'; +} + + static const char **static_shaper_list; static @@ -85,11 +253,16 @@ hb_shape_full (hb_font_t *font, if (unlikely (!buffer->len)) return true; + assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE); + buffer->guess_properties (); hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list); hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features); hb_shape_plan_destroy (shape_plan); + + if (res) + buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; return res; } diff --git a/gfx/harfbuzz/src/hb-shape.h b/gfx/harfbuzz/src/hb-shape.h index 84bf3e76e4de..90a188d2a9c8 100644 --- a/gfx/harfbuzz/src/hb-shape.h +++ b/gfx/harfbuzz/src/hb-shape.h @@ -1,5 +1,6 @@ /* * Copyright © 2009 Red Hat, Inc. + * Copyright © 2012 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -22,6 +23,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod */ #ifndef HB_H_IN @@ -45,6 +47,17 @@ typedef struct hb_feature_t { unsigned int end; } hb_feature_t; +/* len=-1 means str is NUL-terminated */ +hb_bool_t +hb_feature_from_string (const char *str, int len, + hb_feature_t *feature); + +/* something like 128 bytes is more than enough. + * nul-terminates. */ +void +hb_feature_to_string (hb_feature_t *feature, + char *buf, unsigned int size); + void hb_shape (hb_font_t *font, diff --git a/gfx/harfbuzz/src/hb-shaper-list.hh b/gfx/harfbuzz/src/hb-shaper-list.hh index 8e67dbdec63d..6c02de46d2cf 100644 --- a/gfx/harfbuzz/src/hb-shaper-list.hh +++ b/gfx/harfbuzz/src/hb-shaper-list.hh @@ -47,4 +47,8 @@ HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */ HB_SHAPER_IMPLEMENT (old) #endif +#ifdef HAVE_ICU_LE +HB_SHAPER_IMPLEMENT (icu_le) +#endif + HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */ diff --git a/gfx/harfbuzz/src/hb-ucdn.cc b/gfx/harfbuzz/src/hb-ucdn.cc new file mode 100644 index 000000000000..35063043fd6c --- /dev/null +++ b/gfx/harfbuzz/src/hb-ucdn.cc @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2012 Grigori Goronzy + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hb-private.hh" + +#include "hb-unicode-private.hh" + +#include "ucdn.h" + +static const hb_script_t ucdn_script_translate[] = +{ + HB_SCRIPT_COMMON, + HB_SCRIPT_LATIN, + HB_SCRIPT_GREEK, + HB_SCRIPT_CYRILLIC, + HB_SCRIPT_ARMENIAN, + HB_SCRIPT_HEBREW, + HB_SCRIPT_ARABIC, + HB_SCRIPT_SYRIAC, + HB_SCRIPT_THAANA, + HB_SCRIPT_DEVANAGARI, + HB_SCRIPT_BENGALI, + HB_SCRIPT_GURMUKHI, + HB_SCRIPT_GUJARATI, + HB_SCRIPT_ORIYA, + HB_SCRIPT_TAMIL, + HB_SCRIPT_TELUGU, + HB_SCRIPT_KANNADA, + HB_SCRIPT_MALAYALAM, + HB_SCRIPT_SINHALA, + HB_SCRIPT_THAI, + HB_SCRIPT_LAO, + HB_SCRIPT_TIBETAN, + HB_SCRIPT_MYANMAR, + HB_SCRIPT_GEORGIAN, + HB_SCRIPT_HANGUL, + HB_SCRIPT_ETHIOPIC, + HB_SCRIPT_CHEROKEE, + HB_SCRIPT_CANADIAN_ABORIGINAL, + HB_SCRIPT_OGHAM, + HB_SCRIPT_RUNIC, + HB_SCRIPT_KHMER, + HB_SCRIPT_MONGOLIAN, + HB_SCRIPT_HIRAGANA, + HB_SCRIPT_KATAKANA, + HB_SCRIPT_BOPOMOFO, + HB_SCRIPT_HAN, + HB_SCRIPT_YI, + HB_SCRIPT_OLD_ITALIC, + HB_SCRIPT_GOTHIC, + HB_SCRIPT_DESERET, + HB_SCRIPT_INHERITED, + HB_SCRIPT_TAGALOG, + HB_SCRIPT_HANUNOO, + HB_SCRIPT_BUHID, + HB_SCRIPT_TAGBANWA, + HB_SCRIPT_LIMBU, + HB_SCRIPT_TAI_LE, + HB_SCRIPT_LINEAR_B, + HB_SCRIPT_UGARITIC, + HB_SCRIPT_SHAVIAN, + HB_SCRIPT_OSMANYA, + HB_SCRIPT_CYPRIOT, + HB_SCRIPT_BRAILLE, + HB_SCRIPT_BUGINESE, + HB_SCRIPT_COPTIC, + HB_SCRIPT_NEW_TAI_LUE, + HB_SCRIPT_GLAGOLITIC, + HB_SCRIPT_TIFINAGH, + HB_SCRIPT_SYLOTI_NAGRI, + HB_SCRIPT_OLD_PERSIAN, + HB_SCRIPT_KHAROSHTHI, + HB_SCRIPT_BALINESE, + HB_SCRIPT_CUNEIFORM, + HB_SCRIPT_PHOENICIAN, + HB_SCRIPT_PHAGS_PA, + HB_SCRIPT_NKO, + HB_SCRIPT_SUNDANESE, + HB_SCRIPT_LEPCHA, + HB_SCRIPT_OL_CHIKI, + HB_SCRIPT_VAI, + HB_SCRIPT_SAURASHTRA, + HB_SCRIPT_KAYAH_LI, + HB_SCRIPT_REJANG, + HB_SCRIPT_LYCIAN, + HB_SCRIPT_CARIAN, + HB_SCRIPT_LYDIAN, + HB_SCRIPT_CHAM, + HB_SCRIPT_TAI_THAM, + HB_SCRIPT_TAI_VIET, + HB_SCRIPT_AVESTAN, + HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, + HB_SCRIPT_SAMARITAN, + HB_SCRIPT_LISU, + HB_SCRIPT_BAMUM, + HB_SCRIPT_JAVANESE, + HB_SCRIPT_MEETEI_MAYEK, + HB_SCRIPT_IMPERIAL_ARAMAIC, + HB_SCRIPT_OLD_SOUTH_ARABIAN, + HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, + HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, + HB_SCRIPT_OLD_TURKIC, + HB_SCRIPT_KAITHI, + HB_SCRIPT_BATAK, + HB_SCRIPT_BRAHMI, + HB_SCRIPT_MANDAIC, + HB_SCRIPT_CHAKMA, + HB_SCRIPT_MEROITIC_CURSIVE, + HB_SCRIPT_MEROITIC_HIEROGLYPHS, + HB_SCRIPT_MIAO, + HB_SCRIPT_SHARADA, + HB_SCRIPT_SORA_SOMPENG, + HB_SCRIPT_TAKRI, + HB_SCRIPT_UNKNOWN, +}; + +static hb_unicode_combining_class_t +hb_ucdn_combining_class(hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode, + void *user_data) +{ + return (hb_unicode_combining_class_t) ucdn_get_combining_class(unicode); +} + +static unsigned int +hb_ucdn_eastasian_width(hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode, + void *user_data) +{ + 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_codepoint_t unicode, void *user_data) +{ + return (hb_unicode_general_category_t)ucdn_get_general_category(unicode); +} + +static hb_codepoint_t +hb_ucdn_mirroring(hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode, + void *user_data) +{ + return ucdn_mirror(unicode); +} + +static hb_script_t +hb_ucdn_script(hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode, + void *user_data) +{ + return ucdn_script_translate[ucdn_get_script(unicode)]; +} + +static hb_bool_t +hb_ucdn_compose(hb_unicode_funcs_t *ufuncs, hb_codepoint_t a, + hb_codepoint_t b, hb_codepoint_t *ab, void *user_data) +{ + return ucdn_compose(ab, a, b); +} + +static hb_bool_t +hb_ucdn_decompose(hb_unicode_funcs_t *ufuncs, hb_codepoint_t ab, + hb_codepoint_t *a, hb_codepoint_t *b, void *user_data) +{ + return ucdn_decompose(ab, a, b); +} + +static unsigned int +hb_ucdn_decompose_compatibility(hb_unicode_funcs_t *ufuncs, hb_codepoint_t u, + hb_codepoint_t *decomposed, void *user_data) +{ + return ucdn_compat_decompose(u, decomposed); +} + +extern "C" HB_INTERNAL +hb_unicode_funcs_t * +hb_ucdn_get_unicode_funcs (void) +{ + static const hb_unicode_funcs_t _hb_ucdn_unicode_funcs = { + HB_OBJECT_HEADER_STATIC, + + NULL, /* parent */ + true, /* immutable */ + { +#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_ucdn_##name, + HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_UNICODE_FUNC_IMPLEMENT + } + }; + + return const_cast (&_hb_ucdn_unicode_funcs); +} + diff --git a/gfx/harfbuzz/src/hb-unicode-private.hh b/gfx/harfbuzz/src/hb-unicode-private.hh index 7ef582074e88..9f24a9fbc33b 100644 --- a/gfx/harfbuzz/src/hb-unicode-private.hh +++ b/gfx/harfbuzz/src/hb-unicode-private.hh @@ -268,4 +268,13 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil; #define HB_MODIFIED_COMBINING_CLASS_CCC132 132 /* sign u */ +/* Misc */ + +#define HB_UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) \ + (FLAG (gen_cat) & \ + (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \ + FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \ + FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))) + + #endif /* HB_UNICODE_PRIVATE_HH */ diff --git a/gfx/harfbuzz/src/hb-unicode.cc b/gfx/harfbuzz/src/hb-unicode.cc index 2e2d077ec0ae..0a3907eec8c3 100644 --- a/gfx/harfbuzz/src/hb-unicode.cc +++ b/gfx/harfbuzz/src/hb-unicode.cc @@ -112,6 +112,7 @@ hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED #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 */ @@ -134,6 +135,8 @@ hb_unicode_funcs_get_default (void) HB_UNICODE_FUNCS_IMPLEMENT(glib) #elif defined(HAVE_ICU) HB_UNICODE_FUNCS_IMPLEMENT(icu) +#elif defined(HAVE_UCDN) + HB_UNICODE_FUNCS_IMPLEMENT(ucdn) #else #define HB_UNICODE_FUNCS_NIL 1 HB_UNICODE_FUNCS_IMPLEMENT(nil) diff --git a/gfx/harfbuzz/src/hb-uniscribe.cc b/gfx/harfbuzz/src/hb-uniscribe.cc index d732b5741a58..18b88b2234f9 100644 --- a/gfx/harfbuzz/src/hb-uniscribe.cc +++ b/gfx/harfbuzz/src/hb-uniscribe.cc @@ -33,8 +33,6 @@ #include #include -typedef ULONG WIN_ULONG; - #include "hb-uniscribe.h" #include "hb-ot-name-table.hh" @@ -121,8 +119,8 @@ populate_log_font (LOGFONTW *lf, lf->lfHeight = -font->y_scale; lf->lfCharSet = DEFAULT_CHARSET; - hb_blob_t *blob = Sanitizer::sanitize (hb_face_reference_table (font->face, HB_TAG ('n','a','m','e'))); - const name *name_table = Sanitizer::lock_instance (blob); + hb_blob_t *blob = OT::Sanitizer::sanitize (hb_face_reference_table (font->face, HB_TAG ('n','a','m','e'))); + const OT::name *name_table = OT::Sanitizer::lock_instance (blob); unsigned int len = name_table->get_name (3, 1, 0x409, 4, lf->lfFaceName, sizeof (lf->lfFaceName[0]) * LF_FACESIZE) @@ -305,7 +303,7 @@ retry: SCRIPT_ITEM items[MAX_ITEMS + 1]; SCRIPT_CONTROL bidi_control = {0}; SCRIPT_STATE bidi_state = {0}; - WIN_ULONG script_tags[MAX_ITEMS]; + ULONG script_tags[MAX_ITEMS]; int item_count; /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */ diff --git a/gfx/harfbuzz/src/hb-utf-private.hh b/gfx/harfbuzz/src/hb-utf-private.hh new file mode 100644 index 000000000000..8cde8274733c --- /dev/null +++ b/gfx/harfbuzz/src/hb-utf-private.hh @@ -0,0 +1,204 @@ +/* + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_UTF_PRIVATE_HH +#define HB_UTF_PRIVATE_HH + +#include "hb-private.hh" + + +/* UTF-8 */ + +#define HB_UTF8_COMPUTE(Char, Mask, Len) \ + if (Char < 128) { Len = 1; Mask = 0x7f; } \ + else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \ + else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \ + else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \ + else Len = 0; + +static inline const uint8_t * +hb_utf_next (const uint8_t *text, + const uint8_t *end, + hb_codepoint_t *unicode) +{ + hb_codepoint_t c = *text, mask; + unsigned int len; + + /* TODO check for overlong sequences? */ + + HB_UTF8_COMPUTE (c, mask, len); + if (unlikely (!len || (unsigned int) (end - text) < len)) { + *unicode = -1; + return text + 1; + } else { + hb_codepoint_t result; + unsigned int i; + result = c & mask; + for (i = 1; i < len; i++) + { + if (unlikely ((text[i] & 0xc0) != 0x80)) + { + *unicode = -1; + return text + 1; + } + result <<= 6; + result |= (text[i] & 0x3f); + } + *unicode = result; + return text + len; + } +} + +static inline const uint8_t * +hb_utf_prev (const uint8_t *text, + const uint8_t *start, + hb_codepoint_t *unicode) +{ + const uint8_t *end = text; + while (start < text && (*--text & 0xc0) == 0x80 && end - text < 4) + text--; + + hb_codepoint_t c = *text, mask; + unsigned int len; + + /* TODO check for overlong sequences? */ + + HB_UTF8_COMPUTE (c, mask, len); + if (unlikely (!len || (unsigned int) (end - text) != len)) { + *unicode = -1; + return end - 1; + } else { + hb_codepoint_t result; + unsigned int i; + result = c & mask; + for (i = 1; i < len; i++) + { + result <<= 6; + result |= (text[i] & 0x3f); + } + *unicode = result; + return text; + } +} + + +static inline unsigned int +hb_utf_strlen (const uint8_t *text) +{ + return strlen ((const char *) text); +} + + +/* UTF-16 */ + +static inline const uint16_t * +hb_utf_next (const uint16_t *text, + const uint16_t *end, + hb_codepoint_t *unicode) +{ + hb_codepoint_t c = *text++; + + if (unlikely (hb_in_range (c, 0xd800, 0xdbff))) + { + /* high surrogate */ + hb_codepoint_t l; + if (text < end && ((l = *text), likely (hb_in_range (l, 0xdc00, 0xdfff)))) + { + /* low surrogate */ + *unicode = (c << 10) + l - ((0xd800 << 10) - 0x10000 + 0xdc00); + text++; + } else + *unicode = -1; + } else + *unicode = c; + + return text; +} + +static inline const uint16_t * +hb_utf_prev (const uint16_t *text, + const uint16_t *start, + hb_codepoint_t *unicode) +{ + hb_codepoint_t c = *--text; + + if (unlikely (hb_in_range (c, 0xdc00, 0xdfff))) + { + /* low surrogate */ + hb_codepoint_t h; + if (start < text && ((h = *(text - 1)), likely (hb_in_range (h, 0xd800, 0xdbff)))) + { + /* high surrogate */ + *unicode = (h << 10) + c - ((0xd800 << 10) - 0x10000 + 0xdc00); + text--; + } else + *unicode = -1; + } else + *unicode = c; + + return text; +} + + +static inline unsigned int +hb_utf_strlen (const uint16_t *text) +{ + unsigned int l = 0; + while (*text++) l++; + return l; +} + + +/* UTF-32 */ + +static inline const uint32_t * +hb_utf_next (const uint32_t *text, + const uint32_t *end, + hb_codepoint_t *unicode) +{ + *unicode = *text++; + return text; +} + +static inline const uint32_t * +hb_utf_prev (const uint32_t *text, + const uint32_t *start, + hb_codepoint_t *unicode) +{ + *unicode = *--text; + return text; +} + +static inline unsigned int +hb_utf_strlen (const uint32_t *text) +{ + unsigned int l = 0; + while (*text++) l++; + return l; +} + + +#endif /* HB_UTF_PRIVATE_HH */ diff --git a/gfx/harfbuzz/src/hb-version.h b/gfx/harfbuzz/src/hb-version.h index 43ec9cf1d005..e8ed88bdad07 100644 --- a/gfx/harfbuzz/src/hb-version.h +++ b/gfx/harfbuzz/src/hb-version.h @@ -38,9 +38,9 @@ HB_BEGIN_DECLS #define HB_VERSION_MAJOR 0 #define HB_VERSION_MINOR 9 -#define HB_VERSION_MICRO 0 +#define HB_VERSION_MICRO 4 -#define HB_VERSION_STRING "0.9.0" +#define HB_VERSION_STRING "0.9.4" #define HB_VERSION_CHECK(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) >= \ diff --git a/gfx/harfbuzz/src/main.cc b/gfx/harfbuzz/src/main.cc index 07d3d69be746..b362744e2137 100644 --- a/gfx/harfbuzz/src/main.cc +++ b/gfx/harfbuzz/src/main.cc @@ -36,6 +36,8 @@ #include +using namespace OT; + int main (int argc, char **argv) diff --git a/gfx/harfbuzz/src/test-would-substitute.cc b/gfx/harfbuzz/src/test-would-substitute.cc index 95626edf46cb..d15aec48f999 100644 --- a/gfx/harfbuzz/src/test-would-substitute.cc +++ b/gfx/harfbuzz/src/test-would-substitute.cc @@ -99,5 +99,5 @@ main (int argc, char **argv) (argc > 4 && !hb_font_glyph_from_string (font, argv[4], -1, &glyphs[1]))) return 2; - return !hb_ot_layout_would_substitute_lookup (face, glyphs, len, strtol (argv[2], NULL, 0)); + return !hb_ot_layout_would_substitute_lookup (face, strtol (argv[2], NULL, 0), glyphs, len, false); }