From 6dceede190a8211059694191d4f3c089ded94254 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Sat, 20 Dec 2014 19:37:24 +0000 Subject: [PATCH] Bug 1113070 - Update harfbuzz to 0.9.37+ (upstream 7d5e7613ced3dd39d05df83ca7e8952cbecd68f6). r=jdaggett --- gfx/harfbuzz/src/Makefile.am | 43 +- gfx/harfbuzz/src/check-libstdc++.sh | 14 +- gfx/harfbuzz/src/check-static-inits.sh | 4 +- gfx/harfbuzz/src/check-symbols.sh | 10 +- gfx/harfbuzz/src/hb-blob.cc | 5 +- .../src/hb-buffer-deserialize-json.rl | 4 +- gfx/harfbuzz/src/hb-buffer-private.hh | 7 +- gfx/harfbuzz/src/hb-buffer.cc | 4 +- gfx/harfbuzz/src/hb-common.cc | 4 +- gfx/harfbuzz/src/hb-common.h | 5 +- gfx/harfbuzz/src/hb-coretext.cc | 654 ++++++++++++------ gfx/harfbuzz/src/hb-face-private.hh | 2 +- gfx/harfbuzz/src/hb-ft.cc | 6 +- gfx/harfbuzz/src/hb-graphite2.cc | 4 +- gfx/harfbuzz/src/hb-mutex-private.hh | 2 +- gfx/harfbuzz/src/hb-object-private.hh | 107 +-- gfx/harfbuzz/src/hb-open-file-private.hh | 2 + gfx/harfbuzz/src/hb-open-type-private.hh | 120 +++- gfx/harfbuzz/src/hb-ot-font.cc | 205 ++++-- gfx/harfbuzz/src/hb-ot-hhea-table.hh | 65 +- gfx/harfbuzz/src/hb-ot-hmtx-table.hh | 37 +- gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh | 40 +- gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh | 16 +- .../src/hb-ot-layout-gsubgpos-private.hh | 91 ++- .../hb-ot-shape-complex-arabic-fallback.hh | 2 +- .../src/hb-ot-shape-complex-arabic-win1256.hh | 5 +- .../src/hb-ot-shape-complex-indic-machine.hh | 12 +- .../src/hb-ot-shape-complex-indic-machine.rl | 2 +- gfx/harfbuzz/src/hb-private.hh | 111 +-- gfx/harfbuzz/src/hb-set-private.hh | 2 +- gfx/harfbuzz/src/hb-shape-plan.cc | 53 +- gfx/harfbuzz/src/hb-shape.cc | 2 +- gfx/harfbuzz/src/hb-shaper.cc | 2 +- gfx/harfbuzz/src/hb-uniscribe.cc | 14 +- gfx/harfbuzz/src/hb-version.h | 4 +- 35 files changed, 1020 insertions(+), 640 deletions(-) diff --git a/gfx/harfbuzz/src/Makefile.am b/gfx/harfbuzz/src/Makefile.am index ba07ac5d68053..71614a4fac9d3 100644 --- a/gfx/harfbuzz/src/Makefile.am +++ b/gfx/harfbuzz/src/Makefile.am @@ -234,8 +234,8 @@ hb-gobject-enums.%: hb-gobject-enums.%.tmpl $(HBHEADERS) $(AM_V_GEN) $(GLIB_MKENUMS) \ --identifier-prefix hb_ --symbol-prefix hb_gobject \ --template $^ | \ - sed 's/_t_get_type/_get_type/g; s/_T (/ (/g' > "$@.tmp" && \ - mv "$@.tmp" "$@" || ( $(RM) "@.tmp" && false ) + sed 's/_t_get_type/_get_type/g; s/_T (/ (/g' > "$@" \ + || ($(RM) "$@"; false) endif EXTRA_DIST += \ harfbuzz-gobject.pc.in \ @@ -251,8 +251,8 @@ EXTRA_DIST += \ -e 's@%libdir%@$(libdir)@g' \ -e 's@%includedir%@$(includedir)@g' \ -e 's@%VERSION%@$(VERSION)@g' \ - "$<" \ - > "$@.tmp" && mv "$@.tmp" "$@" || ( $(RM) "$@.tmp"; false ) + "$<" > "$@" \ + || ($(RM) "$@"; false) CLEANFILES += $(pkgconfig_DATA) @@ -265,8 +265,9 @@ harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS) sed -e 's/ (.*//' | \ LANG=C sort; \ echo LIBRARY libharfbuzz-$(HB_VERSION_MAJOR).dll; \ - ) >"$@.tmp" - @ ! grep -q hb_ERROR "$@.tmp" && mv "$@.tmp" "$@" || ($(RM) "$@"; false) + ) >"$@" + @ ! grep -q hb_ERROR "$@" \ + || ($(RM) "$@"; false) GENERATORS = \ @@ -278,26 +279,25 @@ EXTRA_DIST += $(GENERATORS) unicode-tables: arabic-table indic-table indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt - $(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-indic-table.cc.tmp && \ - mv hb-ot-shape-complex-indic-table.cc.tmp $(srcdir)/hb-ot-shape-complex-indic-table.cc || \ - ($(RM) hb-ot-shape-complex-indic-table.cc.tmp; false) + $(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-indic-table.cc \ + || ($(RM) hb-ot-shape-complex-indic-table.cc; false) arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt - $(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-arabic-table.hh.tmp && \ - mv hb-ot-shape-complex-arabic-table.hh.tmp $(srcdir)/hb-ot-shape-complex-arabic-table.hh || \ - ($(RM) hb-ot-shape-complex-arabic-table.hh.tmp; false) + $(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-arabic-table.hh \ + || ($(RM) hb-ot-shape-complex-arabic-table.hh; false) built-sources: $(BUILT_SOURCES) .PHONY: unicode-tables arabic-table indic-table built-sources -BUILT_SOURCES += \ - hb-buffer-deserialize-json.hh \ - hb-buffer-deserialize-text.hh \ - hb-ot-shape-complex-indic-machine.hh \ - hb-ot-shape-complex-myanmar-machine.hh \ - hb-ot-shape-complex-sea-machine.hh \ +RAGEL_GENERATED = \ + $(srcdir)/hb-buffer-deserialize-json.hh \ + $(srcdir)/hb-buffer-deserialize-text.hh \ + $(srcdir)/hb-ot-shape-complex-indic-machine.hh \ + $(srcdir)/hb-ot-shape-complex-myanmar-machine.hh \ + $(srcdir)/hb-ot-shape-complex-sea-machine.hh \ $(NULL) +BUILT_SOURCES += $(RAGEL_GENERATED) EXTRA_DIST += \ hb-buffer-deserialize-json.rl \ hb-buffer-deserialize-text.rl \ @@ -305,9 +305,10 @@ EXTRA_DIST += \ hb-ot-shape-complex-myanmar-machine.rl \ hb-ot-shape-complex-sea-machine.rl \ $(NULL) -.rl.hh: - $(AM_V_GEN)$(RAGEL) -e -F1 -o "$@.tmp" "$<" && \ - mv "$@.tmp" "$@" || ( $(RM) "$@.tmp" && false ) +MAINTAINERCLEANFILES += $(RAGEL_GENERATED) +$(srcdir)/%.hh: $(srcdir)/%.rl + $(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \ + || ($(RM) "$@"; false) noinst_PROGRAMS = \ main \ diff --git a/gfx/harfbuzz/src/check-libstdc++.sh b/gfx/harfbuzz/src/check-libstdc++.sh index e7e0e295e1ab9..27deb42dc974e 100755 --- a/gfx/harfbuzz/src/check-libstdc++.sh +++ b/gfx/harfbuzz/src/check-libstdc++.sh @@ -17,14 +17,14 @@ fi tested=false for suffix in so dylib; do so=.libs/libharfbuzz.$suffix - if test -f "$so"; then - echo "Checking that we are not linking to libstdc++" - if ldd $so | grep 'libstdc[+][+]'; then - echo "Ouch, linked to libstdc++" - stat=1 - fi - tested=true + if ! test -f "$so"; then continue; fi + + echo "Checking that we are not linking to libstdc++" + if ldd $so | grep 'libstdc[+][+]'; then + echo "Ouch, linked to libstdc++" + stat=1 fi + tested=true done if ! $tested; then echo "check-libstdc++.sh: libharfbuzz shared library not found; skipping test" diff --git a/gfx/harfbuzz/src/check-static-inits.sh b/gfx/harfbuzz/src/check-static-inits.sh index 83d02c8a9bf53..1446fa73405e8 100755 --- a/gfx/harfbuzz/src/check-static-inits.sh +++ b/gfx/harfbuzz/src/check-static-inits.sh @@ -22,8 +22,8 @@ fi echo "Checking that no object file has static initializers" for obj in $OBJS; do - if objdump -t "$obj" | grep '[.]ctors'; then - echo "Ouch, $obj has static initializers" + if objdump -t "$obj" | grep '[.][cd]tors' | grep -v '\<00*\>'; then + echo "Ouch, $obj has static initializers/finalizers" stat=1 fi done diff --git a/gfx/harfbuzz/src/check-symbols.sh b/gfx/harfbuzz/src/check-symbols.sh index e000b01b86310..b2bf43fcea56e 100755 --- a/gfx/harfbuzz/src/check-symbols.sh +++ b/gfx/harfbuzz/src/check-symbols.sh @@ -16,11 +16,17 @@ fi echo "Checking that we are not exposing internal symbols" tested=false -for so in `ls .libs/lib*.so .libs/lib*.dylib 2>/dev/null` ; do +for suffix in so dylib; do + so=.libs/libharfbuzz.$suffix + if ! test -f "$so"; then continue; fi - EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>' | cut -d' ' -f3`" + EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`" + prefix=`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'` + # On mac, C symbols are prefixed with _ + if test $suffix = dylib; then prefix="_$prefix"; fi + echo "Processing $so" if echo "$EXPORTED_SYMBOLS" | grep -v "^${prefix}_"; then echo "Ouch, internal symbols exposed" diff --git a/gfx/harfbuzz/src/hb-blob.cc b/gfx/harfbuzz/src/hb-blob.cc index b82b4b2a3a3f8..44379301d36eb 100644 --- a/gfx/harfbuzz/src/hb-blob.cc +++ b/gfx/harfbuzz/src/hb-blob.cc @@ -102,7 +102,10 @@ hb_blob_create (const char *data, { hb_blob_t *blob; - if (!length || !(blob = hb_object_create ())) { + if (!length || + length >= 1u << 31 || + data + length < data /* overflows */ || + !(blob = hb_object_create ())) { if (destroy) destroy (user_data); return hb_blob_get_empty (); diff --git a/gfx/harfbuzz/src/hb-buffer-deserialize-json.rl b/gfx/harfbuzz/src/hb-buffer-deserialize-json.rl index 7351b2ab47c4f..91b350f5ac0d5 100644 --- a/gfx/harfbuzz/src/hb-buffer-deserialize-json.rl +++ b/gfx/harfbuzz/src/hb-buffer-deserialize-json.rl @@ -117,8 +117,8 @@ _hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer, const char *tok = NULL; int cs; - hb_glyph_info_t info; - hb_glyph_position_t pos; + hb_glyph_info_t info = {0}; + hb_glyph_position_t pos = {0}; %%{ write init; write exec; diff --git a/gfx/harfbuzz/src/hb-buffer-private.hh b/gfx/harfbuzz/src/hb-buffer-private.hh index 5eccd3c31fc3f..069f9255811b5 100644 --- a/gfx/harfbuzz/src/hb-buffer-private.hh +++ b/gfx/harfbuzz/src/hb-buffer-private.hh @@ -48,15 +48,13 @@ struct hb_buffer_t { ASSERT_POD (); /* Information about how the text in the buffer should be treated */ - hb_unicode_funcs_t *unicode; /* Unicode functions */ - hb_segment_properties_t props; /* Script, language, direction */ hb_buffer_flags_t flags; /* BOT / EOT / etc. */ hb_codepoint_t replacement; /* U+FFFD or something else. */ /* Buffer contents */ - hb_buffer_content_type_t content_type; + hb_segment_properties_t props; /* Script, language, direction */ bool in_error; /* Allocation failed */ bool have_output; /* Whether we have an output buffer going on */ @@ -183,6 +181,9 @@ struct hb_buffer_t { inline bool ensure (unsigned int size) { return likely (!size || size < allocated) ? true : enlarge (size); } + inline bool ensure_inplace (unsigned int size) + { return likely (!size || size < allocated); } + HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out); HB_INTERNAL bool shift_forward (unsigned int count); diff --git a/gfx/harfbuzz/src/hb-buffer.cc b/gfx/harfbuzz/src/hb-buffer.cc index 2377ba40dafc1..74ae273eeca79 100644 --- a/gfx/harfbuzz/src/hb-buffer.cc +++ b/gfx/harfbuzz/src/hb-buffer.cc @@ -178,6 +178,7 @@ hb_buffer_t::reset (void) hb_unicode_funcs_destroy (unicode); unicode = hb_unicode_funcs_get_default (); + flags = HB_BUFFER_FLAG_DEFAULT; replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; clear (); @@ -191,7 +192,6 @@ hb_buffer_t::clear (void) hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; props = default_props; - flags = HB_BUFFER_FLAG_DEFAULT; content_type = HB_BUFFER_CONTENT_TYPE_INVALID; in_error = false; @@ -702,11 +702,11 @@ hb_buffer_get_empty (void) HB_OBJECT_HEADER_STATIC, const_cast (&_hb_unicode_funcs_nil), - HB_SEGMENT_PROPERTIES_DEFAULT, HB_BUFFER_FLAG_DEFAULT, HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, HB_BUFFER_CONTENT_TYPE_INVALID, + HB_SEGMENT_PROPERTIES_DEFAULT, true, /* in_error */ true, /* have_output */ true /* have_positions */ diff --git a/gfx/harfbuzz/src/hb-common.cc b/gfx/harfbuzz/src/hb-common.cc index a089e52cd2cb2..a6a5144794100 100644 --- a/gfx/harfbuzz/src/hb-common.cc +++ b/gfx/harfbuzz/src/hb-common.cc @@ -234,7 +234,7 @@ struct hb_language_item_t { static hb_language_item_t *langs; -#ifdef HAVE_ATEXIT +#ifdef HB_USE_ATEXIT static inline void free_langs (void) { @@ -269,7 +269,7 @@ lang_find_or_insert (const char *key) goto retry; } -#ifdef HAVE_ATEXIT +#ifdef HB_USE_ATEXIT if (!first_lang) atexit (free_langs); /* First person registers atexit() callback. */ #endif diff --git a/gfx/harfbuzz/src/hb-common.h b/gfx/harfbuzz/src/hb-common.h index f5141b9eed156..b6ce3f724ded9 100644 --- a/gfx/harfbuzz/src/hb-common.h +++ b/gfx/harfbuzz/src/hb-common.h @@ -123,12 +123,13 @@ hb_direction_from_string (const char *str, int len); 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_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4) -#define HB_DIRECTION_REVERSE(dir) ((hb_direction_t) (((unsigned int) (dir)) ^ 1)) /* Direction must be valid */ +#define HB_DIRECTION_REVERSE(dir) ((hb_direction_t) (((unsigned int) (dir)) ^ 1)) /* hb_language_t */ diff --git a/gfx/harfbuzz/src/hb-coretext.cc b/gfx/harfbuzz/src/hb-coretext.cc index d92c6baaf61ed..11629cc18ce9e 100644 --- a/gfx/harfbuzz/src/hb-coretext.cc +++ b/gfx/harfbuzz/src/hb-coretext.cc @@ -27,6 +27,7 @@ */ #define HB_SHAPER coretext +#define hb_coretext_shaper_face_data_t CGFont #include "hb-shaper-impl-private.hh" #include "hb-coretext.h" @@ -77,10 +78,6 @@ HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font) * shaper face data */ -struct hb_coretext_shaper_face_data_t { - CGFontRef cg_font; -}; - static void release_data (void *info, const void *data, size_t size) { @@ -93,13 +90,11 @@ release_data (void *info, const void *data, size_t size) hb_coretext_shaper_face_data_t * _hb_coretext_shaper_face_data_create (hb_face_t *face) { - hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t)); - if (unlikely (!data)) - return NULL; + hb_coretext_shaper_face_data_t *data = NULL; if (face->destroy == (hb_destroy_func_t) CGFontRelease) { - data->cg_font = CGFontRetain ((CGFontRef) face->user_data); + data = CGFontRetain ((CGFontRef) face->user_data); } else { @@ -110,14 +105,15 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face) DEBUG_MSG (CORETEXT, face, "Face has empty blob"); CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data); - data->cg_font = CGFontCreateWithDataProvider (provider); - CGDataProviderRelease (provider); + if (likely (provider)) + { + data = CGFontCreateWithDataProvider (provider); + CGDataProviderRelease (provider); + } } - if (unlikely (!data->cg_font)) { + if (unlikely (!data)) { DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed"); - free (data); - return NULL; } return data; @@ -126,8 +122,7 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face) void _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) { - CFRelease (data->cg_font); - free (data); + CFRelease (data); } CGFontRef @@ -135,7 +130,7 @@ hb_coretext_face_get_cg_font (hb_face_t *face) { if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - return face_data->cg_font; + return face_data; } @@ -159,7 +154,7 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font) hb_face_t *face = font->face; hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - data->ct_font = CTFontCreateWithGraphicsFont (face_data->cg_font, font->y_scale, NULL, NULL); + data->ct_font = CTFontCreateWithGraphicsFont (face_data, font->y_scale, NULL, NULL); if (unlikely (!data->ct_font)) { DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); free (data); @@ -332,7 +327,7 @@ struct range_record_t { #define kUpperCaseType 38 /* Table data courtesy of Apple. */ -struct feature_mapping_t { +static const struct feature_mapping_t { FourCharCode otFeatureTag; uint16_t aatFeatureType; uint16_t selectorToEnable; @@ -436,12 +431,29 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); hb_coretext_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); + /* Attach marks to their bases, to match the 'ot' shaper. + * Adapted from hb-ot-shape:hb_form_clusters(). + * Note that this only makes us be closer to the 'ot' shaper, + * but by no means the same. For example, if there's + * B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will + * continue pointing to B2 even though B2 was merged into B1's + * cluster... */ + { + hb_unicode_funcs_t *unicode = buffer->unicode; + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 1; i < count; i++) + if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (unicode->general_category (info[i].codepoint))) + buffer->merge_clusters (i - 1, i + 1); + } + + hb_auto_array_t feature_records; + hb_auto_array_t range_records; + /* * Set up features. * (copied + modified from code from hb-uniscribe.cc) */ - hb_auto_array_t feature_records; - hb_auto_array_t range_records; if (num_features) { /* Sort features by start/end events. */ @@ -549,7 +561,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, CFRelease (attributes); range->font = CTFontCreateCopyWithAttributes (font_data->ct_font, 0.0, NULL, font_desc); - CFRelease (font_desc); } else @@ -584,32 +595,26 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, num_features = 0; } -#define FAIL(...) \ - HB_STMT_START { \ - DEBUG_MSG (CORETEXT, NULL, __VA_ARGS__); \ - return false; \ - } HB_STMT_END; - unsigned int scratch_size; hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size); -#define ALLOCATE_ARRAY(Type, name, len) \ +#define ALLOCATE_ARRAY(Type, name, len, on_no_room) \ Type *name = (Type *) scratch; \ { \ unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \ - assert (_consumed <= scratch_size); \ + if (unlikely (_consumed > scratch_size)) \ + { \ + on_no_room; \ + assert (0); \ + } \ scratch += _consumed; \ scratch_size -= _consumed; \ } -#define utf16_index() var1.u32 - - ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2); - + ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2, /*nothing*/); 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)) @@ -620,232 +625,439 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, } } -#undef utf16_index + ALLOCATE_ARRAY (unsigned int, log_clusters, chars_len, /*nothing*/); + 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. */ + } - CFStringRef string_ref = CFStringCreateWithCharactersNoCopy (NULL, - pchars, chars_len, - kCFAllocatorNull); +#define FAIL(...) \ + HB_STMT_START { \ + DEBUG_MSG (CORETEXT, NULL, __VA_ARGS__); \ + ret = false; \ + goto fail; \ + } HB_STMT_END; - CFMutableAttributedStringRef attr_string = CFAttributedStringCreateMutable (NULL, chars_len); - CFAttributedStringReplaceString (attr_string, CFRangeMake (0, 0), string_ref); - CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), - kCTFontAttributeName, font_data->ct_font); + bool ret = true; + CFStringRef string_ref = NULL; + CTLineRef line = NULL; - if (num_features) + if (0) { - ALLOCATE_ARRAY (unsigned int, log_clusters, chars_len); - - /* 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. */ - } +resize_and_retry: + DEBUG_MSG (CORETEXT, buffer, "Buffer resize"); + /* string_ref uses the scratch-buffer for backing store, and line references + * string_ref (via attr_string). We must release those before resizing buffer. */ + assert (string_ref); + assert (line); + CFRelease (string_ref); + CFRelease (line); + string_ref = NULL; + line = NULL; + + /* Get previous start-of-scratch-area, that we use later for readjusting + * our existing scratch arrays. */ + unsigned int old_scratch_used; + hb_buffer_t::scratch_buffer_t *old_scratch; + old_scratch = buffer->get_scratch_buffer (&old_scratch_used); + old_scratch_used = scratch - old_scratch; + + if (unlikely (!buffer->ensure (buffer->allocated * 2))) + FAIL ("Buffer resize failed"); + + /* 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 (((char *) scratch + ((char *) pchars - (char *) old_scratch))); + log_clusters = reinterpret_cast (((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"); - unsigned int start = 0; - range_record_t *last_range = &range_records[0]; - for (unsigned int k = 0; k < chars_len; k++) + /* Create an attributed string, populate it, and create a line from it, then release attributed string. */ { - range_record_t *range = last_range; - while (log_clusters[k] < range->index_first) - range--; - while (log_clusters[k] > range->index_last) - range++; - if (range != last_range) + CFMutableAttributedStringRef attr_string = CFAttributedStringCreateMutable (kCFAllocatorDefault, + chars_len); + if (unlikely (!attr_string)) + FAIL ("CFAttributedStringCreateMutable failed"); + CFAttributedStringReplaceString (attr_string, CFRangeMake (0, 0), string_ref); + if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction)) { - if (last_range->font) - CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, k - start), - kCTFontAttributeName, last_range->font); - - start = k; + CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), + kCTVerticalFormsAttributeName, kCFBooleanTrue); } - last_range = range; - } - if (start != chars_len && last_range->font) - CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, chars_len - start - 1), - kCTFontAttributeName, last_range->font); - - for (unsigned int i = 0; i < range_records.len; i++) - if (range_records[i].font) - CFRelease (range_records[i].font); - } + if (buffer->props.language) + { +/* What's the iOS equivalent of this check? + * The symbols was introduced in iOS 7.0. + * At any rate, our fallback is safe and works fine. */ +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090 +# define kCTLanguageAttributeName CFSTR ("NSLanguage") +#endif + CFStringRef lang = CFStringCreateWithCStringNoCopy (kCFAllocatorDefault, + hb_language_to_string (buffer->props.language), + kCFStringEncodingUTF8, + kCFAllocatorNull); + if (unlikely (!lang)) + FAIL ("CFStringCreateWithCStringNoCopy failed"); + CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), + kCTLanguageAttributeName, lang); + CFRelease (lang); + } + CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), + kCTFontAttributeName, font_data->ct_font); - CTLineRef line = CTLineCreateWithAttributedString (attr_string); - CFRelease (attr_string); + if (num_features) + { + unsigned int start = 0; + range_record_t *last_range = &range_records[0]; + for (unsigned int k = 0; k < chars_len; k++) + { + range_record_t *range = last_range; + while (log_clusters[k] < range->index_first) + range--; + while (log_clusters[k] > range->index_last) + range++; + if (range != last_range) + { + if (last_range->font) + CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, k - start), + kCTFontAttributeName, last_range->font); - CFArrayRef glyph_runs = CTLineGetGlyphRuns (line); - unsigned int num_runs = CFArrayGetCount (glyph_runs); + start = k; + } - buffer->len = 0; + last_range = range; + } + if (start != chars_len && last_range->font) + CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, chars_len - start), + kCTFontAttributeName, last_range->font); + } - const CFRange range_all = CFRangeMake (0, 0); + int level = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1; + CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &level); + CFDictionaryRef options = CFDictionaryCreate (kCFAllocatorDefault, + (const void **) &kCTTypesetterOptionForcedEmbeddingLevel, + (const void **) &level_number, + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + if (unlikely (!options)) + FAIL ("CFDictionaryCreate failed"); + + CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOptions (attr_string, options); + CFRelease (options); + CFRelease (attr_string); + if (unlikely (!typesetter)) + FAIL ("CTTypesetterCreateWithAttributedStringAndOptions failed"); + + line = CTTypesetterCreateLine (typesetter, CFRangeMake(0, 0)); + CFRelease (typesetter); + if (unlikely (!line)) + FAIL ("CTTypesetterCreateLine failed"); + } - for (unsigned int i = 0; i < num_runs; i++) - { - CTRunRef run = (CTRunRef) CFArrayGetValueAtIndex (glyph_runs, i); - - /* CoreText does automatic font fallback (AKA "cascading") for characters - * not supported by the requested font, and provides no way to turn it off, - * so we detect if the returned run uses a font other than the requested - * one and fill in the buffer with .notdef glyphs instead of random glyph - * indices from a different font. - */ - CFDictionaryRef attributes = CTRunGetAttributes (run); - CTFontRef run_ct_font = static_cast(CFDictionaryGetValue (attributes, kCTFontAttributeName)); - CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0); - if (!CFEqual (run_cg_font, face_data->cg_font)) - { - CFRelease (run_cg_font); + CFArrayRef glyph_runs = CTLineGetGlyphRuns (line); + unsigned int num_runs = CFArrayGetCount (glyph_runs); + DEBUG_MSG (CORETEXT, NULL, "Num runs: %d", num_runs); - CFRange range = CTRunGetStringRange (run); - buffer->ensure (buffer->len + range.length); - if (buffer->in_error) - FAIL ("Buffer resize failed"); - hb_glyph_info_t *info = buffer->info + buffer->len; + buffer->len = 0; + uint32_t status_and = ~0, status_or = 0; - CGGlyph notdef = 0; - double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1); + const CFRange range_all = CFRangeMake (0, 0); - for (CFIndex j = range.location; j < range.location + range.length; j++) + for (unsigned int i = 0; i < num_runs; i++) + { + CTRunRef run = static_cast(CFArrayGetValueAtIndex (glyph_runs, i)); + CTRunStatus run_status = CTRunGetStatus (run); + status_or |= run_status; + status_and &= run_status; + DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status); + + /* CoreText does automatic font fallback (AKA "cascading") for characters + * not supported by the requested font, and provides no way to turn it off, + * so we must detect if the returned run uses a font other than the requested + * one and fill in the buffer with .notdef glyphs instead of random glyph + * indices from a different font. + */ + CFDictionaryRef attributes = CTRunGetAttributes (run); + CTFontRef run_ct_font = static_cast(CFDictionaryGetValue (attributes, kCTFontAttributeName)); + if (!CFEqual (run_ct_font, font_data->ct_font)) + { + /* The run doesn't use our main font instance. We have to figure out + * whether font fallback happened, or this is just CoreText giving us + * another CTFont using the same underlying CGFont. CoreText seems + * to do that in a variety of situations, one of which being vertical + * text, but also perhaps for caching reasons. + * + * First, see if it uses any of our subfonts created to set font features... + * + * Next, compare the CGFont to the one we used to create our fonts. + * Even this doesn't work all the time. + * + * Finally, we compare PS names, which I don't think are unique... + * + * 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. + * + * 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; + break; + } + if (!matched) { - UniChar ch = CFStringGetCharacterAtIndex (string_ref, j); - if (hb_in_range (ch, 0xDC00u, 0xDFFFu) && range.location < j) - { - ch = CFStringGetCharacterAtIndex (string_ref, j - 1); - if (hb_in_range (ch, 0xD800u, 0xDBFFu)) - /* This is the second of a surrogate pair. Don't need .notdef - * for this one. */ - continue; - } - - info->codepoint = notdef; - /* TODO We have to fixup clusters later. See vis_clusters in - * hb-uniscribe.cc for example. */ - info->cluster = j; - - info->mask = advance; - info->var1.u32 = 0; - info->var2.u32 = 0; - - info++; - buffer->len++; - } - continue; - } - CFRelease (run_cg_font); + CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0); + if (run_cg_font) + { + matched = CFEqual (run_cg_font, face_data); + CFRelease (run_cg_font); + } + } + if (!matched) + { + CFStringRef font_ps_name = CTFontCopyName (font_data->ct_font, kCTFontPostScriptNameKey); + CFStringRef run_ps_name = CTFontCopyName (run_ct_font, kCTFontPostScriptNameKey); + CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name, 0); + CFRelease (run_ps_name); + CFRelease (font_ps_name); + if (result == kCFCompareEqualTo) + matched = true; + } + if (!matched) + { + CFRange range = CTRunGetStringRange (run); + DEBUG_MSG (CORETEXT, run, "Run used fallback font: %ld..%ld", + range.location, range.location + range.length); + if (!buffer->ensure_inplace (buffer->len + range.length)) + goto resize_and_retry; + hb_glyph_info_t *info = buffer->info + buffer->len; + + CGGlyph notdef = 0; + double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1); + + unsigned int old_len = buffer->len; + for (CFIndex j = range.location; j < range.location + range.length; j++) + { + UniChar ch = CFStringGetCharacterAtIndex (string_ref, j); + if (hb_in_range (ch, 0xDC00u, 0xDFFFu) && range.location < j) + { + ch = CFStringGetCharacterAtIndex (string_ref, j - 1); + if (hb_in_range (ch, 0xD800u, 0xDBFFu)) + /* This is the second of a surrogate pair. Don't need .notdef + * for this one. */ + continue; + } + + info->codepoint = notdef; + info->cluster = log_clusters[j]; + + info->mask = advance; + info->var1.u32 = 0; + info->var2.u32 = 0; + + info++; + buffer->len++; + } + if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + buffer->reverse_range (old_len, buffer->len); + continue; + } + } - unsigned int num_glyphs = CTRunGetGlyphCount (run); - if (num_glyphs == 0) - continue; + unsigned int num_glyphs = CTRunGetGlyphCount (run); + if (num_glyphs == 0) + continue; - buffer->ensure (buffer->len + num_glyphs); + if (!buffer->ensure_inplace (buffer->len + num_glyphs)) + goto resize_and_retry; - scratch = buffer->get_scratch_buffer (&scratch_size); + hb_glyph_info_t *run_info = buffer->info + buffer->len; - /* Testing indicates that CTRunGetGlyphsPtr, etc (almost?) always - * succeed, and so copying data to our own buffer will be rare. */ + /* Testing used to indicate that CTRunGetGlyphsPtr, etc (almost?) always + * succeed, and so copying data to our own buffer will be rare. Reports + * have it that this changed in OS X 10.10 Yosemite, and NULL is returned + * frequently. At any rate, we can test that codepath by setting USE_PTR + * to false. */ - const CGGlyph* glyphs = CTRunGetGlyphsPtr (run); - if (!glyphs) { - ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs); - CTRunGetGlyphs (run, range_all, glyph_buf); - glyphs = glyph_buf; - } +#define USE_PTR true - const CGPoint* positions = CTRunGetPositionsPtr (run); - if (!positions) { - ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs); - CTRunGetPositions (run, range_all, position_buf); - positions = position_buf; - } +#define SCRATCH_SAVE() \ + unsigned int scratch_size_saved = scratch_size; \ + hb_buffer_t::scratch_buffer_t *scratch_saved = scratch - const CFIndex* string_indices = CTRunGetStringIndicesPtr (run); - if (!string_indices) { - ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs); - CTRunGetStringIndices (run, range_all, index_buf); - string_indices = index_buf; - } +#define SCRATCH_RESTORE() \ + scratch_size = scratch_size_saved; \ + scratch = scratch_saved; + { + SCRATCH_SAVE(); + const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL; + if (!glyphs) { + ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry); + CTRunGetGlyphs (run, range_all, glyph_buf); + glyphs = glyph_buf; + } + const CFIndex* string_indices = USE_PTR ? CTRunGetStringIndicesPtr (run) : NULL; + if (!string_indices) { + ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs, goto resize_and_retry); + CTRunGetStringIndices (run, range_all, index_buf); + string_indices = index_buf; + } + hb_glyph_info_t *info = run_info; + for (unsigned int j = 0; j < num_glyphs; j++) + { + info->codepoint = glyphs[j]; + info->cluster = log_clusters[string_indices[j]]; + info++; + } + SCRATCH_RESTORE(); + } + { + SCRATCH_SAVE(); + const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL; + if (!positions) { + ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs, goto resize_and_retry); + CTRunGetPositions (run, range_all, position_buf); + positions = position_buf; + } + double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL); + DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance); + hb_glyph_info_t *info = run_info; + if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) + { + for (unsigned int j = 0; j < num_glyphs; j++) + { + double advance = (j + 1 < num_glyphs ? positions[j + 1].x : positions[0].x + run_advance) - positions[j].x; + info->mask = advance; + info->var1.u32 = positions[0].x; /* Yes, zero. */ + info->var2.u32 = positions[j].y; + info++; + } + } + else + { + run_advance = -run_advance; + for (unsigned int j = 0; j < num_glyphs; j++) + { + double advance = (j + 1 < num_glyphs ? positions[j + 1].y : positions[0].y + run_advance) - positions[j].y; + info->mask = advance; + info->var1.u32 = positions[j].x; + info->var2.u32 = positions[0].y; /* Yes, zero. */ + info++; + } + } + SCRATCH_RESTORE(); + } +#undef SCRATCH_RESTORE +#undef SCRATCH_SAVE +#undef USE_PTR #undef ALLOCATE_ARRAY - double run_width = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL); - - for (unsigned int j = 0; j < num_glyphs; j++) { - double advance = (j + 1 < num_glyphs ? positions[j + 1].x : positions[0].x + run_width) - positions[j].x; - - hb_glyph_info_t *info = &buffer->info[buffer->len]; - - info->codepoint = glyphs[j]; - info->cluster = string_indices[j]; - - /* Currently, we do all x-positioning by setting the advance, we never use x-offset. */ - info->mask = advance; - info->var1.u32 = 0; - info->var2.u32 = positions[j].y; - - buffer->len++; + buffer->len += num_glyphs; } - } - buffer->clear_positions (); + /* Make sure all runs had the expected direction. */ + bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); + assert (bool (status_and & kCTRunStatusRightToLeft) == backward); + assert (bool (status_or & kCTRunStatusRightToLeft) == backward); - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; ++i) { - hb_glyph_info_t *info = &buffer->info[i]; - hb_glyph_position_t *pos = &buffer->pos[i]; + buffer->clear_positions (); - /* TODO vertical */ - pos->x_advance = info->mask; - pos->x_offset = info->var1.u32; - pos->y_offset = info->var2.u32; - } + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + hb_glyph_position_t *pos = buffer->pos; + if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) + for (unsigned int i = 0; i < count; i++) + { + pos->x_advance = info->mask; + pos->x_offset = info->var1.u32; + pos->y_offset = info->var2.u32; + info++, pos++; + } + else + for (unsigned int i = 0; i < count; i++) + { + pos->y_advance = info->mask; + pos->x_offset = info->var1.u32; + pos->y_offset = info->var2.u32; + info++, pos++; + } - /* Fix up clusters so that we never return out-of-order indices; - * if core text has reordered glyphs, we'll merge them to the - * beginning of the reordered cluster. - * - * This does *not* mean we'll form the same clusters as Uniscribe - * or the native OT backend, only that the cluster indices will be - * monotonic in the output buffer. */ - if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) { - unsigned int prev_cluster = 0; - for (unsigned int i = 0; i < count; i++) { - unsigned int curr_cluster = buffer->info[i].cluster; - if (curr_cluster < prev_cluster) { - for (unsigned int j = i; j > 0; j--) { - if (buffer->info[j - 1].cluster > curr_cluster) - buffer->info[j - 1].cluster = curr_cluster; - else - break; - } + /* Fix up clusters so that we never return out-of-order indices; + * if core text has reordered glyphs, we'll merge them to the + * beginning of the reordered cluster. CoreText is nice enough + * to tell us whenever it has produced nonmonotonic results... + * Note that we assume the input clusters were nonmonotonic to + * begin with. + * + * This does *not* mean we'll form the same clusters as Uniscribe + * or the native OT backend, only that the cluster indices will be + * monotonic in the output buffer. */ + if (count > 1 && (status_or & kCTRunStatusNonMonotonic)) + { + hb_glyph_info_t *info = buffer->info; + if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) + { + unsigned int cluster = info[count - 1].cluster; + for (unsigned int i = count - 1; i > 0; i--) + { + cluster = MIN (cluster, info[i - 1].cluster); + info[i - 1].cluster = cluster; + } } - prev_cluster = curr_cluster; - } - } else { - unsigned int prev_cluster = (unsigned int)-1; - for (unsigned int i = 0; i < count; i++) { - unsigned int curr_cluster = buffer->info[i].cluster; - if (curr_cluster > prev_cluster) { - for (unsigned int j = i; j > 0; j--) { - if (buffer->info[j - 1].cluster < curr_cluster) - buffer->info[j - 1].cluster = curr_cluster; - else - break; - } + else + { + unsigned int cluster = info[0].cluster; + for (unsigned int i = 1; i < count; i++) + { + cluster = MIN (cluster, info[i].cluster); + info[i].cluster = cluster; + } } - prev_cluster = curr_cluster; } } - CFRelease (string_ref); - CFRelease (line); +#undef FAIL + +fail: + if (string_ref) + CFRelease (string_ref); + if (line) + CFRelease (line); + + for (unsigned int i = 0; i < range_records.len; i++) + if (range_records[i].font) + CFRelease (range_records[i].font); - return true; + return ret; } diff --git a/gfx/harfbuzz/src/hb-face-private.hh b/gfx/harfbuzz/src/hb-face-private.hh index 6520d3dbdff2c..c4266fff4f023 100644 --- a/gfx/harfbuzz/src/hb-face-private.hh +++ b/gfx/harfbuzz/src/hb-face-private.hh @@ -66,7 +66,7 @@ struct hb_face_t { { hb_blob_t *blob; - if (unlikely (!this || !reference_table_func)) + if (unlikely (!reference_table_func)) return hb_blob_get_empty (); blob = reference_table_func (/*XXX*/const_cast (this), tag, user_data); diff --git a/gfx/harfbuzz/src/hb-ft.cc b/gfx/harfbuzz/src/hb-ft.cc index 44e0b0bc2a560..c42d484c48bd8 100644 --- a/gfx/harfbuzz/src/hb-ft.cc +++ b/gfx/harfbuzz/src/hb-ft.cc @@ -136,7 +136,7 @@ hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT; + int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) return false; @@ -185,7 +185,7 @@ hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT; + int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) return false; @@ -455,7 +455,7 @@ get_ft_library (void) goto retry; } -#ifdef HAVE_ATEXIT +#ifdef HB_USE_ATEXIT atexit (free_ft_library); /* First person registers atexit() callback. */ #endif } diff --git a/gfx/harfbuzz/src/hb-graphite2.cc b/gfx/harfbuzz/src/hb-graphite2.cc index 709aa94419c34..807c330877116 100644 --- a/gfx/harfbuzz/src/hb-graphite2.cc +++ b/gfx/harfbuzz/src/hb-graphite2.cc @@ -274,8 +274,8 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, while ((DIV_CEIL (sizeof (hb_graphite2_cluster_t) * buffer->len, sizeof (*scratch)) + DIV_CEIL (sizeof (hb_codepoint_t) * glyph_count, sizeof (*scratch))) > scratch_size) { - buffer->ensure (buffer->allocated * 2); - if (unlikely (buffer->in_error)) { + if (unlikely (!buffer->ensure (buffer->allocated * 2))) + { if (feats) gr_featureval_destroy (feats); gr_seg_destroy (seg); return false; diff --git a/gfx/harfbuzz/src/hb-mutex-private.hh b/gfx/harfbuzz/src/hb-mutex-private.hh index eaa21695082f9..6281201958522 100644 --- a/gfx/harfbuzz/src/hb-mutex-private.hh +++ b/gfx/harfbuzz/src/hb-mutex-private.hh @@ -46,7 +46,7 @@ #include typedef CRITICAL_SECTION hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT { NULL, 0, 0, NULL, NULL, 0 } +#define HB_MUTEX_IMPL_INIT {0} #define hb_mutex_impl_init(M) InitializeCriticalSection (M) #define hb_mutex_impl_lock(M) EnterCriticalSection (M) #define hb_mutex_impl_unlock(M) LeaveCriticalSection (M) diff --git a/gfx/harfbuzz/src/hb-object-private.hh b/gfx/harfbuzz/src/hb-object-private.hh index 8a9ae34dbeeb0..7bd0f1624b596 100644 --- a/gfx/harfbuzz/src/hb-object-private.hh +++ b/gfx/harfbuzz/src/hb-object-private.hh @@ -68,8 +68,6 @@ struct hb_reference_count_t #define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT} struct hb_user_data_array_t { - /* TODO Add tracing. */ - struct hb_user_data_item_t { hb_user_data_key_t *key; void *data; @@ -106,69 +104,6 @@ struct hb_object_header_t #define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_INIT} - static inline void *create (unsigned int size) { - hb_object_header_t *obj = (hb_object_header_t *) calloc (1, size); - - if (likely (obj)) - obj->init (); - - return obj; - } - - inline void init (void) { - ref_count.init (1); - user_data.init (); - } - - inline bool is_inert (void) const { - return unlikely (ref_count.is_invalid ()); - } - - inline void reference (void) { - if (unlikely (!this || this->is_inert ())) - return; - ref_count.inc (); - } - - inline bool destroy (void) { - if (unlikely (!this || this->is_inert ())) - return false; - if (ref_count.dec () != 1) - return false; - - ref_count.finish (); /* Do this before user_data */ - user_data.finish (); - - return true; - } - - inline bool set_user_data (hb_user_data_key_t *key, - void * data, - hb_destroy_func_t destroy_func, - hb_bool_t replace) { - if (unlikely (!this || this->is_inert ())) - return false; - - return user_data.set (key, data, destroy_func, replace); - } - - inline void *get_user_data (hb_user_data_key_t *key) { - if (unlikely (!this || this->is_inert ())) - return NULL; - - return user_data.get (key); - } - - inline void trace (const char *function) const { - if (unlikely (!this)) return; - /* TODO We cannot use DEBUG_MSG_FUNC here since that one currently only - * prints the class name and throws away the template info. */ - DEBUG_MSG (OBJECT, (void *) this, - "%s refcount=%d", - function, - this ? ref_count.ref_count : 0); - } - private: ASSERT_POD (); }; @@ -179,32 +114,56 @@ struct hb_object_header_t template static inline void hb_object_trace (const Type *obj, const char *function) { - obj->header.trace (function); + DEBUG_MSG (OBJECT, (void *) obj, + "%s refcount=%d", + function, + obj ? obj->header.ref_count.ref_count : 0); } + template static inline Type *hb_object_create (void) { - Type *obj = (Type *) hb_object_header_t::create (sizeof (Type)); + Type *obj = (Type *) calloc (1, sizeof (Type)); + + if (unlikely (!obj)) + return obj; + + hb_object_init (obj); hb_object_trace (obj, HB_FUNC); return obj; } template +static inline void hb_object_init (Type *obj) +{ + obj->header.ref_count.init (1); + obj->header.user_data.init (); +} +template static inline bool hb_object_is_inert (const Type *obj) { - return unlikely (obj->header.is_inert ()); + return unlikely (obj->header.ref_count.is_invalid ()); } template static inline Type *hb_object_reference (Type *obj) { hb_object_trace (obj, HB_FUNC); - obj->header.reference (); + if (unlikely (!obj || hb_object_is_inert (obj))) + return obj; + obj->header.ref_count.inc (); return obj; } template static inline bool hb_object_destroy (Type *obj) { hb_object_trace (obj, HB_FUNC); - return obj->header.destroy (); + if (unlikely (!obj || hb_object_is_inert (obj))) + return false; + if (obj->header.ref_count.dec () != 1) + return false; + + obj->header.ref_count.finish (); /* Do this before user_data */ + obj->header.user_data.finish (); + return true; } template static inline bool hb_object_set_user_data (Type *obj, @@ -213,14 +172,18 @@ static inline bool hb_object_set_user_data (Type *obj, hb_destroy_func_t destroy, hb_bool_t replace) { - return obj->header.set_user_data (key, data, destroy, replace); + if (unlikely (!obj || hb_object_is_inert (obj))) + return false; + return obj->header.user_data.set (key, data, destroy, replace); } template static inline void *hb_object_get_user_data (Type *obj, hb_user_data_key_t *key) { - return obj->header.get_user_data (key); + if (unlikely (!obj || hb_object_is_inert (obj))) + return NULL; + return obj->header.user_data.get (key); } diff --git a/gfx/harfbuzz/src/hb-open-file-private.hh b/gfx/harfbuzz/src/hb-open-file-private.hh index 57db59db84a53..7500c32f1564a 100644 --- a/gfx/harfbuzz/src/hb-open-file-private.hh +++ b/gfx/harfbuzz/src/hb-open-file-private.hh @@ -197,6 +197,8 @@ struct TTCHeader struct OpenTypeFontFile { + static const hb_tag_t tableTag = HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */ + static const hb_tag_t CFFTag = HB_TAG ('O','T','T','O'); /* OpenType with Postscript outlines */ static const hb_tag_t TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ); /* OpenType with TrueType outlines */ static const hb_tag_t TTCTag = HB_TAG ('t','t','c','f'); /* TrueType Collection */ diff --git a/gfx/harfbuzz/src/hb-open-type-private.hh b/gfx/harfbuzz/src/hb-open-type-private.hh index 475187bae31b5..477d9e28b2c8a 100644 --- a/gfx/harfbuzz/src/hb-open-type-private.hh +++ b/gfx/harfbuzz/src/hb-open-type-private.hh @@ -194,10 +194,11 @@ struct hb_sanitize_context_t { this->start = hb_blob_get_data (this->blob, NULL); this->end = this->start + hb_blob_get_length (this->blob); + assert (this->start <= this->end); /* Must not overflow. */ this->edit_count = 0; this->debug_depth = 0; - DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1, + DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1, "start [%p..%p] (%lu bytes)", this->start, this->end, (unsigned long) (this->end - this->start)); @@ -205,7 +206,7 @@ struct hb_sanitize_context_t inline void end_processing (void) { - DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1, + DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1, "end [%p..%p] %u edit requests", this->start, this->end, this->edit_count); @@ -217,28 +218,31 @@ struct hb_sanitize_context_t inline bool check_range (const void *base, unsigned int len) const { const char *p = (const char *) base; + bool ok = this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len; - hb_auto_trace_t trace - (&this->debug_depth, "SANITIZE", this->blob, NULL, - "check_range [%p..%p] (%d bytes) in [%p..%p]", + DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, + "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s", p, p + len, len, - this->start, this->end); + this->start, this->end, + ok ? "OK" : "OUT-OF-RANGE"); - return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len)); + return likely (ok); } inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const { const char *p = (const char *) base; bool overflows = _hb_unsigned_int_mul_overflows (len, record_size); + unsigned int array_size = record_size * len; + bool ok = !overflows && this->check_range (base, array_size); - hb_auto_trace_t trace - (&this->debug_depth, "SANITIZE", this->blob, NULL, - "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]", - p, p + (record_size * len), record_size, len, (unsigned long) record_size * len, - this->start, this->end); + DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, + "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s", + p, p + (record_size * len), record_size, len, (unsigned int) array_size, + this->start, this->end, + overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE"); - return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len))); + return likely (ok); } template @@ -255,15 +259,14 @@ struct hb_sanitize_context_t const char *p = (const char *) base; this->edit_count++; - hb_auto_trace_t trace - (&this->debug_depth, "SANITIZE", this->blob, NULL, + DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", this->edit_count, p, p + len, len, this->start, this->end, this->writable ? "GRANTED" : "DENIED"); - return TRACE_RETURN (this->writable); + return this->writable; } template @@ -297,7 +300,7 @@ struct Sanitizer c->init (blob); retry: - DEBUG_MSG_FUNC (SANITIZE, blob, "start"); + DEBUG_MSG_FUNC (SANITIZE, c->start, "start"); c->start_processing (); @@ -311,13 +314,13 @@ struct Sanitizer sane = t->sanitize (c); if (sane) { if (c->edit_count) { - DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count); + DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count); /* sanitize again to ensure no toe-stepping */ c->edit_count = 0; sane = t->sanitize (c); if (c->edit_count) { - DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count); + DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count); sane = false; } } @@ -330,7 +333,7 @@ struct Sanitizer if (c->start) { c->writable = true; /* ok, we made it writable by relocating. try again */ - DEBUG_MSG_FUNC (SANITIZE, blob, "retry"); + DEBUG_MSG_FUNC (SANITIZE, c->start, "retry"); goto retry; } } @@ -338,7 +341,7 @@ struct Sanitizer c->end_processing (); - DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED"); + DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED"); if (sane) return blob; else { @@ -533,31 +536,76 @@ template struct BEInt { public: - inline void set (Type i) { hb_be_uint16_put (v,i); } - inline operator Type (void) const { return hb_be_uint16_get (v); } - inline bool operator == (const BEInt& o) const { return hb_be_uint16_eq (v, o.v); } + inline void set (Type V) + { + v[0] = (V >> 8) & 0xFF; + v[1] = (V ) & 0xFF; + } + inline operator Type (void) const + { + return (v[0] << 8) + + (v[1] ); + } + inline bool operator == (const BEInt& o) const + { + return v[0] == o.v[0] + && v[1] == o.v[1]; + } inline bool operator != (const BEInt& o) const { return !(*this == o); } private: uint8_t v[2]; }; template -struct BEInt +struct BEInt { public: - inline void set (Type i) { hb_be_uint32_put (v,i); } - inline operator Type (void) const { return hb_be_uint32_get (v); } - inline bool operator == (const BEInt& o) const { return hb_be_uint32_eq (v, o.v); } - inline bool operator != (const BEInt& o) const { return !(*this == o); } - private: uint8_t v[4]; + inline void set (Type V) + { + v[0] = (V >> 16) & 0xFF; + v[1] = (V >> 8) & 0xFF; + v[2] = (V ) & 0xFF; + } + inline operator Type (void) const + { + return (v[0] << 16) + + (v[1] << 8) + + (v[2] ); + } + inline bool operator == (const BEInt& o) const + { + return v[0] == o.v[0] + && v[1] == o.v[1] + && v[2] == o.v[2]; + } + inline bool operator != (const BEInt& o) const { return !(*this == o); } + private: uint8_t v[3]; }; template -struct BEInt +struct BEInt { public: - inline void set (Type i) { hb_be_uint24_put (v,i); } - inline operator Type (void) const { return hb_be_uint24_get (v); } - inline bool operator == (const BEInt& o) const { return hb_be_uint24_eq (v, o.v); } - inline bool operator != (const BEInt& o) const { return !(*this == o); } - private: uint8_t v[3]; + inline void set (Type V) + { + v[0] = (V >> 24) & 0xFF; + v[1] = (V >> 16) & 0xFF; + v[2] = (V >> 8) & 0xFF; + v[3] = (V ) & 0xFF; + } + inline operator Type (void) const + { + return (v[0] << 24) + + (v[1] << 16) + + (v[2] << 8) + + (v[3] ); + } + inline bool operator == (const BEInt& o) const + { + return v[0] == o.v[0] + && v[1] == o.v[1] + && v[2] == o.v[2] + && v[3] == o.v[3]; + } + inline bool operator != (const BEInt& o) const { return !(*this == o); } + private: uint8_t v[4]; }; /* Integer types in big-endian order and no alignment requirement */ diff --git a/gfx/harfbuzz/src/hb-ot-font.cc b/gfx/harfbuzz/src/hb-ot-font.cc index c9890c592281a..2af2f54a75932 100644 --- a/gfx/harfbuzz/src/hb-ot-font.cc +++ b/gfx/harfbuzz/src/hb-ot-font.cc @@ -35,17 +35,128 @@ #include "hb-ot-hmtx-table.hh" +struct hb_ot_face_metrics_accelerator_t +{ + unsigned int num_metrics; + unsigned int num_advances; + unsigned int default_advance; + 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, + unsigned int default_advance) + { + this->default_advance = default_advance; + this->num_metrics = face->get_num_glyphs (); + + hb_blob_t *_hea_blob = OT::Sanitizer::sanitize (face->reference_table (_hea_tag)); + const OT::_hea *_hea = OT::Sanitizer::lock_instance (_hea_blob); + this->num_advances = _hea->numberOfLongMetrics; + hb_blob_destroy (_hea_blob); + + this->blob = OT::Sanitizer::sanitize (face->reference_table (_mtx_tag)); + if (unlikely (!this->num_advances || + 2 * (this->num_advances + this->num_metrics) < hb_blob_get_length (this->blob))) + { + this->num_metrics = this->num_advances = 0; + hb_blob_destroy (this->blob); + this->blob = hb_blob_get_empty (); + } + this->table = OT::Sanitizer::lock_instance (this->blob); + } + + inline void fini (void) + { + hb_blob_destroy (this->blob); + } + + inline unsigned int get_advance (hb_codepoint_t glyph) const + { + if (unlikely (glyph >= this->num_metrics)) + { + /* If this->num_metrics is zero, it means we don't have the metrics table + * for this direction: return one EM. Otherwise, it means that the glyph + * index is out of bound: return zero. */ + if (this->num_metrics) + return 0; + else + return this->default_advance; + } + + if (glyph >= this->num_advances) + glyph = this->num_advances - 1; + + return this->table->longMetric[glyph].advance; + } +}; + +struct hb_ot_face_cmap_accelerator_t +{ + const OT::CmapSubtable *table; + const OT::CmapSubtable *uvs_table; + hb_blob_t *blob; + + inline void init (hb_face_t *face) + { + this->blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_cmap)); + const OT::cmap *cmap = OT::Sanitizer::lock_instance (this->blob); + const OT::CmapSubtable *subtable = NULL; + const OT::CmapSubtable *subtable_uvs = NULL; + + /* 32-bit subtables. */ + if (!subtable) subtable = cmap->find_subtable (3, 10); + if (!subtable) subtable = cmap->find_subtable (0, 6); + if (!subtable) subtable = cmap->find_subtable (0, 4); + /* 16-bit subtables. */ + if (!subtable) subtable = cmap->find_subtable (3, 1); + if (!subtable) subtable = cmap->find_subtable (0, 3); + if (!subtable) subtable = cmap->find_subtable (0, 2); + if (!subtable) subtable = cmap->find_subtable (0, 1); + if (!subtable) subtable = cmap->find_subtable (0, 0); + /* Meh. */ + if (!subtable) subtable = &OT::Null(OT::CmapSubtable); + + /* UVS subtable. */ + if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5); + /* Meh. */ + if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable); + + this->table = subtable; + this->uvs_table = subtable_uvs; + } + + inline void fini (void) + { + hb_blob_destroy (this->blob); + } + + inline bool get_glyph (hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph) const + { + if (unlikely (variation_selector)) + { + switch (this->uvs_table->get_glyph_variant (unicode, + variation_selector, + glyph)) + { + case OT::GLYPH_VARIANT_NOT_FOUND: return false; + case OT::GLYPH_VARIANT_FOUND: return true; + case OT::GLYPH_VARIANT_USE_DEFAULT: break; + } + } + + return this->table->get_glyph (unicode, glyph); + } +}; + struct hb_ot_font_t { - unsigned int num_glyphs; - unsigned int num_hmetrics; - const OT::hmtx *hmtx; - hb_blob_t *hmtx_blob; - - const OT::CmapSubtable *cmap; - const OT::CmapSubtable *cmap_uvs; - hb_blob_t *cmap_blob; + hb_ot_face_cmap_accelerator_t cmap; + hb_ot_face_metrics_accelerator_t h_metrics; + hb_ot_face_metrics_accelerator_t v_metrics; }; @@ -53,50 +164,16 @@ static hb_ot_font_t * _hb_ot_font_create (hb_font_t *font) { hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t)); + hb_face_t *face = font->face; if (unlikely (!ot_font)) return NULL; - ot_font->num_glyphs = font->face->get_num_glyphs (); + unsigned int upem = face->get_upem (); - { - hb_blob_t *hhea_blob = OT::Sanitizer::sanitize (font->face->reference_table (HB_OT_TAG_hhea)); - const OT::hhea *hhea = OT::Sanitizer::lock_instance (hhea_blob); - ot_font->num_hmetrics = hhea->numberOfHMetrics; - hb_blob_destroy (hhea_blob); - } - ot_font->hmtx_blob = OT::Sanitizer::sanitize (font->face->reference_table (HB_OT_TAG_hmtx)); - if (unlikely (!ot_font->num_hmetrics || - 2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->hmtx_blob))) - { - hb_blob_destroy (ot_font->hmtx_blob); - free (ot_font); - return NULL; - } - ot_font->hmtx = OT::Sanitizer::lock_instance (ot_font->hmtx_blob); - - ot_font->cmap_blob = OT::Sanitizer::sanitize (font->face->reference_table (HB_OT_TAG_cmap)); - const OT::cmap *cmap = OT::Sanitizer::lock_instance (ot_font->cmap_blob); - const OT::CmapSubtable *subtable = NULL; - const OT::CmapSubtable *subtable_uvs = NULL; - - /* 32-bit subtables. */ - if (!subtable) subtable = cmap->find_subtable (0, 6); - if (!subtable) subtable = cmap->find_subtable (0, 4); - if (!subtable) subtable = cmap->find_subtable (3, 10); - /* 16-bit subtables. */ - if (!subtable) subtable = cmap->find_subtable (0, 3); - if (!subtable) subtable = cmap->find_subtable (3, 1); - /* Meh. */ - if (!subtable) subtable = &OT::Null(OT::CmapSubtable); - - /* UVS subtable. */ - if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5); - /* Meh. */ - if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable); - - ot_font->cmap = subtable; - ot_font->cmap_uvs = subtable_uvs; + ot_font->cmap.init (face); + ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1); + ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */ return ot_font; } @@ -104,8 +181,9 @@ _hb_ot_font_create (hb_font_t *font) static void _hb_ot_font_destroy (hb_ot_font_t *ot_font) { - hb_blob_destroy (ot_font->cmap_blob); - hb_blob_destroy (ot_font->hmtx_blob); + ot_font->cmap.fini (); + ot_font->h_metrics.fini (); + ot_font->v_metrics.fini (); free (ot_font); } @@ -121,20 +199,7 @@ hb_ot_get_glyph (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - - if (unlikely (variation_selector)) - { - switch (ot_font->cmap_uvs->get_glyph_variant (unicode, - variation_selector, - glyph)) - { - case OT::GLYPH_VARIANT_NOT_FOUND: return false; - case OT::GLYPH_VARIANT_FOUND: return true; - case OT::GLYPH_VARIANT_USE_DEFAULT: break; - } - } - - return ot_font->cmap->get_glyph (unicode, glyph); + return ot_font->cmap.get_glyph (unicode, variation_selector, glyph); } static hb_position_t @@ -144,14 +209,7 @@ hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - - if (unlikely (glyph >= ot_font->num_glyphs)) - return 0; /* Maybe better to return notdef's advance instead? */ - - if (glyph >= ot_font->num_hmetrics) - glyph = ot_font->num_hmetrics - 1; - - return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advanceWidth); + return font->em_scale_x (ot_font->h_metrics.get_advance (glyph)); } static hb_position_t @@ -160,8 +218,8 @@ hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, hb_codepoint_t glyph, void *user_data HB_UNUSED) { - /* TODO */ - return 0; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + return font->em_scale_y (-ot_font->v_metrics.get_advance (glyph)); } static hb_bool_t @@ -206,6 +264,7 @@ hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, hb_codepoint_t bottom_glyph HB_UNUSED, void *user_data HB_UNUSED) { + /* OpenType doesn't have vertical-kerning other than GPOS. */ return 0; } diff --git a/gfx/harfbuzz/src/hb-ot-hhea-table.hh b/gfx/harfbuzz/src/hb-ot-hhea-table.hh index d433200165cb4..edc0e29cbfbcb 100644 --- a/gfx/harfbuzz/src/hb-ot-hhea-table.hh +++ b/gfx/harfbuzz/src/hb-ot-hhea-table.hh @@ -35,14 +35,19 @@ namespace OT { /* * hhea -- The Horizontal Header Table + * vhea -- The Vertical Header Table */ #define HB_OT_TAG_hhea HB_TAG('h','h','e','a') +#define HB_OT_TAG_vhea HB_TAG('v','h','e','a') -struct hhea +struct _hea { - static const hb_tag_t tableTag = HB_OT_TAG_hhea; + static const hb_tag_t tableTag = HB_TAG('_','h','e','a'); + + static const hb_tag_t hheaTag = HB_OT_TAG_hhea; + static const hb_tag_t vheaTag = HB_OT_TAG_vhea; inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); @@ -51,45 +56,45 @@ struct hhea public: FixedVersion version; /* 0x00010000u for version 1.0. */ - FWORD ascender; /* Typographic ascent. - * (Distance from baseline of highest - * ascender) */ - FWORD descender; /* Typographic descent. - * (Distance from baseline of lowest - * descender) */ - FWORD lineGap; /* Typographic line gap. Negative - * LineGap values are treated as zero - * in Windows 3.1, System 6, and - * System 7. */ - UFWORD advanceWidthMax; /* Maximum advance width value in - * 'hmtx' table. */ - FWORD minLeftSideBearing; /* Minimum left sidebearing value in - * 'hmtx' table. */ - FWORD minRightSideBearing; /* Minimum right sidebearing value; + FWORD ascender; /* Typographic ascent. */ + FWORD descender; /* Typographic descent. */ + FWORD lineGap; /* Typographic line gap. */ + UFWORD advanceMax; /* Maximum advance width/height value in + * metrics table. */ + FWORD minLeadingBearing; /* Minimum left/top sidebearing value in + * metrics table. */ + FWORD minTrailingBearing; /* Minimum right/bottom sidebearing value; * calculated as Min(aw - lsb - - * (xMax - xMin)). */ - FWORD xMaxExtent; /* Max(lsb + (xMax - xMin)). */ + * (xMax - xMin)) for horizontal. */ + FWORD maxExtent; /* horizontal: Max(lsb + (xMax - xMin)), + * vertical: minLeadingBearing+(yMax-yMin). */ SHORT caretSlopeRise; /* Used to calculate the slope of the - * cursor (rise/run); 1 for vertical. */ - SHORT caretSlopeRun; /* 0 for vertical. */ + * cursor (rise/run); 1 for vertical caret, + * 0 for horizontal.*/ + SHORT caretSlopeRun; /* 0 for vertical caret, 1 for horizontal. */ SHORT caretOffset; /* The amount by which a slanted * highlight on a glyph needs * to be shifted to produce the * best appearance. Set to 0 for - * non--slanted fonts */ - SHORT reserved1; /* set to 0 */ - SHORT reserved2; /* set to 0 */ - SHORT reserved3; /* set to 0 */ - SHORT reserved4; /* set to 0 */ + * non-slanted fonts. */ + SHORT reserved1; /* Set to 0. */ + SHORT reserved2; /* Set to 0. */ + SHORT reserved3; /* Set to 0. */ + SHORT reserved4; /* Set to 0. */ SHORT metricDataFormat; /* 0 for current format. */ - USHORT numberOfHMetrics; /* Number of hMetric entries in 'hmtx' - * table */ + USHORT numberOfLongMetrics; /* Number of LongMetric entries in metric + * table. */ public: DEFINE_SIZE_STATIC (36); }; +struct hhea : _hea { + static const hb_tag_t tableTag = HB_OT_TAG_hhea; +}; +struct vhea : _hea { + static const hb_tag_t tableTag = HB_OT_TAG_vhea; +}; + } /* namespace OT */ diff --git a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh index e918e3b3f40f4..317854ce7f858 100644 --- a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh +++ b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh @@ -35,22 +35,27 @@ namespace OT { /* * hmtx -- The Horizontal Metrics Table + * vmtx -- The Vertical Metrics Table */ #define HB_OT_TAG_hmtx HB_TAG('h','m','t','x') +#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x') -struct LongHorMetric +struct LongMetric { - USHORT advanceWidth; - SHORT lsb; + USHORT advance; /* Advance width/height. */ + SHORT lsb; /* Leading (left/top) side bearing. */ public: DEFINE_SIZE_STATIC (4); }; -struct hmtx +struct _mtx { - static const hb_tag_t tableTag = HB_OT_TAG_hmtx; + static const hb_tag_t tableTag = HB_TAG('_','m','t','x'); + + static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx; + static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx; inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); @@ -60,7 +65,7 @@ struct hmtx } public: - LongHorMetric longHorMetric[VAR]; /* Paired advance width and left side + LongMetric longMetric[VAR]; /* Paired advance width and leading * bearing values for each glyph. The * value numOfHMetrics comes from * the 'hhea' table. If the font is @@ -68,23 +73,29 @@ struct hmtx * be in the array, but that entry is * required. The last entry applies to * all subsequent glyphs. */ - SHORT leftSideBearingX[VAR]; /* Here the advanceWidth is assumed - * to be the same as the advanceWidth + SHORT leadingBearingX[VAR]; /* Here the advance is assumed + * to be the same as the advance * for the last entry above. The * number of entries in this array is * derived from numGlyphs (from 'maxp' - * table) minus numberOfHMetrics. This - * generally is used with a run of - * monospaced glyphs (e.g., Kanji + * table) minus numberOfLongMetrics. + * This generally is used with a run + * of monospaced glyphs (e.g., Kanji * fonts or Courier fonts). Only one * run is allowed and it must be at * the end. This allows a monospaced - * font to vary the left side bearing + * font to vary the side bearing * values for each glyph. */ public: - DEFINE_SIZE_ARRAY2 (0, longHorMetric, leftSideBearingX); + DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX); }; +struct hmtx : _mtx { + static const hb_tag_t tableTag = HB_OT_TAG_hmtx; +}; +struct vmtx : _mtx { + static const hb_tag_t tableTag = HB_OT_TAG_vmtx; +}; } /* namespace OT */ diff --git a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh index 8e2860c9131ce..4255f5a8aeac6 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh @@ -345,8 +345,8 @@ struct AnchorMatrix inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const { *found = false; if (unlikely (row >= rows || col >= cols)) return Null(Anchor); - *found = !matrix[row * cols + col].is_null (); - return this+matrix[row * cols + col]; + *found = !matrixZ[row * cols + col].is_null (); + return this+matrixZ[row * cols + col]; } inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) { @@ -354,19 +354,19 @@ struct AnchorMatrix if (!c->check_struct (this)) return TRACE_RETURN (false); if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_RETURN (false); unsigned int count = rows * cols; - if (!c->check_array (matrix, matrix[0].static_size, count)) return TRACE_RETURN (false); + if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return TRACE_RETURN (false); for (unsigned int i = 0; i < count; i++) - if (!matrix[i].sanitize (c, this)) return TRACE_RETURN (false); + if (!matrixZ[i].sanitize (c, this)) return TRACE_RETURN (false); return TRACE_RETURN (true); } USHORT rows; /* Number of rows */ protected: OffsetTo - matrix[VAR]; /* Matrix of offsets to Anchor tables-- + matrixZ[VAR]; /* Matrix of offsets to Anchor tables-- * from beginning of AnchorMatrix table */ public: - DEFINE_SIZE_ARRAY (2, matrix); + DEFINE_SIZE_ARRAY (2, matrixZ); }; @@ -530,7 +530,7 @@ struct SinglePos template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 2: return TRACE_RETURN (c->dispatch (u.format2)); @@ -583,7 +583,7 @@ struct PairSet unsigned int len2 = valueFormats[1].get_len (); unsigned int record_size = USHORT::static_size * (1 + len1 + len2); - const PairValueRecord *record = CastP (array); + const PairValueRecord *record = CastP (arrayZ); unsigned int count = len; for (unsigned int i = 0; i < count; i++) { @@ -602,7 +602,7 @@ struct PairSet unsigned int len2 = valueFormats[1].get_len (); unsigned int record_size = USHORT::static_size * (1 + len1 + len2); - const PairValueRecord *record = CastP (array); + const PairValueRecord *record = CastP (arrayZ); unsigned int count = len; for (unsigned int i = 0; i < count; i++) { @@ -634,20 +634,20 @@ struct PairSet inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) { TRACE_SANITIZE (this); if (!(c->check_struct (this) - && c->check_array (array, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false); + && c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false); unsigned int count = len; - PairValueRecord *record = CastP (array); + PairValueRecord *record = CastP (arrayZ); return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) && closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride)); } protected: USHORT len; /* Number of PairValueRecords */ - USHORT array[VAR]; /* Array of PairValueRecords--ordered + USHORT arrayZ[VAR]; /* Array of PairValueRecords--ordered * by GlyphID of the second glyph */ public: - DEFINE_SIZE_ARRAY (2, array); + DEFINE_SIZE_ARRAY (2, arrayZ); }; struct PairPosFormat1 @@ -822,7 +822,7 @@ struct PairPos template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 2: return TRACE_RETURN (c->dispatch (u.format2)); @@ -989,7 +989,7 @@ struct CursivePos template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); @@ -1088,7 +1088,7 @@ struct MarkBasePos template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); @@ -1209,7 +1209,7 @@ struct MarkLigPos template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); @@ -1328,7 +1328,7 @@ struct MarkMarkPos template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); @@ -1387,7 +1387,7 @@ struct PosLookupSubTable template inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, lookup_type); switch (lookup_type) { case Single: return TRACE_RETURN (u.single.dispatch (c)); case Pair: return TRACE_RETURN (u.pair.dispatch (c)); @@ -1488,8 +1488,8 @@ struct PosLookup : Lookup template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); unsigned int lookup_type = get_type (); + TRACE_DISPATCH (this, lookup_type); unsigned int count = get_subtable_count (); for (unsigned int i = 0; i < count; i++) { typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type); diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh index 2b421a94f549a..5d67be0ec0f31 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh @@ -200,7 +200,7 @@ struct SingleSubst TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); unsigned int format = 2; - int delta; + int delta = 0; if (num_glyphs) { format = 1; /* TODO(serialize) check for wrap-around */ @@ -222,7 +222,7 @@ struct SingleSubst template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 2: return TRACE_RETURN (c->dispatch (u.format2)); @@ -422,7 +422,7 @@ struct MultipleSubst template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); @@ -573,7 +573,7 @@ struct AlternateSubst template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); @@ -889,7 +889,7 @@ struct LigatureSubst template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); @@ -1053,7 +1053,7 @@ struct ReverseChainSingleSubst template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); @@ -1100,7 +1100,7 @@ struct SubstLookupSubTable template inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, lookup_type); switch (lookup_type) { case Single: return TRACE_RETURN (u.single.dispatch (c)); case Multiple: return TRACE_RETURN (u.multiple.dispatch (c)); @@ -1275,8 +1275,8 @@ struct SubstLookup : Lookup template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); unsigned int lookup_type = get_type (); + TRACE_DISPATCH (this, lookup_type); unsigned int count = get_subtable_count (); for (unsigned int i = 0; i < count; i++) { typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type); diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh index 546ff4b0fde32..57fc1e05f767a 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh @@ -38,10 +38,10 @@ namespace OT { -#define TRACE_DISPATCH(this) \ +#define TRACE_DISPATCH(this, format) \ hb_auto_trace_t trace \ (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - ""); + "format %d", (int) format); #ifndef HB_DEBUG_CLOSURE #define HB_DEBUG_CLOSURE (HB_DEBUG+0) @@ -168,6 +168,10 @@ struct hb_collect_glyphs_context_t if (output == hb_set_get_empty ()) return HB_VOID; + /* Return if new lookup was recursed to before. */ + if (recursed_lookups.has (lookup_index)) + return HB_VOID; + hb_set_t *old_before = before; hb_set_t *old_input = input; hb_set_t *old_after = after; @@ -181,6 +185,8 @@ struct hb_collect_glyphs_context_t input = old_input; after = old_after; + recursed_lookups.add (lookup_index); + return HB_VOID; } @@ -190,6 +196,7 @@ struct hb_collect_glyphs_context_t hb_set_t *after; hb_set_t *output; recurse_func_t recurse_func; + hb_set_t recursed_lookups; unsigned int nesting_level_left; unsigned int debug_depth; @@ -205,18 +212,30 @@ struct hb_collect_glyphs_context_t after (glyphs_after ? glyphs_after : hb_set_get_empty ()), output (glyphs_output ? glyphs_output : hb_set_get_empty ()), recurse_func (NULL), + recursed_lookups (), nesting_level_left (nesting_level_left_), - debug_depth (0) {} + debug_depth (0) + { + recursed_lookups.init (); + } + ~hb_collect_glyphs_context_t (void) + { + recursed_lookups.fini (); + } void set_recurse_func (recurse_func_t func) { recurse_func = func; } }; +#ifndef HB_DEBUG_GET_COVERAGE +#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0) +#endif + struct hb_get_coverage_context_t { inline const char *get_name (void) { return "GET_COVERAGE"; } - static const unsigned int max_debug_depth = 0; + static const unsigned int max_debug_depth = HB_DEBUG_GET_COVERAGE; typedef const Coverage &return_t; template inline return_t dispatch (const T &obj) { return obj.get_coverage (); } @@ -1117,9 +1136,9 @@ struct Rule inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const { TRACE_CLOSURE (this); - const LookupRecord *lookupRecord = &StructAtOffset (input, input[0].static_size * (inputCount ? inputCount - 1 : 0)); + const LookupRecord *lookupRecord = &StructAtOffset (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0)); context_closure_lookup (c, - inputCount, input, + inputCount, inputZ, lookupCount, lookupRecord, lookup_context); } @@ -1127,9 +1146,9 @@ struct Rule inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const { TRACE_COLLECT_GLYPHS (this); - const LookupRecord *lookupRecord = &StructAtOffset (input, input[0].static_size * (inputCount ? inputCount - 1 : 0)); + const LookupRecord *lookupRecord = &StructAtOffset (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0)); context_collect_glyphs_lookup (c, - inputCount, input, + inputCount, inputZ, lookupCount, lookupRecord, lookup_context); } @@ -1137,15 +1156,15 @@ struct Rule inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const { TRACE_WOULD_APPLY (this); - const LookupRecord *lookupRecord = &StructAtOffset (input, input[0].static_size * (inputCount ? inputCount - 1 : 0)); - return TRACE_RETURN (context_would_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context)); + const LookupRecord *lookupRecord = &StructAtOffset (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0)); + return TRACE_RETURN (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context)); } inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const { TRACE_APPLY (this); - const LookupRecord *lookupRecord = &StructAtOffset (input, input[0].static_size * (inputCount ? inputCount - 1 : 0)); - return TRACE_RETURN (context_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context)); + const LookupRecord *lookupRecord = &StructAtOffset (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0)); + return TRACE_RETURN (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context)); } public: @@ -1153,8 +1172,8 @@ struct Rule TRACE_SANITIZE (this); return inputCount.sanitize (c) && lookupCount.sanitize (c) - && c->check_range (input, - input[0].static_size * inputCount + && c->check_range (inputZ, + inputZ[0].static_size * inputCount + lookupRecordX[0].static_size * lookupCount); } @@ -1163,12 +1182,12 @@ struct Rule * glyph sequence--includes the first * glyph */ USHORT lookupCount; /* Number of LookupRecords */ - USHORT input[VAR]; /* Array of match inputs--start with + USHORT inputZ[VAR]; /* Array of match inputs--start with * second glyph */ LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in * design order */ public: - DEFINE_SIZE_ARRAY2 (4, input, lookupRecordX); + DEFINE_SIZE_ARRAY2 (4, inputZ, lookupRecordX); }; struct RuleSet @@ -1413,16 +1432,16 @@ struct ContextFormat3 inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); - if (!(this+coverage[0]).intersects (c->glyphs)) + if (!(this+coverageZ[0]).intersects (c->glyphs)) return; - const LookupRecord *lookupRecord = &StructAtOffset (coverage, coverage[0].static_size * glyphCount); + const LookupRecord *lookupRecord = &StructAtOffset (coverageZ, coverageZ[0].static_size * glyphCount); struct ContextClosureLookupContext lookup_context = { {intersects_coverage}, this }; context_closure_lookup (c, - glyphCount, (const USHORT *) (coverage + 1), + glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context); } @@ -1430,16 +1449,16 @@ struct ContextFormat3 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - (this+coverage[0]).add_coverage (c->input); + (this+coverageZ[0]).add_coverage (c->input); - const LookupRecord *lookupRecord = &StructAtOffset (coverage, coverage[0].static_size * glyphCount); + const LookupRecord *lookupRecord = &StructAtOffset (coverageZ, coverageZ[0].static_size * glyphCount); struct ContextCollectGlyphsLookupContext lookup_context = { {collect_coverage}, this }; context_collect_glyphs_lookup (c, - glyphCount, (const USHORT *) (coverage + 1), + glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context); } @@ -1448,41 +1467,42 @@ struct ContextFormat3 { TRACE_WOULD_APPLY (this); - const LookupRecord *lookupRecord = &StructAtOffset (coverage, coverage[0].static_size * glyphCount); + const LookupRecord *lookupRecord = &StructAtOffset (coverageZ, coverageZ[0].static_size * glyphCount); struct ContextApplyLookupContext lookup_context = { {match_coverage}, this }; - return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context)); + return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); } inline const Coverage &get_coverage (void) const { - return this+coverage[0]; + return this+coverageZ[0]; } inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - unsigned int index = (this+coverage[0]).get_coverage (c->buffer->cur().codepoint); + unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); - const LookupRecord *lookupRecord = &StructAtOffset (coverage, coverage[0].static_size * glyphCount); + const LookupRecord *lookupRecord = &StructAtOffset (coverageZ, coverageZ[0].static_size * glyphCount); struct ContextApplyLookupContext lookup_context = { {match_coverage}, this }; - return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context)); + return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); } inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); if (!c->check_struct (this)) return TRACE_RETURN (false); unsigned int count = glyphCount; - if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false); + if (!count) return TRACE_RETURN (false); /* We want to access coverageZ[0] freely. */ + if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return TRACE_RETURN (false); for (unsigned int i = 0; i < count; i++) - if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false); - LookupRecord *lookupRecord = &StructAtOffset (coverage, coverage[0].static_size * count); + if (!coverageZ[i].sanitize (c, this)) return TRACE_RETURN (false); + LookupRecord *lookupRecord = &StructAtOffset (coverageZ, coverageZ[0].static_size * count); return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount)); } @@ -1492,12 +1512,12 @@ struct ContextFormat3 * sequence */ USHORT lookupCount; /* Number of LookupRecords */ OffsetTo - coverage[VAR]; /* Array of offsets to Coverage + coverageZ[VAR]; /* Array of offsets to Coverage * table in glyph sequence order */ LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in * design order */ public: - DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX); + DEFINE_SIZE_ARRAY2 (6, coverageZ, lookupRecordX); }; struct Context @@ -1505,7 +1525,7 @@ struct Context template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 2: return TRACE_RETURN (c->dispatch (u.format2)); @@ -2090,6 +2110,7 @@ struct ChainContextFormat3 if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false); OffsetArrayOf &input = StructAfter > (backtrack); if (!input.sanitize (c, this)) return TRACE_RETURN (false); + if (!input.len) return TRACE_RETURN (false); /* To be consistent with Context. */ OffsetArrayOf &lookahead = StructAfter > (input); if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false); ArrayOf &lookup = StructAfter > (lookahead); @@ -2122,7 +2143,7 @@ struct ChainContext template inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_DISPATCH (this); + TRACE_DISPATCH (this, u.format); switch (u.format) { case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 2: return TRACE_RETURN (c->dispatch (u.format2)); diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh index e5b7ed489c053..dc659e084c517 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh @@ -207,7 +207,7 @@ struct arabic_fallback_plan_t static const arabic_fallback_plan_t arabic_fallback_plan_nil = {}; -#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_WITH_WIN1256) +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256) #define HB_WITH_WIN1256 #endif diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh index 63ed3f8e0ef54..3a20b507d4ed7 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh @@ -313,8 +313,11 @@ OT_TABLE_END /* * Include a second time to get the table data... */ +#if 0 +#include "hb-private.hh" /* Make check-includes.sh happy. */ +#endif #ifdef OT_MEASURE -#include __FILE__ +#include "hb-ot-shape-complex-arabic-win1256.hh" #endif #define HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh index 5fbdcc8366e56..34023decb9926 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh @@ -32,7 +32,7 @@ #include "hb-private.hh" -#line 36 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 36 "hb-ot-shape-complex-indic-machine.hh.tmp" static const unsigned char _indic_syllable_machine_trans_keys[] = { 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, @@ -1550,7 +1550,7 @@ find_syllables (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 1554 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1554 "hb-ot-shape-complex-indic-machine.hh.tmp" { cs = indic_syllable_machine_start; ts = 0; @@ -1567,7 +1567,7 @@ find_syllables (hb_buffer_t *buffer) unsigned int last = 0; unsigned int syllable_serial = 1; -#line 1571 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1571 "hb-ot-shape-complex-indic-machine.hh.tmp" { int _slen; int _trans; @@ -1581,7 +1581,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 1585 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1585 "hb-ot-shape-complex-indic-machine.hh.tmp" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -1700,7 +1700,7 @@ _eof_trans: #line 93 "../../src/hb-ot-shape-complex-indic-machine.rl" {act = 6;} break; -#line 1704 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1704 "hb-ot-shape-complex-indic-machine.hh.tmp" } _again: @@ -1709,7 +1709,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 1713 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1713 "hb-ot-shape-complex-indic-machine.hh.tmp" } if ( ++p != pe ) diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl index f6768a581f2ff..694b235d1d1cb 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl @@ -69,7 +69,7 @@ cn = c.ZWJ?.n?; forced_rakar = ZWJ H ZWJ Ra; symbol = Symbol.N?; matra_group = z{0,3}.M.N?.(H | forced_rakar)?; -syllable_tail = (SM.SM?.ZWNJ?)? A{0,3}? VD{0,2}; +syllable_tail = (z?.SM.SM?.ZWNJ?)? A{0,3}? VD{0,2}; place_holder = PLACEHOLDER | DOTTEDCIRCLE; halant_group = (z?.h.(ZWJ.N?)?); final_halant_group = halant_group | h.ZWNJ; diff --git a/gfx/harfbuzz/src/hb-private.hh b/gfx/harfbuzz/src/hb-private.hh index 5a4ca69915e63..c92cdec5164d7 100644 --- a/gfx/harfbuzz/src/hb-private.hh +++ b/gfx/harfbuzz/src/hb-private.hh @@ -96,6 +96,8 @@ #if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER) #define snprintf _snprintf +/* Windows CE only has _strdup, while rest of Windows has both. */ +#define strdup _strdup #endif #ifdef _MSC_VER @@ -126,10 +128,47 @@ # ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0600 # endif -# define WIN32_LEAN_AND_MEAN -# define STRICT +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +# ifndef STRICT +# define STRICT 1 +# endif #endif +#ifdef _WIN32_WCE +/* Some things not defined on Windows CE. */ +#define MemoryBarrier() +#define getenv(Name) NULL +#define setlocale(Category, Locale) "C" +static int errno = 0; /* Use something better? */ +#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) +# if __GLIBC_PREREQ(2,3) +/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */ +# define HB_USE_ATEXIT 1 +# endif +# elif defined(_MSC_VER) || defined(__MINGW32__) +/* For MSVC: + * http://msdn.microsoft.com/en-ca/library/tze57ck3.aspx + * http://msdn.microsoft.com/en-ca/library/zk17ww08.aspx + * mingw32 headers say atexit is safe to use in shared libraries. + */ +# define HB_USE_ATEXIT 1 +# elif defined(__ANDROID__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +/* This was fixed in Android NKD r8 or r8b: + * https://code.google.com/p/android/issues/detail?id=6455 + * which introduced GCC 4.6: + * https://developer.android.com/tools/sdk/ndk/index.html + */ +# define HB_USE_ATEXIT 1 +# endif +#endif /* Basics */ @@ -500,47 +539,6 @@ struct hb_lockable_set_t }; - - -/* Big-endian handling */ - -static inline uint16_t hb_be_uint16 (const uint16_t v) -{ - const uint8_t *V = (const uint8_t *) &v; - return (V[0] << 8) | V[1]; -} - -static inline uint16_t hb_uint16_swap (const uint16_t v) -{ - return (v >> 8) | (v << 8); -} - -static inline uint32_t hb_uint32_swap (const uint32_t v) -{ - return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); -} - -/* Note, of the following macros, uint16_get is the one called many many times. - * If there is any optimizations to be done, it's in that macro. However, I - * already confirmed that on my T400 ThinkPad at least, using bswap_16(), which - * results in a single ror instruction, does NOT speed this up. In fact, it - * resulted in a minor slowdown. At any rate, note that v may not be correctly - * aligned, so I think the current implementation is optimal. - */ - -#define hb_be_uint16_put(v,V) HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_STMT_END -#define hb_be_uint16_get(v) (uint16_t) ((v[0] << 8) + v[1]) -#define hb_be_uint16_eq(a,b) (a[0] == b[0] && a[1] == b[1]) - -#define hb_be_uint32_put(v,V) HB_STMT_START { v[0] = (V>>24); v[1] = (V>>16); v[2] = (V>>8); v[3] = (V); } HB_STMT_END -#define hb_be_uint32_get(v) (uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3]) -#define hb_be_uint32_eq(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]) - -#define hb_be_uint24_put(v,V) HB_STMT_START { v[0] = (V>>16); v[1] = (V>>8); v[2] = (V); } HB_STMT_END -#define hb_be_uint24_get(v) (uint32_t) ((v[0] << 16) + (v[1] << 8) + v[2]) -#define hb_be_uint24_eq(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) - - /* ASCII tag/character handling */ static inline bool ISALPHA (unsigned char c) @@ -585,6 +583,15 @@ _hb_debug (unsigned int level, #define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT)) #define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0)) +template static inline void +_hb_debug_msg_va (const char *what, + const void *obj, + const char *func, + bool indented, + unsigned int level, + int level_dir, + const char *message, + va_list ap) HB_PRINTF_FUNC(7, 0); template static inline void _hb_debug_msg_va (const char *what, const void *obj, @@ -708,7 +715,9 @@ _hb_debug_msg<0> (const char *what HB_UNUSED, */ template -struct hb_printer_t {}; +struct hb_printer_t { + const char *print (const T&) { return "something"; } +}; template <> struct hb_printer_t { @@ -815,7 +824,9 @@ hb_in_range (T u, T lo, T hi) * to generate a warning than unused variables. */ ASSERT_STATIC (sizeof (hb_assert_unsigned_t) >= 0); - return (u - lo) <= (hi - lo); + /* The casts below are important as if T is smaller than int, + * the subtract results will become a signed int! */ + return (T)(u - lo) <= (T)(hi - lo); } template static inline bool @@ -839,7 +850,7 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) #define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x)) -template inline void +template static inline void hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2) { if (unlikely (!len)) @@ -872,7 +883,7 @@ hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), } while (k); } -template inline void +template static inline void hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *)) { hb_bubble_sort (array, len, compar, (int *) NULL); @@ -901,12 +912,12 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o struct hb_options_t { - int initialized : 1; - int uniscribe_bug_compatible : 1; + unsigned int initialized : 1; + unsigned int uniscribe_bug_compatible : 1; }; union hb_options_union_t { - int i; + unsigned int i; hb_options_t opts; }; ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t)); diff --git a/gfx/harfbuzz/src/hb-set-private.hh b/gfx/harfbuzz/src/hb-set-private.hh index 705f554ce698c..59e8f4559f592 100644 --- a/gfx/harfbuzz/src/hb-set-private.hh +++ b/gfx/harfbuzz/src/hb-set-private.hh @@ -150,7 +150,7 @@ struct hb_set_t bool in_error; inline void init (void) { - header.init (); + hb_object_init (this); clear (); } inline void fini (void) { diff --git a/gfx/harfbuzz/src/hb-shape-plan.cc b/gfx/harfbuzz/src/hb-shape-plan.cc index 5ffc6b1362e47..2166173f9e5e3 100644 --- a/gfx/harfbuzz/src/hb-shape-plan.cc +++ b/gfx/harfbuzz/src/hb-shape-plan.cc @@ -29,6 +29,12 @@ #include "hb-font-private.hh" #include "hb-buffer-private.hh" + +#ifndef HB_DEBUG_SHAPE_PLAN +#define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0) +#endif + + #define HB_SHAPER_IMPLEMENT(shaper) \ HB_SHAPER_DATA_ENSURE_DECLARE(shaper, face) \ HB_SHAPER_DATA_ENSURE_DECLARE(shaper, font) @@ -42,6 +48,11 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan, unsigned int num_user_features, const char * const *shaper_list) { + DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, + "num_features=%d shaper_list=%p", + num_user_features, + shaper_list); + const hb_shaper_pair_t *shapers = _hb_shapers_get (); #define HB_SHAPER_PLAN(shaper) \ @@ -104,6 +115,12 @@ hb_shape_plan_create (hb_face_t *face, unsigned int num_user_features, const char * const *shaper_list) { + DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, + "face=%p num_features=%d shaper_list=%p", + face, + num_user_features, + shaper_list); + hb_shape_plan_t *shape_plan; hb_feature_t *features = NULL; @@ -271,6 +288,11 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, const hb_feature_t *features, unsigned int num_features) { + DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, + "num_features=%d shaper_func=%p", + num_features, + shape_plan->shaper_func); + if (unlikely (hb_object_is_inert (shape_plan) || hb_object_is_inert (font) || hb_object_is_inert (buffer))) @@ -383,6 +405,12 @@ hb_shape_plan_create_cached (hb_face_t *face, unsigned int num_user_features, const char * const *shaper_list) { + DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, + "face=%p num_features=%d shaper_list=%p", + face, + num_user_features, + shaper_list); + hb_shape_plan_proposal_t proposal = { *props, shaper_list, @@ -392,25 +420,22 @@ hb_shape_plan_create_cached (hb_face_t *face, }; if (shaper_list) { - /* Choose shaper. Adapted from hb_shape_plan_plan(). */ -#define HB_SHAPER_PLAN(shaper) \ - HB_STMT_START { \ - if (hb_##shaper##_shaper_face_data_ensure (face)) \ - proposal.shaper_func = _hb_##shaper##_shape; \ - } HB_STMT_END - + /* Choose shaper. Adapted from hb_shape_plan_plan(). + * Must choose shaper exactly the same way as that function. */ for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++) if (0) ; #define HB_SHAPER_IMPLEMENT(shaper) \ - else if (0 == strcmp (*shaper_item, #shaper)) \ - HB_SHAPER_PLAN (shaper); + else if (0 == strcmp (*shaper_item, #shaper) && \ + hb_##shaper##_shaper_face_data_ensure (face)) \ + { \ + proposal.shaper_func = _hb_##shaper##_shape; \ + break; \ + } #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT -#undef HB_SHAPER_PLAN - - if (unlikely (!proposal.shaper_list)) + if (unlikely (!proposal.shaper_func)) return hb_shape_plan_get_empty (); } @@ -419,7 +444,10 @@ hb_shape_plan_create_cached (hb_face_t *face, hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans); for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next) if (hb_shape_plan_matches (node->shape_plan, &proposal)) + { + DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache"); return hb_shape_plan_reference (node->shape_plan); + } /* Not found. */ @@ -442,6 +470,7 @@ hb_shape_plan_create_cached (hb_face_t *face, free (node); goto retry; } + DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, "inserted into cache"); return hb_shape_plan_reference (shape_plan); } diff --git a/gfx/harfbuzz/src/hb-shape.cc b/gfx/harfbuzz/src/hb-shape.cc index 812cf5919be9e..74747f88b89f7 100644 --- a/gfx/harfbuzz/src/hb-shape.cc +++ b/gfx/harfbuzz/src/hb-shape.cc @@ -320,7 +320,7 @@ hb_shape_list_shapers (void) goto retry; } -#ifdef HAVE_ATEXIT +#ifdef HB_USE_ATEXIT atexit (free_static_shaper_list); /* First person registers atexit() callback. */ #endif } diff --git a/gfx/harfbuzz/src/hb-shaper.cc b/gfx/harfbuzz/src/hb-shaper.cc index 44f718aa7023e..6ae260138211a 100644 --- a/gfx/harfbuzz/src/hb-shaper.cc +++ b/gfx/harfbuzz/src/hb-shaper.cc @@ -100,7 +100,7 @@ _hb_shapers_get (void) goto retry; } -#ifdef HAVE_ATEXIT +#ifdef HB_USE_ATEXIT atexit (free_static_shapers); /* First person registers atexit() callback. */ #endif } diff --git a/gfx/harfbuzz/src/hb-uniscribe.cc b/gfx/harfbuzz/src/hb-uniscribe.cc index 6bf87a5f45b27..e7bcad2ea86d2 100644 --- a/gfx/harfbuzz/src/hb-uniscribe.cc +++ b/gfx/harfbuzz/src/hb-uniscribe.cc @@ -43,6 +43,12 @@ #endif +static inline uint16_t hb_uint16_swap (const uint16_t v) +{ return (v >> 8) | (v << 8); } +static inline uint32_t hb_uint32_swap (const uint32_t v) +{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); } + + typedef HRESULT (WINAPI *SIOT) /*ScriptItemizeOpenType*/( const WCHAR *pwcInChars, int cInChars, @@ -245,7 +251,7 @@ hb_uniscribe_shaper_get_funcs (void) goto retry; } -#ifdef HAVE_ATEXIT +#ifdef HB_USE_ATEXIT atexit (free_uniscribe_funcs); /* First person registers atexit() callback. */ #endif } @@ -903,8 +909,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, FAIL ("ScriptShapeOpenType() set fNoGlyphIndex"); if (unlikely (hr == E_OUTOFMEMORY)) { - buffer->ensure (buffer->allocated * 2); - if (buffer->in_error) + if (unlikely (!buffer->ensure (buffer->allocated * 2))) FAIL ("Buffer resize failed"); goto retry; } @@ -973,8 +978,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, #undef utf16_index - buffer->ensure (glyphs_len); - if (buffer->in_error) + if (unlikely (!buffer->ensure (glyphs_len))) FAIL ("Buffer in error"); #undef FAIL diff --git a/gfx/harfbuzz/src/hb-version.h b/gfx/harfbuzz/src/hb-version.h index 86bc1c7c80592..896b065162fb1 100644 --- a/gfx/harfbuzz/src/hb-version.h +++ b/gfx/harfbuzz/src/hb-version.h @@ -38,9 +38,9 @@ HB_BEGIN_DECLS #define HB_VERSION_MAJOR 0 #define HB_VERSION_MINOR 9 -#define HB_VERSION_MICRO 34 +#define HB_VERSION_MICRO 37 -#define HB_VERSION_STRING "0.9.34" +#define HB_VERSION_STRING "0.9.37" #define HB_VERSION_ATLEAST(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) <= \