diff options
author | Martin Stransky <stransky@redhat.com> | 2016-03-03 11:14:11 +0100 |
---|---|---|
committer | Martin Stransky <stransky@redhat.com> | 2016-03-03 11:14:11 +0100 |
commit | b4b4b1aaba948c1f60f856fdf494fb9d68405c0a (patch) | |
tree | c2235f678361d86b37d2d68b36145a2f5ba2c3ba | |
parent | Disabled system libvpx on Fedora 22 where is 1.3.0 (diff) | |
download | librewolf-fedora-ff-b4b4b1aaba948c1f60f856fdf494fb9d68405c0a.tar.gz librewolf-fedora-ff-b4b4b1aaba948c1f60f856fdf494fb9d68405c0a.tar.bz2 librewolf-fedora-ff-b4b4b1aaba948c1f60f856fdf494fb9d68405c0a.zip |
build fixes
-rw-r--r-- | firefox.spec | 7 | ||||
-rw-r--r-- | mozilla-1228540-1.patch | 84 | ||||
-rw-r--r-- | mozilla-1228540.patch | 9138 |
3 files changed, 9227 insertions, 2 deletions
diff --git a/firefox.spec b/firefox.spec index 9405c95..46ab661 100644 --- a/firefox.spec +++ b/firefox.spec @@ -128,6 +128,8 @@ Patch223: rhbz-1291190-appchooser-crash.patch # Upstream patches Patch301: mozilla-1205199.patch +Patch302: mozilla-1228540.patch +Patch303: mozilla-1228540-1.patch # Gtk3 upstream patches @@ -278,6 +280,8 @@ cd %{tarballdir} %patch223 -p1 -b .appchooser-crash %patch301 -p1 -b .1205199 +%patch302 -p1 -b .1228540 +%patch303 -p1 -b .1228540-1 %patch500 -p1 @@ -730,6 +734,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{mozappdir}/browser/components/*.so %{mozappdir}/browser/components/components.manifest %{mozappdir}/browser/defaults/preferences/firefox-redhat-default-prefs.js +%{mozappdir}/browser/features/loop@mozilla.org.xpi %attr(644, root, root) %{mozappdir}/browser/blocklist.xml %dir %{mozappdir}/browser/extensions %{mozappdir}/browser/extensions/* @@ -762,8 +767,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %if %{toolkit_gtk3} %{mozappdir}/gtk2/*.so %endif -%{mozappdir}/chrome.manifest -%{mozappdir}/components %{mozappdir}/defaults/pref/channel-prefs.js %{mozappdir}/dependentlibs.list %{mozappdir}/dictionaries diff --git a/mozilla-1228540-1.patch b/mozilla-1228540-1.patch new file mode 100644 index 0000000..be6ffc3 --- /dev/null +++ b/mozilla-1228540-1.patch @@ -0,0 +1,84 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1452675061 0 +# Wed Jan 13 08:51:01 2016 +0000 +# Node ID cf699e95e98829b465b64a7e0281d95ec851ce8c +# Parent 3c9f357598e86c2f593e9895d5725bf3498f8f5a +Bug 1228540 - pt 2 - Remove our HBGetGlyphHOrigin callback, as the default behavior is sufficient. + +diff --git a/gfx/thebes/gfxHarfBuzzShaper.cpp b/gfx/thebes/gfxHarfBuzzShaper.cpp +--- a/gfx/thebes/gfxHarfBuzzShaper.cpp ++++ b/gfx/thebes/gfxHarfBuzzShaper.cpp +@@ -349,27 +349,16 @@ gfxHarfBuzzShaper::HBGetGlyphVAdvance(hb + static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data); + // Currently, we don't offer gfxFont subclasses a method to override this + // and provide hinted platform-specific vertical advances (analogous to the + // GetGlyphWidth method for horizontal advances). If that proves necessary, + // we'll add a new gfxFont method and call it from here. + return fcd->mShaper->GetGlyphVAdvance(glyph); + } + +-/* static */ +-hb_bool_t +-gfxHarfBuzzShaper::HBGetGlyphHOrigin(hb_font_t *font, void *font_data, +- hb_codepoint_t glyph, +- hb_position_t *x, hb_position_t *y, +- void *user_data) +-{ +- // We work in horizontal coordinates, so no origin adjustment needed here. +- return true; +-} +- + struct VORG { + AutoSwap_PRUint16 majorVersion; + AutoSwap_PRUint16 minorVersion; + AutoSwap_PRInt16 defaultVertOriginY; + AutoSwap_PRUint16 numVertOriginYMetrics; + }; + + struct VORGrec { +@@ -1262,19 +1251,16 @@ gfxHarfBuzzShaper::Initialize() + hb_font_funcs_set_glyph_func(sHBFontFuncs, HBGetGlyph, + nullptr, nullptr); + hb_font_funcs_set_glyph_h_advance_func(sHBFontFuncs, + HBGetGlyphHAdvance, + nullptr, nullptr); + hb_font_funcs_set_glyph_v_advance_func(sHBFontFuncs, + HBGetGlyphVAdvance, + nullptr, nullptr); +- hb_font_funcs_set_glyph_h_origin_func(sHBFontFuncs, +- HBGetGlyphHOrigin, +- nullptr, nullptr); + hb_font_funcs_set_glyph_v_origin_func(sHBFontFuncs, + HBGetGlyphVOrigin, + nullptr, nullptr); + hb_font_funcs_set_glyph_extents_func(sHBFontFuncs, + HBGetGlyphExtents, + nullptr, nullptr); + hb_font_funcs_set_glyph_contour_point_func(sHBFontFuncs, + HBGetContourPoint, +diff --git a/gfx/thebes/gfxHarfBuzzShaper.h b/gfx/thebes/gfxHarfBuzzShaper.h +--- a/gfx/thebes/gfxHarfBuzzShaper.h ++++ b/gfx/thebes/gfxHarfBuzzShaper.h +@@ -56,21 +56,16 @@ public: + hb_codepoint_t glyph, void *user_data); + + // get harfbuzz vertical advance in 16.16 fixed point format. + static hb_position_t + HBGetGlyphVAdvance(hb_font_t *font, void *font_data, + hb_codepoint_t glyph, void *user_data); + + static hb_bool_t +- HBGetGlyphHOrigin(hb_font_t *font, void *font_data, +- hb_codepoint_t glyph, +- hb_position_t *x, hb_position_t *y, +- void *user_data); +- static hb_bool_t + HBGetGlyphVOrigin(hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y, + void *user_data); + + hb_position_t GetHKerning(uint16_t aFirstGlyph, + uint16_t aSecondGlyph) const; + diff --git a/mozilla-1228540.patch b/mozilla-1228540.patch new file mode 100644 index 0000000..3fac3de --- /dev/null +++ b/mozilla-1228540.patch @@ -0,0 +1,9138 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1452639380 0 +# Tue Jan 12 22:56:20 2016 +0000 +# Node ID 3c9f357598e86c2f593e9895d5725bf3498f8f5a +# Parent e790bba372f14241addda469a4bdb7ab00786ab3 +Bug 1228540 - Update harfbuzz to release 1.1.3. + +diff --git a/gfx/harfbuzz/src/Makefile.am b/gfx/harfbuzz/src/Makefile.am +--- a/gfx/harfbuzz/src/Makefile.am ++++ b/gfx/harfbuzz/src/Makefile.am +@@ -43,16 +43,17 @@ HBSOURCES = \ + hb-open-type-private.hh \ + hb-ot-cmap-table.hh \ + hb-ot-glyf-table.hh \ + hb-ot-head-table.hh \ + hb-ot-hhea-table.hh \ + hb-ot-hmtx-table.hh \ + hb-ot-maxp-table.hh \ + hb-ot-name-table.hh \ ++ hb-ot-os2-table.hh \ + hb-ot-tag.cc \ + hb-private.hh \ + hb-set-private.hh \ + hb-set.cc \ + hb-shape.cc \ + hb-shape-plan-private.hh \ + hb-shape-plan.cc \ + hb-shaper-list.hh \ +@@ -387,17 +388,24 @@ dist_check_SCRIPTS = \ + check-defs.sh \ + check-header-guards.sh \ + check-includes.sh \ + check-libstdc++.sh \ + check-static-inits.sh \ + check-symbols.sh \ + $(NULL) + +-TESTS = $(dist_check_SCRIPTS) ++check_PROGRAMS = \ ++ test-ot-tag \ ++ $(NULL) ++test_ot_tag_SOURCES = hb-ot-tag.cc ++test_ot_tag_CPPFLAGS = $(HBCFLAGS) -DMAIN ++test_ot_tag_LDADD = libharfbuzz.la $(HBLIBS) ++ ++TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS) + TESTS_ENVIRONMENT = \ + srcdir="$(srcdir)" \ + MAKE="$(MAKE) $(AM_MAKEFLAGS)" \ + HBSOURCES="$(HBSOURCES)" \ + HBHEADERS="$(HBHEADERS) $(HBNODISTHEADERS)" \ + $(NULL) + + if HAVE_INTROSPECTION +@@ -414,16 +422,17 @@ HarfBuzz_0_0_gir_CFLAGS = \ + $(INCLUDES) \ + $(HBCFLAGS) \ + -DHB_H \ + -DHB_H_IN \ + -DHB_OT_H \ + -DHB_OT_H_IN \ + -DHB_GOBJECT_H \ + -DHB_GOBJECT_H_IN \ ++ -DHB_EXTERN= \ + $(NULL) + HarfBuzz_0_0_gir_LIBS = \ + libharfbuzz.la \ + libharfbuzz-gobject.la \ + $(NULL) + HarfBuzz_0_0_gir_FILES = \ + $(HBHEADERS) \ + $(HBNODISTHEADERS) \ +diff --git a/gfx/harfbuzz/src/check-header-guards.sh b/gfx/harfbuzz/src/check-header-guards.sh +--- a/gfx/harfbuzz/src/check-header-guards.sh ++++ b/gfx/harfbuzz/src/check-header-guards.sh +@@ -4,22 +4,21 @@ LC_ALL=C + export LC_ALL + + test -z "$srcdir" && srcdir=. + stat=0 + + test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'` + test "x$HBSOURCES" = x && HBSOURCES=`cd "$srcdir"; find . -maxdepth 1 -name 'hb-*.cc' -or -name 'hb-*.hh'` + +- + for x in $HBHEADERS $HBSOURCES; do + test -f "$srcdir/$x" && x="$srcdir/$x" +- echo "$x" | grep '[^h]$' -q && continue; ++ echo "$x" | grep -q '[^h]$' && continue; + xx=`echo "$x" | sed 's@.*/@@'` + tag=`echo "$xx" | tr 'a-z.-' 'A-Z_'` +- lines=`grep "\<$tag\>" "$x" | wc -l | sed 's/[ ]*//g'` ++ lines=`grep -w "$tag" "$x" | wc -l | sed 's/[ ]*//g'` + if test "x$lines" != x3; then + echo "Ouch, header file $x does not have correct preprocessor guards" + stat=1 + fi + done + + exit $stat +diff --git a/gfx/harfbuzz/src/gen-indic-table.py b/gfx/harfbuzz/src/gen-indic-table.py +--- a/gfx/harfbuzz/src/gen-indic-table.py ++++ b/gfx/harfbuzz/src/gen-indic-table.py +@@ -86,16 +86,17 @@ short = [{ + "Bindu": 'Bi', + "Cantillation_Mark": 'Ca', + "Joiner": 'ZWJ', + "Non_Joiner": 'ZWNJ', + "Number": 'Nd', + "Visarga": 'Vs', + "Vowel": 'Vo', + "Vowel_Dependent": 'M', ++ "Consonant_Prefixed": 'CPrf', + "Other": 'x', + },{ + "Not_Applicable": 'x', + }] + all_shorts = [{},{}] + + # Add some of the values, to make them more readable, and to avoid duplicates + +diff --git a/gfx/harfbuzz/src/hb-atomic-private.hh b/gfx/harfbuzz/src/hb-atomic-private.hh +--- a/gfx/harfbuzz/src/hb-atomic-private.hh ++++ b/gfx/harfbuzz/src/hb-atomic-private.hh +@@ -114,16 +114,41 @@ typedef int hb_atomic_int_impl_t; + typedef unsigned int hb_atomic_int_impl_t; + #define HB_ATOMIC_INT_IMPL_INIT(V) (V) + #define hb_atomic_int_impl_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V)) + + #define hb_atomic_ptr_impl_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P)) + #define hb_atomic_ptr_impl_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false) + + ++#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__) ++ ++#include <builtins.h> ++ ++ ++static inline int hb_fetch_and_add(volatile int* AI, unsigned int V) { ++ __lwsync(); ++ int result = __fetch_and_add(AI, V); ++ __isync(); ++ return result; ++} ++static inline int hb_compare_and_swaplp(volatile long* P, long O, long N) { ++ __sync(); ++ int result = __compare_and_swaplp (P, &O, N); ++ __sync(); ++ return result; ++} ++ ++typedef int hb_atomic_int_impl_t; ++#define HB_ATOMIC_INT_IMPL_INIT(V) (V) ++#define hb_atomic_int_impl_add(AI, V) hb_fetch_and_add (&(AI), (V)) ++ ++#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P)) ++#define hb_atomic_ptr_impl_cmpexch(P,O,N) hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N)) ++ + #elif !defined(HB_NO_MT) + + #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ + + typedef volatile int hb_atomic_int_impl_t; + #define HB_ATOMIC_INT_IMPL_INIT(V) (V) + #define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V)) + +diff --git a/gfx/harfbuzz/src/hb-blob.h b/gfx/harfbuzz/src/hb-blob.h +--- a/gfx/harfbuzz/src/hb-blob.h ++++ b/gfx/harfbuzz/src/hb-blob.h +@@ -59,68 +59,68 @@ typedef enum { + HB_MEMORY_MODE_DUPLICATE, + HB_MEMORY_MODE_READONLY, + HB_MEMORY_MODE_WRITABLE, + HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE + } hb_memory_mode_t; + + typedef struct hb_blob_t hb_blob_t; + +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_blob_create (const char *data, + unsigned int length, + hb_memory_mode_t mode, + void *user_data, + hb_destroy_func_t destroy); + + /* Always creates with MEMORY_MODE_READONLY. + * Even if the parent blob is writable, we don't + * want the user of the sub-blob to be able to + * modify the parent data as that data may be + * shared among multiple sub-blobs. + */ +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_blob_create_sub_blob (hb_blob_t *parent, + unsigned int offset, + unsigned int length); + +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_blob_get_empty (void); + +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_blob_reference (hb_blob_t *blob); + +-void ++HB_EXTERN void + hb_blob_destroy (hb_blob_t *blob); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_blob_set_user_data (hb_blob_t *blob, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + + +-void * ++HB_EXTERN void * + hb_blob_get_user_data (hb_blob_t *blob, + hb_user_data_key_t *key); + + +-void ++HB_EXTERN void + hb_blob_make_immutable (hb_blob_t *blob); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_blob_is_immutable (hb_blob_t *blob); + + +-unsigned int ++HB_EXTERN unsigned int + hb_blob_get_length (hb_blob_t *blob); + +-const char * ++HB_EXTERN const char * + hb_blob_get_data (hb_blob_t *blob, unsigned int *length); + +-char * ++HB_EXTERN char * + hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length); + + + HB_END_DECLS + + #endif /* HB_BLOB_H */ +diff --git a/gfx/harfbuzz/src/hb-buffer-private.hh b/gfx/harfbuzz/src/hb-buffer-private.hh +--- a/gfx/harfbuzz/src/hb-buffer-private.hh ++++ b/gfx/harfbuzz/src/hb-buffer-private.hh +@@ -119,16 +119,21 @@ struct hb_buffer_t { + + /* Text before / after the main buffer contents. + * Always in Unicode, and ordered outward. + * Index 0 is for "pre-context", 1 for "post-context". */ + static const unsigned int CONTEXT_LENGTH = 5; + hb_codepoint_t context[2][CONTEXT_LENGTH]; + unsigned int context_len[2]; + ++ /* Debugging */ ++ hb_buffer_message_func_t message_func; ++ void *message_data; ++ hb_destroy_func_t message_destroy; ++ + + /* Methods */ + + HB_INTERNAL void reset (void); + HB_INTERNAL void clear (void); + + inline unsigned int backtrack_len (void) const + { return have_output? out_len : idx; } +@@ -169,23 +174,22 @@ struct hb_buffer_t { + /* Copies glyph at idx to output and advance idx. + * If there's no output, just advance idx. */ + inline void + next_glyph (void) + { + if (have_output) + { + if (unlikely (out_info != info || out_len != idx)) { +- if (unlikely (!make_room_for (1, 1))) +- goto done; ++ if (unlikely (!make_room_for (1, 1))) return; + out_info[out_len] = info[idx]; + } + out_len++; + } +- done: ++ + idx++; + } + + /* Advance idx without copying to output. */ + inline void skip_glyph (void) { idx++; } + + inline void reset_masks (hb_mask_t mask) + { +@@ -229,16 +233,29 @@ struct hb_buffer_t { + HB_INTERNAL bool shift_forward (unsigned int count); + + typedef long scratch_buffer_t; + HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size); + + inline void clear_context (unsigned int side) { context_len[side] = 0; } + + HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *)); ++ ++ inline bool messaging (void) { return unlikely (message_func); } ++ inline bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4) ++ { ++ if (!messaging ()) ++ return true; ++ va_list ap; ++ va_start (ap, fmt); ++ bool ret = message_impl (font, fmt, ap); ++ va_end (ap); ++ return ret; ++ } ++ HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0); + }; + + + #define HB_BUFFER_XALLOCATE_VAR(b, func, var, owner) \ + b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \ + sizeof (b->info[0].var), owner) + #define HB_BUFFER_ALLOCATE_VAR(b, var) \ + HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var (), #var) +diff --git a/gfx/harfbuzz/src/hb-buffer-serialize.cc b/gfx/harfbuzz/src/hb-buffer-serialize.cc +--- a/gfx/harfbuzz/src/hb-buffer-serialize.cc ++++ b/gfx/harfbuzz/src/hb-buffer-serialize.cc +@@ -31,55 +31,61 @@ static const char *serialize_formats[] = + "text", + "json", + NULL + }; + + /** + * hb_buffer_serialize_list_formats: + * +- * ++ * Returns a list of supported buffer serialization formats. + * + * Return value: (transfer none): ++ * A string array of buffer serialization formats. Should not be freed. + * +- * Since: 0.9.2 ++ * Since: 0.9.7 + **/ + const char ** + hb_buffer_serialize_list_formats (void) + { + return serialize_formats; + } + + /** + * hb_buffer_serialize_format_from_string: +- * @str: +- * @len: ++ * @str: (array length=len) (element-type uint8_t): a string to parse ++ * @len: length of @str, or -1 if string is %NULL terminated + * +- * ++ * Parses a string into an #hb_buffer_serialize_format_t. Does not check if ++ * @str is a valid buffer serialization format, use ++ * hb_buffer_serialize_list_formats() to get the list of supported formats. + * + * Return value: ++ * The parsed #hb_buffer_serialize_format_t. + * +- * Since: 0.9.2 ++ * Since: 0.9.7 + **/ + hb_buffer_serialize_format_t + hb_buffer_serialize_format_from_string (const char *str, int len) + { + /* Upper-case it. */ + return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020u); + } + + /** + * hb_buffer_serialize_format_to_string: +- * @format: ++ * @format: an #hb_buffer_serialize_format_t to convert. + * +- * ++ * Converts @format to the string corresponding it, or %NULL if it is not a valid ++ * #hb_buffer_serialize_format_t. + * +- * Return value: ++ * Return value: (transfer none): ++ * A %NULL terminated string corresponding to @format. Should not be freed. + * +- * Since: 0.9.2 ++ * Since: 0.9.7 + **/ + const char * + hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) + { + switch (format) + { + case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0]; + case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1]; +@@ -237,56 +243,86 @@ static unsigned int + *buf = '\0'; + } else + return i - start; + } + + return end - start; + } + +-/* Returns number of items, starting at start, that were serialized. */ + /** + * hb_buffer_serialize_glyphs: +- * @buffer: a buffer. +- * @start: +- * @end: +- * @buf: (array length=buf_size): +- * @buf_size: +- * @buf_consumed: (out): +- * @font: +- * @format: +- * @flags: ++ * @buffer: an #hb_buffer_t buffer. ++ * @start: the first item in @buffer to serialize. ++ * @end: the last item in @buffer to serialize. ++ * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to ++ * write serialized buffer into. ++ * @buf_size: the size of @buf. ++ * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf. ++ * @font: (allow-none): the #hb_font_t used to shape this buffer, needed to ++ * read glyph names and extents. If %NULL, and empty font will be used. ++ * @format: the #hb_buffer_serialize_format_t to use for formatting the output. ++ * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties ++ * to serialize. + * +- * ++ * Serializes @buffer into a textual representation of its glyph content, ++ * useful for showing the contents of the buffer, for example during debugging. ++ * There are currently two supported serialization formats: ++ * ++ * ## text ++ * A human-readable, plain text format. ++ * The serialized glyphs will look something like: ++ * ++ * ``` ++ * [uni0651=0@518,0+0|uni0628=0+1897] ++ * ``` ++ * - The serialized glyphs are delimited with `[` and `]`. ++ * - Glyphs are separated with `|` ++ * - Each glyph starts with glyph name, or glyph index if ++ * #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set. Then, ++ * - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, `=` then #hb_glyph_info_t.cluster. ++ * - If #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set, the #hb_glyph_position_t in the format: ++ * - If both #hb_glyph_position_t.x_offset and #hb_glyph_position_t.y_offset are not 0, `@x_offset,y_offset`. Then, ++ * - `+x_advance`, then `,y_advance` if #hb_glyph_position_t.y_advance is not 0. Then, ++ * - If #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set, the ++ * #hb_glyph_extents_t in the format ++ * `<x_bearing,y_bearing,width,height>` ++ * ++ * ## json ++ * TODO. + * + * Return value: ++ * The number of serialized items. + * +- * Since: 0.9.2 ++ * Since: 0.9.7 + **/ + unsigned int + hb_buffer_serialize_glyphs (hb_buffer_t *buffer, + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, +- unsigned int *buf_consumed, /* May be NULL */ +- hb_font_t *font, /* May be NULL */ ++ unsigned int *buf_consumed, ++ hb_font_t *font, + hb_buffer_serialize_format_t format, + hb_buffer_serialize_flags_t flags) + { + assert (start <= end && end <= buffer->len); + + unsigned int sconsumed; + if (!buf_consumed) + buf_consumed = &sconsumed; + *buf_consumed = 0; + + assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || + buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); + ++ if (!buffer->have_positions) ++ flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS; ++ + if (unlikely (start == end)) + return 0; + + if (!font) + font = hb_font_get_empty (); + + switch (format) + { +@@ -350,28 +386,28 @@ parse_int (const char *pp, const char *e + return true; + } + + #include "hb-buffer-deserialize-json.hh" + #include "hb-buffer-deserialize-text.hh" + + /** + * hb_buffer_deserialize_glyphs: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t buffer. + * @buf: (array length=buf_len): + * @buf_len: + * @end_ptr: (out): + * @font: + * @format: + * + * + * + * Return value: + * +- * Since: 0.9.2 ++ * Since: 0.9.7 + **/ + hb_bool_t + hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, + const char *buf, + int buf_len, /* -1 means nul-terminated */ + const char **end_ptr, /* May be NULL */ + hb_font_t *font, /* May be NULL */ + hb_buffer_serialize_format_t format) +diff --git a/gfx/harfbuzz/src/hb-buffer.cc b/gfx/harfbuzz/src/hb-buffer.cc +--- a/gfx/harfbuzz/src/hb-buffer.cc ++++ b/gfx/harfbuzz/src/hb-buffer.cc +@@ -30,33 +30,59 @@ + #include "hb-buffer-private.hh" + #include "hb-utf-private.hh" + + + #ifndef HB_DEBUG_BUFFER + #define HB_DEBUG_BUFFER (HB_DEBUG+0) + #endif + ++/** ++ * SECTION: hb-buffer ++ * @title: Buffers ++ * @short_description: Input and output buffers ++ * @include: hb.h ++ * ++ * Buffers serve dual role in HarfBuzz; they hold the input characters that are ++ * passed hb_shape(), and after shaping they hold the output glyphs. ++ **/ + + /** ++ * hb_segment_properties_equal: ++ * @a: first #hb_segment_properties_t to compare. ++ * @b: second #hb_segment_properties_t to compare. ++ * ++ * Checks the equality of two #hb_segment_properties_t's. ++ * ++ * Return value: (transfer full): ++ * %true if all properties of @a equal those of @b, false otherwise. ++ * + * Since: 0.9.7 + **/ + hb_bool_t + hb_segment_properties_equal (const hb_segment_properties_t *a, + const hb_segment_properties_t *b) + { + return a->direction == b->direction && + a->script == b->script && + a->language == b->language && + a->reserved1 == b->reserved1 && + a->reserved2 == b->reserved2; + + } + + /** ++ * hb_segment_properties_hash: ++ * @p: #hb_segment_properties_t to hash. ++ * ++ * Creates a hash representing @p. ++ * ++ * Return value: ++ * A hash of @p. ++ * + * Since: 0.9.7 + **/ + unsigned int + hb_segment_properties_hash (const hb_segment_properties_t *p) + { + return (unsigned int) p->direction ^ + (unsigned int) p->script ^ + (intptr_t) (p->language); +@@ -319,75 +345,62 @@ hb_buffer_t::swap_buffers (void) + } + + + void + hb_buffer_t::replace_glyphs (unsigned int num_in, + unsigned int num_out, + const uint32_t *glyph_data) + { +- if (unlikely (!make_room_for (num_in, num_out))) +- goto done; +- { ++ if (unlikely (!make_room_for (num_in, num_out))) return; + + merge_clusters (idx, idx + num_in); + + hb_glyph_info_t orig_info = info[idx]; + hb_glyph_info_t *pinfo = &out_info[out_len]; + for (unsigned int i = 0; i < num_out; i++) + { + *pinfo = orig_info; + pinfo->codepoint = glyph_data[i]; + pinfo++; + } + ++ idx += num_in; + out_len += num_out; +- } +-done: +- idx += num_in; + } + + void + hb_buffer_t::output_glyph (hb_codepoint_t glyph_index) + { +- if (unlikely (!make_room_for (0, 1))) +- goto done; ++ if (unlikely (!make_room_for (0, 1))) return; + + out_info[out_len] = info[idx]; + out_info[out_len].codepoint = glyph_index; + + out_len++; +-done: +- ; + } + + void + hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info) + { +- if (unlikely (!make_room_for (0, 1))) +- goto done; ++ if (unlikely (!make_room_for (0, 1))) return; + + out_info[out_len] = glyph_info; + + out_len++; +-done: +- ; + } + + void + hb_buffer_t::copy_glyph (void) + { +- if (unlikely (!make_room_for (0, 1))) +- goto done; ++ if (unlikely (!make_room_for (0, 1))) return; + + out_info[out_len] = info[idx]; + + out_len++; +-done: +- ; + } + + bool + hb_buffer_t::move_to (unsigned int i) + { + if (!have_output) + { + assert (i <= len); +@@ -395,17 +408,17 @@ hb_buffer_t::move_to (unsigned int i) + return true; + } + + assert (i <= out_len + (len - idx)); + + if (out_len < i) + { + unsigned int count = i - out_len; +- if (unlikely (!make_room_for (count, count))) return false; // XXX verify bailout ++ if (unlikely (!make_room_for (count, count))) return false; + + memmove (out_info + out_len, info + idx, count * sizeof (out_info[0])); + idx += count; + out_len += count; + } + else if (out_len > i) + { + /* Tricky part: rewinding... */ +@@ -422,25 +435,23 @@ hb_buffer_t::move_to (unsigned int i) + + return true; + } + + void + hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index) + { + if (unlikely (out_info != info || out_len != idx)) { +- if (unlikely (!make_room_for (1, 1))) +- goto out; ++ if (unlikely (!make_room_for (1, 1))) return; + out_info[out_len] = info[idx]; + } + out_info[out_len].codepoint = glyph_index; + ++ idx++; + out_len++; +-out: +- idx++; + } + + + void + hb_buffer_t::set_masks (hb_mask_t value, + hb_mask_t mask, + unsigned int cluster_start, + unsigned int cluster_end) +@@ -716,19 +727,24 @@ void hb_buffer_t::deallocate_var_all (vo + memset (allocated_var_owner, 0, sizeof (allocated_var_owner)); + } + + /* Public API */ + + /** + * hb_buffer_create: (Xconstructor) + * +- * ++ * Creates a new #hb_buffer_t with all properties to defaults. + * +- * Return value: (transfer full) ++ * Return value: (transfer full): ++ * A newly allocated #hb_buffer_t with a reference count of 1. The initial ++ * reference count should be released with hb_buffer_destroy() when you are done ++ * using the #hb_buffer_t. This function never returns %NULL. If memory cannot ++ * be allocated, a special #hb_buffer_t object will be returned on which ++ * hb_buffer_allocation_successful() returns %false. + * + * Since: 0.9.2 + **/ + hb_buffer_t * + hb_buffer_create (void) + { + hb_buffer_t *buffer; + +@@ -773,54 +789,60 @@ hb_buffer_get_empty (void) + /* Zero is good enough for everything else. */ + }; + + return const_cast<hb_buffer_t *> (&_hb_buffer_nil); + } + + /** + * hb_buffer_reference: (skip) +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Increases the reference count on @buffer by one. This prevents @buffer from ++ * being destroyed until a matching call to hb_buffer_destroy() is made. + * + * Return value: (transfer full): ++ * The referenced #hb_buffer_t. + * + * Since: 0.9.2 + **/ + hb_buffer_t * + hb_buffer_reference (hb_buffer_t *buffer) + { + return hb_object_reference (buffer); + } + + /** + * hb_buffer_destroy: (skip) +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Deallocate the @buffer. ++ * Decreases the reference count on @buffer by one. If the result is zero, then ++ * @buffer and all associated resources are freed. See hb_buffer_reference(). + * + * Since: 0.9.2 + **/ + void + hb_buffer_destroy (hb_buffer_t *buffer) + { + if (!hb_object_destroy (buffer)) return; + + hb_unicode_funcs_destroy (buffer->unicode); + + free (buffer->info); + free (buffer->pos); ++ if (buffer->message_destroy) ++ buffer->message_destroy (buffer->message_data); + + free (buffer); + } + + /** + * hb_buffer_set_user_data: (skip) +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @key: + * @data: + * @destroy: + * @replace: + * + * + * + * Return value: +@@ -834,17 +856,17 @@ hb_buffer_set_user_data (hb_buffer_t + hb_destroy_func_t destroy, + hb_bool_t replace) + { + return hb_object_set_user_data (buffer, key, data, destroy, replace); + } + + /** + * hb_buffer_get_user_data: (skip) +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @key: + * + * + * + * Return value: + * + * Since: 0.9.2 + **/ +@@ -853,50 +875,52 @@ hb_buffer_get_user_data (hb_buffer_t + hb_user_data_key_t *key) + { + return hb_object_get_user_data (buffer, key); + } + + + /** + * hb_buffer_set_content_type: +- * @buffer: a buffer. +- * @content_type: ++ * @buffer: an #hb_buffer_t. ++ * @content_type: the type of buffer contents to set + * +- * ++ * Sets the type of @buffer contents, buffers are either empty, contain ++ * characters (before shaping) or glyphs (the result of shaping). + * + * Since: 0.9.5 + **/ + void + hb_buffer_set_content_type (hb_buffer_t *buffer, + hb_buffer_content_type_t content_type) + { + buffer->content_type = content_type; + } + + /** + * hb_buffer_get_content_type: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * see hb_buffer_set_content_type(). + * +- * Return value: ++ * Return value: ++ * The type of @buffer contents. + * + * Since: 0.9.5 + **/ + hb_buffer_content_type_t + hb_buffer_get_content_type (hb_buffer_t *buffer) + { + return buffer->content_type; + } + + + /** + * hb_buffer_set_unicode_funcs: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @unicode_funcs: + * + * + * + * Since: 0.9.2 + **/ + void + hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, +@@ -911,210 +935,238 @@ hb_buffer_set_unicode_funcs (hb_buffer_t + + hb_unicode_funcs_reference (unicode_funcs); + hb_unicode_funcs_destroy (buffer->unicode); + buffer->unicode = unicode_funcs; + } + + /** + * hb_buffer_get_unicode_funcs: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * + * + * + * Return value: + * + * Since: 0.9.2 + **/ + hb_unicode_funcs_t * + hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) + { + return buffer->unicode; + } + + /** + * hb_buffer_set_direction: +- * @buffer: a buffer. +- * @direction: ++ * @buffer: an #hb_buffer_t. ++ * @direction: the #hb_direction_t of the @buffer + * +- * ++ * Set the text flow direction of the buffer. No shaping can happen without ++ * setting @buffer direction, and it controls the visual direction for the ++ * output glyphs; for RTL direction the glyphs will be reversed. Many layout ++ * features depend on the proper setting of the direction, for example, ++ * reversing RTL text before shaping, then shaping with LTR direction is not ++ * the same as keeping the text in logical order and shaping with RTL ++ * direction. + * + * Since: 0.9.2 + **/ + void + hb_buffer_set_direction (hb_buffer_t *buffer, + hb_direction_t direction) + + { + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->props.direction = direction; + } + + /** + * hb_buffer_get_direction: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * See hb_buffer_set_direction() + * +- * Return value: ++ * Return value: ++ * The direction of the @buffer. + * + * Since: 0.9.2 + **/ + hb_direction_t + hb_buffer_get_direction (hb_buffer_t *buffer) + { + return buffer->props.direction; + } + + /** + * hb_buffer_set_script: +- * @buffer: a buffer. +- * @script: ++ * @buffer: an #hb_buffer_t. ++ * @script: an #hb_script_t to set. + * +- * ++ * Sets the script of @buffer to @script. ++ * ++ * Script is crucial for choosing the proper shaping behaviour for scripts that ++ * require it (e.g. Arabic) and the which OpenType features defined in the font ++ * to be applied. ++ * ++ * You can pass one of the predefined #hb_script_t values, or use ++ * hb_script_from_string() or hb_script_from_iso15924_tag() to get the ++ * corresponding script from an ISO 15924 script tag. + * + * Since: 0.9.2 + **/ + void + hb_buffer_set_script (hb_buffer_t *buffer, + hb_script_t script) + { + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->props.script = script; + } + + /** + * hb_buffer_get_script: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * See hb_buffer_set_script(). + * +- * Return value: ++ * Return value: ++ * The #hb_script_t of the @buffer. + * + * Since: 0.9.2 + **/ + hb_script_t + hb_buffer_get_script (hb_buffer_t *buffer) + { + return buffer->props.script; + } + + /** + * hb_buffer_set_language: +- * @buffer: a buffer. +- * @language: ++ * @buffer: an #hb_buffer_t. ++ * @language: an hb_language_t to set. + * +- * ++ * Sets the language of @buffer to @language. ++ * ++ * Languages are crucial for selecting which OpenType feature to apply to the ++ * buffer which can result in applying language-specific behaviour. Languages ++ * are orthogonal to the scripts, and though they are related, they are ++ * different concepts and should not be confused with each other. ++ * ++ * Use hb_language_from_string() to convert from ISO 639 language codes to ++ * #hb_language_t. + * + * Since: 0.9.2 + **/ + void + hb_buffer_set_language (hb_buffer_t *buffer, + hb_language_t language) + { + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->props.language = language; + } + + /** + * hb_buffer_get_language: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * See hb_buffer_set_language(). + * + * Return value: (transfer none): ++ * The #hb_language_t of the buffer. Must not be freed by the caller. + * + * Since: 0.9.2 + **/ + hb_language_t + hb_buffer_get_language (hb_buffer_t *buffer) + { + return buffer->props.language; + } + + /** + * hb_buffer_set_segment_properties: +- * @buffer: a buffer. +- * @props: ++ * @buffer: an #hb_buffer_t. ++ * @props: an #hb_segment_properties_t to use. + * +- * ++ * Sets the segment properties of the buffer, a shortcut for calling ++ * hb_buffer_set_direction(), hb_buffer_set_script() and ++ * hb_buffer_set_language() individually. + * + * Since: 0.9.7 + **/ + void + hb_buffer_set_segment_properties (hb_buffer_t *buffer, + const hb_segment_properties_t *props) + { + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->props = *props; + } + + /** + * hb_buffer_get_segment_properties: +- * @buffer: a buffer. +- * @props: (out): ++ * @buffer: an #hb_buffer_t. ++ * @props: (out): the output #hb_segment_properties_t. + * +- * ++ * Sets @props to the #hb_segment_properties_t of @buffer. + * + * Since: 0.9.7 + **/ + void + hb_buffer_get_segment_properties (hb_buffer_t *buffer, + hb_segment_properties_t *props) + { + *props = buffer->props; + } + + + /** + * hb_buffer_set_flags: +- * @buffer: a buffer. +- * @flags: ++ * @buffer: an #hb_buffer_t. ++ * @flags: the buffer flags to set. + * +- * ++ * Sets @buffer flags to @flags. See #hb_buffer_flags_t. + * + * Since: 0.9.7 + **/ + void + hb_buffer_set_flags (hb_buffer_t *buffer, + hb_buffer_flags_t flags) + { + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->flags = flags; + } + + /** + * hb_buffer_get_flags: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * See hb_buffer_set_flags(). + * + * Return value: ++ * The @buffer flags. + * + * Since: 0.9.7 + **/ + hb_buffer_flags_t + hb_buffer_get_flags (hb_buffer_t *buffer) + { + return buffer->flags; + } + + /** + * hb_buffer_set_cluster_level: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @cluster_level: + * + * + * + * Since: 0.9.42 + **/ + void + hb_buffer_set_cluster_level (hb_buffer_t *buffer, +@@ -1123,155 +1175,172 @@ hb_buffer_set_cluster_level (hb_buffer_t + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->cluster_level = cluster_level; + } + + /** + * hb_buffer_get_cluster_level: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * + * + * + * Return value: + * + * Since: 0.9.42 + **/ + hb_buffer_cluster_level_t + hb_buffer_get_cluster_level (hb_buffer_t *buffer) + { + return buffer->cluster_level; + } + + + /** + * hb_buffer_set_replacement_codepoint: +- * @buffer: a buffer. +- * @replacement: ++ * @buffer: an #hb_buffer_t. ++ * @replacement: the replacement #hb_codepoint_t + * +- * ++ * Sets the #hb_codepoint_t that replaces invalid entries for a given encoding ++ * when adding text to @buffer. ++ * ++ * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT. + * + * Since: 0.9.31 + **/ + void + hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, + hb_codepoint_t replacement) + { + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->replacement = replacement; + } + + /** + * hb_buffer_get_replacement_codepoint: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * See hb_buffer_set_replacement_codepoint(). + * + * Return value: ++ * The @buffer replacement #hb_codepoint_t. + * + * Since: 0.9.31 + **/ + hb_codepoint_t + hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer) + { + return buffer->replacement; + } + + + /** + * hb_buffer_reset: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Resets the buffer to its initial status, as if it was just newly created ++ * with hb_buffer_create(). + * + * Since: 0.9.2 + **/ + void + hb_buffer_reset (hb_buffer_t *buffer) + { + buffer->reset (); + } + + /** + * hb_buffer_clear_contents: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Similar to hb_buffer_reset(), but does not clear the Unicode functions and ++ * the replacement code point. + * + * Since: 0.9.11 + **/ + void + hb_buffer_clear_contents (hb_buffer_t *buffer) + { + buffer->clear (); + } + + /** + * hb_buffer_pre_allocate: +- * @buffer: a buffer. +- * @size: ++ * @buffer: an #hb_buffer_t. ++ * @size: number of items to pre allocate. + * +- * ++ * Pre allocates memory for @buffer to fit at least @size number of items. + * +- * Return value: ++ * Return value: ++ * %true if @buffer memory allocation succeeded, %false otherwise. + * + * Since: 0.9.2 + **/ + hb_bool_t + hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) + { + return buffer->ensure (size); + } + + /** + * hb_buffer_allocation_successful: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Check if allocating memory for the buffer succeeded. + * +- * Return value: ++ * Return value: ++ * %true if @buffer memory allocation succeeded, %false otherwise. + * + * Since: 0.9.2 + **/ + hb_bool_t + hb_buffer_allocation_successful (hb_buffer_t *buffer) + { + return !buffer->in_error; + } + + /** + * hb_buffer_add: +- * @buffer: a buffer. +- * @codepoint: +- * @cluster: ++ * @buffer: an #hb_buffer_t. ++ * @codepoint: a Unicode code point. ++ * @cluster: the cluster value of @codepoint. + * +- * ++ * Appends a character with the Unicode value of @codepoint to @buffer, and ++ * gives it the initial cluster value of @cluster. Clusters can be any thing ++ * the client wants, they are usually used to refer to the index of the ++ * character in the input text stream and are output in ++ * #hb_glyph_info_t.cluster field. ++ * ++ * This function does not check the validity of @codepoint, it is up to the ++ * caller to ensure it is a valid Unicode code point. + * + * Since: 0.9.7 + **/ + void + hb_buffer_add (hb_buffer_t *buffer, + hb_codepoint_t codepoint, + unsigned int cluster) + { + buffer->add (codepoint, cluster); + buffer->clear_context (1); + } + + /** + * hb_buffer_set_length: +- * @buffer: a buffer. +- * @length: ++ * @buffer: an #hb_buffer_t. ++ * @length: the new length of @buffer. + * +- * ++ * Similar to hb_buffer_pre_allocate(), but clears any new items added at the ++ * end. + * + * Return value: ++ * %true if @buffer memory allocation succeeded, %false otherwise. + * + * Since: 0.9.2 + **/ + hb_bool_t + hb_buffer_set_length (hb_buffer_t *buffer, + unsigned int length) + { + if (unlikely (hb_object_is_inert (buffer))) +@@ -1296,61 +1365,67 @@ hb_buffer_set_length (hb_buffer_t *buff + } + buffer->clear_context (1); + + return true; + } + + /** + * hb_buffer_get_length: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * + * Returns the number of items in the buffer. + * +- * Return value: buffer length. ++ * Return value: ++ * The @buffer length. ++ * The value valid as long as buffer has not been modified. + * + * Since: 0.9.2 + **/ + unsigned int + hb_buffer_get_length (hb_buffer_t *buffer) + { + return buffer->len; + } + + /** + * hb_buffer_get_glyph_infos: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @length: (out): output array length. + * +- * Returns buffer glyph information array. Returned pointer +- * is valid as long as buffer contents are not modified. ++ * Returns @buffer glyph information array. Returned pointer ++ * is valid as long as @buffer contents are not modified. + * +- * Return value: (transfer none) (array length=length): buffer glyph information array. ++ * Return value: (transfer none) (array length=length): ++ * The @buffer glyph information array. ++ * The value valid as long as buffer has not been modified. + * + * Since: 0.9.2 + **/ + hb_glyph_info_t * + hb_buffer_get_glyph_infos (hb_buffer_t *buffer, + unsigned int *length) + { + if (length) + *length = buffer->len; + + return (hb_glyph_info_t *) buffer->info; + } + + /** + * hb_buffer_get_glyph_positions: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @length: (out): output length. + * +- * Returns buffer glyph position array. Returned pointer +- * is valid as long as buffer contents are not modified. ++ * Returns @buffer glyph position array. Returned pointer ++ * is valid as long as @buffer contents are not modified. + * +- * Return value: (transfer none) (array length=length): buffer glyph position array. ++ * Return value: (transfer none) (array length=length): ++ * The @buffer glyph position array. ++ * The value valid as long as buffer has not been modified. + * + * Since: 0.9.2 + **/ + hb_glyph_position_t * + hb_buffer_get_glyph_positions (hb_buffer_t *buffer, + unsigned int *length) + { + if (!buffer->have_positions) +@@ -1359,64 +1434,64 @@ hb_buffer_get_glyph_positions (hb_buffer + if (length) + *length = buffer->len; + + return (hb_glyph_position_t *) buffer->pos; + } + + /** + * hb_buffer_reverse: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * + * Reverses buffer contents. + * + * Since: 0.9.2 + **/ + void + hb_buffer_reverse (hb_buffer_t *buffer) + { + buffer->reverse (); + } + + /** + * hb_buffer_reverse_range: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * @start: start index. + * @end: end index. + * + * Reverses buffer contents between start to end. + * + * Since: 0.9.41 + **/ + void + hb_buffer_reverse_range (hb_buffer_t *buffer, + unsigned int start, unsigned int end) + { + buffer->reverse_range (start, end); + } + + /** + * hb_buffer_reverse_clusters: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * + * Reverses buffer clusters. That is, the buffer contents are + * reversed, then each cluster (consecutive items having the + * same cluster number) are reversed again. + * + * Since: 0.9.2 + **/ + void + hb_buffer_reverse_clusters (hb_buffer_t *buffer) + { + buffer->reverse_clusters (); + } + + /** + * hb_buffer_guess_segment_properties: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * + * Sets unset buffer segment properties based on buffer Unicode + * contents. If buffer is not empty, it must have content type + * %HB_BUFFER_CONTENT_TYPE_UNICODE. + * + * If buffer script is not set (ie. is %HB_SCRIPT_INVALID), it + * will be set to the Unicode script of the first character in + * the buffer that has a script other than %HB_SCRIPT_COMMON, +@@ -1505,111 +1580,141 @@ hb_buffer_add_utf (hb_buffer_t *buffer, + buffer->context[1][buffer->context_len[1]++] = u; + } + + buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; + } + + /** + * hb_buffer_add_utf8: +- * @buffer: a buffer. +- * @text: (array length=text_length) (element-type uint8_t): +- * @text_length: +- * @item_offset: +- * @item_length: ++ * @buffer: an #hb_buffer_t. ++ * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 ++ * characters to append. ++ * @text_length: the length of the @text, or -1 if it is %NULL terminated. ++ * @item_offset: the offset of the first character to add to the @buffer. ++ * @item_length: the number of characters to add to the @buffer, or -1 for the ++ * end of @text (assuming it is %NULL terminated). + * +- * ++ * See hb_buffer_add_codepoints(). ++ * ++ * Replaces invalid UTF-8 characters with the @buffer replacement code point, ++ * see hb_buffer_set_replacement_codepoint(). + * + * Since: 0.9.2 + **/ + void + hb_buffer_add_utf8 (hb_buffer_t *buffer, + const char *text, + int text_length, + unsigned int item_offset, + int item_length) + { + hb_buffer_add_utf<hb_utf8_t> (buffer, (const uint8_t *) text, text_length, item_offset, item_length); + } + + /** + * hb_buffer_add_utf16: +- * @buffer: a buffer. +- * @text: (array length=text_length): +- * @text_length: +- * @item_offset: +- * @item_length: ++ * @buffer: an #hb_buffer_t. ++ * @text: (array length=text_length): an array of UTF-16 characters to append. ++ * @text_length: the length of the @text, or -1 if it is %NULL terminated. ++ * @item_offset: the offset of the first character to add to the @buffer. ++ * @item_length: the number of characters to add to the @buffer, or -1 for the ++ * end of @text (assuming it is %NULL terminated). + * +- * ++ * See hb_buffer_add_codepoints(). ++ * ++ * Replaces invalid UTF-16 characters with the @buffer replacement code point, ++ * see hb_buffer_set_replacement_codepoint(). + * + * Since: 0.9.2 + **/ + void + hb_buffer_add_utf16 (hb_buffer_t *buffer, + const uint16_t *text, + int text_length, + unsigned int item_offset, + int item_length) + { + hb_buffer_add_utf<hb_utf16_t> (buffer, text, text_length, item_offset, item_length); + } + + /** + * hb_buffer_add_utf32: +- * @buffer: a buffer. +- * @text: (array length=text_length): +- * @text_length: +- * @item_offset: +- * @item_length: ++ * @buffer: an #hb_buffer_t. ++ * @text: (array length=text_length): an array of UTF-32 characters to append. ++ * @text_length: the length of the @text, or -1 if it is %NULL terminated. ++ * @item_offset: the offset of the first character to add to the @buffer. ++ * @item_length: the number of characters to add to the @buffer, or -1 for the ++ * end of @text (assuming it is %NULL terminated). + * +- * ++ * See hb_buffer_add_codepoints(). ++ * ++ * Replaces invalid UTF-32 characters with the @buffer replacement code point, ++ * see hb_buffer_set_replacement_codepoint(). + * + * Since: 0.9.2 + **/ + void + hb_buffer_add_utf32 (hb_buffer_t *buffer, + const uint32_t *text, + int text_length, + unsigned int item_offset, + int item_length) + { + hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length); + } + + /** + * hb_buffer_add_latin1: +- * @buffer: a buffer. +- * @text: (array length=text_length) (element-type uint8_t): +- * @text_length: +- * @item_offset: +- * @item_length: ++ * @buffer: an #hb_buffer_t. ++ * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 ++ * characters to append. ++ * @text_length: the length of the @text, or -1 if it is %NULL terminated. ++ * @item_offset: the offset of the first character to add to the @buffer. ++ * @item_length: the number of characters to add to the @buffer, or -1 for the ++ * end of @text (assuming it is %NULL terminated). + * +- * ++ * Similar to hb_buffer_add_codepoints(), but allows only access to first 256 ++ * Unicode code points that can fit in 8-bit strings. ++ * ++ * <note>Has nothing to do with non-Unicode Latin-1 encoding.</note> + * + * Since: 0.9.39 + **/ + void + hb_buffer_add_latin1 (hb_buffer_t *buffer, + const uint8_t *text, + int text_length, + unsigned int item_offset, + int item_length) + { + hb_buffer_add_utf<hb_latin1_t> (buffer, text, text_length, item_offset, item_length); + } + + /** + * hb_buffer_add_codepoints: +- * @buffer: a buffer. +- * @text: (array length=text_length): +- * @text_length: +- * @item_offset: +- * @item_length: ++ * @buffer: a #hb_buffer_t to append characters to. ++ * @text: (array length=text_length): an array of Unicode code points to append. ++ * @text_length: the length of the @text, or -1 if it is %NULL terminated. ++ * @item_offset: the offset of the first code point to add to the @buffer. ++ * @item_length: the number of code points to add to the @buffer, or -1 for the ++ * end of @text (assuming it is %NULL terminated). + * +- * ++ * Appends characters from @text array to @buffer. The @item_offset is the ++ * position of the first character from @text that will be appended, and ++ * @item_length is the number of character. When shaping part of a larger text ++ * (e.g. a run of text from a paragraph), instead of passing just the substring ++ * corresponding to the run, it is preferable to pass the whole ++ * paragraph and specify the run start and length as @item_offset and ++ * @item_length, respectively, to give HarfBuzz the full context to be able, ++ * for example, to do cross-run Arabic shaping or properly handle combining ++ * marks at stat of run. ++ * ++ * This function does not check the validity of @text, it is up to the caller ++ * to ensure it contains a valid Unicode code points. + * + * Since: 0.9.31 + **/ + void + hb_buffer_add_codepoints (hb_buffer_t *buffer, + const hb_codepoint_t *text, + int text_length, + unsigned int item_offset, +@@ -1671,19 +1776,22 @@ normalize_glyphs_cluster (hb_buffer_t *b + pos[i].y_offset -= total_y_advance; + } + hb_stable_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1); + } + } + + /** + * hb_buffer_normalize_glyphs: +- * @buffer: a buffer. ++ * @buffer: an #hb_buffer_t. + * +- * ++ * Reorders a glyph buffer to have canonical in-cluster glyph order / position. ++ * The resulting clusters should behave identical to pre-reordering clusters. ++ * ++ * <note>This has nothing to do with Unicode normalization.</note> + * + * Since: 0.9.2 + **/ + void + hb_buffer_normalize_glyphs (hb_buffer_t *buffer) + { + assert (buffer->have_positions); + assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); +@@ -1719,8 +1827,50 @@ hb_buffer_t::sort (unsigned int start, u + merge_clusters (j, i + 1); + { + hb_glyph_info_t t = info[i]; + memmove (&info[j + 1], &info[j], (i - j) * sizeof (hb_glyph_info_t)); + info[j] = t; + } + } + } ++ ++/* ++ * Debugging. ++ */ ++ ++/** ++ * hb_buffer_set_message_func: ++ * @buffer: an #hb_buffer_t. ++ * @func: (closure user_data) (destroy destroy) (scope notified): ++ * @user_data: ++ * @destroy: ++ * ++ * ++ * ++ * Since: 1.1.3 ++ **/ ++void ++hb_buffer_set_message_func (hb_buffer_t *buffer, ++ hb_buffer_message_func_t func, ++ void *user_data, hb_destroy_func_t destroy) ++{ ++ if (buffer->message_destroy) ++ buffer->message_destroy (buffer->message_data); ++ ++ if (func) { ++ buffer->message_func = func; ++ buffer->message_data = user_data; ++ buffer->message_destroy = destroy; ++ } else { ++ buffer->message_func = NULL; ++ buffer->message_data = NULL; ++ buffer->message_destroy = NULL; ++ } ++} ++ ++bool ++hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap) ++{ ++ char buf[100]; ++ vsnprintf (buf, sizeof (buf), fmt, ap); ++ return (bool) this->message_func (this, font, buf, this->message_data); ++} +diff --git a/gfx/harfbuzz/src/hb-buffer.h b/gfx/harfbuzz/src/hb-buffer.h +--- a/gfx/harfbuzz/src/hb-buffer.h ++++ b/gfx/harfbuzz/src/hb-buffer.h +@@ -35,344 +35,438 @@ + #define HB_BUFFER_H + + #include "hb-common.h" + #include "hb-unicode.h" + #include "hb-font.h" + + HB_BEGIN_DECLS + +- ++/** ++ * hb_glyph_info_t: ++ * @codepoint: either a Unicode code point (before shaping) or a glyph index ++ * (after shaping). ++ * @mask: ++ * @cluster: the index of the character in the original text that corresponds ++ * to this #hb_glyph_info_t, or whatever the client passes to ++ * hb_buffer_add(). More than one #hb_glyph_info_t can have the same ++ * @cluster value, if they resulted from the same character (e.g. one ++ * to many glyph substitution), and when more than one character gets ++ * merged in the same glyph (e.g. many to one glyph substitution) the ++ * #hb_glyph_info_t will have the smallest cluster value of them. ++ * By default some characters are merged into the same cluster ++ * (e.g. combining marks have the same cluster as their bases) ++ * even if they are separate glyphs, hb_buffer_set_cluster_level() ++ * allow selecting more fine-grained cluster handling. ++ * ++ * The #hb_glyph_info_t is the structure that holds information about the ++ * glyphs and their relation to input text. ++ * ++ */ + typedef struct hb_glyph_info_t { + hb_codepoint_t codepoint; + hb_mask_t mask; + uint32_t cluster; + + /*< private >*/ + hb_var_int_t var1; + hb_var_int_t var2; + } hb_glyph_info_t; + ++/** ++ * hb_glyph_position_t: ++ * @x_advance: how much the line advances after drawing this glyph when setting ++ * text in horizontal direction. ++ * @y_advance: how much the line advances after drawing this glyph when setting ++ * text in vertical direction. ++ * @x_offset: how much the glyph moves on the X-axis before drawing it, this ++ * should not affect how much the line advances. ++ * @y_offset: how much the glyph moves on the Y-axis before drawing it, this ++ * should not affect how much the line advances. ++ * ++ * The #hb_glyph_position_t is the structure that holds the positions of the ++ * glyph in both horizontal and vertical directions. All positions in ++ * #hb_glyph_position_t are relative to the current point. ++ * ++ */ + typedef struct hb_glyph_position_t { + hb_position_t x_advance; + hb_position_t y_advance; + hb_position_t x_offset; + hb_position_t y_offset; + + /*< private >*/ + hb_var_int_t var; + } hb_glyph_position_t; + +- ++/** ++ * hb_segment_properties_t: ++ * @direction: the #hb_direction_t of the buffer, see hb_buffer_set_direction(). ++ * @script: the #hb_script_t of the buffer, see hb_buffer_set_script(). ++ * @language: the #hb_language_t of the buffer, see hb_buffer_set_language(). ++ * ++ * The structure that holds various text properties of an #hb_buffer_t. Can be ++ * set and retrieved using hb_buffer_set_segment_properties() and ++ * hb_buffer_get_segment_properties(), respectively. ++ */ + typedef struct hb_segment_properties_t { + hb_direction_t direction; + hb_script_t script; + hb_language_t language; + /*< private >*/ + void *reserved1; + void *reserved2; + } hb_segment_properties_t; + + #define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \ + HB_SCRIPT_INVALID, \ + HB_LANGUAGE_INVALID, \ + NULL, \ + NULL} + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_segment_properties_equal (const hb_segment_properties_t *a, + const hb_segment_properties_t *b); + +-unsigned int ++HB_EXTERN unsigned int + hb_segment_properties_hash (const hb_segment_properties_t *p); + + + +-/* +- * hb_buffer_t ++/** ++ * hb_buffer_t: ++ * ++ * The main structure holding the input text and its properties before shaping, ++ * and output glyphs and their information after shaping. + */ + + typedef struct hb_buffer_t hb_buffer_t; + +-hb_buffer_t * ++HB_EXTERN hb_buffer_t * + hb_buffer_create (void); + +-hb_buffer_t * ++HB_EXTERN hb_buffer_t * + hb_buffer_get_empty (void); + +-hb_buffer_t * ++HB_EXTERN hb_buffer_t * + hb_buffer_reference (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_destroy (hb_buffer_t *buffer); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_buffer_set_user_data (hb_buffer_t *buffer, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + +-void * ++HB_EXTERN void * + hb_buffer_get_user_data (hb_buffer_t *buffer, + hb_user_data_key_t *key); + +- ++/** ++ * hb_buffer_content_type_t: ++ * @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer. ++ * @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping). ++ * @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping). ++ */ + typedef enum { + HB_BUFFER_CONTENT_TYPE_INVALID = 0, + HB_BUFFER_CONTENT_TYPE_UNICODE, + HB_BUFFER_CONTENT_TYPE_GLYPHS + } hb_buffer_content_type_t; + +-void ++HB_EXTERN void + hb_buffer_set_content_type (hb_buffer_t *buffer, + hb_buffer_content_type_t content_type); + +-hb_buffer_content_type_t ++HB_EXTERN hb_buffer_content_type_t + hb_buffer_get_content_type (hb_buffer_t *buffer); + + +-void ++HB_EXTERN void + hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, + hb_unicode_funcs_t *unicode_funcs); + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_buffer_get_unicode_funcs (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_set_direction (hb_buffer_t *buffer, + hb_direction_t direction); + +-hb_direction_t ++HB_EXTERN hb_direction_t + hb_buffer_get_direction (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_set_script (hb_buffer_t *buffer, + hb_script_t script); + +-hb_script_t ++HB_EXTERN hb_script_t + hb_buffer_get_script (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_set_language (hb_buffer_t *buffer, + hb_language_t language); + + +-hb_language_t ++HB_EXTERN hb_language_t + hb_buffer_get_language (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_set_segment_properties (hb_buffer_t *buffer, + const hb_segment_properties_t *props); + +-void ++HB_EXTERN void + hb_buffer_get_segment_properties (hb_buffer_t *buffer, + hb_segment_properties_t *props); + +-void ++HB_EXTERN void + hb_buffer_guess_segment_properties (hb_buffer_t *buffer); + + +-/* ++/** ++ * hb_buffer_flags_t: ++ * @HB_BUFFER_FLAG_DEFAULT: the default buffer flag. ++ * @HB_BUFFER_FLAG_BOT: flag indicating that special handling of the beginning ++ * of text paragraph can be applied to this buffer. Should usually ++ * be set, unless you are passing to the buffer only part ++ * of the text without the full context. ++ * @HB_BUFFER_FLAG_EOT: flag indicating that special handling of the end of text ++ * paragraph can be applied to this buffer, similar to ++ * @HB_BUFFER_FLAG_EOT. ++ * @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES: ++ * flag indication that character with Default_Ignorable ++ * Unicode property should use the corresponding glyph ++ * from the font, instead of hiding them (currently done ++ * by replacing them with the space glyph and zeroing the ++ * advance width.) ++ * + * Since: 0.9.20 + */ + typedef enum { /*< flags >*/ + HB_BUFFER_FLAG_DEFAULT = 0x00000000u, + HB_BUFFER_FLAG_BOT = 0x00000001u, /* Beginning-of-text */ + HB_BUFFER_FLAG_EOT = 0x00000002u, /* End-of-text */ + HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u + } hb_buffer_flags_t; + +-void ++HB_EXTERN void + hb_buffer_set_flags (hb_buffer_t *buffer, + hb_buffer_flags_t flags); + +-hb_buffer_flags_t ++HB_EXTERN hb_buffer_flags_t + hb_buffer_get_flags (hb_buffer_t *buffer); + + /* + * Since: 0.9.42 + */ + typedef enum { + HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0, + HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1, + HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2, + HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES + } hb_buffer_cluster_level_t; + +-void ++HB_EXTERN void + hb_buffer_set_cluster_level (hb_buffer_t *buffer, + hb_buffer_cluster_level_t cluster_level); + +-hb_buffer_cluster_level_t ++HB_EXTERN hb_buffer_cluster_level_t + hb_buffer_get_cluster_level (hb_buffer_t *buffer); + ++/** ++ * HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT: ++ * ++ * The default code point for replacing invalid characters in a given encoding. ++ * Set to U+FFFD REPLACEMENT CHARACTER. ++ * ++ * Since: 0.9.31 ++ */ + #define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu + +-/* Sets codepoint used to replace invalid UTF-8/16/32 entries. +- * Default is 0xFFFDu. */ +-void ++HB_EXTERN void + hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, + hb_codepoint_t replacement); + +-hb_codepoint_t ++HB_EXTERN hb_codepoint_t + hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer); + + +-/* Resets the buffer. Afterwards it's as if it was just created, +- * except that it has a larger buffer allocated perhaps... */ +-void ++HB_EXTERN void + hb_buffer_reset (hb_buffer_t *buffer); + +-/* Like reset, but does NOT clear unicode_funcs and replacement_codepoint. */ +-void ++HB_EXTERN void + hb_buffer_clear_contents (hb_buffer_t *buffer); + +-/* Returns false if allocation failed */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_buffer_pre_allocate (hb_buffer_t *buffer, + unsigned int size); + + +-/* Returns false if allocation has failed before */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_buffer_allocation_successful (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_reverse (hb_buffer_t *buffer); + +-void ++HB_EXTERN void + hb_buffer_reverse_range (hb_buffer_t *buffer, + unsigned int start, unsigned int end); + +-void ++HB_EXTERN void + hb_buffer_reverse_clusters (hb_buffer_t *buffer); + + + /* Filling the buffer in */ + +-void ++HB_EXTERN void + hb_buffer_add (hb_buffer_t *buffer, + hb_codepoint_t codepoint, + unsigned int cluster); + +-void ++HB_EXTERN void + hb_buffer_add_utf8 (hb_buffer_t *buffer, + const char *text, + int text_length, + unsigned int item_offset, + int item_length); + +-void ++HB_EXTERN void + hb_buffer_add_utf16 (hb_buffer_t *buffer, + const uint16_t *text, + int text_length, + unsigned int item_offset, + int item_length); + +-void ++HB_EXTERN void + hb_buffer_add_utf32 (hb_buffer_t *buffer, + const uint32_t *text, + int text_length, + unsigned int item_offset, + int item_length); + +-/* Allows only access to first 256 Unicode codepoints. */ +-void ++HB_EXTERN void + hb_buffer_add_latin1 (hb_buffer_t *buffer, + const uint8_t *text, + int text_length, + unsigned int item_offset, + int item_length); + +-/* Like add_utf32 but does NOT check for invalid Unicode codepoints. */ +-void ++HB_EXTERN void + hb_buffer_add_codepoints (hb_buffer_t *buffer, + const hb_codepoint_t *text, + int text_length, + unsigned int item_offset, + int item_length); + + +-/* Clears any new items added at the end */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_buffer_set_length (hb_buffer_t *buffer, + unsigned int length); + +-/* Return value valid as long as buffer not modified */ +-unsigned int ++HB_EXTERN unsigned int + hb_buffer_get_length (hb_buffer_t *buffer); + + /* Getting glyphs out of the buffer */ + +-/* Return value valid as long as buffer not modified */ +-hb_glyph_info_t * ++HB_EXTERN hb_glyph_info_t * + hb_buffer_get_glyph_infos (hb_buffer_t *buffer, + unsigned int *length); + +-/* Return value valid as long as buffer not modified */ +-hb_glyph_position_t * ++HB_EXTERN hb_glyph_position_t * + hb_buffer_get_glyph_positions (hb_buffer_t *buffer, + unsigned int *length); + + +-/* Reorders a glyph buffer to have canonical in-cluster glyph order / position. +- * The resulting clusters should behave identical to pre-reordering clusters. +- * NOTE: This has nothing to do with Unicode normalization. */ +-void ++HB_EXTERN void + hb_buffer_normalize_glyphs (hb_buffer_t *buffer); + + + /* + * Serialize + */ + +-/* ++/** ++ * hb_buffer_serialize_flags_t: ++ * @HB_BUFFER_SERIALIZE_FLAG_DEFAULT: serialize glyph names, clusters and positions. ++ * @HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS: do not serialize glyph cluster. ++ * @HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS: do not serialize glyph position information. ++ * @HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES: do no serialize glyph name. ++ * @HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS: serialize glyph extents. ++ * ++ * Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs(). ++ * + * Since: 0.9.20 + */ + typedef enum { /*< flags >*/ + HB_BUFFER_SERIALIZE_FLAG_DEFAULT = 0x00000000u, + HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u, + HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u, + HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u, + HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u + } hb_buffer_serialize_flags_t; + ++/** ++ * hb_buffer_serialize_format_t: ++ * @HB_BUFFER_SERIALIZE_FORMAT_TEXT: a human-readable, plain text format. ++ * @HB_BUFFER_SERIALIZE_FORMAT_JSON: a machine-readable JSON format. ++ * @HB_BUFFER_SERIALIZE_FORMAT_INVALID: invalid format. ++ * ++ * The buffer serialization and de-serialization format used in ++ * hb_buffer_serialize_glyphs() and hb_buffer_deserialize_glyphs(). ++ * ++ * Since: 0.9.2 ++ */ + typedef enum { + HB_BUFFER_SERIALIZE_FORMAT_TEXT = HB_TAG('T','E','X','T'), + HB_BUFFER_SERIALIZE_FORMAT_JSON = HB_TAG('J','S','O','N'), + HB_BUFFER_SERIALIZE_FORMAT_INVALID = HB_TAG_NONE + } hb_buffer_serialize_format_t; + +-/* len=-1 means str is NUL-terminated. */ +-hb_buffer_serialize_format_t ++HB_EXTERN hb_buffer_serialize_format_t + hb_buffer_serialize_format_from_string (const char *str, int len); + +-const char * ++HB_EXTERN const char * + hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format); + +-const char ** ++HB_EXTERN const char ** + hb_buffer_serialize_list_formats (void); + +-/* Returns number of items, starting at start, that were serialized. */ +-unsigned int ++HB_EXTERN unsigned int + hb_buffer_serialize_glyphs (hb_buffer_t *buffer, + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, +- unsigned int *buf_consumed, /* May be NULL */ +- hb_font_t *font, /* May be NULL */ ++ unsigned int *buf_consumed, ++ hb_font_t *font, + hb_buffer_serialize_format_t format, + hb_buffer_serialize_flags_t flags); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, + const char *buf, +- int buf_len, /* -1 means nul-terminated */ +- const char **end_ptr, /* May be NULL */ +- hb_font_t *font, /* May be NULL */ ++ int buf_len, ++ const char **end_ptr, ++ hb_font_t *font, + hb_buffer_serialize_format_t format); + + ++/* ++ * Debugging. ++ */ ++ ++typedef hb_bool_t (*hb_buffer_message_func_t) (hb_buffer_t *buffer, ++ hb_font_t *font, ++ const char *message, ++ void *user_data); ++ ++HB_EXTERN void ++hb_buffer_set_message_func (hb_buffer_t *buffer, ++ hb_buffer_message_func_t func, ++ void *user_data, hb_destroy_func_t destroy); ++ ++ + HB_END_DECLS + + #endif /* HB_BUFFER_H */ +diff --git a/gfx/harfbuzz/src/hb-common.cc b/gfx/harfbuzz/src/hb-common.cc +--- a/gfx/harfbuzz/src/hb-common.cc ++++ b/gfx/harfbuzz/src/hb-common.cc +@@ -276,22 +276,25 @@ retry: + #endif + + return lang; + } + + + /** + * hb_language_from_string: +- * @str: (array length=len) (element-type uint8_t): +- * @len: ++ * @str: (array length=len) (element-type uint8_t): a string representing ++ * ISO 639 language code ++ * @len: length of the @str, or -1 if it is %NULL-terminated. + * +- * ++ * Converts @str representing an ISO 639 language code to the corresponding ++ * #hb_language_t. + * + * Return value: (transfer none): ++ * The #hb_language_t corresponding to the ISO 639 language code. + * + * Since: 0.9.2 + **/ + hb_language_t + hb_language_from_string (const char *str, int len) + { + if (!str || !len || !*str) + return HB_LANGUAGE_INVALID; +@@ -309,21 +312,23 @@ hb_language_from_string (const char *str + else + item = lang_find_or_insert (str); + + return likely (item) ? item->lang : HB_LANGUAGE_INVALID; + } + + /** + * hb_language_to_string: +- * @language: ++ * @language: an #hb_language_t to convert. + * +- * ++ * See hb_language_from_string(). + * +- * Return value: (transfer none): ++ * Return value: (transfer none): ++ * A %NULL-terminated string representing the @language. Must not be freed by ++ * the caller. + * + * Since: 0.9.2 + **/ + const char * + hb_language_to_string (hb_language_t language) + { + /* This is actually NULL-safe! */ + return language->s; +@@ -352,21 +357,22 @@ hb_language_get_default (void) + return default_language; + } + + + /* hb_script_t */ + + /** + * hb_script_from_iso15924_tag: +- * @tag: ++ * @tag: an #hb_tag_t representing an ISO 15924 tag. + * +- * ++ * Converts an ISO 15924 script tag to a corresponding #hb_script_t. + * + * Return value: ++ * An #hb_script_t corresponding to the ISO 15924 tag. + * + * Since: 0.9.2 + **/ + hb_script_t + hb_script_from_iso15924_tag (hb_tag_t tag) + { + if (unlikely (tag == HB_TAG_NONE)) + return HB_SCRIPT_INVALID; +@@ -396,38 +402,43 @@ hb_script_from_iso15924_tag (hb_tag_t ta + return (hb_script_t) tag; + + /* Otherwise, return unknown */ + return HB_SCRIPT_UNKNOWN; + } + + /** + * hb_script_from_string: +- * @s: (array length=len) (element-type uint8_t): +- * @len: ++ * @str: (array length=len) (element-type uint8_t): a string representing an ++ * ISO 15924 tag. ++ * @len: length of the @str, or -1 if it is %NULL-terminated. + * +- * ++ * Converts a string @str representing an ISO 15924 script tag to a ++ * corresponding #hb_script_t. Shorthand for hb_tag_from_string() then ++ * hb_script_from_iso15924_tag(). + * + * Return value: ++ * An #hb_script_t corresponding to the ISO 15924 tag. + * + * Since: 0.9.2 + **/ + hb_script_t +-hb_script_from_string (const char *s, int len) ++hb_script_from_string (const char *str, int len) + { +- return hb_script_from_iso15924_tag (hb_tag_from_string (s, len)); ++ return hb_script_from_iso15924_tag (hb_tag_from_string (str, len)); + } + + /** + * hb_script_to_iso15924_tag: +- * @script: ++ * @script: an #hb_script_ to convert. + * +- * ++ * See hb_script_from_iso15924_tag(). + * +- * Return value: ++ * Return value: ++ * An #hb_tag_t representing an ISO 15924 script tag. + * + * Since: 0.9.2 + **/ + hb_tag_t + hb_script_to_iso15924_tag (hb_script_t script) + { + return (hb_tag_t) script; + } +@@ -516,17 +527,17 @@ hb_user_data_array_t::set (hb_user_data_ + + if (replace) { + if (!data && !destroy) { + items.remove (key, lock); + return true; + } + } + hb_user_data_item_t item = {key, data, destroy}; +- bool ret = !!items.replace_or_insert (item, lock, replace); ++ bool ret = !!items.replace_or_insert (item, lock, (bool) replace); + + return ret; + } + + void * + hb_user_data_array_t::get (hb_user_data_key_t *key) + { + hb_user_data_item_t item = {NULL }; +diff --git a/gfx/harfbuzz/src/hb-common.h b/gfx/harfbuzz/src/hb-common.h +--- a/gfx/harfbuzz/src/hb-common.h ++++ b/gfx/harfbuzz/src/hb-common.h +@@ -93,64 +93,69 @@ typedef uint32_t hb_tag_t; + #define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint8_t)(c1))<<24)|(((uint8_t)(c2))<<16)|(((uint8_t)(c3))<<8)|((uint8_t)(c4)))) + #define HB_UNTAG(tag) ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag)) + + #define HB_TAG_NONE HB_TAG(0,0,0,0) + #define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff) + #define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff) + + /* len=-1 means str is NUL-terminated. */ +-hb_tag_t ++HB_EXTERN hb_tag_t + hb_tag_from_string (const char *str, int len); + + /* buf should have 4 bytes. */ +-void ++HB_EXTERN void + hb_tag_to_string (hb_tag_t tag, char *buf); + + +-/* hb_direction_t */ +- ++/** ++ * hb_direction_t: ++ * @HB_DIRECTION_INVALID: Initial, unset direction. ++ * @HB_DIRECTION_LTR: Text is set horizontally from left to right. ++ * @HB_DIRECTION_RTL: Text is set horizontally from right to left. ++ * @HB_DIRECTION_TTB: Text is set vertically from top to bottom. ++ * @HB_DIRECTION_BTT: Text is set vertically from bottom to top. ++ */ + typedef enum { + HB_DIRECTION_INVALID = 0, + HB_DIRECTION_LTR = 4, + HB_DIRECTION_RTL, + HB_DIRECTION_TTB, + HB_DIRECTION_BTT + } hb_direction_t; + + /* len=-1 means str is NUL-terminated */ +-hb_direction_t ++HB_EXTERN hb_direction_t + hb_direction_from_string (const char *str, int len); + +-const char * ++HB_EXTERN const char * + hb_direction_to_string (hb_direction_t direction); + + #define HB_DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4) + /* Direction must be valid for the following */ + #define HB_DIRECTION_IS_HORIZONTAL(dir) ((((unsigned int) (dir)) & ~1U) == 4) + #define HB_DIRECTION_IS_VERTICAL(dir) ((((unsigned int) (dir)) & ~1U) == 6) + #define HB_DIRECTION_IS_FORWARD(dir) ((((unsigned int) (dir)) & ~2U) == 4) + #define HB_DIRECTION_IS_BACKWARD(dir) ((((unsigned int) (dir)) & ~2U) == 5) + #define HB_DIRECTION_REVERSE(dir) ((hb_direction_t) (((unsigned int) (dir)) ^ 1)) + + + /* hb_language_t */ + + typedef const struct hb_language_impl_t *hb_language_t; + +-/* len=-1 means str is NUL-terminated */ +-hb_language_t ++HB_EXTERN hb_language_t + hb_language_from_string (const char *str, int len); + +-const char * ++HB_EXTERN const char * + hb_language_to_string (hb_language_t language); + + #define HB_LANGUAGE_INVALID ((hb_language_t) NULL) + +-hb_language_t ++HB_EXTERN hb_language_t + hb_language_get_default (void); + + + /* hb_script_t */ + + /* http://unicode.org/iso15924/ */ + /* http://goo.gl/x9ilM */ + /* Unicode Character Database property: Script (sc) */ +@@ -319,28 +324,26 @@ typedef enum + _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX, /*< skip >*/ + _HB_SCRIPT_MAX_VALUE_SIGNED = HB_TAG_MAX_SIGNED /*< skip >*/ + + } hb_script_t; + + + /* Script functions */ + +-hb_script_t ++HB_EXTERN hb_script_t + hb_script_from_iso15924_tag (hb_tag_t tag); + +-/* sugar for tag_from_string() then script_from_iso15924_tag */ +-/* len=-1 means s is NUL-terminated */ +-hb_script_t +-hb_script_from_string (const char *s, int len); ++HB_EXTERN hb_script_t ++hb_script_from_string (const char *str, int len); + +-hb_tag_t ++HB_EXTERN hb_tag_t + hb_script_to_iso15924_tag (hb_script_t script); + +-hb_direction_t ++HB_EXTERN hb_direction_t + hb_script_get_horizontal_direction (hb_script_t script); + + + /* User data */ + + typedef struct hb_user_data_key_t { + /*< private >*/ + char unused; +diff --git a/gfx/harfbuzz/src/hb-coretext.cc b/gfx/harfbuzz/src/hb-coretext.cc +--- a/gfx/harfbuzz/src/hb-coretext.cc ++++ b/gfx/harfbuzz/src/hb-coretext.cc +@@ -171,16 +171,53 @@ hb_coretext_shaper_font_data_t * + data->y_mult = (CGFloat) font->y_scale / font_size; + data->ct_font = CTFontCreateWithGraphicsFont (face_data, font_size, NULL, NULL); + if (unlikely (!data->ct_font)) { + DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); + free (data); + return NULL; + } + ++ /* Create font copy with cascade list that has LastResort first; this speeds up CoreText ++ * font fallback which we don't need anyway. */ ++ { ++ // TODO Handle allocation failures? ++ CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize(CFSTR("LastResort"), 0); ++ CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault, ++ (const void **) &last_resort, ++ 1, ++ &kCFTypeArrayCallBacks); ++ CFRelease (last_resort); ++ CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault, ++ (const void **) &kCTFontCascadeListAttribute, ++ (const void **) &cascade_list, ++ 1, ++ &kCFTypeDictionaryKeyCallBacks, ++ &kCFTypeDictionaryValueCallBacks); ++ CFRelease (cascade_list); ++ ++ CTFontDescriptorRef new_font_desc = CTFontDescriptorCreateWithAttributes (attributes); ++ CFRelease (attributes); ++ ++ CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (data->ct_font, 0.0, NULL, new_font_desc); ++ if (new_ct_font) ++ { ++ CFRelease (data->ct_font); ++ data->ct_font = new_ct_font; ++ } ++ else ++ DEBUG_MSG (CORETEXT, font, "Font copy with empty cascade list failed"); ++ } ++ ++ if (unlikely (!data->ct_font)) { ++ DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); ++ free (data); ++ return NULL; ++ } ++ + return data; + } + + void + _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) + { + CFRelease (data->ct_font); + free (data); +@@ -688,17 +725,16 @@ resize_and_retry: + /* Adjust scratch, pchars, and log_cluster arrays. This is ugly, but really the + * cleanest way to do without completely restructuring the rest of this shaper. */ + scratch = buffer->get_scratch_buffer (&scratch_size); + pchars = reinterpret_cast<UniChar *> (((char *) scratch + ((char *) pchars - (char *) old_scratch))); + log_clusters = reinterpret_cast<unsigned int *> (((char *) scratch + ((char *) log_clusters - (char *) old_scratch))); + scratch += old_scratch_used; + scratch_size -= old_scratch_used; + } +-retry: + { + string_ref = CFStringCreateWithCharactersNoCopy (NULL, + pchars, chars_len, + kCFAllocatorNull); + if (unlikely (!string_ref)) + FAIL ("CFStringCreateWithCharactersNoCopy failed"); + + /* Create an attributed string, populate it, and create a line from it, then release attributed string. */ +@@ -843,21 +879,19 @@ retry: + * + * Looks like if we really want to be sure here we have to modify the + * font to change the name table, similar to what we do in the uniscribe + * backend. + * + * However, even that wouldn't work if we were passed in the CGFont to + * begin with. + * +- * Webkit uses a slightly different approach: it installs LastResort +- * as fallback chain, and then checks PS name of used font against +- * LastResort. That one is safe for any font except for LastResort, +- * as opposed to ours, which can fail if we are using any uninstalled +- * font that has the same name as an installed font. ++ * We might switch to checking PS name against "LastResort". That would ++ * be safe for all fonts except for those named "Last Resort". Might be ++ * better than what we have right now. + * + * See: http://github.com/behdad/harfbuzz/pull/36 + */ + bool matched = false; + for (unsigned int i = 0; i < range_records.len; i++) + if (range_records[i].font && CFEqual (run_ct_font, range_records[i].font)) + { + matched = true; +@@ -1124,20 +1158,16 @@ fail: + return ret; + } + + + /* + * AAT shaper + */ + +-HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, face) +-HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, font) +- +- + /* + * shaper face data + */ + + struct hb_coretext_aat_shaper_face_data_t {}; + + hb_coretext_aat_shaper_face_data_t * + _hb_coretext_aat_shaper_face_data_create (hb_face_t *face) +diff --git a/gfx/harfbuzz/src/hb-coretext.h b/gfx/harfbuzz/src/hb-coretext.h +--- a/gfx/harfbuzz/src/hb-coretext.h ++++ b/gfx/harfbuzz/src/hb-coretext.h +@@ -39,22 +39,22 @@ + + HB_BEGIN_DECLS + + + #define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t') + #define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x') + + +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_coretext_face_create (CGFontRef cg_font); + + +-CGFontRef ++HB_EXTERN CGFontRef + hb_coretext_face_get_cg_font (hb_face_t *face); + +-CTFontRef ++HB_EXTERN CTFontRef + hb_coretext_font_get_ct_font (hb_font_t *font); + + + HB_END_DECLS + + #endif /* HB_CORETEXT_H */ +diff --git a/gfx/harfbuzz/src/hb-directwrite.cc b/gfx/harfbuzz/src/hb-directwrite.cc +new file mode 100644 +--- /dev/null ++++ b/gfx/harfbuzz/src/hb-directwrite.cc +@@ -0,0 +1,827 @@ ++/* ++ * Copyright © 2015 Ebrahim Byagowi ++ * ++ * 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. ++ */ ++ ++#define HB_SHAPER directwrite ++#include "hb-shaper-impl-private.hh" ++ ++#include <dwrite.h> ++ ++#include "hb-directwrite.h" ++ ++#include "hb-open-file-private.hh" ++#include "hb-ot-name-table.hh" ++#include "hb-ot-tag.h" ++ ++ ++#ifndef HB_DEBUG_DIRECTWRITE ++#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0) ++#endif ++ ++HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, face) ++HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, font) ++ ++/* ++* shaper face data ++*/ ++ ++struct hb_directwrite_shaper_face_data_t { ++ HANDLE fh; ++ wchar_t face_name[LF_FACESIZE]; ++}; ++ ++/* face_name should point to a wchar_t[LF_FACESIZE] object. */ ++static void ++_hb_generate_unique_face_name(wchar_t *face_name, unsigned int *plen) ++{ ++ /* We'll create a private name for the font from a UUID using a simple, ++ * somewhat base64-like encoding scheme */ ++ const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"; ++ UUID id; ++ UuidCreate ((UUID*)&id); ++ ASSERT_STATIC (2 + 3 * (16 / 2) < LF_FACESIZE); ++ unsigned int name_str_len = 0; ++ face_name[name_str_len++] = 'F'; ++ face_name[name_str_len++] = '_'; ++ unsigned char *p = (unsigned char *)&id; ++ for (unsigned int i = 0; i < 16; i += 2) ++ { ++ /* Spread the 16 bits from two bytes of the UUID across three chars of face_name, ++ * using the bits in groups of 5,5,6 to select chars from enc. ++ * This will generate 24 characters; with the 'F_' prefix we already provided, ++ * the name will be 26 chars (plus the NUL terminator), so will always fit within ++ * face_name (LF_FACESIZE = 32). */ ++ face_name[name_str_len++] = enc[p[i] >> 3]; ++ face_name[name_str_len++] = enc[((p[i] << 2) | (p[i + 1] >> 6)) & 0x1f]; ++ face_name[name_str_len++] = enc[p[i + 1] & 0x3f]; ++ } ++ face_name[name_str_len] = 0; ++ if (plen) ++ *plen = name_str_len; ++} ++ ++/* Destroys blob. */ ++static hb_blob_t * ++_hb_rename_font(hb_blob_t *blob, wchar_t *new_name) ++{ ++ /* Create a copy of the font data, with the 'name' table replaced by a ++ * table that names the font with our private F_* name created above. ++ * For simplicity, we just append a new 'name' table and update the ++ * sfnt directory; the original table is left in place, but unused. ++ * ++ * The new table will contain just 5 name IDs: family, style, unique, ++ * full, PS. All of them point to the same name data with our unique name. ++ */ ++ ++ blob = OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (blob); ++ ++ unsigned int length, new_length, name_str_len; ++ const char *orig_sfnt_data = hb_blob_get_data (blob, &length); ++ ++ _hb_generate_unique_face_name (new_name, &name_str_len); ++ ++ static const uint16_t name_IDs[] = { 1, 2, 3, 4, 6 }; ++ ++ unsigned int name_table_length = OT::name::min_size + ++ ARRAY_LENGTH(name_IDs) * OT::NameRecord::static_size + ++ name_str_len * 2; /* for name data in UTF16BE form */ ++ unsigned int name_table_offset = (length + 3) & ~3; ++ ++ new_length = name_table_offset + ((name_table_length + 3) & ~3); ++ void *new_sfnt_data = calloc(1, new_length); ++ if (!new_sfnt_data) ++ { ++ hb_blob_destroy (blob); ++ return NULL; ++ } ++ ++ memcpy(new_sfnt_data, orig_sfnt_data, length); ++ ++ OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset); ++ name.format.set (0); ++ name.count.set (ARRAY_LENGTH (name_IDs)); ++ name.stringOffset.set (name.get_size()); ++ for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++) ++ { ++ OT::NameRecord &record = name.nameRecord[i]; ++ record.platformID.set(3); ++ record.encodingID.set(1); ++ record.languageID.set(0x0409u); /* English */ ++ record.nameID.set(name_IDs[i]); ++ record.length.set(name_str_len * 2); ++ record.offset.set(0); ++ } ++ ++ /* Copy string data from new_name, converting wchar_t to UTF16BE. */ ++ unsigned char *p = &OT::StructAfter<unsigned char>(name); ++ for (unsigned int i = 0; i < name_str_len; i++) ++ { ++ *p++ = new_name[i] >> 8; ++ *p++ = new_name[i] & 0xff; ++ } ++ ++ /* Adjust name table entry to point to new name table */ ++ const OT::OpenTypeFontFile &file = *(OT::OpenTypeFontFile *) (new_sfnt_data); ++ unsigned int face_count = file.get_face_count (); ++ for (unsigned int face_index = 0; face_index < face_count; face_index++) ++ { ++ /* Note: doing multiple edits (ie. TTC) can be unsafe. There may be ++ * toe-stepping. But we don't really care. */ ++ const OT::OpenTypeFontFace &face = file.get_face (face_index); ++ unsigned int index; ++ if (face.find_table_index (HB_OT_TAG_name, &index)) ++ { ++ OT::TableRecord &record = const_cast<OT::TableRecord &> (face.get_table (index)); ++ record.checkSum.set_for_data (&name, name_table_length); ++ record.offset.set (name_table_offset); ++ record.length.set (name_table_length); ++ } ++ else if (face_index == 0) /* Fail if first face doesn't have 'name' table. */ ++ { ++ free (new_sfnt_data); ++ hb_blob_destroy (blob); ++ return NULL; ++ } ++ } ++ ++ /* The checkSumAdjustment field in the 'head' table is now wrong, ++ * but that doesn't actually seem to cause any problems so we don't ++ * bother. */ ++ ++ hb_blob_destroy (blob); ++ return hb_blob_create ((const char *)new_sfnt_data, new_length, ++ HB_MEMORY_MODE_WRITABLE, NULL, free); ++} ++ ++hb_directwrite_shaper_face_data_t * ++_hb_directwrite_shaper_face_data_create(hb_face_t *face) ++{ ++ hb_directwrite_shaper_face_data_t *data = (hb_directwrite_shaper_face_data_t *)calloc(1, sizeof (hb_directwrite_shaper_face_data_t)); ++ if (unlikely (!data)) ++ return NULL; ++ ++ hb_blob_t *blob = hb_face_reference_blob (face); ++ if (unlikely (!hb_blob_get_length (blob))) ++ DEBUG_MSG(DIRECTWRITE, face, "Face has empty blob"); ++ ++ blob = _hb_rename_font (blob, data->face_name); ++ if (unlikely (!blob)) ++ { ++ free(data); ++ return NULL; ++ } ++ ++ DWORD num_fonts_installed; ++ data->fh = AddFontMemResourceEx ((void *)hb_blob_get_data(blob, NULL), ++ hb_blob_get_length (blob), ++ 0, &num_fonts_installed); ++ if (unlikely (!data->fh)) ++ { ++ DEBUG_MSG (DIRECTWRITE, face, "Face AddFontMemResourceEx() failed"); ++ free (data); ++ return NULL; ++ } ++ ++ return data; ++} ++ ++void ++_hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data) ++{ ++ RemoveFontMemResourceEx(data->fh); ++ free(data); ++} ++ ++ ++/* ++ * shaper font data ++ */ ++ ++struct hb_directwrite_shaper_font_data_t { ++ HDC hdc; ++ LOGFONTW log_font; ++ HFONT hfont; ++}; ++ ++static bool ++populate_log_font (LOGFONTW *lf, ++ hb_font_t *font) ++{ ++ memset (lf, 0, sizeof (*lf)); ++ lf->lfHeight = -font->y_scale; ++ lf->lfCharSet = DEFAULT_CHARSET; ++ ++ hb_face_t *face = font->face; ++ hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); ++ ++ memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName)); ++ ++ return true; ++} ++ ++hb_directwrite_shaper_font_data_t * ++_hb_directwrite_shaper_font_data_create (hb_font_t *font) ++{ ++ if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return NULL; ++ ++ hb_directwrite_shaper_font_data_t *data = (hb_directwrite_shaper_font_data_t *) calloc (1, sizeof (hb_directwrite_shaper_font_data_t)); ++ if (unlikely (!data)) ++ return NULL; ++ ++ data->hdc = GetDC (NULL); ++ ++ if (unlikely (!populate_log_font (&data->log_font, font))) { ++ DEBUG_MSG (DIRECTWRITE, font, "Font populate_log_font() failed"); ++ _hb_directwrite_shaper_font_data_destroy (data); ++ return NULL; ++ } ++ ++ data->hfont = CreateFontIndirectW (&data->log_font); ++ if (unlikely (!data->hfont)) { ++ DEBUG_MSG (DIRECTWRITE, font, "Font CreateFontIndirectW() failed"); ++ _hb_directwrite_shaper_font_data_destroy (data); ++ return NULL; ++ } ++ ++ if (!SelectObject (data->hdc, data->hfont)) { ++ DEBUG_MSG (DIRECTWRITE, font, "Font SelectObject() failed"); ++ _hb_directwrite_shaper_font_data_destroy (data); ++ return NULL; ++ } ++ ++ return data; ++} ++ ++void ++_hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data) ++{ ++ if (data->hdc) ++ ReleaseDC (NULL, data->hdc); ++ if (data->hfont) ++ DeleteObject (data->hfont); ++ free (data); ++} ++ ++LOGFONTW * ++hb_directwrite_font_get_logfontw (hb_font_t *font) ++{ ++ if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL; ++ hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); ++ return &font_data->log_font; ++} ++ ++HFONT ++hb_directwrite_font_get_hfont (hb_font_t *font) ++{ ++ if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL; ++ hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); ++ return font_data->hfont; ++} ++ ++ ++/* ++ * shaper shape_plan data ++ */ ++ ++struct hb_directwrite_shaper_shape_plan_data_t {}; ++ ++hb_directwrite_shaper_shape_plan_data_t * ++_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, ++ const hb_feature_t *user_features HB_UNUSED, ++ unsigned int num_user_features HB_UNUSED) ++{ ++ return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; ++} ++ ++void ++_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan_data_t *data HB_UNUSED) ++{ ++} ++ ++// Most of here TextAnalysis is originally written by Bas Schouten for Mozilla project ++// but now is relicensed to MIT for HarfBuzz use ++class TextAnalysis ++ : public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink ++{ ++public: ++ ++ IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) { return S_OK; } ++ IFACEMETHOD_(ULONG, AddRef)() { return 1; } ++ IFACEMETHOD_(ULONG, Release)() { return 1; } ++ ++ // A single contiguous run of characters containing the same analysis ++ // results. ++ struct Run ++ { ++ UINT32 mTextStart; // starting text position of this run ++ UINT32 mTextLength; // number of contiguous code units covered ++ UINT32 mGlyphStart; // starting glyph in the glyphs array ++ UINT32 mGlyphCount; // number of glyphs associated with this run of ++ // text ++ DWRITE_SCRIPT_ANALYSIS mScript; ++ UINT8 mBidiLevel; ++ bool mIsSideways; ++ ++ inline bool ContainsTextPosition(UINT32 aTextPosition) const ++ { ++ return aTextPosition >= mTextStart ++ && aTextPosition < mTextStart + mTextLength; ++ } ++ ++ Run *nextRun; ++ }; ++ ++public: ++ TextAnalysis(const wchar_t* text, ++ UINT32 textLength, ++ const wchar_t* localeName, ++ DWRITE_READING_DIRECTION readingDirection) ++ : mText(text) ++ , mTextLength(textLength) ++ , mLocaleName(localeName) ++ , mReadingDirection(readingDirection) ++ , mCurrentRun(NULL) { }; ++ ++ ~TextAnalysis() { ++ // delete runs, except mRunHead which is part of the TextAnalysis object ++ for (Run *run = mRunHead.nextRun; run;) { ++ Run *origRun = run; ++ run = run->nextRun; ++ delete origRun; ++ } ++ } ++ ++ STDMETHODIMP GenerateResults(IDWriteTextAnalyzer* textAnalyzer, ++ Run **runHead) { ++ // Analyzes the text using the script analyzer and returns ++ // the result as a series of runs. ++ ++ HRESULT hr = S_OK; ++ ++ // Initially start out with one result that covers the entire range. ++ // This result will be subdivided by the analysis processes. ++ mRunHead.mTextStart = 0; ++ mRunHead.mTextLength = mTextLength; ++ mRunHead.mBidiLevel = ++ (mReadingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT); ++ mRunHead.nextRun = NULL; ++ mCurrentRun = &mRunHead; ++ ++ // Call each of the analyzers in sequence, recording their results. ++ if (SUCCEEDED(hr = textAnalyzer->AnalyzeScript(this, ++ 0, ++ mTextLength, ++ this))) { ++ *runHead = &mRunHead; ++ } ++ ++ return hr; ++ } ++ ++ // IDWriteTextAnalysisSource implementation ++ ++ IFACEMETHODIMP GetTextAtPosition(UINT32 textPosition, ++ OUT WCHAR const** textString, ++ OUT UINT32* textLength) ++ { ++ if (textPosition >= mTextLength) { ++ // No text at this position, valid query though. ++ *textString = NULL; ++ *textLength = 0; ++ } ++ else { ++ *textString = mText + textPosition; ++ *textLength = mTextLength - textPosition; ++ } ++ return S_OK; ++ } ++ ++ IFACEMETHODIMP GetTextBeforePosition(UINT32 textPosition, ++ OUT WCHAR const** textString, ++ OUT UINT32* textLength) ++ { ++ if (textPosition == 0 || textPosition > mTextLength) { ++ // Either there is no text before here (== 0), or this ++ // is an invalid position. The query is considered valid thouh. ++ *textString = NULL; ++ *textLength = 0; ++ } ++ else { ++ *textString = mText; ++ *textLength = textPosition; ++ } ++ return S_OK; ++ } ++ ++ IFACEMETHODIMP_(DWRITE_READING_DIRECTION) ++ GetParagraphReadingDirection() { return mReadingDirection; } ++ ++ IFACEMETHODIMP GetLocaleName(UINT32 textPosition, ++ UINT32* textLength, ++ WCHAR const** localeName) { ++ return S_OK; ++ } ++ ++ IFACEMETHODIMP ++ GetNumberSubstitution(UINT32 textPosition, ++ OUT UINT32* textLength, ++ OUT IDWriteNumberSubstitution** numberSubstitution) ++ { ++ // We do not support number substitution. ++ *numberSubstitution = NULL; ++ *textLength = mTextLength - textPosition; ++ ++ return S_OK; ++ } ++ ++ // IDWriteTextAnalysisSink implementation ++ ++ IFACEMETHODIMP ++ SetScriptAnalysis(UINT32 textPosition, ++ UINT32 textLength, ++ DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis) ++ { ++ SetCurrentRun(textPosition); ++ SplitCurrentRun(textPosition); ++ while (textLength > 0) { ++ Run *run = FetchNextRun(&textLength); ++ run->mScript = *scriptAnalysis; ++ } ++ ++ return S_OK; ++ } ++ ++ IFACEMETHODIMP ++ SetLineBreakpoints(UINT32 textPosition, ++ UINT32 textLength, ++ const DWRITE_LINE_BREAKPOINT* lineBreakpoints) { return S_OK; } ++ ++ IFACEMETHODIMP SetBidiLevel(UINT32 textPosition, ++ UINT32 textLength, ++ UINT8 explicitLevel, ++ UINT8 resolvedLevel) { return S_OK; } ++ ++ IFACEMETHODIMP ++ SetNumberSubstitution(UINT32 textPosition, ++ UINT32 textLength, ++ IDWriteNumberSubstitution* numberSubstitution) { return S_OK; } ++ ++protected: ++ Run *FetchNextRun(IN OUT UINT32* textLength) ++ { ++ // Used by the sink setters, this returns a reference to the next run. ++ // Position and length are adjusted to now point after the current run ++ // being returned. ++ ++ Run *origRun = mCurrentRun; ++ // Split the tail if needed (the length remaining is less than the ++ // current run's size). ++ if (*textLength < mCurrentRun->mTextLength) { ++ SplitCurrentRun(mCurrentRun->mTextStart + *textLength); ++ } ++ else { ++ // Just advance the current run. ++ mCurrentRun = mCurrentRun->nextRun; ++ } ++ *textLength -= origRun->mTextLength; ++ ++ // Return a reference to the run that was just current. ++ return origRun; ++ } ++ ++ void SetCurrentRun(UINT32 textPosition) ++ { ++ // Move the current run to the given position. ++ // Since the analyzers generally return results in a forward manner, ++ // this will usually just return early. If not, find the ++ // corresponding run for the text position. ++ ++ if (mCurrentRun && mCurrentRun->ContainsTextPosition(textPosition)) { ++ return; ++ } ++ ++ for (Run *run = &mRunHead; run; run = run->nextRun) { ++ if (run->ContainsTextPosition(textPosition)) { ++ mCurrentRun = run; ++ return; ++ } ++ } ++ //NS_NOTREACHED("We should always be able to find the text position in one \ ++ // of our runs"); ++ } ++ ++ void SplitCurrentRun(UINT32 splitPosition) ++ { ++ if (!mCurrentRun) { ++ //NS_ASSERTION(false, "SplitCurrentRun called without current run."); ++ // Shouldn't be calling this when no current run is set! ++ return; ++ } ++ // Split the current run. ++ if (splitPosition <= mCurrentRun->mTextStart) { ++ // No need to split, already the start of a run ++ // or before it. Usually the first. ++ return; ++ } ++ Run *newRun = new Run; ++ ++ *newRun = *mCurrentRun; ++ ++ // Insert the new run in our linked list. ++ newRun->nextRun = mCurrentRun->nextRun; ++ mCurrentRun->nextRun = newRun; ++ ++ // Adjust runs' text positions and lengths. ++ UINT32 splitPoint = splitPosition - mCurrentRun->mTextStart; ++ newRun->mTextStart += splitPoint; ++ newRun->mTextLength -= splitPoint; ++ mCurrentRun->mTextLength = splitPoint; ++ mCurrentRun = newRun; ++ } ++ ++protected: ++ // Input ++ // (weak references are fine here, since this class is a transient ++ // stack-based helper that doesn't need to copy data) ++ UINT32 mTextLength; ++ const WCHAR* mText; ++ const WCHAR* mLocaleName; ++ DWRITE_READING_DIRECTION mReadingDirection; ++ ++ // Current processing state. ++ Run *mCurrentRun; ++ ++ // Output is a list of runs starting here ++ Run mRunHead; ++}; ++ ++ ++/* ++ * shaper ++ */ ++ ++hb_bool_t ++_hb_directwrite_shape(hb_shape_plan_t *shape_plan, ++ hb_font_t *font, ++ hb_buffer_t *buffer, ++ const hb_feature_t *features, ++ unsigned int num_features) ++{ ++ hb_face_t *face = font->face; ++ hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); ++ hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); ++ ++ // factory probably should be cached ++ IDWriteFactory* dwriteFactory; ++ DWriteCreateFactory( ++ DWRITE_FACTORY_TYPE_SHARED, ++ __uuidof(IDWriteFactory), ++ reinterpret_cast<IUnknown**>(&dwriteFactory) ++ ); ++ ++ IDWriteGdiInterop *gdiInterop; ++ dwriteFactory->GetGdiInterop (&gdiInterop); ++ IDWriteFontFace* fontFace; ++ gdiInterop->CreateFontFaceFromHdc (font_data->hdc, &fontFace); ++ ++ IDWriteTextAnalyzer* analyzer; ++ dwriteFactory->CreateTextAnalyzer (&analyzer); ++ ++ unsigned int scratch_size; ++ hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size); ++#define ALLOCATE_ARRAY(Type, name, len) \ ++ Type *name = (Type *) scratch; \ ++ { \ ++ unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \ ++ assert (_consumed <= scratch_size); \ ++ scratch += _consumed; \ ++ scratch_size -= _consumed; \ ++ } ++ ++#define utf16_index() var1.u32 ++ ++ ALLOCATE_ARRAY(WCHAR, pchars, buffer->len * 2); ++ ++ unsigned int chars_len = 0; ++ for (unsigned int i = 0; i < buffer->len; i++) ++ { ++ hb_codepoint_t c = buffer->info[i].codepoint; ++ buffer->info[i].utf16_index() = chars_len; ++ if (likely(c <= 0xFFFFu)) ++ pchars[chars_len++] = c; ++ else if (unlikely(c > 0x10FFFFu)) ++ pchars[chars_len++] = 0xFFFDu; ++ else { ++ pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10); ++ pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1)); ++ } ++ } ++ ++ ALLOCATE_ARRAY(WORD, log_clusters, chars_len); ++ if (num_features) ++ { ++ /* Need log_clusters to assign features. */ ++ chars_len = 0; ++ for (unsigned int i = 0; i < buffer->len; i++) ++ { ++ hb_codepoint_t c = buffer->info[i].codepoint; ++ unsigned int cluster = buffer->info[i].cluster; ++ log_clusters[chars_len++] = cluster; ++ if (hb_in_range(c, 0x10000u, 0x10FFFFu)) ++ log_clusters[chars_len++] = cluster; /* Surrogates. */ ++ } ++ } ++ ++ HRESULT hr; ++ // TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES ++ ++ DWRITE_READING_DIRECTION readingDirection = buffer->props.direction ? ++ DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : ++ DWRITE_READING_DIRECTION_LEFT_TO_RIGHT; ++ ++ /* ++ * There's an internal 16-bit limit on some things inside the analyzer, ++ * but we never attempt to shape a word longer than 64K characters ++ * in a single gfxShapedWord, so we cannot exceed that limit. ++ */ ++ UINT32 length = buffer->len; ++ ++ TextAnalysis analysis(pchars, length, NULL, readingDirection); ++ TextAnalysis::Run *runHead; ++ hr = analysis.GenerateResults(analyzer, &runHead); ++ ++ if (FAILED(hr)) { ++ //NS_WARNING("Analyzer failed to generate results."); ++ return false; ++ } ++ ++ UINT32 maxGlyphs = 3 * length / 2 + 16; ++ ++#define INITIAL_GLYPH_SIZE 400 ++ UINT16* clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); ++ UINT16* glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); ++ DWRITE_SHAPING_TEXT_PROPERTIES* textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*) ++ malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES)); ++ DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*) ++ malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES)); ++ ++ UINT32 actualGlyphs; ++ ++ bool backward = HB_DIRECTION_IS_BACKWARD(buffer->props.direction); ++ ++ wchar_t lang[4]; ++ mbstowcs(lang, hb_language_to_string(buffer->props.language), 4); ++ hr = analyzer->GetGlyphs(pchars, length, ++ fontFace, FALSE, ++ buffer->props.direction, ++ &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0, ++ maxGlyphs, clusters, textProperties, ++ glyphs, glyphProperties, &actualGlyphs); ++ ++ if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { ++ free(clusters); ++ free(glyphs); ++ free(textProperties); ++ free(glyphProperties); ++ ++ clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); ++ glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); ++ textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*) ++ malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES)); ++ glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*) ++ malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES)); ++ ++ hr = analyzer->GetGlyphs(pchars, length, ++ fontFace, FALSE, ++ buffer->props.direction, ++ &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0, ++ maxGlyphs, clusters, textProperties, ++ glyphs, glyphProperties, &actualGlyphs); ++ } ++ if (FAILED(hr)) { ++ //NS_WARNING("Analyzer failed to get glyphs."); ++ return false; ++ } ++ ++ FLOAT advances[400]; ++ DWRITE_GLYPH_OFFSET offsets[400]; ++ ++ ++ /* The -2 in the following is to compensate for possible ++ * alignment needed after the WORD array. sizeof(WORD) == 2. */ ++ unsigned int glyphs_size = (scratch_size * sizeof (int)-2) ++ / (sizeof (WORD) + ++ 4 + // sizeof (SCRIPT_GLYPHPROP) + ++ sizeof (int) + ++ 8 + // sizeof (GOFFSET) + ++ sizeof (uint32_t)); ++ ALLOCATE_ARRAY(uint32_t, vis_clusters, glyphs_size); ++ ++#undef ALLOCATE_ARRAY ++ ++ hr = analyzer->GetGlyphPlacements(pchars, ++ clusters, ++ textProperties, ++ length, ++ glyphs, ++ glyphProperties, ++ actualGlyphs, ++ fontFace, ++ face->get_upem(), ++ FALSE, ++ FALSE, ++ &runHead->mScript, ++ NULL, ++ NULL, ++ NULL, ++ 0, ++ advances, ++ offsets); ++ ++ if (FAILED(hr)) { ++ //NS_WARNING("Analyzer failed to get glyph placements."); ++ return false; ++ } ++ ++ unsigned int glyphs_len = actualGlyphs; ++ ++ /* Ok, we've got everything we need, now compose output buffer, ++ * very, *very*, carefully! */ ++ ++ /* Calculate visual-clusters. That's what we ship. */ ++ for (unsigned int i = 0; i < glyphs_len; i++) ++ vis_clusters[i] = -1; ++ for (unsigned int i = 0; i < buffer->len; i++) { ++ uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]]; ++ //*p = MIN (*p, buffer->info[i].cluster); ++ } ++ for (unsigned int i = 1; i < glyphs_len; i++) ++ if (vis_clusters[i] == -1) ++ vis_clusters[i] = vis_clusters[i - 1]; ++ ++#undef utf16_index ++ ++ //if (unlikely (!buffer->ensure (glyphs_len))) ++ // FAIL ("Buffer in error"); ++ ++#undef FAIL ++ ++ /* Set glyph infos */ ++ buffer->len = 0; ++ for (unsigned int i = 0; i < glyphs_len; i++) ++ { ++ hb_glyph_info_t *info = &buffer->info[buffer->len++]; ++ ++ info->codepoint = glyphs[i]; ++ info->cluster = vis_clusters[i]; ++ ++ /* The rest is crap. Let's store position info there for now. */ ++ info->mask = advances[i]; ++ info->var1.u32 = offsets[i].ascenderOffset; ++ info->var2.u32 = -offsets[i].advanceOffset; ++ } ++ ++ free(clusters); ++ free(glyphs); ++ free(textProperties); ++ free(glyphProperties); ++ ++ /* Set glyph positions */ ++ buffer->clear_positions (); ++ for (unsigned int i = 0; i < glyphs_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 = backward ? -info->var1.u32 : info->var1.u32; ++ pos->y_offset = info->var2.u32; ++ } ++ ++ if (backward) ++ hb_buffer_reverse (buffer); ++ ++ /* Wow, done! */ ++ return true; ++} +diff --git a/gfx/harfbuzz/src/hb-directwrite.h b/gfx/harfbuzz/src/hb-directwrite.h +new file mode 100644 +--- /dev/null ++++ b/gfx/harfbuzz/src/hb-directwrite.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright © 2015 Ebrahim Byagowi ++ * ++ * 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. ++ */ ++ ++#ifndef HB_DIRECTWRITE_H ++#define HB_DIRECTWRITE_H ++ ++#include "hb.h" ++ ++HB_BEGIN_DECLS ++ ++HB_END_DECLS ++ ++#endif /* HB_UNISCRIBE_H */ +diff --git a/gfx/harfbuzz/src/hb-face.h b/gfx/harfbuzz/src/hb-face.h +--- a/gfx/harfbuzz/src/hb-face.h ++++ b/gfx/harfbuzz/src/hb-face.h +@@ -38,80 +38,80 @@ HB_BEGIN_DECLS + + + /* + * hb_face_t + */ + + typedef struct hb_face_t hb_face_t; + +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_face_create (hb_blob_t *blob, + unsigned int index); + + typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag, void *user_data); + + /* calls destroy() when not needing user_data anymore */ +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, + void *user_data, + hb_destroy_func_t destroy); + +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_face_get_empty (void); + +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_face_reference (hb_face_t *face); + +-void ++HB_EXTERN void + hb_face_destroy (hb_face_t *face); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_face_set_user_data (hb_face_t *face, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + + +-void * ++HB_EXTERN void * + hb_face_get_user_data (hb_face_t *face, + hb_user_data_key_t *key); + +-void ++HB_EXTERN void + hb_face_make_immutable (hb_face_t *face); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_face_is_immutable (hb_face_t *face); + + +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_face_reference_table (hb_face_t *face, + hb_tag_t tag); + +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_face_reference_blob (hb_face_t *face); + +-void ++HB_EXTERN void + hb_face_set_index (hb_face_t *face, + unsigned int index); + +-unsigned int ++HB_EXTERN unsigned int + hb_face_get_index (hb_face_t *face); + +-void ++HB_EXTERN void + hb_face_set_upem (hb_face_t *face, + unsigned int upem); + +-unsigned int ++HB_EXTERN unsigned int + hb_face_get_upem (hb_face_t *face); + +-void ++HB_EXTERN void + hb_face_set_glyph_count (hb_face_t *face, + unsigned int glyph_count); + +-unsigned int ++HB_EXTERN unsigned int + hb_face_get_glyph_count (hb_face_t *face); + + + HB_END_DECLS + + #endif /* HB_FACE_H */ +diff --git a/gfx/harfbuzz/src/hb-fallback-shape.cc b/gfx/harfbuzz/src/hb-fallback-shape.cc +--- a/gfx/harfbuzz/src/hb-fallback-shape.cc ++++ b/gfx/harfbuzz/src/hb-fallback-shape.cc +@@ -101,17 +101,17 @@ hb_bool_t + * - Handle Variation Selectors? + * - Apply normalization? + * + * This will make the fallback shaper into a dumb "TrueType" + * shaper which many people unfortunately still request. + */ + + hb_codepoint_t space; +- bool has_space = font->get_glyph (' ', 0, &space); ++ bool has_space = (bool) font->get_glyph (' ', 0, &space); + + buffer->clear_positions (); + + hb_direction_t direction = buffer->props.direction; + hb_unicode_funcs_t *unicode = buffer->unicode; + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + hb_glyph_position_t *pos = buffer->pos; +diff --git a/gfx/harfbuzz/src/hb-font-private.hh b/gfx/harfbuzz/src/hb-font-private.hh +--- a/gfx/harfbuzz/src/hb-font-private.hh ++++ b/gfx/harfbuzz/src/hb-font-private.hh +@@ -37,16 +37,18 @@ + + + + /* + * hb_font_funcs_t + */ + + #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ ++ HB_FONT_FUNC_IMPLEMENT (font_h_extents) \ ++ HB_FONT_FUNC_IMPLEMENT (font_v_extents) \ + HB_FONT_FUNC_IMPLEMENT (glyph) \ + HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ + HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ + HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \ + HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \ + HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \ + HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \ + HB_FONT_FUNC_IMPLEMENT (glyph_extents) \ +@@ -75,17 +77,17 @@ struct hb_font_funcs_t { + + /* Don't access these directly. Call font->get_*() instead. */ + union get_t { + struct get_funcs_t { + #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS + #undef HB_FONT_FUNC_IMPLEMENT + } f; +- void (*array[]) (void); ++ void (*array[VAR]) (void); + } get; + }; + + + + /* + * hb_font_t + */ +@@ -155,17 +157,32 @@ struct hb_font_t { + { \ + hb_font_funcs_t *funcs = this->klass; \ + unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ + return has_func (i); \ + } + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS + #undef HB_FONT_FUNC_IMPLEMENT + +- inline hb_bool_t has_glyph (hb_codepoint_t unicode) ++ inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents) ++ { ++ memset (extents, 0, sizeof (*extents)); ++ return klass->get.f.font_h_extents (this, user_data, ++ extents, ++ klass->user_data.font_h_extents); ++ } ++ inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents) ++ { ++ memset (extents, 0, sizeof (*extents)); ++ return klass->get.f.font_v_extents (this, user_data, ++ extents, ++ klass->user_data.font_v_extents); ++ } ++ ++ inline bool has_glyph (hb_codepoint_t unicode) + { + hb_codepoint_t glyph; + return get_glyph (unicode, 0, &glyph); + } + + inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph) + { +@@ -260,16 +277,36 @@ struct hb_font_t { + name, len, + glyph, + klass->user_data.glyph_from_name); + } + + + /* A bit higher-level, and with fallback */ + ++ inline void get_extents_for_direction (hb_direction_t direction, ++ hb_font_extents_t *extents) ++ { ++ if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { ++ if (!get_font_h_extents (extents)) ++ { ++ extents->ascender = y_scale * .8; ++ extents->descender = y_scale - extents->ascender; ++ extents->line_gap = 0; ++ } ++ } else { ++ if (!get_font_v_extents (extents)) ++ { ++ extents->ascender = x_scale / 2; ++ extents->descender = x_scale - extents->ascender; ++ extents->line_gap = 0; ++ } ++ } ++ } ++ + inline void get_glyph_advance_for_direction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) + { + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { + *x = get_glyph_h_advance (glyph); + *y = 0; + } else { +@@ -279,17 +316,17 @@ struct hb_font_t { + } + + /* Internal only */ + inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + *x = get_glyph_h_advance (glyph) / 2; + +- /* TODO use font_metrics.ascent */ ++ /* TODO use font_extents.ascender */ + *y = y_scale; + } + + inline void get_glyph_origin_for_direction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y) + { + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) +diff --git a/gfx/harfbuzz/src/hb-font.cc b/gfx/harfbuzz/src/hb-font.cc +--- a/gfx/harfbuzz/src/hb-font.cc ++++ b/gfx/harfbuzz/src/hb-font.cc +@@ -40,16 +40,64 @@ + #include <string.h> + + + /* + * hb_font_funcs_t + */ + + static hb_bool_t ++hb_font_get_font_h_extents_nil (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ memset (metrics, 0, sizeof (*metrics)); ++ return false; ++} ++static hb_bool_t ++hb_font_get_font_h_extents_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ hb_bool_t ret = font->parent->get_font_h_extents (metrics); ++ if (ret) { ++ metrics->ascender = font->parent_scale_y_distance (metrics->ascender); ++ metrics->descender = font->parent_scale_y_distance (metrics->descender); ++ metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap); ++ } ++ return ret; ++} ++ ++static hb_bool_t ++hb_font_get_font_v_extents_nil (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ memset (metrics, 0, sizeof (*metrics)); ++ return false; ++} ++static hb_bool_t ++hb_font_get_font_v_extents_parent (hb_font_t *font, ++ void *font_data HB_UNUSED, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ hb_bool_t ret = font->parent->get_font_v_extents (metrics); ++ if (ret) { ++ metrics->ascender = font->parent_scale_x_distance (metrics->ascender); ++ metrics->descender = font->parent_scale_x_distance (metrics->descender); ++ metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap); ++ } ++ return ret; ++} ++ ++static hb_bool_t + hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) + { + *glyph = 0; +@@ -104,17 +152,17 @@ static hb_bool_t + hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) + { + *x = *y = 0; +- return false; ++ return true; + } + static hb_bool_t + hb_font_get_glyph_h_origin_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +@@ -275,17 +323,16 @@ hb_font_get_glyph_from_name_parent (hb_f + void *font_data HB_UNUSED, + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) + { + return font->parent->get_glyph_from_name (name, len, glyph); + } + +- + static const hb_font_funcs_t _hb_font_funcs_nil = { + HB_OBJECT_HEADER_STATIC, + + true, /* immutable */ + + { + #define HB_FONT_FUNC_IMPLEMENT(name) NULL, + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +@@ -517,16 +564,52 @@ hb_font_t::has_func (unsigned int i) + if (parent && parent != hb_font_get_empty () && parent->has_func (i)) + return true; + return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i]; + } + + /* Public getters */ + + /** ++ * hb_font_get_h_extents: ++ * @font: a font. ++ * @extents: (out): ++ * ++ * ++ * ++ * Return value: ++ * ++ * Since: 1.1.3 ++ **/ ++hb_bool_t ++hb_font_get_h_extents (hb_font_t *font, ++ hb_font_extents_t *extents) ++{ ++ return font->get_font_h_extents (extents); ++} ++ ++/** ++ * hb_font_get_v_extents: ++ * @font: a font. ++ * @extents: (out): ++ * ++ * ++ * ++ * Return value: ++ * ++ * Since: 1.1.3 ++ **/ ++hb_bool_t ++hb_font_get_v_extents (hb_font_t *font, ++ hb_font_extents_t *extents) ++{ ++ return font->get_font_v_extents (extents); ++} ++ ++/** + * hb_font_get_glyph: + * @font: a font. + * @unicode: + * @variation_selector: + * @glyph: (out): + * + * + * +@@ -741,16 +824,33 @@ hb_font_get_glyph_from_name (hb_font_t * + { + return font->get_glyph_from_name (name, len, glyph); + } + + + /* A bit higher-level, and with fallback */ + + /** ++ * hb_font_get_extents_for_direction: ++ * @font: a font. ++ * @direction: ++ * @extents: ++ * ++ * ++ * ++ * Since: 1.1.3 ++ **/ ++void ++hb_font_get_extents_for_direction (hb_font_t *font, ++ hb_direction_t direction, ++ hb_font_extents_t *extents) ++{ ++ return font->get_extents_for_direction (direction, extents); ++} ++/** + * hb_font_get_glyph_advance_for_direction: + * @font: a font. + * @glyph: + * @direction: + * @x: (out): + * @y: (out): + * + * +diff --git a/gfx/harfbuzz/src/hb-font.h b/gfx/harfbuzz/src/hb-font.h +--- a/gfx/harfbuzz/src/hb-font.h ++++ b/gfx/harfbuzz/src/hb-font.h +@@ -41,61 +41,85 @@ typedef struct hb_font_t hb_font_t; + + + /* + * hb_font_funcs_t + */ + + typedef struct hb_font_funcs_t hb_font_funcs_t; + +-hb_font_funcs_t * ++HB_EXTERN hb_font_funcs_t * + hb_font_funcs_create (void); + +-hb_font_funcs_t * ++HB_EXTERN hb_font_funcs_t * + hb_font_funcs_get_empty (void); + +-hb_font_funcs_t * ++HB_EXTERN hb_font_funcs_t * + hb_font_funcs_reference (hb_font_funcs_t *ffuncs); + +-void ++HB_EXTERN void + hb_font_funcs_destroy (hb_font_funcs_t *ffuncs); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + + +-void * ++HB_EXTERN void * + hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, + hb_user_data_key_t *key); + + +-void ++HB_EXTERN void + hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs); + + +-/* glyph extents */ ++/* font and glyph extents */ ++ ++/* Note that typically ascender is positive and descender negative in coordinate systems that grow up. */ ++typedef struct hb_font_extents_t ++{ ++ hb_position_t ascender; /* typographic ascender. */ ++ hb_position_t descender; /* typographic descender. */ ++ hb_position_t line_gap; /* suggested line spacing gap. */ ++ /*< private >*/ ++ hb_position_t reserved9; ++ hb_position_t reserved8; ++ hb_position_t reserved7; ++ hb_position_t reserved6; ++ hb_position_t reserved5; ++ hb_position_t reserved4; ++ hb_position_t reserved3; ++ hb_position_t reserved2; ++ hb_position_t reserved1; ++} hb_font_extents_t; + + /* Note that height is negative in coordinate systems that grow up. */ + typedef struct hb_glyph_extents_t + { + hb_position_t x_bearing; /* left side of glyph from origin. */ + hb_position_t y_bearing; /* top side of glyph from origin. */ + hb_position_t width; /* distance from left to right side. */ + hb_position_t height; /* distance from top to bottom side. */ + } hb_glyph_extents_t; + ++/* func types */ + +-/* func types */ ++typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data, ++ hb_font_extents_t *metrics, ++ void *user_data); ++typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t; ++typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t; ++ + + typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data); + + + typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data, +@@ -136,377 +160,419 @@ typedef hb_bool_t (*hb_font_get_glyph_fr + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph, + void *user_data); + + + /* func setters */ + + /** ++ * hb_font_funcs_set_font_h_extents_func: ++ * @ffuncs: font functions. ++ * @func: (closure user_data) (destroy destroy) (scope notified): ++ * @user_data: ++ * @destroy: ++ * ++ * ++ * ++ * Since: 1.1.2 ++ **/ ++HB_EXTERN void ++hb_font_funcs_set_font_h_extents_func (hb_font_funcs_t *ffuncs, ++ hb_font_get_font_h_extents_func_t func, ++ void *user_data, hb_destroy_func_t destroy); ++ ++/** ++ * hb_font_funcs_set_font_v_extents_func: ++ * @ffuncs: font functions. ++ * @func: (closure user_data) (destroy destroy) (scope notified): ++ * @user_data: ++ * @destroy: ++ * ++ * ++ * ++ * Since: 1.1.2 ++ **/ ++HB_EXTERN void ++hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs, ++ hb_font_get_font_v_extents_func_t func, ++ void *user_data, hb_destroy_func_t destroy); ++ ++/** + * hb_font_funcs_set_glyph_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_font_funcs_set_glyph_h_advance_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_advance_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_font_funcs_set_glyph_v_advance_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_advance_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_font_funcs_set_glyph_h_origin_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_origin_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_font_funcs_set_glyph_v_origin_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_origin_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_font_funcs_set_glyph_h_kerning_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_kerning_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_font_funcs_set_glyph_v_kerning_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_kerning_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_font_funcs_set_glyph_extents_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_extents_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_font_funcs_set_glyph_contour_point_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_contour_point_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_font_funcs_set_glyph_name_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_name_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_font_funcs_set_glyph_from_name_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_from_name_func_t func, + void *user_data, hb_destroy_func_t destroy); + +- + /* func dispatch */ + +-hb_bool_t ++HB_EXTERN hb_bool_t ++hb_font_get_h_extents (hb_font_t *font, ++ hb_font_extents_t *extents); ++HB_EXTERN hb_bool_t ++hb_font_get_v_extents (hb_font_t *font, ++ hb_font_extents_t *extents); ++ ++HB_EXTERN hb_bool_t + hb_font_get_glyph (hb_font_t *font, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph); + +-hb_position_t ++HB_EXTERN hb_position_t + hb_font_get_glyph_h_advance (hb_font_t *font, + hb_codepoint_t glyph); +-hb_position_t ++HB_EXTERN hb_position_t + hb_font_get_glyph_v_advance (hb_font_t *font, + hb_codepoint_t glyph); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_h_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y); +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_v_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y); + +-hb_position_t ++HB_EXTERN hb_position_t + hb_font_get_glyph_h_kerning (hb_font_t *font, + hb_codepoint_t left_glyph, hb_codepoint_t right_glyph); +-hb_position_t ++HB_EXTERN hb_position_t + hb_font_get_glyph_v_kerning (hb_font_t *font, + hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_contour_point (hb_font_t *font, + hb_codepoint_t glyph, unsigned int point_index, + hb_position_t *x, hb_position_t *y); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_name (hb_font_t *font, + hb_codepoint_t glyph, + char *name, unsigned int size); +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_from_name (hb_font_t *font, + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph); + + + /* high-level funcs, with fallback */ + +-void ++HB_EXTERN void ++hb_font_get_extents_for_direction (hb_font_t *font, ++ hb_direction_t direction, ++ hb_font_extents_t *extents); ++HB_EXTERN void + hb_font_get_glyph_advance_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); +-void ++HB_EXTERN void + hb_font_get_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); +-void ++HB_EXTERN void + hb_font_add_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); +-void ++HB_EXTERN void + hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); + +-void ++HB_EXTERN void + hb_font_get_glyph_kerning_for_direction (hb_font_t *font, + hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_extents_for_origin (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + hb_glyph_extents_t *extents); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, + hb_codepoint_t glyph, unsigned int point_index, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); + + /* Generates gidDDD if glyph has no name. */ +-void ++HB_EXTERN void + hb_font_glyph_to_string (hb_font_t *font, + hb_codepoint_t glyph, + char *s, unsigned int size); + /* Parses gidDDD and uniUUUU strings automatically. */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_glyph_from_string (hb_font_t *font, + const char *s, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph); + + + /* + * hb_font_t + */ + + /* Fonts are very light-weight objects */ + +-hb_font_t * ++HB_EXTERN hb_font_t * + hb_font_create (hb_face_t *face); + +-hb_font_t * ++HB_EXTERN hb_font_t * + hb_font_create_sub_font (hb_font_t *parent); + +-hb_font_t * ++HB_EXTERN hb_font_t * + hb_font_get_empty (void); + +-hb_font_t * ++HB_EXTERN hb_font_t * + hb_font_reference (hb_font_t *font); + +-void ++HB_EXTERN void + hb_font_destroy (hb_font_t *font); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_set_user_data (hb_font_t *font, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + + +-void * ++HB_EXTERN void * + hb_font_get_user_data (hb_font_t *font, + hb_user_data_key_t *key); + +-void ++HB_EXTERN void + hb_font_make_immutable (hb_font_t *font); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_font_is_immutable (hb_font_t *font); + +-void ++HB_EXTERN void + hb_font_set_parent (hb_font_t *font, + hb_font_t *parent); + +-hb_font_t * ++HB_EXTERN hb_font_t * + hb_font_get_parent (hb_font_t *font); + +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_font_get_face (hb_font_t *font); + + +-void ++HB_EXTERN void + hb_font_set_funcs (hb_font_t *font, + hb_font_funcs_t *klass, + void *font_data, + hb_destroy_func_t destroy); + + /* Be *very* careful with this function! */ +-void ++HB_EXTERN void + hb_font_set_funcs_data (hb_font_t *font, + void *font_data, + hb_destroy_func_t destroy); + + +-void ++HB_EXTERN void + hb_font_set_scale (hb_font_t *font, + int x_scale, + int y_scale); + +-void ++HB_EXTERN void + hb_font_get_scale (hb_font_t *font, + int *x_scale, + int *y_scale); + + /* + * A zero value means "no hinting in that direction" + */ +-void ++HB_EXTERN void + hb_font_set_ppem (hb_font_t *font, + unsigned int x_ppem, + unsigned int y_ppem); + +-void ++HB_EXTERN void + hb_font_get_ppem (hb_font_t *font, + unsigned int *x_ppem, + unsigned int *y_ppem); + + + HB_END_DECLS + + #endif /* HB_FONT_H */ +diff --git a/gfx/harfbuzz/src/hb-ft.cc b/gfx/harfbuzz/src/hb-ft.cc +--- a/gfx/harfbuzz/src/hb-ft.cc ++++ b/gfx/harfbuzz/src/hb-ft.cc +@@ -361,16 +361,35 @@ hb_ft_get_glyph_from_name (hb_font_t *fo + if (!FT_Get_Glyph_Name(ft_face, 0, buf, sizeof (buf)) && + len < 0 ? !strcmp (buf, name) : !strncmp (buf, name, len)) + return true; + } + + return *glyph != 0; + } + ++static hb_bool_t ++hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED, ++ void *font_data, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; ++ FT_Face ft_face = ft_font->ft_face; ++ metrics->ascender = ft_face->size->metrics.ascender; ++ metrics->descender = ft_face->size->metrics.descender; ++ metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender); ++ if (font->y_scale < 0) ++ { ++ metrics->ascender = -metrics->ascender; ++ metrics->descender = -metrics->descender; ++ metrics->line_gap = -metrics->line_gap; ++ } ++ return true; ++} + + static hb_font_funcs_t *static_ft_funcs = NULL; + + #ifdef HB_USE_ATEXIT + static + void free_static_ft_funcs (void) + { + hb_font_funcs_destroy (static_ft_funcs); +@@ -382,16 +401,18 @@ static void + { + retry: + hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs); + + if (unlikely (!funcs)) + { + funcs = hb_font_funcs_create (); + ++ hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, NULL, NULL); ++ //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, NULL, NULL); + hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL); + hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL); + hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL); + //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL); + hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, NULL, NULL); + hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, NULL, NULL); + //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL); + hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, NULL, NULL); +diff --git a/gfx/harfbuzz/src/hb-ft.h b/gfx/harfbuzz/src/hb-ft.h +--- a/gfx/harfbuzz/src/hb-ft.h ++++ b/gfx/harfbuzz/src/hb-ft.h +@@ -54,73 +54,73 @@ HB_BEGIN_DECLS + * destroyed after hb-face is destroyed. + * + * Most often you don't want this function. You should use either + * hb_ft_face_create_cached(), or hb_ft_face_create_referenced(). + * In particular, if you are going to pass NULL as destroy, you + * probably should use (the more recent) hb_ft_face_create_referenced() + * instead. + */ +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_ft_face_create (FT_Face ft_face, + hb_destroy_func_t destroy); + + /* This version is like hb_ft_face_create(), except that it caches + * the hb-face using the generic pointer of the ft-face. This means + * that subsequent calls to this function with the same ft-face will + * return the same hb-face (correctly referenced). + * + * Client is still responsible for making sure that ft-face is destroyed + * after hb-face is. + */ +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_ft_face_create_cached (FT_Face ft_face); + + /* This version is like hb_ft_face_create(), except that it calls + * FT_Reference_Face() on ft-face, as such keeping ft-face alive + * as long as the hb-face is. + * + * This is the most convenient version to use. Use it unless you have + * very good reasons not to. + */ +-hb_face_t * ++HB_EXTERN hb_face_t * + hb_ft_face_create_referenced (FT_Face ft_face); + + + /* + * hb-font from ft-face. + */ + + /* + * Note: + * + * Set face size on ft-face before creating hb-font from it. + * Otherwise hb-ft would NOT pick up the font size correctly. + */ + + /* See notes on hb_ft_face_create(). Same issues re lifecycle-management + * apply here. Use hb_ft_font_create_referenced() if you can. */ +-hb_font_t * ++HB_EXTERN hb_font_t * + hb_ft_font_create (FT_Face ft_face, + hb_destroy_func_t destroy); + + /* See notes on hb_ft_face_create_referenced() re lifecycle-management + * issues. */ +-hb_font_t * ++HB_EXTERN hb_font_t * + hb_ft_font_create_referenced (FT_Face ft_face); + +-FT_Face ++HB_EXTERN FT_Face + hb_ft_font_get_face (hb_font_t *font); + +-void ++HB_EXTERN void + hb_ft_font_set_load_flags (hb_font_t *font, int load_flags); + +-int ++HB_EXTERN int + hb_ft_font_get_load_flags (hb_font_t *font); + + /* Makes an hb_font_t use FreeType internally to implement font functions. */ +-void ++HB_EXTERN void + hb_ft_font_set_funcs (hb_font_t *font); + + + HB_END_DECLS + + #endif /* HB_FT_H */ +diff --git a/gfx/harfbuzz/src/hb-glib.cc b/gfx/harfbuzz/src/hb-glib.cc +--- a/gfx/harfbuzz/src/hb-glib.cc ++++ b/gfx/harfbuzz/src/hb-glib.cc +@@ -378,16 +378,18 @@ hb_glib_get_unicode_funcs (void) + #undef HB_UNICODE_FUNC_IMPLEMENT + } + }; + + return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs); + } + + /** ++ * hb_glib_blob_create: ++ * + * Since: 0.9.38 + **/ + hb_blob_t * + hb_glib_blob_create (GBytes *gbytes) + { + gsize size = 0; + gconstpointer data = g_bytes_get_data (gbytes, &size); + return hb_blob_create ((const char *) data, +diff --git a/gfx/harfbuzz/src/hb-glib.h b/gfx/harfbuzz/src/hb-glib.h +--- a/gfx/harfbuzz/src/hb-glib.h ++++ b/gfx/harfbuzz/src/hb-glib.h +@@ -31,25 +31,25 @@ + + #include "hb.h" + + #include <glib.h> + + HB_BEGIN_DECLS + + +-hb_script_t ++HB_EXTERN hb_script_t + hb_glib_script_to_script (GUnicodeScript script); + +-GUnicodeScript ++HB_EXTERN GUnicodeScript + hb_glib_script_from_script (hb_script_t script); + + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_glib_get_unicode_funcs (void); + +-hb_blob_t * ++HB_EXTERN hb_blob_t * + hb_glib_blob_create (GBytes *gbytes); + + + HB_END_DECLS + + #endif /* HB_GLIB_H */ +diff --git a/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl b/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl +--- a/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl ++++ b/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl +@@ -37,17 +37,17 @@ + #include <glib-object.h> + + HB_BEGIN_DECLS + + + /*** END file-header ***/ + + /*** BEGIN value-header ***/ +-GType @enum_name@_get_type (void) G_GNUC_CONST; ++HB_EXTERN GType @enum_name@_get_type (void) G_GNUC_CONST; + #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) + + /*** END value-header ***/ + + /*** BEGIN file-tail ***/ + + HB_END_DECLS + +diff --git a/gfx/harfbuzz/src/hb-gobject-structs.h b/gfx/harfbuzz/src/hb-gobject-structs.h +--- a/gfx/harfbuzz/src/hb-gobject-structs.h ++++ b/gfx/harfbuzz/src/hb-gobject-structs.h +@@ -38,68 +38,68 @@ + HB_BEGIN_DECLS + + + /* Object types */ + + /** + * Since: 0.9.2 + **/ +-GType hb_gobject_blob_get_type (void); ++HB_EXTERN GType hb_gobject_blob_get_type (void); + #define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ()) + + /** + * Since: 0.9.2 + **/ +-GType hb_gobject_buffer_get_type (void); ++HB_EXTERN GType hb_gobject_buffer_get_type (void); + #define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ()) + + /** + * Since: 0.9.2 + **/ +-GType hb_gobject_face_get_type (void); ++HB_EXTERN GType hb_gobject_face_get_type (void); + #define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ()) + + /** + * Since: 0.9.2 + **/ +-GType hb_gobject_font_get_type (void); ++HB_EXTERN GType hb_gobject_font_get_type (void); + #define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ()) + + /** + * Since: 0.9.2 + **/ +-GType hb_gobject_font_funcs_get_type (void); ++HB_EXTERN GType hb_gobject_font_funcs_get_type (void); + #define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ()) + +-GType hb_gobject_set_get_type (void); ++HB_EXTERN GType hb_gobject_set_get_type (void); + #define HB_GOBJECT_TYPE_SET (hb_gobject_set_get_type ()) + +-GType hb_gobject_shape_plan_get_type (void); ++HB_EXTERN GType hb_gobject_shape_plan_get_type (void); + #define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ()) + + /** + * Since: 0.9.2 + **/ +-GType hb_gobject_unicode_funcs_get_type (void); ++HB_EXTERN GType hb_gobject_unicode_funcs_get_type (void); + #define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ()) + + /* Value types */ + +-GType hb_gobject_feature_get_type (void); ++HB_EXTERN GType hb_gobject_feature_get_type (void); + #define HB_GOBJECT_TYPE_FEATURE (hb_gobject_feature_get_type ()) + +-GType hb_gobject_glyph_info_get_type (void); ++HB_EXTERN GType hb_gobject_glyph_info_get_type (void); + #define HB_GOBJECT_TYPE_GLYPH_INFO (hb_gobject_glyph_info_get_type ()) + +-GType hb_gobject_glyph_position_get_type (void); ++HB_EXTERN GType hb_gobject_glyph_position_get_type (void); + #define HB_GOBJECT_TYPE_GLYPH_POSITION (hb_gobject_glyph_position_get_type ()) + +-GType hb_gobject_segment_properties_get_type (void); ++HB_EXTERN GType hb_gobject_segment_properties_get_type (void); + #define HB_GOBJECT_TYPE_SEGMENT_PROPERTIES (hb_gobject_segment_properties_get_type ()) + +-GType hb_gobject_user_data_key_get_type (void); ++HB_EXTERN GType hb_gobject_user_data_key_get_type (void); + #define HB_GOBJECT_TYPE_USER_DATA_KEY (hb_gobject_user_data_key_get_type ()) + + + HB_END_DECLS + + #endif /* HB_GOBJECT_H */ +diff --git a/gfx/harfbuzz/src/hb-graphite2.cc b/gfx/harfbuzz/src/hb-graphite2.cc +--- a/gfx/harfbuzz/src/hb-graphite2.cc ++++ b/gfx/harfbuzz/src/hb-graphite2.cc +@@ -346,27 +346,28 @@ hb_bool_t + { + hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j]; + info->codepoint = gids[clusters[i].base_glyph + j]; + info->cluster = clusters[i].cluster; + } + } + buffer->len = glyph_count; + ++ float yscale = font->y_scale / font->x_scale; + /* Positioning. */ + if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + { + hb_glyph_position_t *pPos; + for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_slot (seg); + is; pPos++, is = gr_slot_next_in_segment (is)) + { + pPos->x_offset = gr_slot_origin_X (is) - curradvx; +- pPos->y_offset = gr_slot_origin_Y (is) - curradvy; ++ pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; + pPos->x_advance = gr_slot_advance_X (is, grface, grfont); +- pPos->y_advance = gr_slot_advance_Y (is, grface, grfont); ++ pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; + curradvx += pPos->x_advance; + curradvy += pPos->y_advance; + } + pPos[-1].x_advance += gr_seg_advance_X(seg) - curradvx; + } + else + { + hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL) + buffer->len - 1; +@@ -382,27 +383,27 @@ hb_bool_t + curradvx += clusx; + curradvy += clusy; + currclus = info->cluster; + clusx = 0.; + clusy = 0.; + for (tis = is, tinfo = info; tis && tinfo->cluster == currclus; tis = gr_slot_prev_in_segment (tis), tinfo--) + { + clusx += gr_slot_advance_X (tis, grface, grfont); +- clusy += gr_slot_advance_Y (tis, grface, grfont); ++ clusy += gr_slot_advance_Y (tis, grface, grfont) * yscale; + } + curradvx += clusx; + curradvy += clusy; + } + pPos->x_advance = gr_slot_advance_X (is, grface, grfont); +- pPos->y_advance = gr_slot_advance_Y (is, grface, grfont); ++ pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; + curradvx -= pPos->x_advance; + curradvy -= pPos->y_advance; + pPos->x_offset = gr_slot_origin_X (is) - curradvx; +- pPos->y_offset = gr_slot_origin_Y (is) - curradvy; ++ pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; + } + hb_buffer_reverse_clusters (buffer); + } + + if (feats) gr_featureval_destroy (feats); + gr_seg_destroy (seg); + + return true; +diff --git a/gfx/harfbuzz/src/hb-graphite2.h b/gfx/harfbuzz/src/hb-graphite2.h +--- a/gfx/harfbuzz/src/hb-graphite2.h ++++ b/gfx/harfbuzz/src/hb-graphite2.h +@@ -31,18 +31,18 @@ + #include <graphite2/Font.h> + + HB_BEGIN_DECLS + + + #define HB_GRAPHITE2_TAG_SILF HB_TAG('S','i','l','f') + + +-gr_face * ++HB_EXTERN gr_face * + hb_graphite2_face_get_gr_face (hb_face_t *face); + +-gr_font * ++HB_EXTERN gr_font * + hb_graphite2_font_get_gr_font (hb_font_t *font); + + + HB_END_DECLS + + #endif /* HB_GRAPHITE2_H */ +diff --git a/gfx/harfbuzz/src/hb-icu.h b/gfx/harfbuzz/src/hb-icu.h +--- a/gfx/harfbuzz/src/hb-icu.h ++++ b/gfx/harfbuzz/src/hb-icu.h +@@ -31,22 +31,22 @@ + + #include "hb.h" + + #include <unicode/uscript.h> + + HB_BEGIN_DECLS + + +-hb_script_t ++HB_EXTERN hb_script_t + hb_icu_script_to_script (UScriptCode script); + +-UScriptCode ++HB_EXTERN UScriptCode + hb_icu_script_from_script (hb_script_t script); + + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_icu_get_unicode_funcs (void); + + + HB_END_DECLS + + #endif /* HB_ICU_H */ +diff --git a/gfx/harfbuzz/src/hb-open-type-private.hh b/gfx/harfbuzz/src/hb-open-type-private.hh +--- a/gfx/harfbuzz/src/hb-open-type-private.hh ++++ b/gfx/harfbuzz/src/hb-open-type-private.hh +@@ -98,19 +98,16 @@ static inline Type& StructAfter(TObject + # define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code) + + + #define DEFINE_SIZE_STATIC(size) \ + DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \ + static const unsigned int static_size = (size); \ + static const unsigned int min_size = (size) + +-/* Size signifying variable-sized array */ +-#define VAR 1 +- + #define DEFINE_SIZE_UNION(size, _member) \ + DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \ + static const unsigned int min_size = (size) + + #define DEFINE_SIZE_MIN(size) \ + DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \ + static const unsigned int min_size = (size) + +@@ -180,17 +177,17 @@ struct hb_dispatch_context_t + + #define TRACE_SANITIZE(this) \ + hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + ""); + + /* This limits sanitizing time on really broken fonts. */ + #ifndef HB_SANITIZE_MAX_EDITS +-#define HB_SANITIZE_MAX_EDITS 8 ++#define HB_SANITIZE_MAX_EDITS 32 + #endif + + struct hb_sanitize_context_t : + hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE> + { + inline hb_sanitize_context_t (void) : + debug_depth (0), + start (NULL), end (NULL), +diff --git a/gfx/harfbuzz/src/hb-ot-font.cc b/gfx/harfbuzz/src/hb-ot-font.cc +--- a/gfx/harfbuzz/src/hb-ot-font.cc ++++ b/gfx/harfbuzz/src/hb-ot-font.cc +@@ -30,34 +30,63 @@ + + #include "hb-font-private.hh" + + #include "hb-ot-cmap-table.hh" + #include "hb-ot-glyf-table.hh" + #include "hb-ot-head-table.hh" + #include "hb-ot-hhea-table.hh" + #include "hb-ot-hmtx-table.hh" ++#include "hb-ot-os2-table.hh" + + + struct hb_ot_face_metrics_accelerator_t + { + unsigned int num_metrics; + unsigned int num_advances; + unsigned int default_advance; ++ unsigned short ascender; ++ unsigned short descender; ++ unsigned short line_gap; ++ + const OT::_mtx *table; + hb_blob_t *blob; + + inline void init (hb_face_t *face, +- hb_tag_t _hea_tag, hb_tag_t _mtx_tag) ++ hb_tag_t _hea_tag, ++ hb_tag_t _mtx_tag, ++ hb_tag_t os2_tag) + { + this->default_advance = face->get_upem (); + ++ bool got_font_extents = false; ++ if (os2_tag) ++ { ++ hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>::sanitize (face->reference_table (os2_tag)); ++ const OT::os2 *os2 = OT::Sanitizer<OT::os2>::lock_instance (os2_blob); ++#define USE_TYPO_METRICS (1u<<7) ++ if (0 != (os2->fsSelection & USE_TYPO_METRICS)) ++ { ++ this->ascender = os2->sTypoAscender; ++ this->descender = os2->sTypoDescender; ++ this->line_gap = os2->sTypoLineGap; ++ got_font_extents = (this->ascender | this->descender) != 0; ++ } ++ hb_blob_destroy (os2_blob); ++ } ++ + hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag)); + const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob); + this->num_advances = _hea->numberOfLongMetrics; ++ if (!got_font_extents) ++ { ++ this->ascender = _hea->ascender; ++ this->descender = _hea->descender; ++ this->line_gap = _hea->lineGap; ++ } + hb_blob_destroy (_hea_blob); + + this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag)); + + /* Cap num_metrics() and num_advances() based on table length. */ + unsigned int len = hb_blob_get_length (this->blob); + if (unlikely (this->num_advances * 4 > len)) + this->num_advances = len / 4; +@@ -247,18 +276,18 @@ static hb_ot_font_t * + _hb_ot_font_create (hb_face_t *face) + { + hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t)); + + if (unlikely (!ot_font)) + return NULL; + + ot_font->cmap.init (face); +- ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx); +- ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx); /* TODO Can we do this lazily? */ ++ ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2); ++ ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE); /* TODO Can we do this lazily? */ + ot_font->glyf.init (face); + + return ot_font; + } + + static void + _hb_ot_font_destroy (hb_ot_font_t *ot_font) + { +@@ -315,16 +344,41 @@ hb_ot_get_glyph_extents (hb_font_t *font + bool ret = ot_font->glyf.get_extents (glyph, extents); + extents->x_bearing = font->em_scale_x (extents->x_bearing); + extents->y_bearing = font->em_scale_y (extents->y_bearing); + extents->width = font->em_scale_x (extents->width); + extents->height = font->em_scale_y (extents->height); + return ret; + } + ++static hb_bool_t ++hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED, ++ void *font_data, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; ++ metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender); ++ metrics->descender = font->em_scale_y (ot_font->h_metrics.descender); ++ metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap); ++ return true; ++} ++ ++static hb_bool_t ++hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED, ++ void *font_data, ++ hb_font_extents_t *metrics, ++ void *user_data HB_UNUSED) ++{ ++ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; ++ metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender); ++ metrics->descender = font->em_scale_x (ot_font->v_metrics.descender); ++ metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap); ++ return true; ++} + + static hb_font_funcs_t *static_ot_funcs = NULL; + + #ifdef HB_USE_ATEXIT + static + void free_static_ot_funcs (void) + { + hb_font_funcs_destroy (static_ot_funcs); +@@ -336,16 +390,18 @@ static hb_font_funcs_t * + { + retry: + hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs); + + if (unlikely (!funcs)) + { + funcs = hb_font_funcs_create (); + ++ hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, NULL, NULL); ++ hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, NULL, NULL); + hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL); + hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL); + hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL); + //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL); + //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL); + //hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL); TODO + //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL); + hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, NULL, NULL); +@@ -365,16 +421,18 @@ retry: + #endif + }; + + return funcs; + } + + + /** ++ * hb_ot_font_set_funcs: ++ * + * Since: 0.9.28 + **/ + void + hb_ot_font_set_funcs (hb_font_t *font) + { + hb_ot_font_t *ot_font = _hb_ot_font_create (font->face); + if (unlikely (!ot_font)) + return; +diff --git a/gfx/harfbuzz/src/hb-ot-font.h b/gfx/harfbuzz/src/hb-ot-font.h +--- a/gfx/harfbuzz/src/hb-ot-font.h ++++ b/gfx/harfbuzz/src/hb-ot-font.h +@@ -31,15 +31,15 @@ + #ifndef HB_OT_FONT_H + #define HB_OT_FONT_H + + #include "hb.h" + + HB_BEGIN_DECLS + + +-void ++HB_EXTERN void + hb_ot_font_set_funcs (hb_font_t *font); + + + HB_END_DECLS + + #endif /* HB_OT_FONT_H */ +diff --git a/gfx/harfbuzz/src/hb-ot-head-table.hh b/gfx/harfbuzz/src/hb-ot-head-table.hh +--- a/gfx/harfbuzz/src/hb-ot-head-table.hh ++++ b/gfx/harfbuzz/src/hb-ot-head-table.hh +@@ -50,17 +50,19 @@ struct head + unsigned int upem = unitsPerEm; + /* If no valid head table found, assume 1000, which matches typical Type1 usage. */ + return 16 <= upem && upem <= 16384 ? upem : 1000; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); +- return_trace (c->check_struct (this) && likely (version.major == 1)); ++ return_trace (c->check_struct (this) && ++ version.major == 1 && ++ magicNumber == 0x5F0F3CF5u); + } + + protected: + FixedVersion version; /* Version of the head table--currently + * 0x00010000u for version 1.0. */ + FixedVersion fontRevision; /* Set by font manufacturer. */ + ULONG checkSumAdjustment; /* To compute: set it to 0, sum the + * entire font as ULONG, then store +diff --git a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh +--- a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh ++++ b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh +@@ -540,16 +540,19 @@ struct Feature + + OffsetTo<FeatureParams> new_offset; + /* Check that it did not overflow. */ + new_offset.set (new_offset_int); + if (new_offset == new_offset_int && + c->try_set (&featureParams, new_offset) && + !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)) + return_trace (false); ++ ++ if (c->edit_count > 1) ++ c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */ + } + + return_trace (true); + } + + OffsetTo<FeatureParams> + featureParams; /* Offset to Feature Parameters table (if one + * has been defined for the feature), relative +diff --git a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh +--- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh ++++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh +@@ -737,17 +737,17 @@ struct PairPosFormat1 + DEFINE_SIZE_ARRAY (10, pairSet); + }; + + struct PairPosFormat2 + { + inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + TRACE_COLLECT_GLYPHS (this); +- /* (this+coverage).add_coverage (c->input); // Don't need this. */ ++ (this+coverage).add_coverage (c->input); + + unsigned int count1 = class1Count; + const ClassDef &klass1 = this+classDef1; + for (unsigned int i = 0; i < count1; i++) + klass1.add_class (c->input, i); + + unsigned int count2 = class2Count; + const ClassDef &klass2 = this+classDef2; +diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh +--- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh ++++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh +@@ -840,37 +840,43 @@ static inline bool ligate_input (hb_appl + } + c->replace_glyph_with_ligature (lig_glyph, klass); + + for (unsigned int i = 1; i < count; i++) + { + while (buffer->idx < match_positions[i] && !buffer->in_error) + { + if (!is_mark_ligature) { ++ unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); ++ if (this_comp == 0) ++ this_comp = last_num_components; + unsigned int new_lig_comp = components_so_far - last_num_components + +- MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->cur()), 1u), last_num_components); +- _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); ++ MIN (this_comp, last_num_components); ++ _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); + } + buffer->next_glyph (); + } + + last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); + last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur()); + components_so_far += last_num_components; + + /* Skip the base glyph */ + buffer->idx++; + } + + if (!is_mark_ligature && last_lig_id) { + /* Re-adjust components for any marks following. */ + for (unsigned int i = buffer->idx; i < buffer->len; i++) { + if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) { ++ unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]); ++ if (!this_comp) ++ break; + unsigned int new_lig_comp = components_so_far - last_num_components + +- MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->info[i]), 1u), last_num_components); ++ MIN (this_comp, last_num_components); + _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp); + } else + break; + } + } + return_trace (true); + } + +@@ -966,16 +972,21 @@ static inline bool apply_lookup (hb_appl + } + + for (unsigned int i = 0; i < lookupCount; i++) + { + unsigned int idx = lookupRecord[i].sequenceIndex; + if (idx >= count) + continue; + ++ /* Don't recurse to ourself at same position. ++ * Note that this test is too naive, it doesn't catch longer loops. */ ++ if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index) ++ continue; ++ + buffer->move_to (match_positions[idx]); + + unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len (); + if (!c->recurse (lookupRecord[i].lookupListIndex)) + continue; + + unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len (); + int delta = new_len - orig_len; +diff --git a/gfx/harfbuzz/src/hb-ot-layout-private.hh b/gfx/harfbuzz/src/hb-ot-layout-private.hh +--- a/gfx/harfbuzz/src/hb-ot-layout-private.hh ++++ b/gfx/harfbuzz/src/hb-ot-layout-private.hh +@@ -512,21 +512,19 @@ static inline bool + static inline void + _hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info) + { + info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED | + HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED); + } + + static inline void +-_hb_glyph_info_clear_substituted_and_ligated_and_multiplied (hb_glyph_info_t *info) ++_hb_glyph_info_clear_substituted (hb_glyph_info_t *info) + { +- info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED | +- HB_OT_LAYOUT_GLYPH_PROPS_LIGATED | +- HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED); ++ info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED); + } + + + /* Allocation / deallocation. */ + + static inline void + _hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer) + { +diff --git a/gfx/harfbuzz/src/hb-ot-layout.cc b/gfx/harfbuzz/src/hb-ot-layout.cc +--- a/gfx/harfbuzz/src/hb-ot-layout.cc ++++ b/gfx/harfbuzz/src/hb-ot-layout.cc +@@ -125,26 +125,30 @@ static inline const OT::GPOS& + + hb_bool_t + hb_ot_layout_has_glyph_classes (hb_face_t *face) + { + return _get_gdef (face).has_glyph_classes (); + } + + /** ++ * hb_ot_layout_get_glyph_class: ++ * + * Since: 0.9.7 + **/ + hb_ot_layout_glyph_class_t + hb_ot_layout_get_glyph_class (hb_face_t *face, + hb_codepoint_t glyph) + { + return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph); + } + + /** ++ * hb_ot_layout_get_glyphs_in_class: ++ * + * Since: 0.9.7 + **/ + void + hb_ot_layout_get_glyphs_in_class (hb_face_t *face, + hb_ot_layout_glyph_class_t klass, + hb_set_t *glyphs /* OUT */) + { + return _get_gdef (face).get_glyphs_in_class (klass, glyphs); +@@ -360,16 +364,18 @@ hb_ot_layout_language_get_required_featu + table_tag, + script_index, + language_index, + feature_index, + NULL); + } + + /** ++ * hb_ot_layout_language_get_required_feature: ++ * + * Since: 0.9.30 + **/ + hb_bool_t + hb_ot_layout_language_get_required_feature (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int language_index, + unsigned int *feature_index, +@@ -447,16 +453,18 @@ hb_ot_layout_language_find_feature (hb_f + } + } + + if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX; + return false; + } + + /** ++ * hb_ot_layout_feature_get_lookups: ++ * + * Since: 0.9.7 + **/ + unsigned int + hb_ot_layout_feature_get_lookups (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + unsigned int start_offset, + unsigned int *lookup_count /* IN/OUT */, +@@ -464,16 +472,18 @@ hb_ot_layout_feature_get_lookups (hb_fac + { + 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); + } + + /** ++ * hb_ot_layout_table_get_lookup_count: ++ * + * Since: 0.9.22 + **/ + unsigned int + hb_ot_layout_table_get_lookup_count (hb_face_t *face, + hb_tag_t table_tag) + { + switch (table_tag) + { +@@ -624,16 +634,18 @@ static void + language_index, + features, + lookup_indexes); + } + } + } + + /** ++ * hb_ot_layout_collect_lookups: ++ * + * Since: 0.9.8 + **/ + void + hb_ot_layout_collect_lookups (hb_face_t *face, + hb_tag_t table_tag, + const hb_tag_t *scripts, + const hb_tag_t *languages, + const hb_tag_t *features, +@@ -668,16 +680,18 @@ hb_ot_layout_collect_lookups (hb_face_t + languages, + features, + lookup_indexes); + } + } + } + + /** ++ * hb_ot_layout_lookup_collect_glyphs: ++ * + * Since: 0.9.7 + **/ + void + hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, + hb_tag_t table_tag, + unsigned int lookup_index, + hb_set_t *glyphs_before, /* OUT. May be NULL */ + hb_set_t *glyphs_input, /* OUT. May be NULL */ +@@ -716,16 +730,18 @@ hb_ot_layout_lookup_collect_glyphs (hb_f + + hb_bool_t + hb_ot_layout_has_substitution (hb_face_t *face) + { + return &_get_gsub (face) != &OT::Null(OT::GSUB); + } + + /** ++ * hb_ot_layout_lookup_would_substitute: ++ * + * Since: 0.9.7 + **/ + hb_bool_t + hb_ot_layout_lookup_would_substitute (hb_face_t *face, + unsigned int lookup_index, + const hb_codepoint_t *glyphs, + unsigned int glyphs_length, + hb_bool_t zero_context) +@@ -737,17 +753,17 @@ hb_ot_layout_lookup_would_substitute (hb + hb_bool_t + hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face, + unsigned int lookup_index, + const hb_codepoint_t *glyphs, + unsigned int glyphs_length, + hb_bool_t zero_context) + { + if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false; +- OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context); ++ OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context); + + const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); + + return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]); + } + + void + hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer) +@@ -757,16 +773,18 @@ hb_ot_layout_substitute_start (hb_font_t + + void + hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer) + { + OT::GSUB::substitute_finish (font, buffer); + } + + /** ++ * hb_ot_layout_lookup_substitute_closure: ++ * + * Since: 0.9.7 + **/ + void + hb_ot_layout_lookup_substitute_closure (hb_face_t *face, + unsigned int lookup_index, + hb_set_t *glyphs) + { + OT::hb_closure_context_t c (face, glyphs); +@@ -794,16 +812,18 @@ hb_ot_layout_position_start (hb_font_t * + + void + hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer) + { + OT::GPOS::position_finish (font, buffer); + } + + /** ++ * hb_ot_layout_get_size_params: ++ * + * Since: 0.9.10 + **/ + hb_bool_t + hb_ot_layout_get_size_params (hb_face_t *face, + unsigned int *design_size, /* OUT. May be NULL */ + unsigned int *subfamily_id, /* OUT. May be NULL */ + unsigned int *subfamily_name_id, /* OUT. May be NULL */ + unsigned int *range_start, /* OUT. May be NULL */ +@@ -1003,35 +1023,25 @@ inline void hb_ot_map_t::apply (const Pr + unsigned int i = 0; + OT::hb_apply_context_t c (table_index, font, buffer); + c.set_recurse_func (Proxy::Lookup::apply_recurse_func); + + for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) { + const stage_map_t *stage = &stages[table_index][stage_index]; + for (; i < stage->last_lookup; i++) + { +-#if 0 +- char buf[4096]; +- hb_buffer_serialize_glyphs (buffer, 0, buffer->len, +- buf, sizeof (buf), NULL, +- font, +- HB_BUFFER_SERIALIZE_FORMAT_TEXT, +- Proxy::table_index == 0 ? +- HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS : +- HB_BUFFER_SERIALIZE_FLAG_DEFAULT); +- printf ("buf: [%s]\n", buf); +-#endif +- + unsigned int lookup_index = lookups[table_index][i].index; ++ if (!buffer->message (font, "start lookup %d", lookup_index)) continue; + c.set_lookup_index (lookup_index); + c.set_lookup_mask (lookups[table_index][i].mask); + c.set_auto_zwj (lookups[table_index][i].auto_zwj); + apply_string<Proxy> (&c, + proxy.table.get_lookup (lookup_index), + proxy.accels[lookup_index]); ++ (void) buffer->message (font, "end lookup %d", lookup_index); + } + + if (stage->pause_func) + { + buffer->clear_output (); + stage->pause_func (plan, font, buffer); + } + } +diff --git a/gfx/harfbuzz/src/hb-ot-layout.h b/gfx/harfbuzz/src/hb-ot-layout.h +--- a/gfx/harfbuzz/src/hb-ot-layout.h ++++ b/gfx/harfbuzz/src/hb-ot-layout.h +@@ -43,170 +43,170 @@ HB_BEGIN_DECLS + #define HB_OT_TAG_GPOS HB_TAG('G','P','O','S') + #define HB_OT_TAG_JSTF HB_TAG('J','S','T','F') + + + /* + * GDEF + */ + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_has_glyph_classes (hb_face_t *face); + + typedef enum { + HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED = 0, + HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH = 1, + HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE = 2, + HB_OT_LAYOUT_GLYPH_CLASS_MARK = 3, + HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT = 4 + } hb_ot_layout_glyph_class_t; + +-hb_ot_layout_glyph_class_t ++HB_EXTERN hb_ot_layout_glyph_class_t + hb_ot_layout_get_glyph_class (hb_face_t *face, + hb_codepoint_t glyph); + +-void ++HB_EXTERN void + hb_ot_layout_get_glyphs_in_class (hb_face_t *face, + hb_ot_layout_glyph_class_t klass, + hb_set_t *glyphs /* OUT */); + + + /* Not that useful. Provides list of attach points for a glyph that a + * client may want to cache */ +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_get_attach_points (hb_face_t *face, + hb_codepoint_t glyph, + unsigned int start_offset, + unsigned int *point_count /* IN/OUT */, + unsigned int *point_array /* OUT */); + + /* Ligature caret positions */ +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_get_ligature_carets (hb_font_t *font, + hb_direction_t direction, + hb_codepoint_t glyph, + unsigned int start_offset, + unsigned int *caret_count /* IN/OUT */, + hb_position_t *caret_array /* OUT */); + + + /* + * GSUB/GPOS feature query and enumeration interface + */ + + #define HB_OT_LAYOUT_NO_SCRIPT_INDEX 0xFFFFu + #define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu + #define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_table_get_script_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int start_offset, + unsigned int *script_count /* IN/OUT */, + hb_tag_t *script_tags /* OUT */); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_table_find_script (hb_face_t *face, + hb_tag_t table_tag, + hb_tag_t script_tag, + unsigned int *script_index); + + /* Like find_script, but takes zero-terminated array of scripts to test */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_table_choose_script (hb_face_t *face, + hb_tag_t table_tag, + const hb_tag_t *script_tags, + unsigned int *script_index, + hb_tag_t *chosen_script); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_table_get_feature_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int start_offset, + unsigned int *feature_count /* IN/OUT */, + hb_tag_t *feature_tags /* OUT */); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_script_get_language_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int start_offset, + unsigned int *language_count /* IN/OUT */, + hb_tag_t *language_tags /* OUT */); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_script_find_language (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + hb_tag_t language_tag, + unsigned int *language_index); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_language_get_required_feature_index (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int language_index, + unsigned int *feature_index); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_language_get_required_feature (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int language_index, + unsigned int *feature_index, + hb_tag_t *feature_tag); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_language_get_feature_indexes (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int language_index, + unsigned int start_offset, + unsigned int *feature_count /* IN/OUT */, + unsigned int *feature_indexes /* OUT */); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_language_get_feature_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int language_index, + unsigned int start_offset, + unsigned int *feature_count /* IN/OUT */, + hb_tag_t *feature_tags /* OUT */); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_language_find_feature (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int language_index, + hb_tag_t feature_tag, + unsigned int *feature_index); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_feature_get_lookups (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + unsigned int start_offset, + unsigned int *lookup_count /* IN/OUT */, + unsigned int *lookup_indexes /* OUT */); + +-unsigned int ++HB_EXTERN unsigned int + hb_ot_layout_table_get_lookup_count (hb_face_t *face, + hb_tag_t table_tag); + + +-void ++HB_EXTERN void + hb_ot_layout_collect_lookups (hb_face_t *face, + hb_tag_t table_tag, + const hb_tag_t *scripts, + const hb_tag_t *languages, + const hb_tag_t *features, + hb_set_t *lookup_indexes /* OUT */); + +-void ++HB_EXTERN void + hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, + hb_tag_t table_tag, + unsigned int lookup_index, + hb_set_t *glyphs_before, /* OUT. May be NULL */ + hb_set_t *glyphs_input, /* OUT. May be NULL */ + hb_set_t *glyphs_after, /* OUT. May be NULL */ + hb_set_t *glyphs_output /* OUT. May be NULL */); + +@@ -223,77 +223,77 @@ typedef struct + + typedef hb_bool_t + (*hb_ot_layout_glyph_sequence_func_t) (hb_font_t *font, + hb_tag_t table_tag, + unsigned int lookup_index, + const hb_ot_layout_glyph_sequence_t *sequence, + void *user_data); + +-void ++HB_EXTERN void + Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face, + hb_tag_t table_tag, + unsigned int lookup_index, + hb_ot_layout_glyph_sequence_func_t callback, + void *user_data); + #endif + + + /* + * GSUB + */ + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_has_substitution (hb_face_t *face); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_lookup_would_substitute (hb_face_t *face, + unsigned int lookup_index, + const hb_codepoint_t *glyphs, + unsigned int glyphs_length, + hb_bool_t zero_context); + +-void ++HB_EXTERN void + hb_ot_layout_lookup_substitute_closure (hb_face_t *face, + unsigned int lookup_index, + hb_set_t *glyphs + /*TODO , hb_bool_t inclusive */); + + #ifdef HB_NOT_IMPLEMENTED + /* Note: You better have GDEF when using this API, or marks won't do much. */ +-hb_bool_t ++HB_EXTERN hb_bool_t + Xhb_ot_layout_lookup_substitute (hb_font_t *font, + unsigned int lookup_index, + const hb_ot_layout_glyph_sequence_t *sequence, + unsigned int out_size, + hb_codepoint_t *glyphs_out, /* OUT */ + unsigned int *clusters_out, /* OUT */ + unsigned int *out_length /* OUT */); + #endif + + + /* + * GPOS + */ + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_has_positioning (hb_face_t *face); + + #ifdef HB_NOT_IMPLEMENTED + /* Note: You better have GDEF when using this API, or marks won't do much. */ +-hb_bool_t ++HB_EXTERN hb_bool_t + Xhb_ot_layout_lookup_position (hb_font_t *font, + unsigned int lookup_index, + const hb_ot_layout_glyph_sequence_t *sequence, + hb_glyph_position_t *positions /* IN / OUT */); + #endif + + /* Optical 'size' feature info. Returns true if found. + * http://www.microsoft.com/typography/otspec/features_pt.htm#size */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_ot_layout_get_size_params (hb_face_t *face, + unsigned int *design_size, /* OUT. May be NULL */ + unsigned int *subfamily_id, /* OUT. May be NULL */ + unsigned int *subfamily_name_id, /* OUT. May be NULL */ + unsigned int *range_start, /* OUT. May be NULL */ + unsigned int *range_end /* OUT. May be NULL */); + + +diff --git a/gfx/harfbuzz/src/hb-ot-map-private.hh b/gfx/harfbuzz/src/hb-ot-map-private.hh +--- a/gfx/harfbuzz/src/hb-ot-map-private.hh ++++ b/gfx/harfbuzz/src/hb-ot-map-private.hh +@@ -198,17 +198,18 @@ struct hb_ot_map_builder_t + hb_tag_t tag; + unsigned int seq; /* sequence#, used for stable sorting only */ + unsigned int max_value; + hb_ot_map_feature_flags_t flags; + unsigned int default_value; /* for non-global features, what should the unset glyphs take */ + unsigned int stage[2]; /* GSUB/GPOS */ + + static int cmp (const feature_info_t *a, const feature_info_t *b) +- { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); } ++ { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : ++ (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); } + }; + + struct stage_info_t { + unsigned int index; + hb_ot_map_t::pause_func_t pause_func; + }; + + HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func); +diff --git a/gfx/harfbuzz/src/hb-ot-map.cc b/gfx/harfbuzz/src/hb-ot-map.cc +--- a/gfx/harfbuzz/src/hb-ot-map.cc ++++ b/gfx/harfbuzz/src/hb-ot-map.cc +@@ -84,17 +84,17 @@ hb_ot_map_builder_t::hb_ot_map_builder_t + hb_tag_t script_tags[3] = {HB_TAG_NONE, HB_TAG_NONE, HB_TAG_NONE}; + hb_tag_t language_tag; + + hb_ot_tags_from_script (props.script, &script_tags[0], &script_tags[1]); + language_tag = hb_ot_tag_from_language (props.language); + + for (unsigned int table_index = 0; table_index < 2; table_index++) { + hb_tag_t table_tag = table_tags[table_index]; +- found_script[table_index] = hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]); ++ found_script[table_index] = (bool) hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]); + hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]); + } + } + + void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, + hb_ot_map_feature_flags_t flags) + { + feature_info_t *info = feature_infos.push(); +diff --git a/gfx/harfbuzz/src/hb-ot-os2-table.hh b/gfx/harfbuzz/src/hb-ot-os2-table.hh +new file mode 100644 +--- /dev/null ++++ b/gfx/harfbuzz/src/hb-ot-os2-table.hh +@@ -0,0 +1,105 @@ ++/* ++ * Copyright © 2011,2012 Google, Inc. ++ * ++ * This is part of HarfBuzz, a text shaping library. ++ * ++ * Permission is hereby granted, without written agreement and without ++ * license or royalty fees, to use, copy, modify, and distribute this ++ * software and its documentation for any purpose, provided that the ++ * above copyright notice and the following two paragraphs appear in ++ * all copies of this software. ++ * ++ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR ++ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ++ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN ++ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, ++ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ++ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO ++ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ++ * ++ * Google Author(s): Behdad Esfahbod ++ */ ++ ++#ifndef HB_OT_OS2_TABLE_HH ++#define HB_OT_OS2_TABLE_HH ++ ++#include "hb-open-type-private.hh" ++ ++ ++namespace OT { ++ ++/* ++ * OS/2 and Windows Metrics ++ * http://www.microsoft.com/typography/otspec/os2.htm ++ */ ++ ++#define HB_OT_TAG_os2 HB_TAG('O','S','/','2') ++ ++struct os2 ++{ ++ static const hb_tag_t tableTag = HB_OT_TAG_os2; ++ ++ inline bool sanitize (hb_sanitize_context_t *c) const ++ { ++ TRACE_SANITIZE (this); ++ return_trace (c->check_struct (this)); ++ } ++ ++ public: ++ USHORT version; ++ ++ /* Version 0 */ ++ SHORT xAvgCharWidth; ++ USHORT usWeightClass; ++ USHORT usWidthClass; ++ USHORT fsType; ++ SHORT ySubscriptXSize; ++ SHORT ySubscriptYSize; ++ SHORT ySubscriptXOffset; ++ SHORT ySubscriptYOffset; ++ SHORT ySuperscriptXSize; ++ SHORT ySuperscriptYSize; ++ SHORT ySuperscriptXOffset; ++ SHORT ySuperscriptYOffset; ++ SHORT yStrikeoutSize; ++ SHORT yStrikeoutPosition; ++ SHORT sFamilyClass; ++ BYTE panose[10]; ++ ULONG ulUnicodeRange[4]; ++ Tag achVendID; ++ USHORT fsSelection; ++ USHORT usFirstCharIndex; ++ USHORT usLastCharIndex; ++ SHORT sTypoAscender; ++ SHORT sTypoDescender; ++ SHORT sTypoLineGap; ++ USHORT usWinAscent; ++ USHORT usWinDescent; ++ ++ /* Version 1 */ ++ //ULONG ulCodePageRange1; ++ //ULONG ulCodePageRange2; ++ ++ /* Version 2 */ ++ //SHORT sxHeight; ++ //SHORT sCapHeight; ++ //USHORT usDefaultChar; ++ //USHORT usBreakChar; ++ //USHORT usMaxContext; ++ ++ /* Version 5 */ ++ //USHORT usLowerOpticalPointSize; ++ //USHORT usUpperOpticalPointSize; ++ ++ public: ++ DEFINE_SIZE_STATIC (78); ++}; ++ ++} /* namespace OT */ ++ ++ ++#endif /* HB_OT_OS2_TABLE_HH */ +diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc +--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc ++++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc +@@ -218,26 +218,26 @@ collect_features_arabic (hb_ot_shape_pla + map->add_gsub_pause (NULL); + } + + map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK); + if (plan->props.script == HB_SCRIPT_ARABIC) + map->add_gsub_pause (arabic_fallback_shape); + + map->add_global_bool_feature (HB_TAG('c','a','l','t')); +- map->add_gsub_pause (NULL); + + /* The spec includes 'cswh'. Earlier versions of Windows + * used to enable this by default, but testing suggests + * that Windows 8 and later do not enable it by default, + * and spec now says 'Off by default'. + * We disabled this in ae23c24c32. + * Note that IranNastaliq uses this feature extensively + * to fixup broken glyph sequences. Oh well... + * Test case: U+0643,U+0640,U+0631. */ ++ //map->add_gsub_pause (NULL); + //map->add_global_bool_feature (HB_TAG('c','s','w','h')); + map->add_global_bool_feature (HB_TAG('m','s','e','t')); + } + + #include "hb-ot-shape-complex-arabic-fallback.hh" + + struct arabic_shape_plan_t + { +@@ -458,20 +458,16 @@ apply_stch (const hb_ot_shape_plan_t *pl + * stretch / position the stretched pieces to the left / preceding glyphs. */ + + /* We do a two pass implementation: + * First pass calculates the exact number of extra glyphs we need, + * We then enlarge buffer to have that much room, + * Second pass applies the stretch, copying things to the end of buffer. + */ + +- /* 30 = 2048 / 70. +- * https://www.microsoft.com/typography/cursivescriptguidelines.mspx */ +- hb_position_t overlap = font->x_scale / 30; +- DEBUG_MSG (ARABIC, NULL, "overlap for stretching is %d", overlap); + int sign = font->x_scale < 0 ? -1 : +1; + unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT + typedef enum { MEASURE, CUT } step_t; + + for (step_t step = MEASURE; step <= CUT; step = (step_t) (step + 1)) + { + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; +@@ -499,28 +495,25 @@ apply_stch (const hb_ot_shape_plan_t *pl + int n_fixed = 0; + int n_repeating = 0; + + unsigned int end = i; + while (i && + hb_in_range<unsigned> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING)) + { + i--; +- hb_glyph_extents_t extents; +- if (!font->get_glyph_extents (info[i].codepoint, &extents)) +- extents.width = 0; +- extents.width -= overlap; ++ hb_position_t width = font->get_glyph_h_advance (info[i].codepoint); + if (info[i].arabic_shaping_action() == STCH_FIXED) + { +- w_fixed += extents.width; ++ w_fixed += width; + n_fixed++; + } + else + { +- w_repeating += extents.width; ++ w_repeating += width; + n_repeating++; + } + } + unsigned int start = i; + unsigned int context = i; + while (context && + !hb_in_range<unsigned> (info[context - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING) && + (_hb_glyph_info_is_default_ignorable (&info[context - 1]) || +@@ -535,44 +528,54 @@ apply_stch (const hb_ot_shape_plan_t *pl + step == MEASURE ? "measuring" : "cutting", context, start, end); + DEBUG_MSG (ARABIC, NULL, "rest of word: count=%d width %d", start - context, w_total); + DEBUG_MSG (ARABIC, NULL, "fixed tiles: count=%d width=%d", n_fixed, w_fixed); + DEBUG_MSG (ARABIC, NULL, "repeating tiles: count=%d width=%d", n_repeating, w_repeating); + + /* Number of additional times to repeat each repeating tile. */ + int n_copies = 0; + +- hb_position_t w_remaining = w_total - w_fixed - overlap; ++ hb_position_t w_remaining = w_total - w_fixed; + if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0) +- n_copies = (sign * w_remaining + sign * w_repeating / 4) / (sign * w_repeating) - 1; ++ n_copies = (sign * w_remaining) / (sign * w_repeating) - 1; ++ ++ /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */ ++ hb_position_t extra_repeat_overlap = 0; ++ hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1); ++ if (shortfall > 0) ++ { ++ ++n_copies; ++ hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining; ++ if (excess > 0) ++ extra_repeat_overlap = excess / (n_copies * n_repeating); ++ } + + if (step == MEASURE) + { + extra_glyphs_needed += n_copies * n_repeating; + DEBUG_MSG (ARABIC, NULL, "will add extra %d copies of repeating tiles", n_copies); + } + else + { +- hb_position_t x_offset = -overlap; ++ hb_position_t x_offset = 0; + for (unsigned int k = end; k > start; k--) + { +- hb_glyph_extents_t extents; +- if (!font->get_glyph_extents (info[k - 1].codepoint, &extents)) +- extents.width = 0; +- extents.width -= overlap; ++ hb_position_t width = font->get_glyph_h_advance (info[k - 1].codepoint); + + unsigned int repeat = 1; + if (info[k - 1].arabic_shaping_action() == STCH_REPEATING) + repeat += n_copies; + + DEBUG_MSG (ARABIC, NULL, "appending %d copies of glyph %d; j=%d", + repeat, info[k - 1].codepoint, j); + for (unsigned int n = 0; n < repeat; n++) + { +- x_offset -= extents.width; ++ x_offset -= width; ++ if (n > 0) ++ x_offset += extra_repeat_overlap; + pos[k - 1].x_offset = x_offset; + /* Append copy. */ + --j; + info[j] = info[k - 1]; + pos[j] = pos[k - 1]; + } + } + } +diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc +--- a/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc ++++ b/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc +@@ -35,11 +35,11 @@ const hb_ot_complex_shaper_t _hb_ot_comp + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ + NULL, /* postprocess_glyphs */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + NULL, /* compose */ + NULL, /* setup_masks */ +- HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, ++ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + true, /* fallback_position */ + }; +diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc +--- a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc ++++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc +@@ -63,17 +63,17 @@ compose_hebrew (const hb_ot_shape_normal + 0x0000u, /* FINAL TSADI */ + 0xFB46u, /* TSADI */ + 0xFB47u, /* QOF */ + 0xFB48u, /* RESH */ + 0xFB49u, /* SHIN */ + 0xFB4Au /* TAV */ + }; + +- bool found = c->unicode->compose (a, b, ab); ++ bool found = (bool) c->unicode->compose (a, b, ab); + + if (!found && !c->plan->has_mark) + { + /* Special-case Hebrew presentation forms that are excluded from + * standard normalization, but wanted for old fonts. */ + switch (b) { + case 0x05B4u: /* HIRIQ */ + if (a == 0x05D9u) { /* YOD */ +diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh +--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh ++++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh +@@ -104,37 +104,41 @@ enum indic_position_t { + }; + + /* Categories used in IndicSyllabicCategory.txt from UCD. */ + enum indic_syllabic_category_t { + INDIC_SYLLABIC_CATEGORY_OTHER = OT_X, + + INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Symbol, + INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM, +- INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* TODO */ ++ INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* Don't care. */ + INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK = OT_A, + INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C, + INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C, + INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM, + INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C, ++ INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER = OT_M, /* U+17CD only. */ + INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM, + INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_PLACEHOLDER, + INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA = OT_Repha, ++ INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED = OT_X, /* Don't care. */ + INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM, + INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_N, ++ INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_Repha, /* TODO */ + INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, +- INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_H, /* TODO */ ++ INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng, + INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ, + INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X, + INDIC_SYLLABIC_CATEGORY_NON_JOINER = OT_ZWNJ, + INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N, + INDIC_SYLLABIC_CATEGORY_NUMBER = OT_PLACEHOLDER, +- INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* TODO */ +- INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_H, /* TODO */ ++ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* Don't care. */ ++ INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_M, /* Is like a vowel matra. */ + INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS, ++ INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER = OT_M, /* Misc Khmer signs. */ + INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X, + INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N, + INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H, + INDIC_SYLLABIC_CATEGORY_VISARGA = OT_SM, + INDIC_SYLLABIC_CATEGORY_VOWEL = OT_V, + INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT = OT_M, + INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT = OT_V + }; +@@ -157,24 +161,30 @@ enum indic_matra_category_t { + INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT, + INDIC_MATRA_CATEGORY_TOP_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT, + + INDIC_MATRA_CATEGORY_OVERSTRUCK = POS_AFTER_MAIN, + INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = POS_PRE_M + }; + + #define INDIC_COMBINE_CATEGORIES(S,M) \ +- (ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || \ +- ( \ +- S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \ +- S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \ +- S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \ +- S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \ +- S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \ +- S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \ +- false)) + \ +- ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \ +- ((M << 8) | S)) ++ ( \ ++ ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \ ++ ( S | \ ++ ( \ ++ ( \ ++ S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \ ++ S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \ ++ S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \ ++ S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \ ++ S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \ ++ S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \ ++ false \ ++ ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \ ++ ) << 8 \ ++ ) \ ++ ) \ ++ ) + + HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE + hb_indic_get_categories (hb_codepoint_t u); + + #endif /* HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH */ +diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc +--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc ++++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc +@@ -1,315 +1,323 @@ + /* == Start of generated table == */ + /* + * The following table is generated by running: + * + * ./gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt + * + * on files with these headers: + * +- * # IndicSyllabicCategory-7.0.0.txt +- * # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP] +- * # IndicMatraCategory-7.0.0.txt +- * # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP] +- * # Blocks-7.0.0.txt +- * # Date: 2014-04-03, 23:23:00 GMT [RP, KW] ++ * # IndicSyllabicCategory-8.0.0.txt ++ * # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI] ++ * # IndicPositionalCategory-8.0.0.txt ++ * # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI] ++ * # Blocks-8.0.0.txt ++ * # Date: 2014-11-10, 23:04:00 GMT [KW] + */ + + #include "hb-ot-shape-complex-indic-private.hh" + + + #define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 13 chars; Avagraha */ +-#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 59 chars; Bindu */ ++#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 60 chars; Bindu */ + #define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */ +-#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 30 chars; Cantillation_Mark */ +-#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 1744 chars; Consonant */ ++#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 52 chars; Cantillation_Mark */ ++#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 1805 chars; Consonant */ + #define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 7 chars; Consonant_Dead */ +-#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 61 chars; Consonant_Final */ ++#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 62 chars; Consonant_Final */ + #define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */ +-#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 19 chars; Consonant_Medial */ +-#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 11 chars; Consonant_Placeholder */ ++#define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */ ++#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 22 chars; Consonant_Medial */ ++#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 13 chars; Consonant_Placeholder */ + #define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 1 chars; Consonant_Preceding_Repha */ ++#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 2 chars; Consonant_Prefixed */ + #define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 61 chars; Consonant_Subjoined */ + #define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 4 chars; Consonant_Succeeding_Repha */ ++#define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 4 chars; Consonant_With_Stacker */ + #define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 2 chars; Gemination_Mark */ + #define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 7 chars; Invisible_Stacker */ + #define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */ + #define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */ + #define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */ +-#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 18 chars; Nukta */ +-#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 408 chars; Number */ ++#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 23 chars; Nukta */ ++#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 420 chars; Number */ + #define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */ + #define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */ +-#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 15 chars; Pure_Killer */ +-#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 3 chars; Register_Shifter */ ++#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 16 chars; Pure_Killer */ ++#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */ ++#define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 20 chars; Syllable_Modifier */ + #define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */ +-#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 62 chars; Tone_Mark */ ++#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 42 chars; Tone_Mark */ + #define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 22 chars; Virama */ + #define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 29 chars; Visarga */ + #define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */ +-#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 553 chars; Vowel_Dependent */ +-#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 395 chars; Vowel_Independent */ ++#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 572 chars; Vowel_Dependent */ ++#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 404 chars; Vowel_Independent */ + +-#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 142 chars; Bottom */ ++#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 256 chars; Bottom */ + #define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 2 chars; Bottom_And_Right */ +-#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 57 chars; Left */ ++#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 55 chars; Left */ + #define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 21 chars; Left_And_Right */ + #define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */ +-#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 2 chars; Overstruck */ +-#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 163 chars; Right */ +-#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 169 chars; Top */ ++#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */ ++#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 249 chars; Right */ ++#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 324 chars; Top */ + #define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */ + #define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */ + #define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 6 chars; Top_And_Left */ + #define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 4 chars; Top_And_Left_And_Right */ + #define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 13 chars; Top_And_Right */ +-#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 15 chars; Visual_Order_Left */ ++#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 19 chars; Visual_Order_Left */ + + #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M) + + + static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { + + + #define indic_offset_0x0028u 0 + + + /* Basic Latin */ + + /* 0028 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), _(x,x), _(x,x), + /* 0030 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0038 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x00d0u 24 ++#define indic_offset_0x00b0u 24 + + + /* Latin-1 Supplement */ + ++ /* 00B0 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 00B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 00C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 00C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 00D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), + +-#define indic_offset_0x0900u 32 ++#define indic_offset_0x0900u 64 + + + /* Devanagari */ + +- /* 0900 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0900 */ _(Bi,T), _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 0908 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 0910 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0920 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0928 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,x), _(A,x), _(M,R), _(M,L), ++ /* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,B), _(A,x), _(M,R), _(M,L), + /* 0940 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), + /* 0948 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(M,L), _(M,R), +- /* 0950 */ _(x,x), _(TM,x), _(TM,x), _(x,x), _(x,x), _(M,T), _(M,B), _(M,B), ++ /* 0950 */ _(x,x), _(Ca,T), _(Ca,B), _(x,T), _(x,T), _(M,T), _(M,B), _(M,B), + /* 0958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0960 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0968 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0970 */ _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 0978 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + + /* Bengali */ + +- /* 0980 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0980 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x), + /* 0990 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 09A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 09A8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 09B0 */ _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), +- /* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,L), ++ /* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L), + /* 09C0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L), + /* 09C8 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,B), _(CD,x), _(x,x), + /* 09D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), + /* 09D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), + /* 09E0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 09E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 09F0 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Gurmukhi */ + +- /* 0A00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0A00 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0A08 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x), + /* 0A10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0A18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0A28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0A30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), +- /* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(x,x), _(M,R), _(M,L), ++ /* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(x,x), _(M,R), _(M,L), + /* 0A40 */ _(M,R), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), + /* 0A48 */ _(M,T), _(x,x), _(x,x), _(M,T), _(M,T), _(V,B), _(x,x), _(x,x), + /* 0A50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0A58 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), + /* 0A60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0A68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), +- /* 0A70 */ _(Bi,x), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,x), _(x,x), _(x,x), ++ /* 0A70 */ _(Bi,T), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,B), _(x,x), _(x,x), + /* 0A78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Gujarati */ + +- /* 0A80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0A80 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0A88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), + /* 0A90 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0A98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0AA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0AA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0AB0 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), +- /* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,L), ++ /* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L), + /* 0AC0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(x,x), _(M,T), + /* 0AC8 */ _(M,T), _(M,TR), _(x,x), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x), + /* 0AD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0AD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0AF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 0AF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 0AF8 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Oriya */ + +- /* 0B00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0B00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x), + /* 0B10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0B28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0B30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), +- /* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,T), ++ /* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T), + /* 0B40 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L), + /* 0B48 */ _(M,TL), _(x,x), _(x,x), _(M,LR),_(M,TLR), _(V,B), _(x,x), _(x,x), + /* 0B50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,TR), + /* 0B58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), + /* 0B60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0B68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0B70 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Tamil */ + +- /* 0B80 */ _(x,x), _(x,x), _(Bi,x), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0B80 */ _(x,x), _(x,x), _(Bi,T), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0B88 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(VI,x), + /* 0B90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(x,x), _(x,x), + /* 0B98 */ _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(C,x), _(C,x), + /* 0BA0 */ _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), + /* 0BA8 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), + /* 0BB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0BB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), +- /* 0BC0 */ _(M,T), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L), ++ /* 0BC0 */ _(M,T), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L), + /* 0BC8 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T), _(x,x), _(x,x), + /* 0BD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), + /* 0BD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0BE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0BE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0BF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Telugu */ + +- /* 0C00 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0C00 */ _(Bi,T), _(Bi,R), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), + /* 0C10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0C28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0C30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0C38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(A,x), _(M,T), _(M,T), + /* 0C40 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,T), + /* 0C48 */ _(M,TB), _(x,x), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), _(x,x), + /* 0C50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(x,x), +- /* 0C58 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 0C58 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0C78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Kannada */ + +- /* 0C80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0C80 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0C88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), + /* 0C90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0C98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0CA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0CA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0CB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), +- /* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,T), ++ /* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T), + /* 0CC0 */ _(M,TR), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,TR), + /* 0CC8 */ _(M,TR), _(x,x), _(M,TR), _(M,TR), _(M,T), _(V,T), _(x,x), _(x,x), + /* 0CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), + /* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(x,x), + /* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), +- /* 0CF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 0CF0 */ _(x,x),_(CWS,x),_(CWS,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Malayalam */ + +- /* 0D00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0D00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), + /* 0D10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 0D18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0D20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0D28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0D30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0D38 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(A,x), _(M,R), _(M,R), + /* 0D40 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(x,x), _(M,L), _(M,L), + /* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T),_(CPR,x), _(x,x), + /* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), +- /* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x), + /* 0D60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0D68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0D70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0D78 */ _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), + + /* Sinhala */ + +- /* 0D80 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 0D80 */ _(x,x), _(x,x), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0D88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 0D90 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), + /* 0D98 */ _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0DA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0DA8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0DB0 */ _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 0DB8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), + /* 0DC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), + /* 0DC8 */ _(x,x), _(x,x), _(V,T), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), + /* 0DD0 */ _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), _(x,x), _(M,B), _(x,x), + /* 0DD8 */ _(M,R), _(M,L), _(M,TL), _(M,L), _(M,LR),_(M,TLR), _(M,LR), _(M,R), + /* 0DE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 0DE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 0DF0 */ _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x1000u 1304 ++#define indic_offset_0x1000u 1336 + + + /* Myanmar */ + + /* 1000 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1008 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1010 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1020 */ _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 1028 */ _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), +- /* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,x), _(TM,x), +- /* 1038 */ _(Vs,x), _(IS,x), _(PK,T), _(CM,x), _(CM,x), _(CM,x), _(CM,x), _(C,x), ++ /* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,T), _(TM,B), ++ /* 1038 */ _(Vs,R), _(IS,x), _(PK,T), _(CM,R), _(CM,x), _(CM,B), _(CM,B), _(C,x), + /* 1040 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1048 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), _(x,x), + /* 1050 */ _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), +- /* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,x), _(CM,x), +- /* 1060 */ _(CM,x), _(C,x), _(M,R), _(TM,x), _(TM,x), _(C,x), _(C,x), _(M,R), +- /* 1068 */ _(M,R), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(C,x), ++ /* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,B), _(CM,B), ++ /* 1060 */ _(CM,B), _(C,x), _(M,R), _(TM,R), _(TM,R), _(C,x), _(C,x), _(M,R), ++ /* 1068 */ _(M,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(C,x), _(C,x), + /* 1070 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(C,x), _(C,x), _(C,x), + /* 1078 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 1080 */ _(C,x), _(C,x), _(CM,x), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,x), +- /* 1088 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(TM,x), ++ /* 1080 */ _(C,x), _(C,x), _(CM,B), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,R), ++ /* 1088 */ _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,B), _(C,x), _(TM,R), + /* 1090 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), +- /* 1098 */ _(Nd,x), _(Nd,x), _(TM,x), _(TM,x), _(M,R), _(M,T), _(x,x), _(x,x), ++ /* 1098 */ _(Nd,x), _(Nd,x), _(TM,R), _(TM,R), _(M,R), _(M,T), _(x,x), _(x,x), + +-#define indic_offset_0x1700u 1464 ++#define indic_offset_0x1700u 1496 + + + /* Tagalog */ + + /* 1700 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1708 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), + /* 1710 */ _(C,x), _(C,x), _(M,T), _(M,B), _(PK,B), _(x,x), _(x,x), _(x,x), + /* 1718 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +@@ -340,36 +348,36 @@ static const INDIC_TABLE_ELEMENT_TYPE in + /* 1780 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1788 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1790 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1798 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 17A0 */ _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 17A8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 17B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(M,R), _(M,T), + /* 17B8 */ _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,TL),_(M,TLR), +- /* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,x), _(Vs,x), +- /* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(RS,T),_(CSR,T), _(M,T), _(M,T), _(M,T), +- /* 17D0 */ _(M,T), _(PK,T), _(IS,x), _(M,T), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(x,x), _(x,x), _(x,x), ++ /* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,T), _(Vs,R), ++ /* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(SM,T),_(CSR,T), _(CK,T), _(SM,T), _(SM,T), ++ /* 17D0 */ _(SM,T), _(PK,T), _(IS,x), _(SM,T), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(x,T), _(x,x), _(x,x), + /* 17E0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 17E8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x1900u 1704 ++#define indic_offset_0x1900u 1736 + + + /* Limbu */ + + /* 1900 */ _(CP,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1908 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), + /* 1920 */ _(M,T), _(M,T), _(M,B), _(M,R), _(M,R), _(M,TR), _(M,TR), _(M,T), +- /* 1928 */ _(M,T), _(CS,x), _(CS,x), _(CS,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 1930 */ _(CF,x), _(CF,x), _(Bi,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), +- /* 1938 */ _(CF,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 1928 */ _(M,T), _(CS,R), _(CS,R), _(CS,R), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 1930 */ _(CF,R), _(CF,R), _(Bi,B), _(CF,R), _(CF,R), _(CF,R), _(CF,R), _(CF,R), ++ /* 1938 */ _(CF,R), _(CF,B), _(M,T), _(SM,B), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1940 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x), + /* 1948 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + + /* Tai Le */ + + /* 1950 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1960 */ _(C,x), _(C,x), _(C,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), +@@ -380,20 +388,20 @@ static const INDIC_TABLE_ELEMENT_TYPE in + /* New Tai Lue */ + + /* 1980 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1988 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1990 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 19A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 19A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 19B0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,L), _(M,L), _(M,L), +- /* 19B8 */ _(M,R), _(M,R), _(M,L), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), ++ /* 19B0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R),_(M,VOL),_(M,VOL),_(M,VOL), ++ /* 19B8 */ _(M,R), _(M,R),_(M,VOL), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), + /* 19C0 */ _(M,R), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), +- /* 19C8 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 19C8 */ _(TM,R), _(TM,R), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 19D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 19D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 19E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 19E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 19F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 19F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Buginese */ +@@ -406,110 +414,120 @@ static const INDIC_TABLE_ELEMENT_TYPE in + /* Tai Tham */ + + /* 1A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1A28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1A30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1A38 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1A40 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1A48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), +- /* 1A50 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(CM,L), _(CM,x), _(CF,x), +- /* 1A58 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x), ++ /* 1A50 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(CM,L), _(CM,B), _(CF,R), ++ /* 1A58 */ _(CF,T), _(CF,T), _(CF,T), _(CF,B), _(CF,B), _(CF,B), _(CF,B), _(x,x), + /* 1A60 */ _(IS,x), _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T), + /* 1A68 */ _(M,T), _(M,B), _(M,B), _(M,T), _(M,B), _(M,R), _(M,L), _(M,L), +- /* 1A70 */ _(M,L), _(M,L), _(M,L), _(M,T), _(M,T), _(TM,x), _(TM,x), _(TM,x), +- /* 1A78 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 1A70 */ _(M,L), _(M,L), _(M,L), _(M,T), _(M,T), _(TM,T), _(TM,T), _(TM,T), ++ /* 1A78 */ _(TM,T), _(TM,T), _(SM,T), _(SM,T), _(SM,T), _(x,x), _(x,x), _(SM,B), + /* 1A80 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1A88 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1A90 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1A98 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x1b00u 2120 ++#define indic_offset_0x1b00u 2152 + + + /* Balinese */ + +- /* 1B00 */ _(Bi,x), _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 1B00 */ _(Bi,T), _(Bi,T), _(Bi,T),_(CSR,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), + /* 1B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 1B10 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1B28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 1B30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(N,x), _(M,R), _(M,T), _(M,T), ++ /* 1B30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(N,T), _(M,R), _(M,T), _(M,T), + /* 1B38 */ _(M,B), _(M,B), _(M,B), _(M,BR), _(M,TB),_(M,TBR), _(M,L), _(M,L), + /* 1B40 */ _(M,LR), _(M,LR), _(M,T), _(M,TR), _(V,R), _(C,x), _(C,x), _(C,x), + /* 1B48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1B50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1B58 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1B60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 1B68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 1B70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 1B68 */ _(x,x), _(x,x), _(x,x), _(x,T), _(x,B), _(x,T), _(x,T), _(x,T), ++ /* 1B70 */ _(x,T), _(x,T), _(x,T), _(x,T), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Sundanese */ + +- /* 1B80 */ _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 1B80 */ _(Bi,T),_(CSR,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 1B88 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1B90 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1B98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 1BA0 */ _(C,x), _(CS,x), _(CS,x), _(CS,x), _(M,T), _(M,B), _(M,L), _(M,R), +- /* 1BA8 */ _(M,T), _(M,T), _(PK,R), _(IS,x), _(CS,x), _(CS,x), _(C,x), _(C,x), ++ /* 1BA0 */ _(C,x), _(CS,R), _(CS,B), _(CS,B), _(M,T), _(M,B), _(M,L), _(M,R), ++ /* 1BA8 */ _(M,T), _(M,T), _(PK,R), _(IS,x), _(CS,B), _(CS,B), _(C,x), _(C,x), + /* 1BB0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1BB8 */ _(Nd,x), _(Nd,x), _(A,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x), + + /* Batak */ + + /* 1BC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1BC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1BD0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1BD8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 1BE0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(N,x), _(M,R), ++ /* 1BE0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(N,T), _(M,R), + /* 1BE8 */ _(M,T), _(M,T), _(M,R), _(M,R), _(M,R), _(M,T), _(M,R), _(M,T), +- /* 1BF0 */ _(CF,x), _(CF,x), _(PK,R), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 1BF0 */ _(CF,T), _(CF,T), _(PK,R), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Lepcha */ + + /* 1C00 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1C08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1C10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 1C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 1C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CS,x), _(CS,x), _(M,R), _(M,L), +- /* 1C28 */ _(M,L), _(M,TL), _(M,R), _(M,R), _(M,B), _(CF,x), _(CF,x), _(CF,x), +- /* 1C30 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(Bi,L), _(Bi,L), _(x,x), _(N,x), ++ /* 1C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CS,R), _(CS,R), _(M,R), _(M,L), ++ /* 1C28 */ _(M,L), _(M,TL), _(M,R), _(M,R), _(M,B), _(CF,T), _(CF,T), _(CF,T), ++ /* 1C30 */ _(CF,T), _(CF,T), _(CF,T), _(CF,T), _(Bi,L), _(Bi,L), _(SM,T), _(N,B), + /* 1C38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 1C40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 1C48 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), + +-#define indic_offset_0x1cd0u 2456 ++#define indic_offset_0x1cd0u 2488 + + + /* Vedic Extensions */ + +- /* 1CD0 */ _(TM,x), _(TM,x), _(TM,x), _(x,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), +- /* 1CD8 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), +- /* 1CE0 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 1CE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(TM,x), _(x,x), _(x,x), _(x,x), ++ /* 1CD0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(x,x), _(Ca,O), _(Ca,B), _(Ca,B), _(Ca,B), ++ /* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B), ++ /* 1CE0 */ _(Ca,T), _(Ca,R), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), ++ /* 1CE8 */ _(x,O), _(x,x), _(x,x), _(x,x), _(x,x), _(x,B), _(x,x), _(x,x), ++ /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(Ca,T), _(x,x), _(x,x), _(x,x), ++ /* 1CF8 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x2008u 2496 ++#define indic_offset_0x2008u 2536 + + + /* General Punctuation */ + + /* 2008 */ _(x,x), _(x,x), _(x,x), _(x,x),_(ZWNJ,x),_(ZWJ,x), _(x,x), _(x,x), +- /* 2010 */ _(x,x), _(x,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x), ++ /* 2010 */ _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0xa800u 2512 ++#define indic_offset_0x2070u 2552 ++ ++ ++ /* Superscripts and Subscripts */ ++ ++ /* 2070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(SM,x), _(x,x), _(x,x), _(x,x), ++ /* 2078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 2080 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x), ++ ++#define indic_offset_0xa800u 2576 + + + /* Syloti Nagri */ + + /* A800 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(PK,T), _(C,x), +- /* A808 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* A808 */ _(C,x), _(C,x), _(C,x), _(Bi,T), _(C,x), _(C,x), _(C,x), _(C,x), + /* A810 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A818 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A820 */ _(C,x), _(C,x), _(C,x), _(M,R), _(M,R), _(M,B), _(M,T), _(M,R), + /* A828 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A830 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A838 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Phags-pa */ +@@ -520,158 +538,158 @@ static const INDIC_TABLE_ELEMENT_TYPE in + /* A858 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Vo,x), _(Vo,x), + /* A860 */ _(Vo,x), _(Vo,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Vo,x), _(CS,x), + /* A868 */ _(CS,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A870 */ _(C,x), _(CS,x), _(C,x), _(Bi,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A878 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Saurashtra */ + +- /* A880 */ _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* A880 */ _(Bi,R), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* A888 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* A890 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A898 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A8A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A8A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* A8B0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(M,R), _(M,R), _(M,R), ++ /* A8B0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CF,R), _(M,R), _(M,R), _(M,R), + /* A8B8 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), + /* A8C0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x), _(x,x), + /* A8C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A8D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* A8D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Devanagari Extended */ + +- /* A8E0 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), +- /* A8E8 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), +- /* A8F0 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), ++ /* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), ++ /* A8F0 */ _(Ca,T), _(Ca,T), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A8F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Kayah Li */ + + /* A900 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* A908 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A920 */ _(C,x), _(C,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), +- /* A928 */ _(Vo,x), _(Vo,x), _(Vo,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(x,x), ++ /* A928 */ _(Vo,x), _(Vo,x), _(Vo,x), _(TM,B), _(TM,B), _(TM,B), _(x,x), _(x,x), + + /* Rejang */ + + /* A930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A938 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A940 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,B), +- /* A948 */ _(M,B), _(M,B), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B), _(CF,x), +- /* A950 */ _(CF,x), _(CF,x), _(CF,x), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* A948 */ _(M,B), _(M,B), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B), _(CF,T), ++ /* A950 */ _(CF,T), _(CF,T), _(CF,R), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x), + /* A958 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A960 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A968 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A970 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A978 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Javanese */ + +- /* A980 */ _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* A980 */ _(Bi,T), _(Bi,T),_(CSR,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* A988 */ _(VI,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), + /* A990 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A9A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A9A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* A9B0 */ _(C,x), _(C,x), _(C,x), _(N,x), _(M,R), _(M,R), _(M,T), _(M,T), +- /* A9B8 */ _(M,B), _(M,B), _(M,L), _(M,L), _(M,T), _(CS,x), _(CM,x), _(CM,x), ++ /* A9B0 */ _(C,x), _(C,x), _(C,x), _(N,T), _(M,R), _(M,R), _(M,T), _(M,T), ++ /* A9B8 */ _(M,B), _(M,B), _(M,L), _(M,L), _(M,T), _(CS,R), _(CM,R), _(CM,R), + /* A9C0 */ _(V,BR), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A9C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A9D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* A9D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Myanmar Extended-B */ + +- /* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(C,x), ++ /* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T), _(x,x), _(C,x), + /* A9E8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* A9F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* A9F8 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), + + /* Cham */ + + /* AA00 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), + /* AA08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA28 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(M,B), _(M,T), _(M,L), +- /* AA30 */ _(M,L), _(M,T), _(M,B), _(CM,x), _(CM,L), _(CM,x), _(CM,x), _(x,x), ++ /* AA30 */ _(M,L), _(M,T), _(M,B), _(CM,R), _(CM,L), _(CM,B), _(CM,B), _(x,x), + /* AA38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* AA40 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), +- /* AA48 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x), _(x,x), ++ /* AA40 */ _(CF,x), _(CF,x), _(CF,x), _(CF,T), _(CF,x), _(CF,x), _(CF,x), _(CF,x), ++ /* AA48 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,T), _(CF,R), _(x,x), _(x,x), + /* AA50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* AA58 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Myanmar Extended-A */ + + /* AA60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(C,x), ++ /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x), + + /* Tai Viet */ + + /* AA80 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA88 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA90 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AA98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AAA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AAA8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AAB0 */ _(M,T), _(M,R), _(M,T), _(M,T), _(M,B),_(M,VOL),_(M,VOL), _(M,T), +- /* AAB8 */ _(M,T),_(M,VOL), _(M,R),_(M,VOL),_(M,VOL), _(M,R), _(M,T), _(TM,x), +- /* AAC0 */ _(TL,x), _(TM,x), _(TL,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* AAB8 */ _(M,T),_(M,VOL), _(M,R),_(M,VOL),_(M,VOL), _(M,R), _(M,T), _(TM,T), ++ /* AAC0 */ _(TL,x), _(TM,T), _(TL,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* AAC8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* AAD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* AAD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Meetei Mayek Extensions */ + + /* AAE0 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* AAE8 */ _(C,x), _(C,x), _(C,x), _(M,L), _(M,B), _(M,T), _(M,L), _(M,R), +- /* AAF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Vs,x), _(IS,x), _(x,x), ++ /* AAF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Vs,R), _(IS,x), _(x,x), + +-#define indic_offset_0xabc0u 3272 ++#define indic_offset_0xabc0u 3336 + + + /* Meetei Mayek */ + + /* ABC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* ABC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), + /* ABD0 */ _(C,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* ABD8 */ _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), + /* ABE0 */ _(CF,x), _(CF,x), _(CF,x), _(M,R), _(M,R), _(M,T), _(M,R), _(M,R), +- /* ABE8 */ _(M,B), _(M,R), _(M,R), _(x,x), _(TM,x), _(PK,B), _(x,x), _(x,x), ++ /* ABE8 */ _(M,B), _(M,R), _(M,R), _(x,x), _(TM,R), _(PK,B), _(x,x), _(x,x), + /* ABF0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* ABF8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x10a00u 3336 ++#define indic_offset_0x10a00u 3400 + + + /* Kharoshthi */ + + /* 10A00 */ _(C,x), _(M,O), _(M,B), _(M,B), _(x,x), _(M,T), _(M,O), _(x,x), +- /* 10A08 */ _(x,x), _(x,x), _(x,x), _(x,x), _(M,B), _(x,x), _(Bi,x), _(Vs,x), ++ /* 10A08 */ _(x,x), _(x,x), _(x,x), _(x,x), _(M,B), _(M,B), _(Bi,B), _(Vs,T), + /* 10A10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), + /* 10A18 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 10A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 10A28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 10A30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 10A38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(IS,x), ++ /* 10A38 */ _(N,T), _(N,B), _(N,B), _(x,x), _(x,x), _(x,x), _(x,x), _(IS,x), + /* 10A40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + +-#define indic_offset_0x11000u 3408 ++#define indic_offset_0x11000u 3472 + + + /* Brahmi */ + +- /* 11000 */ _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 11000 */ _(Bi,R), _(Bi,T), _(Vs,R),_(CWS,x),_(CWS,x), _(VI,x), _(VI,x), _(VI,x), + /* 11008 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11010 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11020 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11028 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11030 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11038 */ _(M,T), _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B), + /* 11040 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), +@@ -680,62 +698,62 @@ static const INDIC_TABLE_ELEMENT_TYPE in + /* 11058 */_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x), + /* 11060 */_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x), _(Nd,x), _(Nd,x), + /* 11068 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 11070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(NJ,x), + + /* Kaithi */ + +- /* 11080 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 11080 */ _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11088 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 11090 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11098 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 110A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 110A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 110B0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,T), _(M,T), _(M,R), +- /* 110B8 */ _(M,R), _(V,B), _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 110B8 */ _(M,R), _(V,B), _(N,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x11100u 3600 ++#define indic_offset_0x11100u 3664 + + + /* Chakma */ + +- /* 11100 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), ++ /* 11100 */ _(Bi,T), _(Bi,T), _(Vs,T), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), + /* 11108 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11110 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11118 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11120 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T), + /* 11128 */ _(M,T), _(M,T), _(M,B), _(M,B), _(M,L), _(M,T), _(M,TB), _(M,TB), + /* 11130 */ _(M,T), _(M,B), _(M,B), _(IS,x), _(PK,T), _(x,x), _(Nd,x), _(Nd,x), + /* 11138 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 11140 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11148 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Mahajani */ + + /* 11150 */ _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(C,x), _(C,x), _(C,x), + /* 11158 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11160 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11168 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 11170 */ _(C,x), _(C,x), _(C,x), _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 11170 */ _(C,x), _(C,x), _(C,x), _(N,B), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11178 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Sharada */ + +- /* 11180 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 11180 */ _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11188 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11190 */ _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11198 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 111A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 111A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 111B0 */ _(C,x), _(C,x), _(C,x), _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), + /* 111B8 */ _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,TR), +- /* 111C0 */ _(V,R), _(A,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 111C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 111C0 */ _(V,R), _(A,x),_(CPrf,x),_(CPrf,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 111C8 */ _(x,x), _(x,x), _(N,x), _(M,T), _(M,B), _(x,x), _(x,x), _(x,x), + /* 111D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 111D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Sinhala Archaic Numbers */ + + /* 111E0 */ _(x,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 111E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 111F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), +@@ -744,163 +762,193 @@ static const INDIC_TABLE_ELEMENT_TYPE in + /* Khojki */ + + /* 11200 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11208 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11210 */ _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11218 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11220 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11228 */ _(C,x), _(C,x), _(C,x), _(C,x), _(M,R), _(M,R), _(M,R), _(M,B), +- /* 11230 */ _(M,T), _(M,T), _(M,TR), _(M,TR), _(Bi,x), _(V,R), _(N,x), _(GM,T), ++ /* 11230 */ _(M,T), _(M,T), _(M,TR), _(M,TR), _(Bi,T), _(V,R), _(N,T), _(GM,T), + +-#define indic_offset_0x112b0u 3912 ++#define indic_offset_0x11280u 3976 + + ++ /* Multani */ ++ ++ /* 11280 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(x,x), ++ /* 11288 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), ++ /* 11290 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* 11298 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), ++ /* 112A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* 112A8 */ _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ + /* Khudawadi */ + + /* 112B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 112B8 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 112C0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 112C8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 112D0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 112D8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Bi,x), ++ /* 112D8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Bi,T), + /* 112E0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), +- /* 112E8 */ _(M,T), _(N,x), _(PK,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 112E8 */ _(M,T), _(N,B), _(PK,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 112F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 112F8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Grantha */ + +- /* 11300 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), ++ /* 11300 */ _(Bi,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 11308 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x), + /* 11310 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), + /* 11318 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11320 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11328 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11330 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), + /* 11338 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,R), + /* 11340 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(x,x), _(M,L), + /* 11348 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,R), _(x,x), _(x,x), + /* 11350 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), + /* 11358 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- /* 11360 */ _(VI,x), _(VI,x), _(M,R), _(M,R), _(x,x), _(x,x), _(Ca,x), _(Ca,x), +- /* 11368 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), +- /* 11370 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), ++ /* 11360 */ _(VI,x), _(VI,x), _(M,R), _(M,R), _(x,x), _(x,x), _(Ca,T), _(Ca,T), ++ /* 11368 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(x,x), _(x,x), _(x,x), ++ /* 11370 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x11480u 4112 ++#define indic_offset_0x11480u 4224 + + + /* Tirhuta */ + + /* 11480 */ _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11488 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), + /* 11490 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11498 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 114A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 114A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 114B0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,B), +- /* 114B8 */ _(M,B), _(M,L), _(M,T), _(M,TL), _(M,LR), _(M,R), _(M,LR), _(Bi,x), +- /* 114C0 */ _(Bi,x), _(Vs,x), _(V,B), _(N,x), _(A,x), _(x,x), _(x,x), _(x,x), ++ /* 114B8 */ _(M,B), _(M,L), _(M,T), _(M,TL), _(M,LR), _(M,R), _(M,LR), _(Bi,T), ++ /* 114C0 */ _(Bi,T), _(Vs,R), _(V,B), _(N,B), _(A,x), _(x,x), _(x,x), _(x,x), + /* 114C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 114D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 114D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-#define indic_offset_0x11580u 4208 ++#define indic_offset_0x11580u 4320 + + + /* Siddham */ + + /* 11580 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11588 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), + /* 11590 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11598 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 115A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 115A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,R), + /* 115B0 */ _(M,L), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), +- /* 115B8 */ _(M,L), _(M,TL), _(M,LR),_(M,TLR), _(Bi,x), _(Bi,x), _(Vs,x), _(V,B), +- /* 115C0 */ _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), +- +-#define indic_offset_0x11600u 4280 +- ++ /* 115B8 */ _(M,L), _(M,TL), _(M,LR),_(M,TLR), _(Bi,T), _(Bi,T), _(Vs,R), _(V,B), ++ /* 115C0 */ _(N,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115D8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), ++ /* 115E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 115F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Modi */ + + /* 11600 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11608 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), + /* 11610 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11618 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11620 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11628 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11630 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,B), +- /* 11638 */ _(M,B), _(M,T), _(M,T), _(M,R), _(M,R), _(Bi,x), _(Vs,x), _(V,B), +- /* 11640 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 11638 */ _(M,B), _(M,T), _(M,T), _(M,R), _(M,R), _(Bi,T), _(Vs,R), _(V,B), ++ /* 11640 */ _(M,T), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11648 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11650 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 11658 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11660 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11668 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11670 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 11678 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + + /* Takri */ + + /* 11680 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 11688 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11690 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 11698 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), + /* 116A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), +- /* 116A8 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(Vs,x), _(M,T), _(M,L), _(M,R), +- /* 116B0 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,T), _(N,x), ++ /* 116A8 */ _(C,x), _(C,x), _(C,x), _(Bi,T), _(Vs,R), _(M,T), _(M,L), _(M,R), ++ /* 116B0 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,R), _(N,B), + /* 116B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 116C0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), + /* 116C8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 116F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + +-}; /* Table items: 4488; occupancy: 73% */ ++ /* Ahom */ ++ ++ /* 11700 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* 11708 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* 11710 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), ++ /* 11718 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(CM,B), _(CM,x), _(CM,T), ++ /* 11720 */ _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), _(M,B), _(M,L), _(M,T), ++ /* 11728 */ _(M,B), _(M,T), _(M,T), _(PK,T), _(x,x), _(x,x), _(x,x), _(x,x), ++ /* 11730 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), ++ /* 11738 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), ++ ++}; /* Table items: 4768; occupancy: 72% */ + + INDIC_TABLE_ELEMENT_TYPE + hb_indic_get_categories (hb_codepoint_t u) + { + switch (u >> 12) + { + case 0x0u: + if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u]; +- if (hb_in_range (u, 0x00D0u, 0x00D7u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u]; ++ if (hb_in_range (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u]; + if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u]; + if (unlikely (u == 0x00A0u)) return _(CP,x); + break; + + case 0x1u: + if (hb_in_range (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u]; + if (hb_in_range (u, 0x1700u, 0x17EFu)) return indic_table[u - 0x1700u + indic_offset_0x1700u]; + if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return indic_table[u - 0x1900u + indic_offset_0x1900u]; + if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u]; +- if (hb_in_range (u, 0x1CD0u, 0x1CF7u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u]; ++ if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u]; + break; + + case 0x2u: + if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u]; ++ if (hb_in_range (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u]; + if (unlikely (u == 0x25CCu)) return _(CP,x); + break; + + case 0xAu: + if (hb_in_range (u, 0xA800u, 0xAAF7u)) return indic_table[u - 0xA800u + indic_offset_0xa800u]; + if (hb_in_range (u, 0xABC0u, 0xABFFu)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u]; + break; + + case 0x10u: + if (hb_in_range (u, 0x10A00u, 0x10A47u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u]; + break; + + case 0x11u: + if (hb_in_range (u, 0x11000u, 0x110BFu)) return indic_table[u - 0x11000u + indic_offset_0x11000u]; + if (hb_in_range (u, 0x11100u, 0x11237u)) return indic_table[u - 0x11100u + indic_offset_0x11100u]; +- if (hb_in_range (u, 0x112B0u, 0x11377u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u]; ++ if (hb_in_range (u, 0x11280u, 0x11377u)) return indic_table[u - 0x11280u + indic_offset_0x11280u]; + if (hb_in_range (u, 0x11480u, 0x114DFu)) return indic_table[u - 0x11480u + indic_offset_0x11480u]; +- if (hb_in_range (u, 0x11580u, 0x115C7u)) return indic_table[u - 0x11580u + indic_offset_0x11580u]; +- if (hb_in_range (u, 0x11600u, 0x116CFu)) return indic_table[u - 0x11600u + indic_offset_0x11600u]; ++ if (hb_in_range (u, 0x11580u, 0x1173Fu)) return indic_table[u - 0x11580u + indic_offset_0x11580u]; + break; + + default: + break; + } + return _(x,x); + } + +@@ -909,32 +957,36 @@ hb_indic_get_categories (hb_codepoint_t + #undef ISC_A + #undef ISC_Bi + #undef ISC_BJN + #undef ISC_Ca + #undef ISC_C + #undef ISC_CD + #undef ISC_CF + #undef ISC_CHL ++#undef ISC_CK + #undef ISC_CM + #undef ISC_CP + #undef ISC_CPR ++#undef ISC_CPrf + #undef ISC_CS + #undef ISC_CSR ++#undef ISC_CWS + #undef ISC_GM + #undef ISC_IS + #undef ISC_ZWJ + #undef ISC_ML + #undef ISC_ZWNJ + #undef ISC_N + #undef ISC_Nd + #undef ISC_NJ + #undef ISC_x + #undef ISC_PK + #undef ISC_RS ++#undef ISC_SM + #undef ISC_TL + #undef ISC_TM + #undef ISC_V + #undef ISC_Vs + #undef ISC_Vo + #undef ISC_M + #undef ISC_VI + +diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc +--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc ++++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc +@@ -171,34 +171,18 @@ set_indic_properties (hb_glyph_info_t &i + indic_category_t cat = (indic_category_t) (type & 0x7Fu); + indic_position_t pos = (indic_position_t) (type >> 8); + + + /* + * Re-assign category + */ + +- +- /* The spec says U+0952 is OT_A. However, testing shows that Uniscribe +- * treats a whole bunch of characters similarly. +- * TESTS: For example, for U+0951: +- * U+092E,U+0947,U+0952 +- * U+092E,U+0952,U+0947 +- * U+092E,U+0947,U+0951 +- * U+092E,U+0951,U+0947 +- * U+092E,U+0951,U+0952 +- * U+092E,U+0952,U+0951 +- */ +- if (unlikely (hb_in_ranges (u, 0x0951u, 0x0952u, +- 0x1CD0u, 0x1CD2u, +- 0x1CD4u, 0x1CE1u) || +- u == 0x1CF4u)) +- cat = OT_A; + /* The following act more like the Bindus. */ +- else if (unlikely (hb_in_range (u, 0x0953u, 0x0954u))) ++ if (unlikely (hb_in_range (u, 0x0953u, 0x0954u))) + cat = OT_SM; + /* The following act like consonants. */ + else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u, + 0x1CF5u, 0x1CF6u))) + cat = OT_C; + /* TODO: The following should only be allowed after a Visarga. + * For now, just treat them like regular tone marks. */ + else if (unlikely (hb_in_range (u, 0x1CE2u, 0x1CE8u))) +@@ -211,25 +195,22 @@ set_indic_properties (hb_glyph_info_t &i + /* The following take marks in standalone clusters, similar to Avagraha. */ + else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u, + 0x1CE9u, 0x1CECu, + 0x1CEEu, 0x1CF1u))) + { + cat = OT_Symbol; + ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol); + } +- else if (unlikely (hb_in_range (u, 0x17CDu, 0x17D1u) || +- u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */ ++ else if (unlikely (u == 0x17DDu)) /* https://github.com/roozbehp/unicode-data/issues/2 */ + { +- /* These are like Top Matras. */ + cat = OT_M; + pos = POS_ABOVE_C; + } + else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */ +- else if (unlikely (u == 0x17D2u)) cat = OT_Coeng; /* Khmer coeng */ + else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) + cat = OT_PLACEHOLDER; + else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE; + else if (unlikely (u == 0xA982u)) cat = OT_SM; /* Javanese repha. */ + else if (unlikely (u == 0xA9BEu)) cat = OT_CM2; /* Javanese medial ya. */ + else if (unlikely (u == 0xA9BDu)) { cat = OT_M; pos = POS_POST_C; } /* Javanese vocalic r. */ + + +@@ -552,18 +533,25 @@ data_create_indic (const hb_ot_shape_pla + indic_plan->config = &indic_configs[i]; + break; + } + + indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2'); + indic_plan->virama_glyph = (hb_codepoint_t) -1; + + /* Use zero-context would_substitute() matching for new-spec of the main +- * Indic scripts, and scripts with one spec only, but not for old-specs. */ +- bool zero_context = !indic_plan->is_old_spec; ++ * Indic scripts, and scripts with one spec only, but not for old-specs. ++ * The new-spec for all dual-spec scripts says zero-context matching happens. ++ * ++ * However, testing with Malayalam shows that old and new spec both allow ++ * context. Testing with Bengali new-spec however shows that it doesn't. ++ * So, the heuristic here is the way it is. It should *only* be changed, ++ * as we discover more cases of what Windows does. DON'T TOUCH OTHERWISE. ++ */ ++ bool zero_context = !indic_plan->is_old_spec && plan->props.script != HB_SCRIPT_MALAYALAM; + indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context); + indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context); + indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context); + indic_plan->pstf.init (&plan->map, HB_TAG('p','s','t','f'), zero_context); + + for (unsigned int i = 0; i < ARRAY_LENGTH (indic_plan->mask_array); i++) + indic_plan->mask_array[i] = (indic_features[i].flags & F_GLOBAL) ? + 0 : plan->map.get_1_mask (indic_features[i].tag); +@@ -1343,16 +1331,35 @@ final_reordering_syllable (const hb_ot_s + base++; + info[base].indic_position() = POS_BASE_C; + + try_pref = false; + } + break; + } + } ++ /* For Malayalam, skip over unformed below- (but NOT post-) forms. */ ++ if (buffer->props.script == HB_SCRIPT_MALAYALAM) ++ { ++ for (unsigned int i = base + 1; i < end; i++) ++ { ++ while (i < end && is_joiner (info[i])) ++ i++; ++ if (i == end || !is_halant_or_coeng (info[i])) ++ break; ++ i++; /* Skip halant. */ ++ while (i < end && is_joiner (info[i])) ++ i++; ++ if (i < end && is_consonant (info[i]) && info[i].indic_position() == POS_BELOW_C) ++ { ++ base = i; ++ info[base].indic_position() = POS_BASE_C; ++ } ++ } ++ } + + if (start < base && info[base].indic_position() > POS_BASE_C) + base--; + break; + } + if (base == end && start < base && + is_one_of (info[base - 1], FLAG (OT_ZWJ))) + base--; +@@ -1801,33 +1808,33 @@ decompose_indic (const hb_ot_shape_norma + { + /* Ok, safe to use Uniscribe-style decomposition. */ + *a = 0x0DD9u; + *b = ab; + return true; + } + } + +- return c->unicode->decompose (ab, a, b); ++ return (bool) c->unicode->decompose (ab, a, b); + } + + static bool + compose_indic (const hb_ot_shape_normalize_context_t *c, + hb_codepoint_t a, + hb_codepoint_t b, + hb_codepoint_t *ab) + { + /* Avoid recomposing split matras. */ + if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a))) + return false; + + /* Composition-exclusion exceptions that we want to recompose. */ + if (a == 0x09AFu && b == 0x09BCu) { *ab = 0x09DFu; return true; } + +- return c->unicode->compose (a, b, ab); ++ return (bool) c->unicode->compose (a, b, ab); + } + + + const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = + { + "indic", + collect_features_indic, + override_features_indic, +diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc +--- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc ++++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc +@@ -194,16 +194,20 @@ set_myanmar_properties (hb_glyph_info_t + case 0x1004u: case 0x101Bu: case 0x105Au: + cat = (indic_category_t) OT_Ra; + break; + + case 0x1032u: case 0x1036u: + cat = (indic_category_t) OT_A; + break; + ++ case 0x1039u: ++ cat = (indic_category_t) OT_H; ++ break; ++ + case 0x103Au: + cat = (indic_category_t) OT_As; + break; + + case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u: + case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u: + case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u: + case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u: +diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh +--- a/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh ++++ b/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh +@@ -39,19 +39,17 @@ + #define complex_var_u8_1() var2.u8[3] + + + enum hb_ot_shape_zero_width_marks_type_t { + HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, + // HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, +- HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, +- +- HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE ++ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE + }; + + + /* Master OT shaper list */ + #define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \ + HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \ + HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \ + HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \ +diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc +--- a/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc ++++ b/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc +@@ -372,11 +372,11 @@ const hb_ot_complex_shaper_t _hb_ot_comp + NULL, /* data_create */ + NULL, /* data_destroy */ + preprocess_text_thai, + NULL, /* postprocess_glyphs */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + NULL, /* compose */ + NULL, /* setup_masks */ +- HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, ++ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + false,/* fallback_position */ + }; +diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc +--- a/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc ++++ b/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc +@@ -52,11 +52,11 @@ const hb_ot_complex_shaper_t _hb_ot_comp + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ + NULL, /* postprocess_glyphs */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + NULL, /* compose */ + NULL, /* setup_masks */ +- HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, ++ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + true, /* fallback_position */ + }; +diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc +--- a/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc ++++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc +@@ -280,16 +280,19 @@ setup_rphf_mask (const hb_ot_shape_plan_ + info[i].mask |= mask; + } + } + + static void + setup_topographical_masks (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer) + { ++ const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data; ++ if (use_plan->arabic_plan) ++ return; + + ASSERT_STATIC (INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4); + hb_mask_t masks[4], all_masks = 0; + for (unsigned int i = 0; i < 4; i++) + { + masks[i] = plan->map.get_1_mask (arabic_features[i]); + if (masks[i] == plan->map.get_global_mask ()) + masks[i] = 0; +@@ -355,17 +358,17 @@ setup_syllables (const hb_ot_shape_plan_ + static void + clear_substitution_flags (const hb_ot_shape_plan_t *plan, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) + { + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) +- _hb_glyph_info_clear_substituted_and_ligated_and_multiplied (&info[i]); ++ _hb_glyph_info_clear_substituted (&info[i]); + } + + static void + record_rphf (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) + { + const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data; +@@ -400,66 +403,71 @@ record_pref (const hb_ot_shape_plan_t *p + if (_hb_glyph_info_substituted (&info[i])) + { + info[i].use_category() = USE_VPre; + break; + } + } + } + ++static inline bool ++is_halant (const hb_glyph_info_t &info) ++{ ++ return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info); ++} ++ + static void + reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end) + { + syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); + /* Only a few syllable types need reordering. */ + if (unlikely (!(FLAG_SAFE (syllable_type) & + (FLAG (virama_terminated_cluster) | + FLAG (consonant_cluster) | + FLAG (vowel_cluster) | + FLAG (broken_cluster) | + 0)))) + return; + + hb_glyph_info_t *info = buffer->info; + +-#define HALANT_FLAGS FLAG(USE_H) + #define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB) | FLAG (USE_IV)) + + /* Move things forward. */ + if (info[start].use_category() == USE_R && end - start > 1) + { + /* Got a repha. Reorder it to after first base, before first halant. */ + for (unsigned int i = start + 1; i < end; i++) +- if (FLAG_UNSAFE (info[i].use_category()) & (HALANT_FLAGS | BASE_FLAGS)) ++ if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i])) + { + /* If we hit a halant, move before it; otherwise it's a base: move to it's + * place, and shift things in between backward. */ + +- if (info[i].use_category() == USE_H) ++ if (is_halant (info[i])) + i--; + + buffer->merge_clusters (start, i + 1); + hb_glyph_info_t t = info[start]; + memmove (&info[start], &info[start + 1], (i - start) * sizeof (info[0])); + info[i] = t; + + break; + } + } + + /* Move things back. */ + unsigned int j = end; + for (unsigned int i = start; i < end; i++) + { + uint32_t flag = FLAG_UNSAFE (info[i].use_category()); +- if (flag & (HALANT_FLAGS | BASE_FLAGS)) ++ if ((flag & (BASE_FLAGS)) || is_halant (info[i])) + { +- /* If we hit a halant, move before it; otherwise it's a base: move to it's ++ /* If we hit a halant, move after it; otherwise it's a base: move to it's + * place, and shift things in between backward. */ +- if (info[i].use_category() == USE_H) ++ if (is_halant (info[i])) + j = i + 1; + else + j = i; + } + else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) && + /* Only move the first component of a MultipleSubst. */ + 0 == _hb_glyph_info_get_lig_comp (&info[i]) && + j < i) +@@ -553,17 +561,17 @@ compose_use (const hb_ot_shape_normalize + hb_codepoint_t a, + hb_codepoint_t b, + hb_codepoint_t *ab) + { + /* Avoid recomposing split matras. */ + if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a))) + return false; + +- return c->unicode->compose (a, b, ab); ++ return (bool)c->unicode->compose (a, b, ab); + } + + + const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use = + { + "use", + collect_features_use, + NULL, /* override_features */ +diff --git a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc +--- a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc ++++ b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc +@@ -71,26 +71,26 @@ + */ + + static bool + decompose_unicode (const hb_ot_shape_normalize_context_t *c, + hb_codepoint_t ab, + hb_codepoint_t *a, + hb_codepoint_t *b) + { +- return c->unicode->decompose (ab, a, b); ++ return (bool) c->unicode->decompose (ab, a, b); + } + + static bool + compose_unicode (const hb_ot_shape_normalize_context_t *c, + hb_codepoint_t a, + hb_codepoint_t b, + hb_codepoint_t *ab) + { +- return c->unicode->compose (a, b, ab); ++ return (bool) c->unicode->compose (a, b, ab); + } + + static inline void + set_glyph (hb_glyph_info_t &info, hb_font_t *font) + { + font->get_glyph (info.codepoint, 0, &info.glyph_index()); + } + +@@ -122,17 +122,17 @@ decompose (const hb_ot_shape_normalize_c + hb_codepoint_t a, b, a_glyph, b_glyph; + hb_buffer_t * const buffer = c->buffer; + hb_font_t * const font = c->font; + + if (!c->decompose (c, ab, &a, &b) || + (b && !font->get_glyph (b, 0, &b_glyph))) + return 0; + +- bool has_a = font->get_glyph (a, 0, &a_glyph); ++ bool has_a = (bool) font->get_glyph (a, 0, &a_glyph); + if (shortest && has_a) { + /* Output a and b */ + output_char (buffer, a, a_glyph); + if (likely (b)) { + output_char (buffer, b, b_glyph); + return 2; + } + return 1; +diff --git a/gfx/harfbuzz/src/hb-ot-shape.cc b/gfx/harfbuzz/src/hb-ot-shape.cc +--- a/gfx/harfbuzz/src/hb-ot-shape.cc ++++ b/gfx/harfbuzz/src/hb-ot-shape.cc +@@ -657,42 +657,43 @@ hb_ot_position_default (hb_ot_shape_cont + unsigned int count = c->buffer->len; + hb_glyph_info_t *info = c->buffer->info; + hb_glyph_position_t *pos = c->buffer->pos; + + if (HB_DIRECTION_IS_HORIZONTAL (direction)) + { + for (unsigned int i = 0; i < count; i++) + pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint); ++ /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ + if (c->font->has_glyph_h_origin_func ()) + for (unsigned int i = 0; i < count; i++) + c->font->subtract_glyph_h_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); + } + else + { + for (unsigned int i = 0; i < count; i++) ++ { + pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint); +- if (c->font->has_glyph_v_origin_func ()) +- for (unsigned int i = 0; i < count; i++) +- c->font->subtract_glyph_v_origin (info[i].codepoint, +- &pos[i].x_offset, +- &pos[i].y_offset); ++ c->font->subtract_glyph_v_origin (info[i].codepoint, ++ &pos[i].x_offset, ++ &pos[i].y_offset); ++ } + } + if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK) + _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer); + } + + static inline bool + hb_ot_position_complex (hb_ot_shape_context_t *c) + { + bool ret = false; + unsigned int count = c->buffer->len; +- bool has_positioning = hb_ot_layout_has_positioning (c->face); ++ bool has_positioning = (bool) hb_ot_layout_has_positioning (c->face); + /* If the font has no GPOS, AND, no fallback positioning will + * happen, AND, direction is forward, then when zeroing mark + * widths, we shift the mark with it, such that the mark + * is positioned hanging over the previous glyph. When + * direction is backward we don't shift and it will end up + * hanging over the next glyph after the final reordering. + * If fallback positinoing happens or GPOS is present, we don't + * care. +@@ -721,24 +722,26 @@ hb_ot_position_complex (hb_ot_shape_cont + + if (has_positioning) + { + hb_glyph_info_t *info = c->buffer->info; + hb_glyph_position_t *pos = c->buffer->pos; + + /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */ + ++ /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ + if (c->font->has_glyph_h_origin_func ()) + for (unsigned int i = 0; i < count; i++) + c->font->add_glyph_h_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); + + c->plan->position (c->font, c->buffer); + ++ /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ + if (c->font->has_glyph_h_origin_func ()) + for (unsigned int i = 0; i < count; i++) + c->font->subtract_glyph_h_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); + + ret = true; + } +@@ -847,16 +850,18 @@ hb_bool_t + hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features}; + hb_ot_shape_internal (&c); + + return true; + } + + + /** ++ * hb_ot_shape_plan_collect_lookups: ++ * + * Since: 0.9.7 + **/ + void + hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, + hb_tag_t table_tag, + hb_set_t *lookup_indexes /* OUT */) + { + /* XXX Does the first part always succeed? */ +@@ -880,16 +885,18 @@ add_char (hb_font_t *font, + hb_codepoint_t m = unicode->mirroring (u); + if (m != u && font->get_glyph (m, 0, &glyph)) + glyphs->add (glyph); + } + } + + + /** ++ * hb_ot_shape_glyphs_closure: ++ * + * Since: 0.9.2 + **/ + void + hb_ot_shape_glyphs_closure (hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + hb_set_t *glyphs) +diff --git a/gfx/harfbuzz/src/hb-ot-shape.h b/gfx/harfbuzz/src/hb-ot-shape.h +--- a/gfx/harfbuzz/src/hb-ot-shape.h ++++ b/gfx/harfbuzz/src/hb-ot-shape.h +@@ -31,23 +31,23 @@ + #ifndef HB_OT_SHAPE_H + #define HB_OT_SHAPE_H + + #include "hb.h" + + HB_BEGIN_DECLS + + /* TODO port to shape-plan / set. */ +-void ++HB_EXTERN void + hb_ot_shape_glyphs_closure (hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + hb_set_t *glyphs); + +-void ++HB_EXTERN void + hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, + hb_tag_t table_tag, + hb_set_t *lookup_indexes /* OUT */); + + HB_END_DECLS + + #endif /* HB_OT_SHAPE_H */ +diff --git a/gfx/harfbuzz/src/hb-ot-tag.cc b/gfx/harfbuzz/src/hb-ot-tag.cc +--- a/gfx/harfbuzz/src/hb-ot-tag.cc ++++ b/gfx/harfbuzz/src/hb-ot-tag.cc +@@ -350,17 +350,16 @@ static const LangTag ot_languages[] = { + {"guz", HB_TAG('G','U','Z',' ')}, /* Ekegusii/Gusii */ + {"gv", HB_TAG('M','N','X',' ')}, /* Manx */ + {"ha", HB_TAG('H','A','U',' ')}, /* Hausa */ + {"har", HB_TAG('H','R','I',' ')}, /* Harari */ + {"haw", HB_TAG('H','A','W',' ')}, /* Hawaiian */ + {"hay", HB_TAG('H','A','Y',' ')}, /* Haya */ + {"haz", HB_TAG('H','A','Z',' ')}, /* Hazaragi */ + {"he", HB_TAG('I','W','R',' ')}, /* Hebrew */ +- {"hz", HB_TAG('H','E','R',' ')}, /* Herero */ + {"hi", HB_TAG('H','I','N',' ')}, /* Hindi */ + {"hil", HB_TAG('H','I','L',' ')}, /* Hiligaynon */ + {"hnd", HB_TAG('H','N','D',' ')}, /* [Southern] Hindko */ + {"hne", HB_TAG('C','H','H',' ')}, /* Chattisgarhi */ + {"hno", HB_TAG('H','N','D',' ')}, /* [Northern] Hindko */ + {"ho", HB_TAG('H','M','O',' ')}, /* Hiri Motu */ + {"hoc", HB_TAG('H','O',' ',' ')}, /* Ho */ + {"hoj", HB_TAG('H','A','R',' ')}, /* Harauti */ +@@ -596,18 +595,18 @@ static const LangTag ot_languages[] = { + {"rue", HB_TAG('R','S','Y',' ')}, /* Rusyn */ + {"rup", HB_TAG('R','U','P',' ')}, /* Aromanian/Arumanian/Macedo-Romanian */ + {"rw", HB_TAG('R','U','A',' ')}, /* Kinyarwanda */ + {"rwr", HB_TAG('M','A','W',' ')}, /* Marwari (India) */ + {"sa", HB_TAG('S','A','N',' ')}, /* Sanskrit */ + {"sah", HB_TAG('Y','A','K',' ')}, /* Yakut */ + {"sas", HB_TAG('S','A','S',' ')}, /* Sasak */ + {"sat", HB_TAG('S','A','T',' ')}, /* Santali */ ++ {"sc", HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */ + {"sck", HB_TAG('S','A','D',' ')}, /* Sadri */ +- {"sc", HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */ + {"scn", HB_TAG('S','C','N',' ')}, /* Sicilian */ + {"sco", HB_TAG('S','C','O',' ')}, /* Scots */ + {"scs", HB_TAG('S','L','A',' ')}, /* [North] Slavey */ + {"sd", HB_TAG('S','N','D',' ')}, /* Sindhi */ + {"se", HB_TAG('N','S','M',' ')}, /* Northern Sami */ + {"seh", HB_TAG('S','N','A',' ')}, /* Sena */ + {"sel", HB_TAG('S','E','L',' ')}, /* Selkup */ + {"sg", HB_TAG('S','G','O',' ')}, /* Sango */ +@@ -685,29 +684,29 @@ static const LangTag ot_languages[] = { + {"umb", HB_TAG('U','M','B',' ')}, /* Umbundu */ + {"unr", HB_TAG('M','U','N',' ')}, /* Mundari */ + {"ur", HB_TAG('U','R','D',' ')}, /* Urdu */ + {"uz", HB_TAG('U','Z','B',' ')}, /* Uzbek [macrolanguage] */ + {"uzn", HB_TAG('U','Z','B',' ')}, /* Northern Uzbek */ + {"uzs", HB_TAG('U','Z','B',' ')}, /* Southern Uzbek */ + {"ve", HB_TAG('V','E','N',' ')}, /* Venda */ + {"vec", HB_TAG('V','E','C',' ')}, /* Venetian */ ++ {"vi", HB_TAG('V','I','T',' ')}, /* Vietnamese */ + {"vls", HB_TAG('F','L','E',' ')}, /* Vlaams */ +- {"vi", HB_TAG('V','I','T',' ')}, /* Vietnamese */ + {"vmw", HB_TAG('M','A','K',' ')}, /* Makhuwa */ + {"vo", HB_TAG('V','O','L',' ')}, /* Volapük */ + {"vro", HB_TAG('V','R','O',' ')}, /* Võro */ + {"wa", HB_TAG('W','L','N',' ')}, /* Walloon */ + {"war", HB_TAG('W','A','R',' ')}, /* Waray (Philippines) */ + {"wbm", HB_TAG('W','A',' ',' ')}, /* Wa */ + {"wbr", HB_TAG('W','A','G',' ')}, /* Wagdi */ + {"wle", HB_TAG('S','I','G',' ')}, /* Wolane */ ++ {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */ + {"wry", HB_TAG('M','A','W',' ')}, /* Merwari */ + {"wtm", HB_TAG('W','T','M',' ')}, /* Mewati */ +- {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */ + {"xal", HB_TAG('K','L','M',' ')}, /* Kalmyk */ + {"xh", HB_TAG('X','H','S',' ')}, /* Xhosa */ + {"xog", HB_TAG('X','O','G',' ')}, /* Soga */ + {"xom", HB_TAG('K','M','O',' ')}, /* Komo (Sudan) */ + {"xsl", HB_TAG('S','S','L',' ')}, /* South Slavey */ + {"xst", HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) */ + {"xwo", HB_TAG('T','O','D',' ')}, /* Written Oirat (Todo) */ + {"yao", HB_TAG('Y','A','O',' ')}, /* Yao */ +@@ -923,9 +922,32 @@ hb_ot_tag_to_language (hb_tag_t tag) + buf[9] = tag & 0xFF; + if (buf[9] == 0x20) + buf[9] = '\0'; + buf[10] = '\0'; + return hb_language_from_string ((char *) buf, -1); + } + } + ++static inline void ++test_langs_sorted (void) ++{ ++ for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++) ++ { ++ int c = lang_compare_first_component (ot_languages[i-1].language, ot_languages[i].language); ++ if (c >= 0) ++ { ++ fprintf (stderr, "ot_languages not sorted at index %d: %s %d %s\n", ++ i, ot_languages[i-1].language, c, ot_languages[i].language); ++ abort(); ++ } ++ } ++} + ++#ifdef MAIN ++int ++main (void) ++{ ++ test_langs_sorted (); ++ return 0; ++} ++ ++#endif +diff --git a/gfx/harfbuzz/src/hb-ot-tag.h b/gfx/harfbuzz/src/hb-ot-tag.h +--- a/gfx/harfbuzz/src/hb-ot-tag.h ++++ b/gfx/harfbuzz/src/hb-ot-tag.h +@@ -34,26 +34,26 @@ + #include "hb.h" + + HB_BEGIN_DECLS + + + #define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T') + #define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't') + +-void ++HB_EXTERN void + hb_ot_tags_from_script (hb_script_t script, + hb_tag_t *script_tag_1, + hb_tag_t *script_tag_2); + +-hb_script_t ++HB_EXTERN hb_script_t + hb_ot_tag_to_script (hb_tag_t tag); + +-hb_tag_t ++HB_EXTERN hb_tag_t + hb_ot_tag_from_language (hb_language_t language); + +-hb_language_t ++HB_EXTERN hb_language_t + hb_ot_tag_to_language (hb_tag_t tag); + + + HB_END_DECLS + + #endif /* HB_OT_TAG_H */ +diff --git a/gfx/harfbuzz/src/hb-private.hh b/gfx/harfbuzz/src/hb-private.hh +--- a/gfx/harfbuzz/src/hb-private.hh ++++ b/gfx/harfbuzz/src/hb-private.hh +@@ -48,19 +48,16 @@ + /* We only use these two for debug output. However, the debug code is + * always seen by the compiler (and optimized out in non-debug builds. + * If including these becomes a problem, we can start thinking about + * someway around that. */ + #include <stdio.h> + #include <errno.h> + #include <stdarg.h> + +-#ifdef _MSC_VER +-#include <windows.h> /* ensure DEFINE_ENUM_FLAG_OPERATORS is defined */ +-#endif + + /* Compile-time custom allocator support. */ + + #if defined(hb_malloc_impl) \ + && defined(hb_calloc_impl) \ + && defined(hb_realloc_impl) \ + && defined(hb_free_impl) + extern "C" void* hb_malloc_impl(size_t size); +@@ -177,16 +174,19 @@ extern "C" void hb_free_impl(void *ptr) + # define setlocale(Category, Locale) "C" + static int errno = 0; /* Use something better? */ + # endif + # elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) + # define getenv(Name) NULL + # endif + # if defined(_MSC_VER) && _MSC_VER < 1900 + # define snprintf _snprintf ++# elif defined(_MSC_VER) && _MSC_VER >= 1900 ++# /* Covers VC++ Error for strdup being a deprecated POSIX name and to instead use _strdup instead */ ++# define strdup _strdup + # endif + #endif + + #if HAVE_ATEXIT + /* atexit() is only safe to be called from shared libraries on certain + * platforms. Whitelist. + * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */ + # if defined(__linux) && defined(__GLIBC_PREREQ) +@@ -894,37 +894,32 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, + } + + + /* Enable bitwise ops on enums marked as flags_t */ + /* To my surprise, looks like the function resolver is happy to silently cast + * one enum to another... So this doesn't provide the type-checking that I + * originally had in mind... :(. + * +- * On MSVC use DEFINE_ENUM_FLAG_OPERATORS. See: +- * https://github.com/behdad/harfbuzz/pull/163 ++ * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163 + */ + #ifdef _MSC_VER + # pragma warning(disable:4200) + # pragma warning(disable:4800) +-# define HB_MARK_AS_FLAG_T(flags_t) DEFINE_ENUM_FLAG_OPERATORS (##flags_t##); +-#else +-# define HB_MARK_AS_FLAG_T(flags_t) template <> class hb_mark_as_flags_t<flags_t> {}; +-template <class T> class hb_mark_as_flags_t; +-template <class T> static inline T operator | (T l, T r) +-{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T ((unsigned int) l | (unsigned int) r); } +-template <class T> static inline T operator & (T l, T r) +-{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T ((unsigned int) l & (unsigned int) r); } +-template <class T> static inline T operator ~ (T r) +-{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T (~(unsigned int) r); } +-template <class T> static inline T& operator |= (T &l, T r) +-{ hb_mark_as_flags_t<T> unused HB_UNUSED; l = l | r; return l; } +-template <class T> static inline T& operator &= (T& l, T r) +-{ hb_mark_as_flags_t<T> unused HB_UNUSED; l = l & r; return l; } + #endif ++#define HB_MARK_AS_FLAG_T(T) \ ++ extern "C++" { \ ++ static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \ ++ static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \ ++ static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \ ++ static inline T operator ~ (T r) { return T (~(unsigned int) r); } \ ++ static inline T& operator |= (T &l, T r) { l = l | r; return l; } \ ++ static inline T& operator &= (T& l, T r) { l = l & r; return l; } \ ++ static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \ ++ } + + + /* Useful for set-operations on small enums. + * For example, for testing "x ∈ {x1, x2, x3}" use: + * (FLAG_SAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) + */ + #define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((x) < 32) + (1U << (x))) + #define FLAG_SAFE(x) (1U << (x)) +@@ -1005,10 +1000,12 @@ static inline hb_options_t + hb_options (void) + { + if (unlikely (!_hb_options.i)) + _hb_options_init (); + + return _hb_options.opts; + } + ++/* Size signifying variable-sized array */ ++#define VAR 1 + + #endif /* HB_PRIVATE_HH */ +diff --git a/gfx/harfbuzz/src/hb-set.h b/gfx/harfbuzz/src/hb-set.h +--- a/gfx/harfbuzz/src/hb-set.h ++++ b/gfx/harfbuzz/src/hb-set.h +@@ -39,119 +39,119 @@ HB_BEGIN_DECLS + /* + * Since: 0.9.21 + */ + #define HB_SET_VALUE_INVALID ((hb_codepoint_t) -1) + + typedef struct hb_set_t hb_set_t; + + +-hb_set_t * ++HB_EXTERN hb_set_t * + hb_set_create (void); + +-hb_set_t * ++HB_EXTERN hb_set_t * + hb_set_get_empty (void); + +-hb_set_t * ++HB_EXTERN hb_set_t * + hb_set_reference (hb_set_t *set); + +-void ++HB_EXTERN void + hb_set_destroy (hb_set_t *set); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_set_user_data (hb_set_t *set, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + +-void * ++HB_EXTERN void * + hb_set_get_user_data (hb_set_t *set, + hb_user_data_key_t *key); + + + /* Returns false if allocation has failed before */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_allocation_successful (const hb_set_t *set); + +-void ++HB_EXTERN void + hb_set_clear (hb_set_t *set); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_is_empty (const hb_set_t *set); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_has (const hb_set_t *set, + hb_codepoint_t codepoint); + + /* Right now limited to 16-bit integers. Eventually will do full codepoint range, sans -1 + * which we will use as a sentinel. */ +-void ++HB_EXTERN void + hb_set_add (hb_set_t *set, + hb_codepoint_t codepoint); + +-void ++HB_EXTERN void + hb_set_add_range (hb_set_t *set, + hb_codepoint_t first, + hb_codepoint_t last); + +-void ++HB_EXTERN void + hb_set_del (hb_set_t *set, + hb_codepoint_t codepoint); + +-void ++HB_EXTERN void + hb_set_del_range (hb_set_t *set, + hb_codepoint_t first, + hb_codepoint_t last); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_is_equal (const hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_set (hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_union (hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_intersect (hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_subtract (hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_symmetric_difference (hb_set_t *set, + const hb_set_t *other); + +-void ++HB_EXTERN void + hb_set_invert (hb_set_t *set); + +-unsigned int ++HB_EXTERN unsigned int + hb_set_get_population (const hb_set_t *set); + + /* Returns -1 if set empty. */ +-hb_codepoint_t ++HB_EXTERN hb_codepoint_t + hb_set_get_min (const hb_set_t *set); + + /* Returns -1 if set empty. */ +-hb_codepoint_t ++HB_EXTERN hb_codepoint_t + hb_set_get_max (const hb_set_t *set); + + /* Pass -1 in to get started. */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_next (const hb_set_t *set, + hb_codepoint_t *codepoint); + + /* Pass -1 for first and last to get started. */ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_set_next_range (const hb_set_t *set, + hb_codepoint_t *first, + hb_codepoint_t *last); + + + HB_END_DECLS + + #endif /* HB_SET_H */ +diff --git a/gfx/harfbuzz/src/hb-shape-plan.h b/gfx/harfbuzz/src/hb-shape-plan.h +--- a/gfx/harfbuzz/src/hb-shape-plan.h ++++ b/gfx/harfbuzz/src/hb-shape-plan.h +@@ -33,57 +33,57 @@ + + #include "hb-common.h" + #include "hb-font.h" + + HB_BEGIN_DECLS + + typedef struct hb_shape_plan_t hb_shape_plan_t; + +-hb_shape_plan_t * ++HB_EXTERN hb_shape_plan_t * + hb_shape_plan_create (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const char * const *shaper_list); + +-hb_shape_plan_t * ++HB_EXTERN hb_shape_plan_t * + hb_shape_plan_create_cached (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const char * const *shaper_list); + +-hb_shape_plan_t * ++HB_EXTERN hb_shape_plan_t * + hb_shape_plan_get_empty (void); + +-hb_shape_plan_t * ++HB_EXTERN hb_shape_plan_t * + hb_shape_plan_reference (hb_shape_plan_t *shape_plan); + +-void ++HB_EXTERN void + hb_shape_plan_destroy (hb_shape_plan_t *shape_plan); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + +-void * ++HB_EXTERN void * + hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, + hb_user_data_key_t *key); + + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_shape_plan_execute (hb_shape_plan_t *shape_plan, + hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features); + +-const char * ++HB_EXTERN const char * + hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan); + + + HB_END_DECLS + + #endif /* HB_SHAPE_PLAN_H */ +diff --git a/gfx/harfbuzz/src/hb-shape.cc b/gfx/harfbuzz/src/hb-shape.cc +--- a/gfx/harfbuzz/src/hb-shape.cc ++++ b/gfx/harfbuzz/src/hb-shape.cc +@@ -205,23 +205,25 @@ parse_one_feature (const char **pp, cons + parse_feature_value_postfix (pp, end, feature) && + parse_space (pp, end) && + *pp == end; + } + + /** + * hb_feature_from_string: + * @str: (array length=len) (element-type uint8_t): a string to parse +- * @len: length of @str, or -1 if string is nul-terminated ++ * @len: length of @str, or -1 if string is %NULL terminated + * @feature: (out): the #hb_feature_t to initialize with the parsed values + * +- * Parses a string into a #hb_feature_t. If @len is -1 then @str is +- * %NULL-terminated. ++ * Parses a string into a #hb_feature_t. + * +- * Return value: %TRUE if @str is successfully parsed, %FALSE otherwise ++ * TODO: document the syntax here. ++ * ++ * Return value: ++ * %true if @str is successfully parsed, %false otherwise. + * + * Since: 0.9.5 + **/ + hb_bool_t + hb_feature_from_string (const char *str, int len, + hb_feature_t *feature) + { + hb_feature_t feat; +diff --git a/gfx/harfbuzz/src/hb-shape.h b/gfx/harfbuzz/src/hb-shape.h +--- a/gfx/harfbuzz/src/hb-shape.h ++++ b/gfx/harfbuzz/src/hb-shape.h +@@ -42,37 +42,37 @@ HB_BEGIN_DECLS + + typedef struct hb_feature_t { + hb_tag_t tag; + uint32_t value; + unsigned int start; + unsigned int end; + } hb_feature_t; + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_feature_from_string (const char *str, int len, + hb_feature_t *feature); + +-void ++HB_EXTERN void + hb_feature_to_string (hb_feature_t *feature, + char *buf, unsigned int size); + + +-void ++HB_EXTERN void + hb_shape (hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_shape_full (hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + const char * const *shaper_list); + +-const char ** ++HB_EXTERN const char ** + hb_shape_list_shapers (void); + + + HB_END_DECLS + + #endif /* HB_SHAPE_H */ +diff --git a/gfx/harfbuzz/src/hb-shaper-list.hh b/gfx/harfbuzz/src/hb-shaper-list.hh +--- a/gfx/harfbuzz/src/hb-shaper-list.hh ++++ b/gfx/harfbuzz/src/hb-shaper-list.hh +@@ -41,15 +41,18 @@ HB_SHAPER_IMPLEMENT (coretext_aat) + + #ifdef HAVE_OT + HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */ + #endif + + #ifdef HAVE_UNISCRIBE + HB_SHAPER_IMPLEMENT (uniscribe) + #endif ++#ifdef HAVE_DIRECTWRITE ++HB_SHAPER_IMPLEMENT (directwrite) ++#endif + #ifdef HAVE_CORETEXT + HB_SHAPER_IMPLEMENT (coretext) + #endif + + #ifdef HAVE_FALLBACK + HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */ + #endif +diff --git a/gfx/harfbuzz/src/hb-unicode.h b/gfx/harfbuzz/src/hb-unicode.h +--- a/gfx/harfbuzz/src/hb-unicode.h ++++ b/gfx/harfbuzz/src/hb-unicode.h +@@ -169,52 +169,52 @@ typedef enum + */ + + typedef struct hb_unicode_funcs_t hb_unicode_funcs_t; + + + /* + * just give me the best implementation you've got there. + */ +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_unicode_funcs_get_default (void); + + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_unicode_funcs_create (hb_unicode_funcs_t *parent); + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_unicode_funcs_get_empty (void); + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs); + +-void ++HB_EXTERN void + hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, + hb_bool_t replace); + + +-void * ++HB_EXTERN void * + hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, + hb_user_data_key_t *key); + + +-void ++HB_EXTERN void + hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs); + +-hb_unicode_funcs_t * ++HB_EXTERN hb_unicode_funcs_t * + hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs); + + + /* + * funcs + */ + + /* typedefs */ +@@ -280,191 +280,207 @@ typedef unsigned int (*hb_unicode_deco + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_combining_class_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_unicode_funcs_set_eastasian_width_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_eastasian_width_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_unicode_funcs_set_general_category_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_general_category_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_unicode_funcs_set_mirroring_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_mirroring_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_unicode_funcs_set_script_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_script_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_unicode_funcs_set_compose_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_compose_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_unicode_funcs_set_decompose_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_decompose_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /** + * hb_unicode_funcs_set_decompose_compatibility_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +-void ++HB_EXTERN void + hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs, + hb_unicode_decompose_compatibility_func_t func, + void *user_data, hb_destroy_func_t destroy); + + /* accessors */ + + /** ++ * hb_unicode_combining_class: ++ * + * Since: 0.9.2 + **/ +-hb_unicode_combining_class_t ++HB_EXTERN hb_unicode_combining_class_t + hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + + /** ++ * hb_unicode_eastasian_width: ++ * + * Since: 0.9.2 + **/ +-unsigned int ++HB_EXTERN unsigned int + hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + + /** ++ * hb_unicode_general_category: ++ * + * Since: 0.9.2 + **/ +-hb_unicode_general_category_t ++HB_EXTERN hb_unicode_general_category_t + hb_unicode_general_category (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + + /** ++ * hb_unicode_mirroring: ++ * + * Since: 0.9.2 + **/ +-hb_codepoint_t ++HB_EXTERN hb_codepoint_t + hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + + /** ++ * hb_unicode_script: ++ * + * Since: 0.9.2 + **/ +-hb_script_t ++HB_EXTERN hb_script_t + hb_unicode_script (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + + /** ++ * hb_unicode_compose: ++ * + * Since: 0.9.2 + **/ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_unicode_compose (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t a, + hb_codepoint_t b, + hb_codepoint_t *ab); + + /** ++ * hb_unicode_decompose: ++ * + * Since: 0.9.2 + **/ +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t ab, + hb_codepoint_t *a, + hb_codepoint_t *b); + + /** ++ * hb_unicode_decompose_compatibility: ++ * + * Since: 0.9.2 + **/ +-unsigned int ++HB_EXTERN unsigned int + hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t u, + hb_codepoint_t *decomposed); + + HB_END_DECLS + + #endif /* HB_UNICODE_H */ +diff --git a/gfx/harfbuzz/src/hb-uniscribe.cc b/gfx/harfbuzz/src/hb-uniscribe.cc +--- a/gfx/harfbuzz/src/hb-uniscribe.cc ++++ b/gfx/harfbuzz/src/hb-uniscribe.cc +@@ -914,17 +914,17 @@ retry: + log_clusters + chars_offset, + char_props + chars_offset, + glyphs + glyphs_offset, + glyph_props + glyphs_offset, + (int *) &glyphs_len); + + if (unlikely (items[i].a.fNoGlyphIndex)) + FAIL ("ScriptShapeOpenType() set fNoGlyphIndex"); +- if (unlikely (hr == E_OUTOFMEMORY)) ++ if (unlikely (hr == E_OUTOFMEMORY || hr == E_NOT_SUFFICIENT_BUFFER)) + { + if (unlikely (!buffer->ensure (buffer->allocated * 2))) + FAIL ("Buffer resize failed"); + goto retry; + } + if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT)) + { + if (items[i].a.eScript == SCRIPT_UNDEFINED) +@@ -1014,17 +1014,17 @@ retry: + buffer->clear_positions (); + double x_mult = font_data->x_mult, y_mult = font_data->y_mult; + for (unsigned int i = 0; i < glyphs_len; i++) + { + hb_glyph_info_t *info = &buffer->info[i]; + hb_glyph_position_t *pos = &buffer->pos[i]; + + /* TODO vertical */ +- pos->x_advance = x_mult * info->mask; ++ pos->x_advance = x_mult * (int32_t) info->mask; + pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32); + pos->y_offset = y_mult * info->var2.i32; + } + + if (backward) + hb_buffer_reverse (buffer); + + /* Wow, done! */ +diff --git a/gfx/harfbuzz/src/hb-uniscribe.h b/gfx/harfbuzz/src/hb-uniscribe.h +--- a/gfx/harfbuzz/src/hb-uniscribe.h ++++ b/gfx/harfbuzz/src/hb-uniscribe.h +@@ -29,18 +29,18 @@ + + #include "hb.h" + + #include <windows.h> + + HB_BEGIN_DECLS + + +-LOGFONTW * ++HB_EXTERN LOGFONTW * + hb_uniscribe_font_get_logfontw (hb_font_t *font); + +-HFONT ++HB_EXTERN HFONT + hb_uniscribe_font_get_hfont (hb_font_t *font); + + + HB_END_DECLS + + #endif /* HB_UNISCRIBE_H */ +diff --git a/gfx/harfbuzz/src/hb-version.h b/gfx/harfbuzz/src/hb-version.h +--- a/gfx/harfbuzz/src/hb-version.h ++++ b/gfx/harfbuzz/src/hb-version.h +@@ -33,34 +33,34 @@ + + #include "hb-common.h" + + HB_BEGIN_DECLS + + + #define HB_VERSION_MAJOR 1 + #define HB_VERSION_MINOR 1 +-#define HB_VERSION_MICRO 0 ++#define HB_VERSION_MICRO 3 + +-#define HB_VERSION_STRING "1.1.0" ++#define HB_VERSION_STRING "1.1.3" + + #define HB_VERSION_ATLEAST(major,minor,micro) \ + ((major)*10000+(minor)*100+(micro) <= \ + HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO) + + +-void ++HB_EXTERN void + hb_version (unsigned int *major, + unsigned int *minor, + unsigned int *micro); + +-const char * ++HB_EXTERN const char * + hb_version_string (void); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_version_atleast (unsigned int major, + unsigned int minor, + unsigned int micro); + + + HB_END_DECLS + + #endif /* HB_VERSION_H */ +diff --git a/gfx/harfbuzz/src/hb-version.h.in b/gfx/harfbuzz/src/hb-version.h.in +--- a/gfx/harfbuzz/src/hb-version.h.in ++++ b/gfx/harfbuzz/src/hb-version.h.in +@@ -42,25 +42,25 @@ HB_BEGIN_DECLS + + #define HB_VERSION_STRING "@HB_VERSION@" + + #define HB_VERSION_ATLEAST(major,minor,micro) \ + ((major)*10000+(minor)*100+(micro) <= \ + HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO) + + +-void ++HB_EXTERN void + hb_version (unsigned int *major, + unsigned int *minor, + unsigned int *micro); + +-const char * ++HB_EXTERN const char * + hb_version_string (void); + +-hb_bool_t ++HB_EXTERN hb_bool_t + hb_version_atleast (unsigned int major, + unsigned int minor, + unsigned int micro); + + + HB_END_DECLS + + #endif /* HB_VERSION_H */ +diff --git a/gfx/harfbuzz/src/hb.h b/gfx/harfbuzz/src/hb.h +--- a/gfx/harfbuzz/src/hb.h ++++ b/gfx/harfbuzz/src/hb.h +@@ -23,16 +23,20 @@ + * + * Red Hat Author(s): Behdad Esfahbod + */ + + #ifndef HB_H + #define HB_H + #define HB_H_IN + ++#ifndef HB_EXTERN ++#define HB_EXTERN extern ++#endif ++ + #include "hb-blob.h" + #include "hb-buffer.h" + #include "hb-common.h" + #include "hb-deprecated.h" + #include "hb-face.h" + #include "hb-font.h" + #include "hb-set.h" + #include "hb-shape.h" +diff --git a/gfx/harfbuzz/src/sample.py b/gfx/harfbuzz/src/sample.py +--- a/gfx/harfbuzz/src/sample.py ++++ b/gfx/harfbuzz/src/sample.py +@@ -28,16 +28,22 @@ del blob + font = hb.font_create (face) + upem = hb.face_get_upem (face) + del face + hb.font_set_scale (font, upem, upem) + #hb.ft_font_set_funcs (font) + hb.ot_font_set_funcs (font) + + buf = hb.buffer_create () ++class Debugger(object): ++ def message (self, buf, font, msg, data, _x_what_is_this): ++ print(msg) ++ return True ++debugger = Debugger() ++hb.buffer_set_message_func (buf, debugger.message, 1, 0) + hb.buffer_add_utf8 (buf, text.encode('utf-8'), 0, -1) + hb.buffer_guess_segment_properties (buf) + + hb.shape (font, buf, []) + del font + + infos = hb.buffer_get_glyph_infos (buf) + positions = hb.buffer_get_glyph_positions (buf) +diff --git a/gfx/harfbuzz/src/test.cc b/gfx/harfbuzz/src/test.cc +--- a/gfx/harfbuzz/src/test.cc ++++ b/gfx/harfbuzz/src/test.cc +@@ -115,17 +115,17 @@ main (int argc, char **argv) + { + hb_glyph_info_t *info = &infos[i]; + hb_glyph_position_t *pos = &positions[i]; + + printf ("cluster %d glyph 0x%x at (%d,%d)+(%d,%d)\n", + info->cluster, + info->codepoint, + pos->x_offset, +- pos->x_offset, ++ pos->y_offset, + pos->x_advance, + pos->y_advance); + + } + + hb_buffer_destroy (buffer); + hb_font_destroy (font); + hb_face_destroy (face); |