diff --git a/gfx/harfbuzz/Makefile.am b/gfx/harfbuzz/Makefile.am index 8b69c2d78..1d8f2e7c7 100644 --- a/gfx/harfbuzz/Makefile.am +++ b/gfx/harfbuzz/Makefile.am @@ -2,32 +2,27 @@ NULL = -SUBDIRS = src util test +ACLOCAL_AMFLAGS = -I m4 -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = harfbuzz.pc +SUBDIRS = src util test docs win32 EXTRA_DIST = \ autogen.sh \ harfbuzz.doap \ + README.python \ + BUILD.md \ + CMakeLists.txt \ $(NULL) MAINTAINERCLEANFILES = \ + $(GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL) \ + $(GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL) \ + $(GITIGNORE_MAINTAINERCLEANFILES_MAKEFILE_IN) \ $(srcdir)/INSTALL \ - $(srcdir)/aclocal.m4 \ - $(srcdir)/autoscan.log \ - $(srcdir)/compile \ - $(srcdir)/config.guess \ - $(srcdir)/config.h.in \ - $(srcdir)/config.sub \ - $(srcdir)/configure.scan \ - $(srcdir)/depcomp \ - $(srcdir)/install-sh \ - $(srcdir)/ltmain.sh \ - $(srcdir)/missing \ - $(srcdir)/mkinstalldirs \ $(srcdir)/ChangeLog \ - `find "$(srcdir)" -type f -name Makefile.in -print` + $(srcdir)/gtk-doc.make \ + $(srcdir)/m4/gtk-doc.m4 \ + $(NULL) # @@ -36,28 +31,37 @@ MAINTAINERCLEANFILES = \ CHANGELOG_RANGE = ChangeLog: $(srcdir)/ChangeLog $(srcdir)/ChangeLog: - $(AM_V_GEN) if test -d "$(srcdir)/.git"; then \ - (GIT_DIR=$(top_srcdir)/.git ./missing --run \ - git log $(CHANGELOG_RANGE) --stat) | fmt --split-only > $@.tmp \ - && mv -f $@.tmp $@ \ + $(AM_V_GEN) if test -d "$(top_srcdir)/.git"; then \ + (GIT_DIR=$(top_srcdir)/.git \ + $(GIT) log $(CHANGELOG_RANGE) --stat) | fmt --split-only > $@.tmp \ + && mv -f $@.tmp "$(srcdir)/ChangeLog" \ || ($(RM) $@.tmp; \ echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \ - (test -f $@ || echo git-log is required to generate this file >> $@)); \ + (test -f $@ || echo git-log is required to generate this file >> "$(srcdir)/$@")); \ else \ test -f $@ || \ (echo A git checkout and git-log is required to generate ChangeLog >&2 && \ - echo A git checkout and git-log is required to generate this file >> $@); \ + echo A git checkout and git-log is required to generate this file >> "$(srcdir)/$@"); \ fi -.PHONY: $(srcdir)/ChangeLog +.PHONY: ChangeLog $(srcdir)/ChangeLog # # Release engineering # +DISTCHECK_CONFIGURE_FLAGS = \ + --enable-gtk-doc \ + --disable-doc-cross-references \ + --with-gobject \ + --enable-introspection \ + $(NULL) + # TODO: Copy infrastructure from cairo +# TAR_OPTIONS is not set as env var for 'make dist'. How to fix that? TAR_OPTIONS = --owner=0 --group=0 + dist-hook: dist-clear-sticky-bits # Clean up any sticky bits we may inherit from parent dir dist-clear-sticky-bits: diff --git a/gfx/harfbuzz/NEWS b/gfx/harfbuzz/NEWS new file mode 100644 index 000000000..92e5a5370 --- /dev/null +++ b/gfx/harfbuzz/NEWS @@ -0,0 +1,1694 @@ +Overview of changes leading to 1.5.1 +Tuesday, September 5, 2017 +==================================== + +- Fix "unsafe-to-break" in fallback shaping and other corner cases. + All our tests pass with --verify now, meaning unsafe-to-break API + works as expected. +- Add --unicodes to hb-view / hb-shape. +- [indic] Treat Consonant_With_Stacker as consonant. This will need + further tweaking. +- hb_buffer_diff() tweaks. + + +Overview of changes leading to 1.5.0 +Wednesday, August 23, 2017 +==================================== + +- Misc new API, for appending a buffer to another, and for comparing + contents of two buffers for types of differences. + +- New "unsafe-to-break" API. Can be used to speed up reshaping + in line-breaking situations. Essentially, after shaping, it returns + positions in the input string (some of the cluster boundaries) that + are "safe to break" in that if the text is segmented at that position + and two sides reshaped and concatenated, the shaping result is + exactly the same as shaping the text in one piece. + + hb-view and hb-shape and hb-shape now take --verify, which verifies + the above property. + + Some corner cases of the implementation are still not quite working. + Those will be fixed in subsequent releases. + +- New API: + +hb_buffer_append() + +hb_glyph_flags_t +HB_GLYPH_FLAG_UNSAFE_TO_BREAK +HB_GLYPH_FLAG_DEFINED +hb_glyph_info_get_glyph_flags() + +HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS + +hb_buffer_diff_flags_t +HB_BUFFER_DIFF_FLAG_EQUAL +HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH +HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH +HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT +HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT +HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH +HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH +HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH +HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH +hb_buffer_diff + + +Overview of changes leading to 1.4.8 +Tuesday, August 8, 2017 +==================================== + +- Major fix to avar table handling. +- Rename hb-shape --show-message to --trace. +- Build fixes. + + +Overview of changes leading to 1.4.7 +Tuesday, July 18, 2017 +==================================== + +- Multiple Indic, Tibetan, and Cham fixes. +- CoreText: Allow disabling kerning. +- Adjust Arabic feature order again. +- Misc build fixes. + + +Overview of changes leading to 1.4.6 +Sunday, April 23, 2017 +==================================== + +- Graphite2: Fix RTL positioning issue. +- Backlist GDEF of more versions of Padauk and Tahoma. +- New, experimental, cmake alternative build system. + + +Overview of changes leading to 1.4.5 +Friday, March 10, 2017 +==================================== + +- Revert "Fix Context lookup application when moving back after a glyph..." + This introduced memory access problems. To be fixed properly soon. + + +Overview of changes leading to 1.4.4 +Sunday, March 5, 2017 +==================================== + +- Fix Context lookup application when moving back after a glyph deletion. +- Fix buffer-overrun in Bengali. + + +Overview of changes leading to 1.4.3 +Saturday, February 25, 2017 +==================================== + +- Route Adlam script to Arabic shaper. +- Misc fixes. +- New API: + hb_font_set_face() +- Deprecate API: + hb_graphite2_font_get_gr_font() + + +Overview of changes leading to 1.4.2 +Monday, January 23, 2017 +==================================== + +- Implement OpenType Font Variation tables avar/fvar/HVAR/VVAR. +- hb-shape and hb-view now accept --variations. +- New API: + +hb_variation_t +hb_variation_from_string() +hb_variation_to_string() + +hb_font_set_variations() +hb_font_set_var_coords_design() +hb_font_get_var_coords_normalized() + +hb-ot-var.h: +hb_ot_var_axis_t +hb_ot_var_has_data() +hb_ot_var_get_axis_count() +hb_ot_var_get_axes() +hb_ot_var_find_axis() +hb_ot_var_normalize_variations() +hb_ot_var_normalize_coords() + +- MVAR to be implemented later. Access to named instances to be + implemented later as well. + +- Misc fixes. + + +Overview of changes leading to 1.4.1 +Thursday, January 5, 2017 +==================================== + +- Always build and use UCDN for Unicode data by default. + Reduces dependence on version of Unicode data in glib, + specially in the Windows bundles we are shipping, which + have very old glib. + + +Overview of changes leading to 1.4.0 +Thursday, January 5, 2017 +==================================== + +- Merged "OpenType GX" branch which adds core of support for + OpenType 1.8 Font Variations. To that extent, the relevant + new API is: + +New API: +hb_font_set_var_coords_normalized() + + with supporting API: + +New API: +HB_OT_LAYOUT_NO_VARIATIONS_INDEX +hb_ot_layout_table_find_feature_variations() +hb_ot_layout_feature_with_variations_get_lookups() +hb_shape_plan_create2() +hb_shape_plan_create_cached2() + + Currently variations in GSUB/GPOS/GDEF are fully supported, + and no other tables are supported. In particular, fvar/avar + are NOT supported, hence the hb_font_set_var_coords_normalized() + taking normalized coordinates. API to take design coordinates + will be added in the future. + + HVAR/VVAR/MVAR support will also be added to hb-ot-font in the + future. + +- Fix regression in GDEF glyph class processing. +- Add decompositions for Chakma, Limbu, and Balinese in USE shaper. +- Misc fixes. + + +Overview of changes leading to 1.3.4 +Monday, December 5, 2016 +==================================== + +- Fix vertical glyph origin in hb-ot-font. +- Implement CBDT/CBLC color font glyph extents in hb-ot-font. + + +Overview of changes leading to 1.3.3 +Wednesday, September 28, 2016 +==================================== + +- Implement parsing of OpenType MATH table. +New API: +HB_OT_TAG_MATH +HB_OT_MATH_SCRIPT +hb_ot_math_constant_t +hb_ot_math_kern_t +hb_ot_math_glyph_variant_t +hb_ot_math_glyph_part_flags_t +hb_ot_math_glyph_part_t +hb_ot_math_has_data +hb_ot_math_get_constant +hb_ot_math_get_glyph_italics_correction +hb_ot_math_get_glyph_top_accent_attachment +hb_ot_math_get_glyph_kerning +hb_ot_math_is_glyph_extended_shape +hb_ot_math_get_glyph_variants +hb_ot_math_get_min_connector_overlap +hb_ot_math_get_glyph_assembly + + +Overview of changes leading to 1.3.2 +Wednesday, September 27, 2016 +==================================== + +- Fix build of hb-coretext on older OS X versions. + + +Overview of changes leading to 1.3.1 +Wednesday, September 7, 2016 +==================================== + +- Blacklist bad GDEF of more fonts (Padauk). +- More CoreText backend crash fixes with OS X 10.9.5. +- Misc fixes. + + +Overview of changes leading to 1.3.0 +Thursday, July 21, 2016 +==================================== + +- Update to Unicode 9.0.0 +- Move Javanese from Indic shaper to Universal Shaping Engine. +- Allow MultipleSubst to delete a glyph (matching Windows engine). +- Update Universal Shaping Engine to latest draft from Microsoft. +- DirectWrite backend improvements. Note: this backend is for testing ONLY. +- CoreText backend improvements with unreachable fonts. +- Implement symbol fonts (cmap 3.0.0) in hb-ft and hb-ot-font. +- Blacklist bad GDEF of more fonts (Tahoma & others). +- Misc fixes. + + +Overview of changes leading to 1.2.7 +Monday, May 2, 2016 +==================================== + +- Blacklist another version of Times New Roman (Bold) Italic from Windows 7. +- Fix Mongolian Free Variation Selectors shaping with certain fonts. +- Fix Tibetan shorthand contractions shaping. +- Improved list of language tag mappings. +- Unbreak build on Windows CE. +- Make 'glyf' table loading lazy in hb-ot-font. + + +Overview of changes leading to 1.2.6 +Friday, April 8, 2016 +==================================== + +- Blacklist GDEF table of another set of Times New Roman (Bold) Italic. +- DirectWrite backend improvements. Note: DirectWrite backend is + exclusively for our internal testing and should NOT be used in any + production system whatsoever. + + +Overview of changes leading to 1.2.5 +Monday, April 4, 2016 +==================================== + +- Fix GDEF mark-filtering-set, which was broken in 1.2.3. + + +Overview of changes leading to 1.2.4 +Thursday, March 17, 2016 +==================================== + +- Synthesize GDEF glyph class for any glyph that does not have one in GDEF. + I really hope we don't discover broken fonts that shape badly with this + change. +- Misc build and other minor fixes. +- API changes: + - Added HB_NDEBUG. It's fine for production systems to define this to + disable high-overhead debugging checks. However, I also reduced the + overhead of those checks, so it's a non-issue right now. You can + forget it. Just not defining anything at all is fine. + + +Overview of changes leading to 1.2.3 +Thursday, February 25, 2016 +==================================== + +- Blacklist GDEF table of certain versions of Times New Roman (Bold) Italic, + due to bug in glyph class of ASCII double-quote character. This should + address "regression" introduced in 1.2.0 when we switched mark zeroing + in most shapers from BY_UNICODE_LATE to BY_GDEF_LATE. + This fourth release in a week should finally stablize things... + +- hb-ot-font's get_glyph() implementation saw some optimizations. Though, + might be really hard to measure in real-world situations. + +- Also, two rather small API changes: + +We now disable some time-consuming internal bookkeeping if built with NDEBUG +defined. This is a first time that we use NDEBUG to disable debug code. If +there exist production systems that do NOT want to enable NDEBUG, please let +me know and I'll add HB_NDEBUG. + +Added get_nominal_glyph() and get_variation_glyph() instead of get_glyph() + +New API: +- hb_font_get_nominal_glyph_func_t +- hb_font_get_variation_glyph_func_t +- hb_font_funcs_set_nominal_glyph_func() +- hb_font_funcs_set_variation_glyph_func() +- hb_font_get_nominal_glyph() +- hb_font_get_variation_glyph() + +Deprecated API: +- hb_font_get_glyph_func_t +- hb_font_funcs_set_glyph_func() + +Clients that implement their own font-funcs are encouraged to replace +their get_glyph() implementation with a get_nominal_glyph() and +get_variation_glyph() pair. The variation version can assume that +variation_selector argument is not zero. Old (deprecated) functions +will continue working indefinitely using internal gymnastics; it is +just more efficient to use the new functions. + + +Overview of changes leading to 1.2.2 +Wednesday, February 24, 2016 +==================================== + +- Fix regression with mark positioning with fonts that have + non-zero mark advances. This was introduced in 1.2.0 while + trying to make mark and cursive attachments to work together. + I have partially reverted that, so this version is much more + like what we had before. All clients who updated to 1.2.0 + should update to this version. + + +Overview of changes leading to 1.2.1 +Tuesday, February 23, 2016 +==================================== + +- CoreText: Fix bug with wrong scale if font scale was changed later. + https://github.com/libass/libass/issues/212 +- CoreText: Drastically speed up font initialization. +- CoreText: Fix tiny leak. +- Group ZWJ/ZWNJ with previous syllable under cluster-level=0. + https://github.com/behdad/harfbuzz/issues/217 +- Add test/shaping/README.md about how to add tests to the suite. + + +Overview of changes leading to 1.2.0 +Friday, February 19, 2016 +==================================== + +- Fix various issues (hangs mostly) in case of memory allocation failure. +- Change mark zeroing types of most shapers from BY_UNICODE_LATE to + BY_GDEF_LATE. This seems to be what Uniscribe does. +- Change mark zeroing of USE shaper from NONE to BY_GDEF_EARLY. That's + what Windows does. +- Allow GPOS cursive connection on marks, and fix the interaction with + mark attachment. This work resulted in some changes to how mark + attachments work. See: + https://github.com/behdad/harfbuzz/issues/211 + https://github.com/behdad/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2 +- Graphite2 shaper: improved negative advance handling (eg. Nastaliq). +- Add nmake-based build system for Windows. +- Minor speedup. +- Misc. improvements. + + +Overview of changes leading to 1.1.3 +Monday, January 11, 2016 +==================================== + +- Ported Indic shaper to Unicode 8.0 data. +- Universal Shaping Engine fixes. +- Speed up CoreText shaper when font fallback happens in CoreText. +- Documentation improvements, thanks to Khaled Hosny. +- Very rough directwrite shaper for testing, thanks to Ebrahim Byagowi. +- Misc bug fixes. +- New API: + + * Font extents: + hb_font_extents_t + hb_font_get_font_extents_func_t + hb_font_get_font_h_extents_func_t + hb_font_get_font_v_extents_func_t + hb_font_funcs_set_font_h_extents_func + hb_font_funcs_set_font_v_extents_func + hb_font_get_h_extents + hb_font_get_v_extents + hb_font_get_extents_for_direction + + * Buffer message (aka debug): + hb_buffer_message_func_t + hb_buffer_set_message_func() + Actual message protocol to be fleshed out later. + + +Overview of changes leading to 1.1.2 +Wednesday, November 26, 2015 +==================================== + +- Fix badly-broken fallback shaper that affected terminology. + https://github.com/behdad/harfbuzz/issues/187 +- Fix y_scaling in Graphite shaper. +- API changes: + * An unset glyph_h_origin() function in font-funcs now (sensibly) + implies horizontal origin at 0,0. Ie, the nil callback returns + true instead of false. As such, implementations that have a + glyph_h_origin() that simply returns true, can remove that function + with HarfBuzz >= 1.1.2. This results in a tiny speedup. + + +Overview of changes leading to 1.1.1 +Wednesday, November 24, 2015 +==================================== + +- Build fixes, specially for hb-coretext. + + +Overview of changes leading to 1.1.0 +Wednesday, November 18, 2015 +==================================== + +- Implement 'stch' stretch feature for Syriac Abbreviation Mark. + https://github.com/behdad/harfbuzz/issues/141 +- Disable use of decompose_compatibility() callback. +- Implement "shaping" of various Unicode space characters, even + if the font does not support them. + https://github.com/behdad/harfbuzz/issues/153 +- If font does not support U+2011 NO-BREAK HYPHEN, fallback to + U+2010 HYPHEN. +- Changes resulting from libFuzzer continuous fuzzing: + * Reject font tables that need more than 8 edits, + * Bound buffer growth during shaping to 32x, + * Fix assertions and other issues at OOM / buffer max-growth. +- Misc fixes and optimizations. +- API changes: + * All fonts created with hb_font_create() now inherit from + (ie. have parent) hb_font_get_empty(). + + +Overview of changes leading to 1.0.6 +Thursday, October 15, 2015 +==================================== + +- Reduce max nesting level in OT lookups from 8 to 6. + Should not affect any real font as far as I know. +- Fix memory access issue in ot-font. +- Revert default load-flags of fonts created using hb_ft_font_create() + back to FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING. This was changed in + last release (1.0.5), but caused major issues, so revert. + https://github.com/behdad/harfbuzz/issues/143 + + +Overview of changes leading to 1.0.5 +Tuesday, October 13, 2015 +==================================== + +- Fix multiple memory access bugs discovered using libFuzzer. + https://github.com/behdad/harfbuzz/issues/139 + Everyone should upgrade to this version as soon as possible. + We now have continuous fuzzing set up, to avoid issues like + these creeping in again. +- Misc fixes. + +- New API: + * hb_font_set_parent(). + * hb_ft_font_[sg]et_load_flags() + The default flags for fonts created using hb_ft_font_create() + has changed to default to FT_LOAD_DEFAULT now. Previously it + was defaulting to FT_LOAD_DFEAULT|FT_LOAD_NO_HINTING. + +- API changes: + * Fonts now default to units-per-EM as their scale, instead of 0. + * hb_font_create_sub_font() does NOT make parent font immutable + anymore. hb_font_make_immutable() does. + + +Overview of changes leading to 1.0.4 +Wednesday, September 30, 2015 +==================================== + +- Fix minor out-of-bounds read error. + + +Overview of changes leading to 1.0.3 +Tuesday, September 1, 2015 +==================================== + +- Start of user documentation, from Simon Cozens! +- Implement glyph_extents() for TrueType fonts in hb-ot-font. +- Improve GPOS cursive attachments with conflicting lookups. +- More fixes for cluster-level = 1. +- Uniscribe positioning fix. + + +Overview of changes leading to 1.0.2 +Wednesday, August 19, 2015 +==================================== + +- Fix shaping with cluster-level > 0. +- Fix Uniscribe backend font-size scaling. +- Declare dependencies in harfbuzz.pc. + FreeType is not declared though, to avoid bugs in pkg-config + 0.26 with recursive dependencies. +- Slightly improved debug infrastructure. More to come later. +- Misc build fixes. + + +Overview of changes leading to 1.0.1 +Monday, July 27, 2015 +==================================== + +- Fix out-of-bounds access in USE shaper. + + +Overview of changes leading to 1.0.0 +Sunday, July 26, 2015 +==================================== + +- Implement Universal Shaping Engine: + https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm + http://blogs.windows.com/bloggingwindows/2015/02/23/windows-shapes-the-worlds-languages/ +- Bump version to 1.0.0. The soname was NOT bumped. + + +Overview of changes leading to 0.9.42 +Thursday, July 26, 2015 +===================================== + +- New API to allow for retrieving finer-grained cluster + mappings if the client desires to handle them. Default + behavior is unchanged. +- Fix cluster merging when removing default-ignorables. +- Update to Unicode 8.0 +- hb-graphite2 fixes. +- Misc fixes. +- Removed HB_NO_MERGE_CLUSTERS hack. +- New API: + hb_buffer_cluster_level_t enum + hb_buffer_get_cluster_level() + hb_buffer_set_cluster_level() + hb-shape / hb-view --cluster-level + + +Overview of changes leading to 0.9.41 +Thursday, June 18, 2015 +===================================== + +- Fix hb-coretext with trailing whitespace in right-to-left. +- New API: hb_buffer_reverse_range(). +- Allow implementing atomic ops in config.h. +- Fix hb_language_t in language bindings. +- Misc fixes. + + +Overview of changes leading to 0.9.40 +Friday, March 20, 2015 +===================================== + +- Another hb-coretext crasher fix. Ouch! +- Happy Norouz! + + +Overview of changes leading to 0.9.39 +Wednesday, March 4, 2015 +===================================== + +- Critical hb-coretext fixes. +- Optimizations and refactoring; no functional change + expected. +- Misc build fixes. + + +Overview of changes leading to 0.9.38 +Friday, January 23, 2015 +===================================== + +- Fix minor out-of-bounds access in Indic shaper. +- Change New Tai Lue shaping engine from South-East Asian to default, + reflecting change in Unicode encoding model. +- Add hb-shape --font-size. Can take up to two numbers for separate + x / y size. +- Fix CoreText and FreeType scale issues with negative scales. +- Reject blobs larger than 2GB. This might break some icu-le-hb clients + that need security fixes. See: + http://www.icu-project.org/trac/ticket/11450 +- Avoid accessing font tables during face destruction, in casce rogue + clients released face data already. +- Fix up gobject-introspection a bit. Python bindings kinda working. + See README.python. +- Misc fixes. +- API additions: + hb_ft_face_create_referenced() + hb_ft_font_create_referenced() + + +Overview of changes leading to 0.9.37 +Wednesday, December 17, 2014 +===================================== + +- Fix out-of-bounds access in Context lookup format 3. +- Indic: Allow ZWJ/ZWNJ before syllable modifiers. + + +Overview of changes leading to 0.9.36 +Thursday, November 20, 2014 +===================================== + +- First time that three months went by without a release since + 0.9.2 was released on August 10, 2012! +- Fix performance bug in hb_ot_collect_glyphs(): + https://bugzilla.mozilla.org/show_bug.cgi?id=1090869 +- Add basic vertical-text support to hb-ot-font. +- Misc build fixes. + + +Overview of changes leading to 0.9.35 +Saturday, August 13, 2014 +===================================== + +- Fix major shape-plan caching bug when more than one shaper were + provided to hb_shape_full() (as exercised by XeTeX). + http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg1246370.html +- Fix Arabic fallback shaping regression. This was broken in 0.9.32. +- Major hb-coretext fixes. That backend is complete now, including + respecing buffer direction and language, down to vertical writing. +- Build fixes for Windows CE. Should build fine now. +- Misc fixes: + Use atexit() only if it's safe to call from shared library + https://bugs.freedesktop.org/show_bug.cgi?id=82246 + Mandaic had errors in its Unicode Joining_Type + https://bugs.freedesktop.org/show_bug.cgi?id=82306 +- API changes: + + * hb_buffer_clear_contents() does not reset buffer flags now. + + After 763e5466c0a03a7c27020e1e2598e488612529a7, one doesn't + need to set flags for different pieces of text. The flags now + are something the client sets up once, depending on how it + actually uses the buffer. As such, don't clear it in + clear_contents(). + + I don't expect any changes to be needed to any existing client. + + +Overview of changes leading to 0.9.34 +Saturday, August 2, 2014 +===================================== + +- hb_feature_from_string() now accepts CSS font-feature-settings format. +- As a result, hb-shape / hb-view --features also accept CSS-style strings. + Eg, "'liga' off" is accepted now. +- Add old-spec Myanmar shaper: + https://bugs.freedesktop.org/show_bug.cgi?id=81775 +- Don't apply 'calt' in Hangul shaper. +- Fix mark advance zeroing for Hebrew shaper: + https://bugs.freedesktop.org/show_bug.cgi?id=76767 +- Implement Windows-1256 custom Arabic shaping. Only built on Windows, + and requires help from get_glyph(). Used by Firefox. + https://bugzilla.mozilla.org/show_bug.cgi?id=1045139 +- Disable 'liga' in vertical text. +- Build fixes. +- API changes: + + * Make HB_BUFFER_FLAG_BOT/EOT easier to use. + + Previously, we expected users to provide BOT/EOT flags when the + text *segment* was at paragraph boundaries. This meant that for + clients that provide full paragraph to HarfBuzz (eg. Pango), they + had code like this: + + hb_buffer_set_flags (hb_buffer, + (item_offset == 0 ? HB_BUFFER_FLAG_BOT : 0) | + (item_offset + item_length == paragraph_length ? + HB_BUFFER_FLAG_EOT : 0)); + + hb_buffer_add_utf8 (hb_buffer, + paragraph_text, paragraph_length, + item_offset, item_length); + + After this change such clients can simply say: + + hb_buffer_set_flags (hb_buffer, + HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT); + + hb_buffer_add_utf8 (hb_buffer, + paragraph_text, paragraph_length, + item_offset, item_length); + + Ie, HarfBuzz itself checks whether the segment is at the beginning/end + of the paragraph. Clients that only pass item-at-a-time to HarfBuzz + continue not setting any flags whatsoever. + + Another way to put it is: if there's pre-context text in the buffer, + HarfBuzz ignores the BOT flag. If there's post-context, it ignores + EOT flag. + + +Overview of changes leading to 0.9.33 +Tuesday, July 22, 2014 +===================================== + +- Turn off ARabic 'cswh' feature that was accidentally turned on. +- Add HB_TAG_MAX_SIGNED. +- Make hb_face_make_immutable() really make face immutable! +- Windows build fixes. + + +Overview of changes leading to 0.9.32 +Thursday, July 17, 2014 +===================================== + +- Apply Arabic shaping features in spec order exactly. +- Another fix for Mongolian free variation selectors. +- For non-Arabic scripts in Arabic shaper apply 'rlig' and 'calt' + together. +- Minor adjustment to U+FFFD logic. +- Fix hb-coretext build. + + +Overview of changes leading to 0.9.31 +Wednesday, July 16, 2014 +===================================== + +- Only accept valid UTF-8/16/32; we missed many cases before. +- Better shaping of invalid UTF-8/16/32. Falls back to + U+FFFD REPLACEMENT CHARACTER now. +- With all changes in this release, the buffer will contain fully + valid Unicode after hb_buffer_add_utf8/16/32 no matter how + broken the input is. This can be overriden though. See below. +- Fix Mongolian Variation Selectors for fonts without GDEF. +- Fix minor invalid buffer access. +- Accept zh-Hant and zh-Hans language tags. hb_ot_tag_to_language() + now uses these instead of private tags. +- Build fixes. +- New API: + * hb_buffer_add_codepoints(). This does what hb_buffer_add_utf32() + used to do, ie. no validity check on the input at all. add_utf32 + now replaces invalid Unicode codepoints with the replacement + character (see below). + * hb_buffer_set_replacement_codepoint() + * hb_buffer_get_replacement_codepoint() + Previously, in hb_buffer_add_utf8 and hb_buffer_add_utf16, when + we detected broken input, we replaced that with (hb_codepoint_t)-1. + This has changed to use U+FFFD now, but can be changed using these + new API. + + +Overview of changes leading to 0.9.30 +Wednesday, July 9, 2014 +===================================== + +- Update to Unicode 7.0.0: + * New scripts Manichaean and Psalter Pahlavi are shaped using + Arabic shaper. + * All the other new scripts to through the generic shaper for + now. +- Minor Indic improvements. +- Fix graphite2 backend cluster mapping [crasher!] +- API changes: + * New HB_SCRIPT_* values for Unicode 7.0 scripts. + * New function hb_ot_layout_language_get_required_feature(). +- Build fixes. + + +Overview of changes leading to 0.9.29 +Thursday, May 29, 2014 +===================================== + +- Implement cmap in hb-ot-font.h. No variation-selectors yet. +- Myanmar: Allow MedialYa+Asat. +- Various Indic fixes: + * Support most characters in Extended Devanagary and Vedic + Unicode blocks. + * Allow digits and a some punctuation as consonant placeholders. +- Build fixes. + + +Overview of changes leading to 0.9.28 +Monday, April 28, 2014 +===================================== + +- Unbreak old-spec Indic shaping. (bug 76705) +- Fix shaping of U+17DD and U+0FC6. +- Add HB_NO_MERGE_CLUSTERS build option. NOT to be enabled by default + for shipping libraries. It's an option for further experimentation + right now. When we are sure how to do it properly, we will add + public run-time API for the functionality. +- Build fixes. + + +Overview of changes leading to 0.9.27 +Tuesday, March 18, 2014 +===================================== + +- Don't use "register" storage class specifier +- Wrap definition of free_langs() with HAVE_ATEXIT +- Add coretext_aat shaper and hb_coretext_face_create() constructor +- If HAVE_ICU_BUILTIN is defined, use hb-icu Unicode callbacks +- Add Myanmar test case from OpenType Myanmar spec +- Only do fallback Hebrew composition if no GPOS 'mark' available +- Allow bootstrapping without gtk-doc +- Use AM_MISSING_PROG for ragel and git +- Typo in ucdn's Makefile.am +- Improve MemoryBarrier() implementation + + +Overview of changes leading to 0.9.26 +Thursday, January 30, 2014 +===================================== + +- Misc fixes. +- Fix application of 'rtlm' feature. +- Automatically apply frac/numr/dnom around U+2044 FRACTION SLASH. +- New header: hb-ot-shape.h +- Uniscribe: fix scratch-buffer accounting. +- Reorder Tai Tham SAKOT to after tone-marks. +- Add Hangul shaper. +- New files: + hb-ot-shape-complex-hangul.cc + hb-ot-shape-complex-hebrew.cc + hb-ot-shape-complex-tibetan.cc +- Disable 'cswh' feature in Arabic shaper. +- Coretext: better handle surrogate pairs. +- Add HB_TAG_MAX and _HB_SCRIPT_MAX_VALUE. + + +Overview of changes leading to 0.9.25 +Wednesday, December 4, 2013 +===================================== + +- Myanmar shaper improvements. +- Avoid font fallback in CoreText backend. +- Additional OpenType language tag mappiongs. +- More aggressive shape-plan caching. +- Build with / require automake 1.13. +- Build with libtool 2.4.2.418 alpha to support ppc64le. + + +Overview of changes leading to 0.9.24 +Tuesday, November 13, 2013 +===================================== + +- Misc compiler warning fixes with clang. +- No functional changes. + + +Overview of changes leading to 0.9.23 +Monday, October 28, 2013 +===================================== + +- "Udupi HarfBuzz Hackfest", Paris, October 14..18 2013. +- Fix (Chain)Context recursion with non-monotone lookup positions. +- Misc Indic bug fixes. +- New Javanese / Buginese shaping, similar to Windows 8.1. + + +Overview of changes leading to 0.9.22 +Thursday, October 3, 2013 +===================================== + +- Fix use-after-end-of-scope in hb_language_from_string(). +- Fix hiding of default_ignorables if font doesn't have space glyph. +- Protect against out-of-range lookup indices. + +- API Changes: + + * Added hb_ot_layout_table_get_lookup_count() + + +Overview of changes leading to 0.9.21 +Monday, September 16, 2013 +===================================== + +- Rename gobject-introspection library name from harfbuzz to HarfBuzz. +- Remove (long disabled) hb-old and hb-icu-le test shapers. +- Misc gtk-doc and gobject-introspection annotations. +- Misc fixes. +- API changes: + + * Add HB_SET_VALUE_INVALID + +Overview of changes leading to 0.9.20 +Thursday, August 29, 2013 +===================================== + +General: +- Misc substitute_closure() fixes. +- Build fixes. + +Documentation: +- gtk-doc boilerplate integrated. Docs are built now, but + contain no contents. By next release hopefully we have + some content in. Enable using --enable-gtk-doc. + +GObject and Introspection: +- Added harfbuzz-gobject library (hb-gobject.h) that has type + bindings for all HarfBuzz objects and enums. Enable using + --with-gobject. +- Added gobject-introspection boilerplate. Nothing useful + right now. Work in progress. Gets enabled automatically if + --with-gobject is used. Override with --disable-introspection. + +OpenType shaper: +- Apply 'mark' in Myanmar shaper. +- Don't apply 'dlig' by default. + +Uniscribe shaper: +- Support user features. +- Fix loading of fonts that are also installed on the system. +- Fix shaping of Arabic Presentation Forms. +- Fix build with wide chars. + +CoreText shaper: +- Support user features. + +Source changes: +- hb_face_t code moved to hb-face.h / hb-face.cc. +- Added hb-deprecated.h. + +API changes: +- Added HB_DISABLE_DEPRECATED. +- Deprecated HB_SCRIPT_CANADIAN_ABORIGINAL; replaced by + HB_SCRIPT_CANADIAN_SYLLABICS. +- Deprecated HB_BUFFER_FLAGS_DEFAULT; replaced by + HB_BUFFER_FLAG_DEFAULT. +- Deprecated HB_BUFFER_SERIALIZE_FLAGS_DEFAULT; replaced by + HB_BUFFER_SERIALIZE_FLAG_DEFAULT. + + +Overview of changes leading to 0.9.19 +Tuesday, July 16, 2013 +===================================== + +- Build fixes. +- Better handling of multiple variation selectors in a row. +- Pass on variation selector to GSUB if not consumed by cmap. +- Fix undefined memory access. +- Add Javanese config to Indic shaper. +- Misc bug fixes. + +Overview of changes leading to 0.9.18 +Tuesday, May 28, 2013 +===================================== + +New build system: + +- All unneeded code is all disabled by default, + +- Uniscribe and CoreText shapers can be enabled with their --with options, + +- icu_le and old shapers cannot be enabled for now, + +- glib, freetype, and cairo will be detected automatically. + They can be force on/off'ed with their --with options, + +- icu and graphite2 are default off, can be enabled with their --with + options, + +Moreover, ICU support is now build into a separate library: +libharfbuzz-icu.so, and a new harfbuzz-icu.pc is shipped for it. +Distros can enable ICU now without every application on earth +getting linked to via libharfbuzz.so. + +For distros I recommend that they make sure they are building --with-glib +--with-freetype --with-cairo, --with-icu, and optionally --with-graphite2; +And package harfbuzz and harfbuzz-icu separately. + + +Overview of changes leading to 0.9.17 +Monday, May 20, 2013 +===================================== + +- Build fixes. +- Fix bug in hb_set_get_min(). +- Fix regression with Arabic mark positioning / width-zeroing. + +Overview of changes leading to 0.9.16 +Friday, April 19, 2013 +===================================== + +- Major speedup in OpenType lookup processing. With the Amiri + Arabic font, this release is over 3x faster than previous + release. All scripts / languages should see this speedup. + +- New --num-iterations option for hb-shape / hb-view; useful for + profiling. + +Overview of changes leading to 0.9.15 +Friday, April 05, 2013 +===================================== + +- Build fixes. +- Fix crasher in graphite2 shaper. +- Fix Arabic mark width zeroing regression. +- Don't compose Hangul jamo into Unicode syllables. + + +Overview of changes leading to 0.9.14 +Thursday, March 21, 2013 +===================================== + +- Build fixes. +- Fix time-consuming sanitize with malicious fonts. +- Implement hb_buffer_deserialize_glyphs() for both json and text. +- Do not ignore Hangul filler characters. +- Indic fixes: + * Fix Malayalam pre-base reordering interaction with post-forms. + * Further adjust ZWJ handling. Should fix known regressions from + 0.9.13. + + +Overview of changes leading to 0.9.13 +Thursday, February 25, 2013 +===================================== + +- Build fixes. +- Ngapi HarfBuzz Hackfest in London (February 2013): + * Fixed all known Indic bugs, + * New Win8-style Myanmar shaper, + * New South-East Asian shaper for Tai Tham, Cham, and New Tai Lue, + * Smartly ignore Default_Ignorable characters (joiners, etc) wheb + matching GSUB/GPOS lookups, + * Fix 'Phags-Pa U+A872 shaping, + * Fix partial disabling of default-on features, + * Allow disabling of TrueType kerning. +- Fix possible crasher with broken fonts with overlapping tables. +- Removed generated files from git again. So, one needs ragel to + bootstrap from the git tree. + +API changes: +- hb_shape() and related APIs now abort if buffer direction is + HB_DIRECTION_INVALID. Previously, hb_shape() was calling + hb_buffer_guess_segment_properties() on the buffer before + shaping. The heuristics in that function are fragile. If the + user really wants the old behvaior, they can call that function + right before calling hb_shape() to get the old behavior. +- hb_blob_create_sub_blob() always creates sub-blob with + HB_MEMORY_MODE_READONLY. See comments for the reason. + + +Overview of changes leading to 0.9.12 +Thursday, January 18, 2013 +===================================== + +- Build fixes for Sun compiler. +- Minor bug fix. + +Overview of changes leading to 0.9.11 +Thursday, January 10, 2013 +===================================== + +- Build fixes. +- Fix GPOS mark attachment with null Anchor offsets. +- [Indic] Fix old-spec reordering of viramas if sequence ends in one. +- Fix multi-threaded shaper data creation crash. +- Add atomic ops for Solaris. + +API changes: +- Rename hb_buffer_clear() to hb_buffer_clear_contents(). + + +Overview of changes leading to 0.9.10 +Thursday, January 3, 2013 +===================================== + +- [Indic] Fixed rendering of Malayalam dot-reph +- Updated OT language tags. +- Updated graphite2 backend. +- Improved hb_ot_layout_get_size_params() logic. +- Improve hb-shape/hb-view help output. +- Fixed hb-set.h implementation to not crash. +- Fixed various issues with hb_ot_layout_collect_lookups(). +- Various build fixes. + +New API: + +hb_graphite2_face_get_gr_face() +hb_graphite2_font_get_gr_font() +hb_coretext_face_get_cg_font() + +Modified API: + +hb_ot_layout_get_size_params() + + +Overview of changes leading to 0.9.9 +Wednesday, December 5, 2012 +==================================== + +- Fix build on Windows. +- Minor improvements. + + +Overview of changes leading to 0.9.8 +Tuesday, December 4, 2012 +==================================== + + +- Actually implement hb_shape_plan_get_shaper (). +- Make UCDB data tables const. +- Lots of internal refactoring in OTLayout tables. +- Flesh out hb_ot_layout_lookup_collect_glyphs(). + +New API: + +hb_ot_layout_collect_lookups() +hb_ot_layout_get_size_params() + + +Overview of changes leading to 0.9.7 +Sunday, November 21, 2012 +==================================== + + +HarfBuzz "All-You-Can-Eat-Sushi" (aka Vancouver) Hackfest and follow-on fixes. + +- Fix Arabic contextual joining using pre-context text. +- Fix Sinhala "split matra" mess. +- Fix Khmer shaping with broken fonts. +- Implement Thai "PUA" shaping for old fonts. +- Do NOT route Kharoshthi script through the Indic shaper. +- Disable fallback positioning for Indic and Thai shapers. +- Misc fixes. + + +hb-shape / hb-view changes: + +- Add --text-before and --text-after +- Add --bot / --eot / --preserve-default-ignorables +- hb-shape --output-format=json + + +New API: + +hb_buffer_clear() + +hb_buffer_flags_t + +HB_BUFFER_FLAGS_DEFAULT +HB_BUFFER_FLAG_BOT +HB_BUFFER_FLAG_EOT +HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES + +hb_buffer_set_flags() +hb_buffer_get_flags() + +HB_BUFFER_SERIALIZE_FLAGS +hb_buffer_serialize_glyphs() +hb_buffer_deserialize_glyphs() +hb_buffer_serialize_list_formats() + +hb_set_add_range() +hb_set_del_range() +hb_set_get_population() +hb_set_next_range() + +hb_face_[sg]et_glyph_count() + +hb_segment_properties_t +HB_SEGMENT_PROPERTIES_DEFAULT +hb_segment_properties_equal() +hb_segment_properties_hash() + +hb_buffer_set_segment_properties() +hb_buffer_get_segment_properties() + +hb_ot_layout_glyph_class_t +hb_ot_layout_get_glyph_class() +hb_ot_layout_get_glyphs_in_class() + +hb_shape_plan_t +hb_shape_plan_create() +hb_shape_plan_create_cached() +hb_shape_plan_get_empty() +hb_shape_plan_reference() +hb_shape_plan_destroy() +hb_shape_plan_set_user_data() +hb_shape_plan_get_user_data() +hb_shape_plan_execute() +hb_shape_plan_get_shaper() + +hb_ot_shape_plan_collect_lookups() + + +API changes: + +- Remove "mask" parameter from hb_buffer_add(). +- Rename hb_ot_layout_would_substitute_lookup() and hb_ot_layout_substitute_closure_lookup(). +- hb-set.h API const correction. +- Renamed hb_set_min/max() to hb_set_get_min/max(). +- Rename hb_ot_layout_feature_get_lookup_indexes() to hb_ot_layout_feature_get_lookups(). +- Rename hb_buffer_guess_properties() to hb_buffer_guess_segment_properties(). + + + +Overview of changes leading to 0.9.6 +Sunday, November 13, 2012 +==================================== + +- Don't clear pre-context text if no new context is provided. +- Fix ReverseChainingSubstLookup, which was totally borked. +- Adjust output format of hb-shape a bit. +- Include config.h.in in-tree. Makes it easier for alternate build systems. +- Fix hb_buffer_set_length(buffer, 0) invalid memory allocation. +- Use ICU LayoutEngine's C API instead of C++. Avoids much headache. +- Drop glyphs for all of Unicode Default_Ignorable characters. +- Misc build fixes. + +Arabic shaper: +- Enable 'dlig' and 'mset' features in Arabic shaper. +- Implement 'Phags-pa shaping, improve Mongolian. + +Indic shaper: +- Decompose Sinhala split matras the way old HarfBuzz / Pango did. +- Initial support for Consonant Medials. +- Start adding new-style Myanmar shaping. +- Make reph and 'pref' logic introspect the font. +- Route Meetei-Mayek through the Indic shaper. +- Don't apply 'liga' in Indic shaper. +- Improve Malayalam pre-base reordering Ra interaction with Chillus. + + + +Overview of changes leading to 0.9.5 +Sunday, October 14, 2012 +==================================== + +- Synthetic-GSUB Arabic fallback shaping. + +- Misc Indic improvements. + +- Add build system support for pthread. + +- Imported UCDN for in-tree Unicode callbacks implementation. + +- Context-aware Arabic joining. + +- Misc other fixes. + +- New API: + + hb_feature_to/from-string() + hb_buffer_[sg]et_content_type() + + + +Overview of changes leading to 0.9.4 +Tuesday, Sep 03, 2012 +==================================== + +- Indic improvements with old-spec Malayalam. + +- Better fallback glyph positioning, specially with Thai / Lao marks. + +- Implement dotted-circle insertion. + +- Better Arabic fallback shaping / ligation. + +- Added ICU LayoutEngine backend for testing. Call it by the 'icu_le' name. + +- Misc fixes. + + + +Overview of changes leading to 0.9.3 +Friday, Aug 18, 2012 +==================================== + +- Fixed fallback mark positioning for left-to-right text. + +- Improve mark positioning for the remaining combining classes. + +- Unbreak Thai and fallback Arabic shaping. + +- Port Arabic shaper to shape-plan caching. + +- Use new ICU normalizer functions. + + + +Overview of changes leading to 0.9.2 +Friday, Aug 10, 2012 +==================================== + +- Over a thousand commits! This is the first major release of HarfBuzz. + +- HarfBuzz is feature-complete now! It should be in par, or better, than + both Pango's shapers and old HarfBuzz / Qt shapers. + +- New Indic shaper, supporting main Indic scripts, Sinhala, and Khmer. + +- Improved Arabic shaper, with fallback Arabic shaping, supporting Arabic, + Sinhala, N'ko, Mongolian, and Mandaic. + +- New Thai / Lao shaper. + +- Tibetan / Hangul support in the generic shaper. + +- Synthetic GDEF support for fonts without a GDEF table. + +- Fallback mark positioning for fonts without a GPOS table. + +- Unicode normalization shaping heuristic during glyph mapping. + +- New experimental Graphite2 backend. + +- New Uniscribe backend (primarily for testing). + +- New CoreText backend (primarily for testing). + +- Major optimization and speedup. + +- Test suites and testing infrastructure (work in progress). + +- Greatly improved hb-view cmdline tool. + +- hb-shape cmdline tool. + +- Unicode 6.1 support. + +Summary of API changes: + +o Changed API: + + - Users are expected to only include main header files now (ie. hb.h, + hb-glib.h, hb-ft.h, ...) + + - All struct tag names had their initial underscore removed. + Ie. "struct _hb_buffer_t" is "struct hb_buffer_t" now. + + - All set_user_data() functions now take a "replace" boolean parameter. + + - hb_buffer_create() takes zero arguments now. + Use hb_buffer_pre_allocate() to pre-allocate. + + - hb_buffer_add_utf*() now accept -1 for length parameteres, + meaning "nul-terminated". + + - hb_direction_t enum values changed. + + - All *_from_string() APIs now take a length parameter to allow for + non-nul-terminated strings. A -1 length means "nul-terminated". + + - Typedef for hb_language_t changed. + + - hb_get_table_func_t renamed to hb_reference_table_func_t. + + - hb_ot_layout_table_choose_script() + + - Various renames in hb-unicode.h. + +o New API: + + - hb_buffer_guess_properties() + Automatically called by hb_shape(). + + - hb_buffer_normalize_glyphs() + + - hb_tag_from_string() + + - hb-coretext.h + + - hb-uniscribe.h + + - hb_face_reference_blob() + - hb_face_[sg]et_index() + - hb_face_set_upem() + + - hb_font_get_glyph_name_func_t + hb_font_get_glyph_from_name_func_t + hb_font_funcs_set_glyph_name_func() + hb_font_funcs_set_glyph_from_name_func() + hb_font_get_glyph_name() + hb_font_get_glyph_from_name() + hb_font_glyph_to_string() + hb_font_glyph_from_string() + + - hb_font_set_funcs_data() + + - hb_ft_font_set_funcs() + - hb_ft_font_get_face() + + - hb-gobject.h (work in progress) + + - hb_ot_shape_glyphs_closure() + hb_ot_layout_substitute_closure_lookup() + + - hb-set.h + + - hb_shape_full() + + - hb_unicode_combining_class_t + + - hb_unicode_compose_func_t + hb_unicode_decompose_func_t + hb_unicode_decompose_compatibility_func_t + hb_unicode_funcs_set_compose_func() + hb_unicode_funcs_set_decompose_func() + hb_unicode_funcs_set_decompose_compatibility_func() + hb_unicode_compose() + hb_unicode_decompose() + hb_unicode_decompose_compatibility() + +o Removed API: + + - hb_ft_get_font_funcs() + + - hb_ot_layout_substitute_start() + hb_ot_layout_substitute_lookup() + hb_ot_layout_substitute_finish() + hb_ot_layout_position_start() + hb_ot_layout_position_lookup() + hb_ot_layout_position_finish() + + + +Overview of changes leading to 0.6.0 +Friday, May 27, 2011 +==================================== + +- Vertical text support in GPOS +- Almost all API entries have unit tests now, under test/ +- All thread-safety issues are fixed + +Summary of API changes follows. + + +* Simple Types API: + + o New API: + HB_LANGUAGE_INVALID + hb_language_get_default() + hb_direction_to_string() + hb_direction_from_string() + hb_script_get_horizontal_direction() + HB_UNTAG() + + o Renamed API: + hb_category_t renamed to hb_unicode_general_category_t + + o Changed API: + hb_language_t is a typed pointers now + + o Removed API: + HB_TAG_STR() + + +* Use ISO 15924 tags for hb_script_t: + + o New API: + hb_script_from_iso15924_tag() + hb_script_to_iso15924_tag() + hb_script_from_string() + + o Changed API: + HB_SCRIPT_* enum members changed value. + + +* Buffer API streamlined: + + o New API: + hb_buffer_reset() + hb_buffer_set_length() + hb_buffer_allocation_successful() + + o Renamed API: + hb_buffer_ensure() renamed to hb_buffer_pre_allocate() + hb_buffer_add_glyph() renamed to hb_buffer_add() + + o Removed API: + hb_buffer_clear() + hb_buffer_clear_positions() + + o Changed API: + hb_buffer_get_glyph_infos() takes an out length parameter now + hb_buffer_get_glyph_positions() takes an out length parameter now + + +* Blob API streamlined: + + o New API: + hb_blob_get_data() + hb_blob_get_data_writable() + + o Renamed API: + hb_blob_create_empty() renamed to hb_blob_get_empty() + + o Removed API: + hb_blob_lock() + hb_blob_unlock() + hb_blob_is_writable() + hb_blob_try_writable() + + o Changed API: + hb_blob_create() takes user_data before destroy now + + +* Unicode functions API: + + o Unicode function vectors can subclass other unicode function vectors now. + Unimplemented callbacks in the subclass automatically chainup to the parent. + + o All hb_unicode_funcs_t callbacks take a user_data now. Their setters + take a user_data and its respective destroy callback. + + o New API: + hb_unicode_funcs_get_empty() + hb_unicode_funcs_get_default() + hb_unicode_funcs_get_parent() + + o Changed API: + hb_unicode_funcs_create() now takes a parent_funcs. + + o Removed func getter functions: + hb_unicode_funcs_get_mirroring_func() + hb_unicode_funcs_get_general_category_func() + hb_unicode_funcs_get_script_func() + hb_unicode_funcs_get_combining_class_func() + hb_unicode_funcs_get_eastasian_width_func() + + +* Face API: + + o Renamed API: + hb_face_get_table() renamed to hb_face_reference_table() + hb_face_create_for_data() renamed to hb_face_create() + + o Changed API: + hb_face_create_for_tables() takes user_data before destroy now + hb_face_reference_table() returns empty blob instead of NULL + hb_get_table_func_t accepts the face as first parameter now + +* Font API: + + o Fonts can subclass other fonts now. Unimplemented callbacks in the + subclass automatically chainup to the parent. When chaining up, + scale is adjusted if the parent font has a different scale. + + o All hb_font_funcs_t callbacks take a user_data now. Their setters + take a user_data and its respective destroy callback. + + o New API: + hb_font_get_parent() + hb_font_funcs_get_empty() + hb_font_create_sub_font() + + o Removed API: + hb_font_funcs_copy() + hb_font_unset_funcs() + + o Removed func getter functions: + hb_font_funcs_get_glyph_func() + hb_font_funcs_get_glyph_advance_func() + hb_font_funcs_get_glyph_extents_func() + hb_font_funcs_get_contour_point_func() + hb_font_funcs_get_kerning_func() + + o Changed API: + hb_font_create() takes a face and references it now + hb_font_set_funcs() takes user_data before destroy now + hb_font_set_scale() accepts signed integers now + hb_font_get_contour_point_func_t now takes glyph first, then point_index + hb_font_get_glyph_func_t returns a success boolean now + + +* Changed object model: + + o All object types have a _get_empty() now: + hb_blob_get_empty() + hb_buffer_get_empty() + hb_face_get_empty() + hb_font_get_empty() + hb_font_funcs_get_empty() + hb_unicode_funcs_get_empty() + + o Added _set_user_data() and _get_user_data() for all object types: + hb_blob_get_user_data() + hb_blob_set_user_data() + hb_buffer_get_user_data() + hb_buffer_set_user_data() + hb_face_get_user_data() + hb_face_set_user_data() + hb_font_funcs_get_user_data() + hb_font_funcs_set_user_data() + hb_font_get_user_data() + hb_font_set_user_data() + hb_unicode_funcs_get_user_data() + hb_unicode_funcs_set_user_data() + + o Removed the _get_reference_count() from all object types: + hb_blob_get_reference_count() + hb_buffer_get_reference_count() + hb_face_get_reference_count() + hb_font_funcs_get_reference_count() + hb_font_get_reference_count() + hb_unicode_funcs_get_reference_count() + + o Added _make_immutable() and _is_immutable() for all object types except for buffer: + hb_blob_make_immutable() + hb_blob_is_immutable() + hb_face_make_immutable() + hb_face_is_immutable() + + +* Changed API for vertical text support + + o The following callbacks where removed: + hb_font_get_glyph_advance_func_t + hb_font_get_kerning_func_t + + o The following new callbacks added instead: + hb_font_get_glyph_h_advance_func_t + hb_font_get_glyph_v_advance_func_t + hb_font_get_glyph_h_origin_func_t + hb_font_get_glyph_v_origin_func_t + hb_font_get_glyph_h_kerning_func_t + hb_font_get_glyph_v_kerning_func_t + + o The following API removed as such: + hb_font_funcs_set_glyph_advance_func() + hb_font_funcs_set_kerning_func() + hb_font_get_glyph_advance() + hb_font_get_kerning() + + o New API added instead: + hb_font_funcs_set_glyph_h_advance_func() + hb_font_funcs_set_glyph_v_advance_func() + hb_font_funcs_set_glyph_h_origin_func() + hb_font_funcs_set_glyph_v_origin_func() + hb_font_funcs_set_glyph_h_kerning_func() + hb_font_funcs_set_glyph_v_kerning_func() + hb_font_get_glyph_h_advance() + hb_font_get_glyph_v_advance() + hb_font_get_glyph_h_origin() + hb_font_get_glyph_v_origin() + hb_font_get_glyph_h_kerning() + hb_font_get_glyph_v_kerning() + + o The following higher-leve API added for convenience: + hb_font_get_glyph_advance_for_direction() + hb_font_get_glyph_origin_for_direction() + hb_font_add_glyph_origin_for_direction() + hb_font_subtract_glyph_origin_for_direction() + hb_font_get_glyph_kerning_for_direction() + hb_font_get_glyph_extents_for_origin() + hb_font_get_glyph_contour_point_for_origin() + + +* OpenType Layout API: + + o New API: + hb_ot_layout_position_start() + hb_ot_layout_substitute_start() + hb_ot_layout_substitute_finish() + + +* Glue code: + + o New API: + hb_glib_script_to_script() + hb_glib_script_from_script() + hb_icu_script_to_script() + hb_icu_script_from_script() + + +* Version API added: + + o New API: + HB_VERSION_MAJOR + HB_VERSION_MINOR + HB_VERSION_MICRO + HB_VERSION_STRING + HB_VERSION_CHECK() + hb_version() + hb_version_string() + hb_version_check() + + diff --git a/gfx/harfbuzz/README b/gfx/harfbuzz/README index 74e739da5..69a1bdd9f 100644 --- a/gfx/harfbuzz/README +++ b/gfx/harfbuzz/README @@ -1,3 +1,8 @@ +[![Build Status](https://travis-ci.org/behdad/harfbuzz.svg)](https://travis-ci.org/behdad/harfbuzz) +[![Build Status](https://ci.appveyor.com/api/projects/status/4oaq58ns2h0m2soa?svg=true)](https://ci.appveyor.com/project/behdad/harfbuzz) +[![Coverage Status](https://img.shields.io/coveralls/behdad/harfbuzz.svg)](https://coveralls.io/r/behdad/harfbuzz) +[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/) + This is HarfBuzz, a text shaping library. For bug reports, mailing list, and other information please visit: diff --git a/gfx/harfbuzz/README-mozilla b/gfx/harfbuzz/README-mozilla index dc176cff8..251bbb6a1 100644 --- a/gfx/harfbuzz/README-mozilla +++ b/gfx/harfbuzz/README-mozilla @@ -1,20 +1,21 @@ -gfx/harfbuzz status as of 2015-04-25: +gfx/harfbuzz status as of 2017-09-05: This directory contains the harfbuzz source from the 'master' branch of https://github.com/behdad/harfbuzz. +Current version: 1.5.1 + UPDATING: Note that gfx/harfbuzz/src/hb-version.h is not present in the upstream Git repository. It is created at build time by the harfbuzz build system; but as we don't use that build system in mozilla, it is necessary to refresh -this files when updating harfbuzz, and check them into the mozilla tree. +this file when updating harfbuzz, and check it into the mozilla tree. The normal approach to updating harfbuzz, therefore, is to pull the latest HB source into a scratch directory and do a local build; then copy the original -sources AND the generated headers mentioned above from the build directory into +sources AND the generated header mentioned above from the build directory into the mozilla tree. -In addition, the src/Makefile.in file here is NOT from upstream, nor is it -generated from src/Makefile.am (the original harfbuzz version); it is a mozilla- -specific makefile that is maintained by hand. +If the collection of source files changes, manual updates to moz.build may be +needed, as we don't use the upstream makefiles. diff --git a/gfx/harfbuzz/THANKS b/gfx/harfbuzz/THANKS new file mode 100644 index 000000000..940cfde5c --- /dev/null +++ b/gfx/harfbuzz/THANKS @@ -0,0 +1,7 @@ +Bradley Grainger +Khaled Hosny +Kenichi Ishibashi +Ryan Lortie +Jeff Muizelaar +suzuki toshiya +Philip Withnall diff --git a/gfx/harfbuzz/TODO b/gfx/harfbuzz/TODO index 7a99cd2b2..4f37f605b 100644 --- a/gfx/harfbuzz/TODO +++ b/gfx/harfbuzz/TODO @@ -1,70 +1,55 @@ General fixes: ============= -- Move feature parsing from util into the library +- AAT 'morx' implementation. + +- Return "safe-to-break" bit from shaping. + +- Implement 'rand' feature. + +- mask propagation? (when ligation, "or" the masks). + + +API issues: +=========== + +- API to accept a list of languages? + +- Add init_func to font_funcs. Adjust ft. - 'const' for getter APIs? (use mutable internally) -- Fix TT 'kern' on/off and GPOS interaction (move kerning before GPOS) - -- Do proper rounding when scaling from font space? - -- Misc features: - * init/medi/fina/isol for non-cursive scripts - * vkna,hkna etc for kana, *jmo for hangul, etc - -- Move non-native direction and normalization handling to the generic non-OT - layer, such that uniscribe and other backends can use. - -- Uniscribe backend needs to enforce one direction only, otherwise cluster - values can confused the user. +- Remove hb_ot_shape_glyphs_closure()? -API issues to fix before 1.0: -============================ +API additions +============= -- Rename all internal symbols (static ones even) to have _hb prefix? +- Language to/from script. -- Add pkg-config files for glue codes (harfbuzz-glib, etc) - -- Figure out how many .so objects, how to link, etc +- blob_from_file? - Add hb-cairo glue - Add sanitize API (and a cached version, that saves result on blob user-data) -- Add glib GBoxedType stuff and introspection - - -API to add (maybe after 1.0): -============================ - -- Add Uniscribe face / font get API - - BCP 47 language handling / API (language_matches?) -- Add hb_face_get_glyph_count()? +- Add hb_font_create_unscaled()? -- Add hb_font_create_linear()? - -- Add hb_shape_plan()/hb_shape_execute() - -- Add query API for aalt-like features? +- Add query / enumeration API for aalt-like features? - SFNT api? get_num_faces? get_table_tags? (there's something in stash) - Add segmentation API -- Add hb-fribidi? +- Add hb-fribidi glue? -hb-view enhancements: -==================== +hb-view / hb-shape enhancements: +=============================== -- Add --format -- Add --width, --height, --auto-size, --align, etc? -- Port to GOption, --help -- Add XML and JSON formats +- Add --width, --height, --auto-size, --ink-box, --align, etc? Tests to write: @@ -76,10 +61,9 @@ Tests to write: - Finish test-unicode.c, grep for TODO +- GObject, FreeType, etc -Optimizations: -============= +- hb_cache_t and relatives -- Avoid allocating blob objects internally for for_data() faces? - -- Add caching layer to hb-ft +- hb_feature_to/from_string +- hb_buffer_[sg]et_contents diff --git a/gfx/harfbuzz/autogen.sh b/gfx/harfbuzz/autogen.sh index 833a6219c..ff1b0c0c9 100755 --- a/gfx/harfbuzz/autogen.sh +++ b/gfx/harfbuzz/autogen.sh @@ -19,9 +19,22 @@ which pkg-config || { exit 1 } +echo -n "checking for libtoolize... " +which glibtoolize || which libtoolize || { + echo "*** No libtoolize (libtool) found, please install it ***" + exit 1 +} +echo -n "checking for gtkdocize... " +if which gtkdocize ; then + gtkdocize --copy || exit 1 +else + echo "*** No gtkdocize (gtk-doc) found, skipping documentation ***" + echo "EXTRA_DIST = " > gtk-doc.make +fi + echo -n "checking for autoreconf... " which autoreconf || { - echo "*** No autoreconf found, please install it ***" + echo "*** No autoreconf (autoconf) found, please install it ***" exit 1 } diff --git a/gfx/harfbuzz/configure.ac b/gfx/harfbuzz/configure.ac index 7be991dcf..9151abc05 100644 --- a/gfx/harfbuzz/configure.ac +++ b/gfx/harfbuzz/configure.ac @@ -1,24 +1,32 @@ AC_PREREQ([2.64]) -AC_INIT([harfbuzz], - [0.7.0], - [http://bugs.freedesktop.org/enter_bug.cgi?product=harfbuzz], +AC_INIT([HarfBuzz], + [1.5.1], + [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) -AC_CONFIG_SRCDIR([harfbuzz.pc.in]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_SRCDIR([src/harfbuzz.pc.in]) AC_CONFIG_HEADERS([config.h]) -AM_INIT_AUTOMAKE([1.11.1 gnu dist-bzip2 no-dist-gzip -Wall no-define]) +AM_INIT_AUTOMAKE([1.11.1 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability]) +AM_CONDITIONAL(AUTOMAKE_OLDER_THAN_1_13, test $am__api_version = 1.11 -o $am__api_version = 1.12) AM_SILENT_RULES([yes]) +# Initialize libtool +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) +LT_PREREQ([2.2]) +LT_INIT([disable-static]) + # Check for programs +AC_USE_SYSTEM_EXTENSIONS AC_PROG_CC AM_PROG_CC_C_O AC_PROG_CXX - -# Initialize libtool -LT_PREREQ([2.2]) -LT_INIT([disable-static]) +AC_SYS_LARGEFILE +PKG_PROG_PKG_CONFIG([0.20]) +AM_MISSING_PROG([RAGEL], [ragel]) +AM_MISSING_PROG([GIT], [git]) # Version m4_define(hb_version_triplet,m4_split(AC_PACKAGE_VERSION,[[.]])) @@ -45,18 +53,28 @@ m4_if(m4_eval(hb_version_minor % 2), [1], m4_define([hb_libtool_age], m4_eval(hb_version_int - hb_libtool_revision)) m4_define([hb_libtool_current], - m4_eval(hb_version_major + hb_libtool_age)) + m4_eval(hb_libtool_age)) HB_LIBTOOL_VERSION_INFO=hb_libtool_current:hb_libtool_revision:hb_libtool_age AC_SUBST(HB_LIBTOOL_VERSION_INFO) -dnl GTK_DOC_CHECK([1.15],[--flavour no-tmpl]) +# Documentation +have_gtk_doc=false +m4_ifdef([GTK_DOC_CHECK], [ +GTK_DOC_CHECK([1.15],[--flavour no-tmpl]) + if test "x$enable_gtk_doc" = xyes; then + have_gtk_doc=true + fi +], [ + AM_CONDITIONAL([ENABLE_GTK_DOC], false) +]) # Functions and headers -AC_CHECK_FUNCS(mprotect sysconf getpagesize mmap _setmode) -AC_CHECK_HEADERS(unistd.h sys/mman.h io.h) +AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty) +AC_CHECK_HEADERS(unistd.h sys/mman.h) # Compiler flags AC_CANONICAL_HOST +AC_CHECK_ALIGNOF([struct{char;}]) if test "x$GCC" = "xyes"; then # Make symbols link locally @@ -65,29 +83,96 @@ if test "x$GCC" = "xyes"; then # Make sure we don't link to libstdc++ CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions" + # Assorted warnings + CXXFLAGS="$CXXFLAGS -Wcast-align" + + case "$host" in + *-*-mingw*) + ;; + *) + # Hide inline methods + CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden" + ;; + esac + case "$host" in arm-*-*) - # Request byte alignment on arm - CXXFLAGS="$CXXFLAGS -mstructure-size-boundary=8" + if test "x$ac_cv_alignof_struct_char__" != x1; then + # Request byte alignment + CXXFLAGS="$CXXFLAGS -mstructure-size-boundary=8" + fi ;; esac fi +AM_CONDITIONAL(HAVE_GCC, test "x$GCC" = "xyes") + +hb_os_win32=no +AC_MSG_CHECKING([for native Win32]) +case "$host" in + *-*-mingw*) + hb_os_win32=yes + ;; +esac +AC_MSG_RESULT([$hb_os_win32]) +AM_CONDITIONAL(OS_WIN32, test "$hb_os_win32" = "yes") + +have_pthread=false +if test "$hb_os_win32" = no; then + AX_PTHREAD([have_pthread=true]) +fi +if $have_pthread; then + AC_DEFINE(HAVE_PTHREAD, 1, [Have POSIX threads]) +fi +AM_CONDITIONAL(HAVE_PTHREAD, $have_pthread) + dnl ========================================================================== -PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, have_glib=true, have_glib=false) +have_ot=true +if $have_ot; then + AC_DEFINE(HAVE_OT, 1, [Have native OpenType Layout backend]) +fi +AM_CONDITIONAL(HAVE_OT, $have_ot) + +have_fallback=true +if $have_fallback; then + AC_DEFINE(HAVE_FALLBACK, 1, [Have simple TrueType Layout backend]) +fi +AM_CONDITIONAL(HAVE_FALLBACK, $have_fallback) + +dnl =========================================================================== + +AC_ARG_WITH(glib, + [AS_HELP_STRING([--with-glib=@<:@yes/no/auto@:>@], + [Use glib @<:@default=auto@:>@])],, + [with_glib=auto]) +have_glib=false +GLIB_DEPS="glib-2.0 >= 2.19.1" +AC_SUBST(GLIB_DEPS) +if test "x$with_glib" = "xyes" -o "x$with_glib" = "xauto"; then + PKG_CHECK_MODULES(GLIB, $GLIB_DEPS, have_glib=true, :) +fi +if test "x$with_glib" = "xyes" -a "x$have_glib" != "xtrue"; then + AC_MSG_ERROR([glib support requested but glib-2.0 not found]) +fi if $have_glib; then AC_DEFINE(HAVE_GLIB, 1, [Have glib2 library]) fi AM_CONDITIONAL(HAVE_GLIB, $have_glib) -PKG_CHECK_MODULES(GTHREAD, gthread-2.0, have_gthread=true, have_gthread=false) -if $have_gthread; then - AC_DEFINE(HAVE_GTHREAD, 1, [Have gthread2 library]) -fi -AM_CONDITIONAL(HAVE_GTHREAD, $have_gthread) +dnl =========================================================================== -PKG_CHECK_MODULES(GOBJECT, gobject-2.0 glib-2.0 >= 2.16, have_gobject=true, have_gobject=false) +AC_ARG_WITH(gobject, + [AS_HELP_STRING([--with-gobject=@<:@yes/no/auto@:>@], + [Use gobject @<:@default=auto@:>@])],, + [with_gobject=no]) +have_gobject=false +if test "x$with_gobject" = "xyes" -o "x$with_gobject" = "xauto"; then + PKG_CHECK_MODULES(GOBJECT, gobject-2.0 glib-2.0, have_gobject=true, :) +fi +if test "x$with_gobject" = "xyes" -a "x$have_gobject" != "xtrue"; then + AC_MSG_ERROR([gobject support requested but gobject-2.0 / glib-2.0 not found]) +fi if $have_gobject; then AC_DEFINE(HAVE_GOBJECT, 1, [Have gobject2 library]) GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` @@ -95,15 +180,47 @@ if $have_gobject; then fi AM_CONDITIONAL(HAVE_GOBJECT, $have_gobject) +dnl =========================================================================== + + +dnl =========================================================================== +# Gobject-Introspection +have_introspection=false +m4_ifdef([GOBJECT_INTROSPECTION_CHECK], [ + if $have_gobject; then + GOBJECT_INTROSPECTION_CHECK([1.34.0]) + if test "x$found_introspection" = xyes; then + have_introspection=true + fi + else + AM_CONDITIONAL([HAVE_INTROSPECTION], false) + fi +], [ + AM_CONDITIONAL([HAVE_INTROSPECTION], false) +]) + dnl ========================================================================== -PKG_CHECK_MODULES(CAIRO, cairo >= 1.8.0, have_cairo=true, have_cairo=false) +AC_ARG_WITH(cairo, + [AS_HELP_STRING([--with-cairo=@<:@yes/no/auto@:>@], + [Use cairo @<:@default=auto@:>@])],, + [with_cairo=auto]) +have_cairo=false +if test "x$with_cairo" = "xyes" -o "x$with_cairo" = "xauto"; then + PKG_CHECK_MODULES(CAIRO, cairo >= 1.8.0, have_cairo=true, :) +fi +if test "x$with_cairo" = "xyes" -a "x$have_cairo" != "xtrue"; then + AC_MSG_ERROR([cairo support requested but not found]) +fi if $have_cairo; then AC_DEFINE(HAVE_CAIRO, 1, [Have cairo graphics library]) fi AM_CONDITIONAL(HAVE_CAIRO, $have_cairo) -PKG_CHECK_MODULES(CAIRO_FT, cairo-ft, have_cairo_ft=true, have_cairo_ft=false) +have_cairo_ft=false +if $have_cairo; then + PKG_CHECK_MODULES(CAIRO_FT, cairo-ft, have_cairo_ft=true, :) +fi if $have_cairo_ft; then AC_DEFINE(HAVE_CAIRO_FT, 1, [Have cairo-ft support in cairo graphics library]) fi @@ -111,79 +228,304 @@ AM_CONDITIONAL(HAVE_CAIRO_FT, $have_cairo_ft) dnl ========================================================================== -PKG_CHECK_MODULES(ICU, icu, have_icu=true, [ - have_icu=true - AC_CHECK_HEADERS(unicode/uchar.h,, have_icu=false) - AC_MSG_CHECKING([for libicuuc]) - LIBS_old=$LIBS - LIBS="$LIBS -licuuc" - AC_TRY_LINK([#include ], - [u_getIntPropertyValue (0, (UProperty)0);], - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no);have_icu=false) - LIBS=$LIBS_old - if $have_icu; then - ICU_CFLAGS=-D_REENTRANT - ICU_LIBS="-licuuc" - AC_SUBST(ICU_CFLAGS) - AC_SUBST(ICU_LIBS) +AC_ARG_WITH(fontconfig, + [AS_HELP_STRING([--with-fontconfig=@<:@yes/no/auto@:>@], + [Use fontconfig @<:@default=auto@:>@])],, + [with_fontconfig=auto]) +have_fontconfig=false +if test "x$with_fontconfig" = "xyes" -o "x$with_fontconfig" = "xauto"; then + PKG_CHECK_MODULES(FONTCONFIG, fontconfig, have_fontconfig=true, :) +fi +if test "x$with_fontconfig" = "xyes" -a "x$have_fontconfig" != "xtrue"; then + AC_MSG_ERROR([fontconfig support requested but not found]) +fi +if $have_fontconfig; then + AC_DEFINE(HAVE_FONTCONFIG, 1, [Have fontconfig library]) +fi +AM_CONDITIONAL(HAVE_FONTCONFIG, $have_fontconfig) + +dnl ========================================================================== + +AC_ARG_WITH(icu, + [AS_HELP_STRING([--with-icu=@<:@yes/no/builtin/auto@:>@], + [Use ICU @<:@default=auto@:>@])],, + [with_icu=auto]) +have_icu=false +if test "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" -o "x$with_icu" = "xauto"; then + PKG_CHECK_MODULES(ICU, icu-uc, have_icu=true, :) + + dnl Fallback to icu-config if ICU pkg-config files could not be found + if test "$have_icu" != "true"; then + AC_CHECK_TOOL(ICU_CONFIG, icu-config, no) + AC_MSG_CHECKING([for ICU by using icu-config fallback]) + if test "$ICU_CONFIG" != "no" && "$ICU_CONFIG" --version >/dev/null; then + have_icu=true + # We don't use --cflags as this gives us a lot of things that we don't + # necessarily want, like debugging and optimization flags + # See man (1) icu-config for more info. + ICU_CFLAGS=`$ICU_CONFIG --cppflags` + ICU_LIBS=`$ICU_CONFIG --ldflags-searchpath --ldflags-libsonly` + AC_SUBST(ICU_CFLAGS) + AC_SUBST(ICU_LIBS) + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi fi -]) +fi +if test \( "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" \) -a "x$have_icu" != "xtrue"; then + AC_MSG_ERROR([icu support requested but icu-uc not found]) +fi + if $have_icu; then + CXXFLAGS="$CXXFLAGS `$PKG_CONFIG --variable=CXXFLAGS icu-uc`" AC_DEFINE(HAVE_ICU, 1, [Have ICU library]) + if test "x$with_icu" = "xbuiltin"; then + AC_DEFINE(HAVE_ICU_BUILTIN, 1, [Use hb-icu Unicode callbacks]) + fi fi AM_CONDITIONAL(HAVE_ICU, $have_icu) +AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin") -dnl ========================================================================== +dnl =========================================================================== -PKG_CHECK_MODULES(GRAPHITE, graphite2, have_graphite=true, have_graphite=false) -if $have_graphite; then - AC_DEFINE(HAVE_GRAPHITE, 1, [Have Graphite library]) +AC_ARG_WITH(ucdn, + [AS_HELP_STRING([--with-ucdn=@<:@yes/no@:>@], + [Use builtin UCDN library @<:@default=yes@:>@])],, + [with_ucdn=yes]) +have_ucdn=false +if test "x$with_ucdn" = "xyes"; then + have_ucdn=true fi -AM_CONDITIONAL(HAVE_GRAPHITE, $have_graphite) +if $have_ucdn; then + AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions]) +fi +AM_CONDITIONAL(HAVE_UCDN, $have_ucdn) dnl ========================================================================== -PKG_CHECK_MODULES(FREETYPE, freetype2 >= 2.3.8, have_freetype=true, have_freetype=false) +AC_ARG_WITH(graphite2, + [AS_HELP_STRING([--with-graphite2=@<:@yes/no/auto@:>@], + [Use the graphite2 library @<:@default=no@:>@])],, + [with_graphite2=no]) +have_graphite2=false +GRAPHITE2_DEPS="graphite2" +AC_SUBST(GRAPHITE2_DEPS) +if test "x$with_graphite2" = "xyes" -o "x$with_graphite2" = "xauto"; then + PKG_CHECK_MODULES(GRAPHITE2, $GRAPHITE2_DEPS, have_graphite2=true, :) + if test "x$have_graphite2" != "xtrue"; then + # If pkg-config is not available, graphite2 can still be there + ac_save_CFLAGS="$CFLAGS" + ac_save_CPPFLAGS="$CPPFLAGS" + CFLAGS="$CFLAGS $GRAPHITE2_CFLAGS" + CPPFLAGS="$CPPFLAGS $GRAPHITE2_CFLAGS" + AC_CHECK_HEADER(graphite2/Segment.h, have_graphite2=true, :) + CPPFLAGS="$ac_save_CPPFLAGS" + CFLAGS="$ac_save_CFLAGS" + fi +fi +if test "x$with_graphite2" = "xyes" -a "x$have_graphite2" != "xtrue"; then + AC_MSG_ERROR([graphite2 support requested but libgraphite2 not found]) +fi +if $have_graphite2; then + AC_DEFINE(HAVE_GRAPHITE2, 1, [Have Graphite2 library]) +fi +AM_CONDITIONAL(HAVE_GRAPHITE2, $have_graphite2) + +dnl ========================================================================== + +AC_ARG_WITH(freetype, + [AS_HELP_STRING([--with-freetype=@<:@yes/no/auto@:>@], + [Use the FreeType library @<:@default=auto@:>@])],, + [with_freetype=auto]) +have_freetype=false +FREETYPE_DEPS="freetype2 >= 12.0.6" +AC_SUBST(FREETYPE_DEPS) +if test "x$with_freetype" = "xyes" -o "x$with_freetype" = "xauto"; then + # See freetype/docs/VERSION.DLL; 12.0.6 means freetype-2.4.2 + PKG_CHECK_MODULES(FREETYPE, $FREETYPE_DEPS, have_freetype=true, :) +fi +if test "x$with_freetype" = "xyes" -a "x$have_freetype" != "xtrue"; then + AC_MSG_ERROR([FreeType support requested but libfreetype2 not found]) +fi if $have_freetype; then AC_DEFINE(HAVE_FREETYPE, 1, [Have FreeType 2 library]) - _save_libs="$LIBS" - _save_cflags="$CFLAGS" + save_libs=$LIBS LIBS="$LIBS $FREETYPE_LIBS" - CFLAGS="$CFLAGS $FREETYPE_CFLAGS" - AC_CHECK_FUNCS(FT_Face_GetCharVariantIndex) - LIBS="$_save_libs" - CFLAGS="$_save_cflags" + AC_CHECK_FUNCS(FT_Get_Var_Blend_Coordinates) + LIBS=$save_libs fi AM_CONDITIONAL(HAVE_FREETYPE, $have_freetype) dnl =========================================================================== -have_ot=true; -if $have_ot; then - AC_DEFINE(HAVE_OT, 1, [Have native OpenType Layout backend]) +AC_ARG_WITH(uniscribe, + [AS_HELP_STRING([--with-uniscribe=@<:@yes/no/auto@:>@], + [Use the Uniscribe library @<:@default=no@:>@])],, + [with_uniscribe=no]) +have_uniscribe=false +if test "x$with_uniscribe" = "xyes" -o "x$with_uniscribe" = "xauto"; then + AC_CHECK_HEADERS(usp10.h windows.h, have_uniscribe=true) +fi +if test "x$with_uniscribe" = "xyes" -a "x$have_uniscribe" != "xtrue"; then + AC_MSG_ERROR([uniscribe support requested but not found]) fi -AM_CONDITIONAL(HAVE_OT, $have_ot) - -dnl =========================================================================== - -AC_CHECK_HEADERS(usp10.h windows.h, have_uniscribe=true, have_uniscribe=false) if $have_uniscribe; then UNISCRIBE_CFLAGS= - UNISCRIBE_LIBS="-lusp10 -lgdi32" + UNISCRIBE_LIBS="-lusp10 -lgdi32 -lrpcrt4" AC_SUBST(UNISCRIBE_CFLAGS) AC_SUBST(UNISCRIBE_LIBS) - AC_DEFINE(HAVE_UNISCRIBE, 1, [Have Uniscribe backend]) + AC_DEFINE(HAVE_UNISCRIBE, 1, [Have Uniscribe library]) fi AM_CONDITIONAL(HAVE_UNISCRIBE, $have_uniscribe) +dnl =========================================================================== + +AC_ARG_WITH(directwrite, + [AS_HELP_STRING([--with-directwrite=@<:@yes/no/auto@:>@], + [Use the DirectWrite library (experimental) @<:@default=no@:>@])],, + [with_directwrite=no]) +have_directwrite=false +AC_LANG_PUSH([C++]) +if test "x$with_directwrite" = "xyes" -o "x$with_directwrite" = "xauto"; then + AC_CHECK_HEADERS(dwrite.h, have_directwrite=true) +fi +AC_LANG_POP([C++]) +if test "x$with_directwrite" = "xyes" -a "x$have_directwrite" != "xtrue"; then + AC_MSG_ERROR([directwrite support requested but not found]) +fi +if $have_directwrite; then + DIRECTWRITE_CXXFLAGS= + DIRECTWRITE_LIBS="-ldwrite" + AC_SUBST(DIRECTWRITE_CXXFLAGS) + AC_SUBST(DIRECTWRITE_LIBS) + AC_DEFINE(HAVE_DIRECTWRITE, 1, [Have DirectWrite library]) +fi +AM_CONDITIONAL(HAVE_DIRECTWRITE, $have_directwrite) + +dnl =========================================================================== + +AC_ARG_WITH(coretext, + [AS_HELP_STRING([--with-coretext=@<:@yes/no/auto@:>@], + [Use CoreText @<:@default=no@:>@])],, + [with_coretext=no]) +have_coretext=false +if test "x$with_coretext" = "xyes" -o "x$with_coretext" = "xauto"; then + AC_CHECK_TYPE(CTFontRef, have_coretext=true,, [#include ]) + + if $have_coretext; then + CORETEXT_CFLAGS= + CORETEXT_LIBS="-framework ApplicationServices" + AC_SUBST(CORETEXT_CFLAGS) + AC_SUBST(CORETEXT_LIBS) + else + # On iOS CoreText and CoreGraphics are stand-alone frameworks + if test "x$have_coretext" != "xtrue"; then + # Check for a different symbol to avoid getting cached result. + AC_CHECK_TYPE(CTRunRef, have_coretext=true,, [#include ]) + fi + + if $have_coretext; then + CORETEXT_CFLAGS= + CORETEXT_LIBS="-framework CoreText -framework CoreGraphics" + AC_SUBST(CORETEXT_CFLAGS) + AC_SUBST(CORETEXT_LIBS) + fi + fi +fi +if test "x$with_coretext" = "xyes" -a "x$have_coretext" != "xtrue"; then + AC_MSG_ERROR([CoreText support requested but libcoretext not found]) +fi +if $have_coretext; then + AC_DEFINE(HAVE_CORETEXT, 1, [Have Core Text backend]) +fi +AM_CONDITIONAL(HAVE_CORETEXT, $have_coretext) + +dnl =========================================================================== + +AC_CACHE_CHECK([for Intel atomic primitives], hb_cv_have_intel_atomic_primitives, [ + hb_cv_have_intel_atomic_primitives=false + AC_TRY_LINK([ + void memory_barrier (void) { __sync_synchronize (); } + int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); } + int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); } + void mutex_unlock (int *m) { __sync_lock_release (m); } + ], [], hb_cv_have_intel_atomic_primitives=true + ) +]) +if $hb_cv_have_intel_atomic_primitives; then + AC_DEFINE(HAVE_INTEL_ATOMIC_PRIMITIVES, 1, [Have Intel __sync_* atomic primitives]) +fi + +dnl =========================================================================== + +AC_CACHE_CHECK([for Solaris atomic operations], hb_cv_have_solaris_atomic_ops, [ + hb_cv_have_solaris_atomic_ops=false + AC_TRY_LINK([ + #include + /* This requires Solaris Studio 12.2 or newer: */ + #include + void memory_barrier (void) { __machine_rw_barrier (); } + int atomic_add (volatile unsigned *i) { return atomic_add_int_nv (i, 1); } + void *atomic_ptr_cmpxchg (volatile void **target, void *cmp, void *newval) { return atomic_cas_ptr (target, cmp, newval); } + ], [], hb_cv_have_solaris_atomic_ops=true + ) +]) +if $hb_cv_have_solaris_atomic_ops; then + AC_DEFINE(HAVE_SOLARIS_ATOMIC_OPS, 1, [Have Solaris __machine_*_barrier and atomic_* operations]) +fi + +if test "$os_win32" = no && ! $have_pthread; then + AC_CHECK_HEADERS(sched.h) + AC_SEARCH_LIBS(sched_yield,rt,AC_DEFINE(HAVE_SCHED_YIELD, 1, [Have sched_yield])) +fi + +dnl =========================================================================== + AC_CONFIG_FILES([ Makefile -harfbuzz.pc src/Makefile src/hb-version.h +src/hb-ucdn/Makefile util/Makefile test/Makefile +test/api/Makefile +test/fuzzing/Makefile +test/shaping/Makefile +docs/Makefile +docs/version.xml +win32/Makefile +win32/config.h.win32 ]) AC_OUTPUT + +AC_MSG_NOTICE([ + +Build configuration: + +Unicode callbacks (you want at least one): + Builtin (UCDN): ${have_ucdn} + Glib: ${have_glib} + ICU: ${have_icu} + +Font callbacks (the more the better): + FreeType: ${have_freetype} + +Tools used for command-line utilities: + Cairo: ${have_cairo} + Fontconfig: ${have_fontconfig} + +Additional shapers (the more the better): + Graphite2: ${have_graphite2} + +Platform shapers (not normally needed): + CoreText: ${have_coretext} + Uniscribe: ${have_uniscribe} + DirectWrite: ${have_directwrite} + +Other features: + Documentation: ${have_gtk_doc} + GObject bindings: ${have_gobject} + Introspection: ${have_introspection} +]) diff --git a/gfx/harfbuzz/git.mk b/gfx/harfbuzz/git.mk index 088ef0b54..bd39ae10d 100644 --- a/gfx/harfbuzz/git.mk +++ b/gfx/harfbuzz/git.mk @@ -1,18 +1,25 @@ -# git.mk +# git.mk, a small Makefile to autogenerate .gitignore files +# for autotools-based projects. # # Copyright 2009, Red Hat, Inc. +# Copyright 2010,2011,2012,2013 Behdad Esfahbod # Written by Behdad Esfahbod # # Copying and distribution of this file, with or without modification, -# are permitted in any medium without royalty provided the copyright +# is permitted in any medium without royalty provided the copyright # notice and this notice are preserved. # -# The canonical source for this file is pango/git.mk, or whereever the -# header of pango/git.mk suggests in the future. +# The latest version of this file can be downloaded from: +GIT_MK_URL = https://raw.githubusercontent.com/behdad/git.mk/master/git.mk +# +# Bugs, etc, should be reported upstream at: +# https://github.com/behdad/git.mk # # To use in your project, import this file in your git repo's toplevel, # then do "make -f git.mk". This modifies all Makefile.am files in -# your project to include git.mk. +# your project to -include git.mk. Remember to add that line to new +# Makefile.am files you create in your project, or just rerun the +# "make -f git.mk". # # This enables automatic .gitignore generation. If you need to ignore # more files, add them to the GITIGNOREFILES variable in your Makefile.am. @@ -22,7 +29,7 @@ # # The only case that you need to manually add a file to GITIGNOREFILES is # when remove files in one of mostlyclean-local, clean-local, distclean-local, -# or maintainer-clean-local. +# or maintainer-clean-local make targets. # # Note that for files like editor backup, etc, there are better places to # ignore them. See "man gitignore". @@ -30,18 +37,25 @@ # If "make maintainer-clean" removes the files but they are not recognized # by this script (that is, if "git status" shows untracked files still), send # me the output of "git status" as well as your Makefile.am and Makefile for -# the directories involved. +# the directories involved and I'll diagnose. # # For a list of toplevel files that should be in MAINTAINERCLEANFILES, see -# pango/Makefile.am. +# Makefile.am.sample in the git.mk git repo. # # Don't EXTRA_DIST this file. It is supposed to only live in git clones, # not tarballs. It serves no useful purpose in tarballs and clutters the # build dir. # # This file knows how to handle autoconf, automake, libtool, gtk-doc, -# gnome-doc-utils, intltool. +# gnome-doc-utils, yelp.m4, mallard, intltool, gsettings, dejagnu, appdata, +# appstream. # +# This makefile provides the following targets: +# +# - all: "make all" will build all gitignore files. +# - gitignore: makes all gitignore files in the current dir and subdirs. +# - .gitignore: make gitignore file for the current dir. +# - gitignore-recurse: makes all gitignore files in the subdirs. # # KNOWN ISSUES: # @@ -53,13 +67,74 @@ # example. # + + +############################################################################### +# Variables user modules may want to add to toplevel MAINTAINERCLEANFILES: +############################################################################### + +# +# Most autotools-using modules should be fine including this variable in their +# toplevel MAINTAINERCLEANFILES: +GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL = \ + $(srcdir)/aclocal.m4 \ + $(srcdir)/autoscan.log \ + $(srcdir)/configure.scan \ + `AUX_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_AUX_DIR:$$1' ./configure.ac); \ + test "x$$AUX_DIR" = "x$(srcdir)/" && AUX_DIR=$(srcdir); \ + for x in \ + ar-lib \ + compile \ + config.guess \ + config.sub \ + depcomp \ + install-sh \ + ltmain.sh \ + missing \ + mkinstalldirs \ + test-driver \ + ylwrap \ + ; do echo "$$AUX_DIR/$$x"; done` \ + `cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_HEADERS:$$1' ./configure.ac | \ + head -n 1 | while read f; do echo "$(srcdir)/$$f.in"; done` +# +# All modules should also be fine including the following variable, which +# removes automake-generated Makefile.in files: +GITIGNORE_MAINTAINERCLEANFILES_MAKEFILE_IN = \ + `cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_FILES:$$1' ./configure.ac | \ + while read f; do \ + case $$f in Makefile|*/Makefile) \ + test -f "$(srcdir)/$$f.am" && echo "$(srcdir)/$$f.in";; esac; \ + done` +# +# Modules that use libtool and use AC_CONFIG_MACRO_DIR() may also include this, +# though it's harmless to include regardless. +GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL = \ + `MACRO_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_MACRO_DIR:$$1' ./configure.ac); \ + if test "x$$MACRO_DIR" != "x$(srcdir)/"; then \ + for x in \ + libtool.m4 \ + ltoptions.m4 \ + ltsugar.m4 \ + ltversion.m4 \ + lt~obsolete.m4 \ + ; do echo "$$MACRO_DIR/$$x"; done; \ + fi` + + + +############################################################################### +# Default rule is to install ourselves in all Makefile.am files: +############################################################################### + git-all: git-mk-install git-mk-install: - @echo Installing git makefile - @any_failed=; find $(top_srcdir) -name Makefile.am | while read x; do \ + @echo "Installing git makefile" + @any_failed=; \ + find "`test -z "$(top_srcdir)" && echo . || echo "$(top_srcdir)"`" -name Makefile.am | while read x; do \ if grep 'include .*/git.mk' $$x >/dev/null; then \ - echo $$x already includes git.mk; \ + echo "$$x already includes git.mk"; \ else \ failed=; \ echo "Updating $$x"; \ @@ -71,55 +146,114 @@ git-mk-install: mv $$x.tmp $$x || failed=1; \ fi; \ if test x$$failed = x; then : else \ - echo Failed updating $$x; >&2 \ + echo "Failed updating $$x"; >&2 \ any_failed=1; \ fi; \ fi; done; test -z "$$any_failed" -.PHONY: git-all git-mk-install +git-mk-update: + wget $(GIT_MK_URL) -O $(top_srcdir)/git.mk + +.PHONY: git-all git-mk-install git-mk-update -### .gitignore generation + +############################################################################### +# Actual .gitignore generation: +############################################################################### $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk - $(AM_V_GEN) \ - { \ + @echo "git.mk: Generating $@" + @{ \ if test "x$(DOC_MODULE)" = x -o "x$(DOC_MAIN_SGML_FILE)" = x; then :; else \ for x in \ $(DOC_MODULE)-decl-list.txt \ $(DOC_MODULE)-decl.txt \ tmpl/$(DOC_MODULE)-unused.sgml \ "tmpl/*.bak" \ + $(REPORT_FILES) \ + $(DOC_MODULE).pdf \ xml html \ - ; do echo /$$x; done; \ + ; do echo "/$$x"; done; \ + FLAVOR=$$(cd $(top_srcdir); $(AUTOCONF) --trace 'GTK_DOC_CHECK:$$2' ./configure.ac); \ + case $$FLAVOR in *no-tmpl*) echo /tmpl;; esac; \ + if echo "$(SCAN_OPTIONS)" | grep -q "\-\-rebuild-types"; then \ + echo "/$(DOC_MODULE).types"; \ + fi; \ + if echo "$(SCAN_OPTIONS)" | grep -q "\-\-rebuild-sections"; then \ + echo "/$(DOC_MODULE)-sections.txt"; \ + fi; \ + if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + for x in \ + $(SETUP_FILES) \ + $(DOC_MODULE).types \ + ; do echo "/$$x"; done; \ + fi; \ fi; \ - if test "x$(DOC_MODULE)" = x -o "x$(DOC_LINGUAS)" = x; then :; else \ + if test "x$(DOC_MODULE)$(DOC_ID)" = x -o "x$(DOC_LINGUAS)" = x; then :; else \ + for lc in $(DOC_LINGUAS); do \ + for x in \ + $(if $(DOC_MODULE),$(DOC_MODULE).xml) \ + $(DOC_PAGES) \ + $(DOC_INCLUDES) \ + ; do echo "/$$lc/$$x"; done; \ + done; \ for x in \ - $(_DOC_C_DOCS) \ - $(_DOC_LC_DOCS) \ $(_DOC_OMF_ALL) \ $(_DOC_DSK_ALL) \ $(_DOC_HTML_ALL) \ - $(_DOC_POFILES) \ + $(_DOC_MOFILES) \ + $(DOC_H_FILE) \ "*/.xml2po.mo" \ "*/*.omf.out" \ ; do echo /$$x; done; \ fi; \ + if test "x$(HELP_ID)" = x -o "x$(HELP_LINGUAS)" = x; then :; else \ + for lc in $(HELP_LINGUAS); do \ + for x in \ + $(HELP_FILES) \ + "$$lc.stamp" \ + "$$lc.mo" \ + ; do echo "/$$lc/$$x"; done; \ + done; \ + fi; \ + if test "x$(gsettings_SCHEMAS)" = x; then :; else \ + for x in \ + $(gsettings_SCHEMAS:.xml=.valid) \ + $(gsettings__enum_file) \ + ; do echo "/$$x"; done; \ + fi; \ + if test "x$(appdata_XML)" = x; then :; else \ + for x in \ + $(appdata_XML:.xml=.valid) \ + ; do echo "/$$x"; done; \ + fi; \ + if test "x$(appstream_XML)" = x; then :; else \ + for x in \ + $(appstream_XML:.xml=.valid) \ + ; do echo "/$$x"; done; \ + fi; \ if test -f $(srcdir)/po/Makefile.in.in; then \ for x in \ po/Makefile.in.in \ + po/Makefile.in.in~ \ po/Makefile.in \ po/Makefile \ + po/Makevars.template \ po/POTFILES \ + po/Rules-quot \ po/stamp-it \ po/.intltool-merge-cache \ "po/*.gmo" \ + "po/*.header" \ "po/*.mo" \ + "po/*.sed" \ + "po/*.sin" \ po/$(GETTEXT_PACKAGE).pot \ intltool-extract.in \ intltool-merge.in \ intltool-update.in \ - ; do echo /$$x; done; \ + ; do echo "/$$x"; done; \ fi; \ if test -f $(srcdir)/configure; then \ for x in \ @@ -129,21 +263,38 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk stamp-h1 \ libtool \ config.lt \ - ; do echo /$$x; done; \ + ; do echo "/$$x"; done; \ + fi; \ + if test "x$(DEJATOOL)" = x; then :; else \ + for x in \ + $(DEJATOOL) \ + ; do echo "/$$x.sum"; echo "/$$x.log"; done; \ + echo /site.exp; \ + fi; \ + if test "x$(am__dirstamp)" = x; then :; else \ + echo "$(am__dirstamp)"; \ + fi; \ + if test "x$(LTCOMPILE)" = x -a "x$(LTCXXCOMPILE)" = x -a "x$(GTKDOC_RUN)" = x; then :; else \ + for x in \ + "*.lo" \ + ".libs" "_libs" \ + ; do echo "$$x"; done; \ fi; \ for x in \ .gitignore \ $(GITIGNOREFILES) \ $(CLEANFILES) \ - $(PROGRAMS) \ - $(check_PROGRAMS) \ - $(EXTRA_PROGRAMS) \ - $(LTLIBRARIES) \ + $(PROGRAMS) $(check_PROGRAMS) $(EXTRA_PROGRAMS) \ + $(LIBRARIES) $(check_LIBRARIES) $(EXTRA_LIBRARIES) \ + $(LTLIBRARIES) $(check_LTLIBRARIES) $(EXTRA_LTLIBRARIES) \ so_locations \ - .libs _libs \ $(MOSTLYCLEANFILES) \ - "*.$(OBJEXT)" \ - "*.lo" \ + $(TEST_LOGS) \ + $(TEST_LOGS:.log=.trs) \ + $(TEST_SUITE_LOG) \ + $(TESTS:=.test) \ + "*.gcda" \ + "*.gcno" \ $(DISTCLEANFILES) \ $(am__CONFIG_DISTCLEAN_FILES) \ $(CONFIG_CLEAN_FILES) \ @@ -151,7 +302,10 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk "*.tab.c" \ $(MAINTAINERCLEANFILES) \ $(BUILT_SOURCES) \ - $(DEPDIR) \ + $(patsubst %.vala,%.c,$(filter %.vala,$(SOURCES))) \ + $(filter %_vala.stamp,$(DIST_COMMON)) \ + $(filter %.vapi,$(DIST_COMMON)) \ + $(filter $(addprefix %,$(notdir $(patsubst %.vapi,%.h,$(filter %.vapi,$(DIST_COMMON))))),$(DIST_COMMON)) \ Makefile \ Makefile.in \ "*.orig" \ @@ -159,7 +313,12 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk "*.bak" \ "*~" \ ".*.sw[nop]" \ - ; do echo /$$x; done; \ + ".dirstamp" \ + ; do echo "/$$x"; done; \ + for x in \ + "*.$(OBJEXT)" \ + $(DEPDIR) \ + ; do echo "$$x"; done; \ } | \ sed "s@^/`echo "$(srcdir)" | sed 's/\(.\)/[\1]/g'`/@/@" | \ sed 's@/[.]/@/@g' | \ @@ -167,16 +326,20 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk mv $@.tmp $@; all: $(srcdir)/.gitignore gitignore-recurse-maybe -gitignore-recurse-maybe: - @if test "x$(SUBDIRS)" = "x$(DIST_SUBDIRS)"; then :; else \ - $(MAKE) $(AM_MAKEFLAGS) gitignore-recurse; \ - fi; -gitignore-recurse: - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) .gitignore gitignore-recurse || echo "Skipping $$subdir"); \ - done gitignore: $(srcdir)/.gitignore gitignore-recurse +gitignore-recurse-maybe: + @for subdir in $(DIST_SUBDIRS); do \ + case " $(SUBDIRS) " in \ + *" $$subdir "*) :;; \ + *) test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore || echo "Skipping $$subdir");; \ + esac; \ + done +gitignore-recurse: + @for subdir in $(DIST_SUBDIRS); do \ + test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore || echo "Skipping $$subdir"); \ + done + maintainer-clean: gitignore-clean gitignore-clean: -rm -f $(srcdir)/.gitignore diff --git a/gfx/harfbuzz/harfbuzz.doap b/gfx/harfbuzz/harfbuzz.doap new file mode 100644 index 000000000..d2896ebef --- /dev/null +++ b/gfx/harfbuzz/harfbuzz.doap @@ -0,0 +1,24 @@ + + + harfbuzz + Text shaping library + + + + + + + + + Behdad Esfahbod + + + + diff --git a/gfx/harfbuzz/harfbuzz.pc.in b/gfx/harfbuzz/harfbuzz.pc.in deleted file mode 100644 index e92319e15..000000000 --- a/gfx/harfbuzz/harfbuzz.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: harfbuzz -Description: Text shaping library -Version: @VERSION@ - -Libs: -L${libdir} -lharfbuzz -Cflags: -I${includedir}/harfbuzz diff --git a/gfx/harfbuzz/src/Makefile.am b/gfx/harfbuzz/src/Makefile.am index fe14287a2..0c077d990 100644 --- a/gfx/harfbuzz/src/Makefile.am +++ b/gfx/harfbuzz/src/Makefile.am @@ -1,6 +1,5 @@ # Process this file with automake to produce Makefile.in -NULL = SUBDIRS = DIST_SUBDIRS = BUILT_SOURCES = @@ -19,120 +18,25 @@ fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la lib_LTLIBRARIES = libharfbuzz.la +include Makefile.sources + HBCFLAGS = HBLIBS = HBNONPCLIBS = HBDEPS = -HBSOURCES = \ - hb-atomic-private.hh \ - hb-blob.cc \ - hb-buffer-deserialize-json.hh \ - hb-buffer-deserialize-text.hh \ - hb-buffer-private.hh \ - hb-buffer-serialize.cc \ - hb-buffer.cc \ - hb-cache-private.hh \ - hb-common.cc \ - hb-face-private.hh \ - hb-face.cc \ - hb-font-private.hh \ - hb-font.cc \ - hb-mutex-private.hh \ - hb-object-private.hh \ - hb-open-file-private.hh \ - hb-open-type-private.hh \ - hb-ot-cmap-table.hh \ - hb-ot-glyf-table.hh \ - hb-ot-head-table.hh \ - hb-ot-hhea-table.hh \ - hb-ot-hmtx-table.hh \ - hb-ot-maxp-table.hh \ - hb-ot-name-table.hh \ - hb-ot-tag.cc \ - hb-private.hh \ - hb-set-private.hh \ - hb-set.cc \ - hb-shape.cc \ - hb-shape-plan-private.hh \ - hb-shape-plan.cc \ - hb-shaper-list.hh \ - hb-shaper-impl-private.hh \ - hb-shaper-private.hh \ - hb-shaper.cc \ - hb-unicode-private.hh \ - hb-unicode.cc \ - hb-utf-private.hh \ - hb-warning.cc \ - $(NULL) -HBHEADERS = \ - hb.h \ - hb-blob.h \ - hb-buffer.h \ - hb-common.h \ - hb-deprecated.h \ - hb-face.h \ - hb-font.h \ - hb-set.h \ - hb-shape.h \ - hb-shape-plan.h \ - hb-unicode.h \ - $(NULL) -HBNODISTHEADERS = \ - hb-version.h \ - $(NULL) +HBSOURCES = $(HB_BASE_sources) +HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources) +HBHEADERS = $(HB_BASE_headers) +HBNODISTHEADERS = $(HB_NODIST_headers) if HAVE_OT -HBSOURCES += \ - hb-ot-font.cc \ - hb-ot-layout.cc \ - hb-ot-layout-common-private.hh \ - hb-ot-layout-gdef-table.hh \ - hb-ot-layout-gpos-table.hh \ - hb-ot-layout-gsubgpos-private.hh \ - hb-ot-layout-gsub-table.hh \ - hb-ot-layout-jstf-table.hh \ - hb-ot-layout-private.hh \ - hb-ot-map.cc \ - hb-ot-map-private.hh \ - hb-ot-shape.cc \ - hb-ot-shape-complex-arabic.cc \ - hb-ot-shape-complex-arabic-fallback.hh \ - hb-ot-shape-complex-arabic-private.hh \ - hb-ot-shape-complex-arabic-table.hh \ - hb-ot-shape-complex-arabic-win1256.hh \ - hb-ot-shape-complex-default.cc \ - hb-ot-shape-complex-hangul.cc \ - hb-ot-shape-complex-hebrew.cc \ - hb-ot-shape-complex-indic.cc \ - hb-ot-shape-complex-indic-machine.hh \ - hb-ot-shape-complex-indic-private.hh \ - hb-ot-shape-complex-indic-table.cc \ - hb-ot-shape-complex-myanmar.cc \ - hb-ot-shape-complex-myanmar-machine.hh \ - hb-ot-shape-complex-thai.cc \ - hb-ot-shape-complex-tibetan.cc \ - hb-ot-shape-complex-use.cc \ - hb-ot-shape-complex-use-machine.hh \ - hb-ot-shape-complex-use-private.hh \ - hb-ot-shape-complex-use-table.cc \ - hb-ot-shape-complex-private.hh \ - hb-ot-shape-normalize-private.hh \ - hb-ot-shape-normalize.cc \ - hb-ot-shape-fallback-private.hh \ - hb-ot-shape-fallback.cc \ - hb-ot-shape-private.hh \ - $(NULL) -HBHEADERS += \ - hb-ot.h \ - hb-ot-font.h \ - hb-ot-layout.h \ - hb-ot-shape.h \ - hb-ot-tag.h \ - $(NULL) +HBSOURCES += $(HB_OT_sources) +HBSOURCES += $(HB_OT_RAGEL_GENERATED_sources) +HBHEADERS += $(HB_OT_headers) endif if HAVE_FALLBACK -HBSOURCES += hb-fallback-shape.cc +HBSOURCES += $(HB_FALLBACK_sources) endif if HAVE_PTHREAD @@ -144,8 +48,8 @@ if HAVE_GLIB HBCFLAGS += $(GLIB_CFLAGS) HBLIBS += $(GLIB_LIBS) HBDEPS += $(GLIB_DEPS) -HBSOURCES += hb-glib.cc -HBHEADERS += hb-glib.h +HBSOURCES += $(HB_GLIB_sources) +HBHEADERS += $(HB_GLIB_headers) endif if HAVE_FREETYPE @@ -157,37 +61,44 @@ HBLIBS += $(FREETYPE_LIBS) # fine but pkg-config 0.26 as shipped in Ubuntu 14.04 crashes. Remove # in a year or two, or otherwise work around it... #HBDEPS += $(FREETYPE_DEPS) -HBSOURCES += hb-ft.cc -HBHEADERS += hb-ft.h +HBSOURCES += $(HB_FT_sources) +HBHEADERS += $(HB_FT_headers) endif if HAVE_GRAPHITE2 HBCFLAGS += $(GRAPHITE2_CFLAGS) HBLIBS += $(GRAPHITE2_LIBS) HBDEPS += $(GRAPHITE2_DEPS) -HBSOURCES += hb-graphite2.cc -HBHEADERS += hb-graphite2.h +HBSOURCES += $(HB_GRAPHITE2_sources) +HBHEADERS += $(HB_GRAPHITE2_headers) endif if HAVE_UNISCRIBE HBCFLAGS += $(UNISCRIBE_CFLAGS) HBNONPCLIBS += $(UNISCRIBE_LIBS) -HBSOURCES += hb-uniscribe.cc -HBHEADERS += hb-uniscribe.h +HBSOURCES += $(HB_UNISCRIBE_sources) +HBHEADERS += $(HB_UNISCRIBE_headers) +endif + +if HAVE_DIRECTWRITE +HBCFLAGS += $(DIRECTWRITE_CXXFLAGS) +HBNONPCLIBS += $(DIRECTWRITE_LIBS) +HBSOURCES += $(HB_DIRECTWRITE_sources) +HBHEADERS += $(HB_DIRECTWRITE_headers) endif if HAVE_CORETEXT HBCFLAGS += $(CORETEXT_CFLAGS) HBNONPCLIBS += $(CORETEXT_LIBS) -HBSOURCES += hb-coretext.cc -HBHEADERS += hb-coretext.h +HBSOURCES += $(HB_CORETEXT_sources) +HBHEADERS += $(HB_CORETEXT_headers) endif if HAVE_UCDN SUBDIRS += hb-ucdn HBCFLAGS += -I$(srcdir)/hb-ucdn HBLIBS += hb-ucdn/libhb-ucdn.la -HBSOURCES += hb-ucdn.cc +HBSOURCES += $(HB_UCDN_sources) endif DIST_SUBDIRS += hb-ucdn @@ -221,6 +132,7 @@ pkgconfig_DATA = harfbuzz.pc EXTRA_DIST += harfbuzz.pc.in FUZZING_CPPFLAGS= \ + -DHB_NDEBUG \ -DHB_MAX_NESTING_LEVEL=3 \ -DHB_SANITIZE_MAX_EDITS=3 \ -DHB_BUFFER_MAX_EXPANSION_FACTOR=3 \ @@ -237,34 +149,41 @@ EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES) CLEANFILES += libharfbuzz-fuzzing.la if HAVE_ICU +if HAVE_ICU_BUILTIN +HBCFLAGS += $(ICU_CFLAGS) +HBLIBS += $(ICU_LIBS) +HBSOURCES += $(HB_ICU_sources) +HBHEADERS += $(HB_ICU_headers) +else lib_LTLIBRARIES += libharfbuzz-icu.la -libharfbuzz_icu_la_SOURCES = hb-icu.cc +libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources) libharfbuzz_icu_la_CPPFLAGS = $(ICU_CFLAGS) libharfbuzz_icu_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la -pkginclude_HEADERS += hb-icu.h +pkginclude_HEADERS += $(HB_ICU_headers) pkgconfig_DATA += harfbuzz-icu.pc endif +endif EXTRA_DIST += harfbuzz-icu.pc.in if HAVE_GOBJECT lib_LTLIBRARIES += libharfbuzz-gobject.la -libharfbuzz_gobject_la_SOURCES = hb-gobject-structs.cc -nodist_libharfbuzz_gobject_la_SOURCES = hb-gobject-enums.cc +libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_sources) +nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_ENUM_sources) libharfbuzz_gobject_la_CPPFLAGS = $(GOBJECT_CFLAGS) libharfbuzz_gobject_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined libharfbuzz_gobject_la_LIBADD = $(GOBJECT_LIBS) libharfbuzz.la -pkginclude_HEADERS += hb-gobject.h hb-gobject-structs.h -nodist_pkginclude_HEADERS += hb-gobject-enums.h +pkginclude_HEADERS += $(HB_GOBJECT_headers) +nodist_pkginclude_HEADERS += $(HB_GOBJECT_ENUM_headers) pkgconfig_DATA += harfbuzz-gobject.pc BUILT_SOURCES += \ - hb-gobject-enums.cc \ - hb-gobject-enums.h \ + $(HB_GOBJECT_ENUM_sources) \ + $(HB_GOBJECT_ENUM_headers) \ $(NULL) DISTCLEANFILES += \ - hb-gobject-enums.cc \ - hb-gobject-enums.h \ + $(HB_GOBJECT_ENUM_sources) \ + $(HB_GOBJECT_ENUM_headers) \ $(NULL) hb-gobject-enums.%: hb-gobject-enums.%.tmpl $(HBHEADERS) $(AM_V_GEN) $(GLIB_MKENUMS) \ @@ -301,7 +220,7 @@ harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS) (cat $^ || echo 'hb_ERROR ()' ) | \ $(EGREP) '^hb_.* \(' | \ sed -e 's/ (.*//' | \ - LANG=C sort; \ + LC_ALL=C sort; \ echo LIBRARY libharfbuzz-0.dll; \ ) >"$@" @ ! grep -q hb_ERROR "$@" \ @@ -334,19 +253,13 @@ built-sources: $(BUILT_SOURCES) .PHONY: unicode-tables arabic-table indic-table use-table built-sources 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-use-machine.hh \ + $(patsubst %,$(srcdir)/%,$(HB_BASE_RAGEL_GENERATED_sources)) \ + $(patsubst %,$(srcdir)/%,$(HB_OT_RAGEL_GENERATED_sources)) \ $(NULL) BUILT_SOURCES += $(RAGEL_GENERATED) EXTRA_DIST += \ - hb-buffer-deserialize-json.rl \ - hb-buffer-deserialize-text.rl \ - hb-ot-shape-complex-indic-machine.rl \ - hb-ot-shape-complex-myanmar-machine.rl \ - hb-ot-shape-complex-use-machine.rl \ + $(HB_BASE_RAGEL_sources) \ + $(HB_OT_RAGEL_sources) \ $(NULL) MAINTAINERCLEANFILES += $(RAGEL_GENERATED) $(srcdir)/%.hh: $(srcdir)/%.rl @@ -382,6 +295,8 @@ test_buffer_serialize_SOURCES = test-buffer-serialize.cc test_buffer_serialize_CPPFLAGS = $(HBCFLAGS) test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS) +check: harfbuzz.def # For check-defs.sh + dist_check_SCRIPTS = \ check-c-linkage-decls.sh \ check-defs.sh \ @@ -392,7 +307,14 @@ dist_check_SCRIPTS = \ check-symbols.sh \ $(NULL) -TESTS = $(dist_check_SCRIPTS) +check_PROGRAMS = \ + test-ot-tag \ + $(NULL) +test_ot_tag_SOURCES = hb-ot-tag.cc +test_ot_tag_CPPFLAGS = $(HBCFLAGS) -DMAIN +test_ot_tag_LDADD = libharfbuzz.la $(HBLIBS) + +TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS) TESTS_ENVIRONMENT = \ srcdir="$(srcdir)" \ MAKE="$(MAKE) $(AM_MAKEFLAGS)" \ @@ -419,6 +341,7 @@ HarfBuzz_0_0_gir_CFLAGS = \ -DHB_OT_H_IN \ -DHB_GOBJECT_H \ -DHB_GOBJECT_H_IN \ + -DHB_EXTERN= \ $(NULL) HarfBuzz_0_0_gir_LIBS = \ libharfbuzz.la \ @@ -428,10 +351,10 @@ HarfBuzz_0_0_gir_FILES = \ $(HBHEADERS) \ $(HBNODISTHEADERS) \ $(HBSOURCES) \ - hb-gobject-enums.cc \ - hb-gobject-enums.h \ - hb-gobject-structs.cc \ - hb-gobject-structs.h \ + $(HB_GOBJECT_ENUM_sources) \ + $(HB_GOBJECT_ENUM_headers) \ + $(HB_GOBJECT_sources) \ + $(HB_GOBJECT_STRUCTS_headers) \ $(NULL) girdir = $(datadir)/gir-1.0 diff --git a/gfx/harfbuzz/src/Makefile.in b/gfx/harfbuzz/src/Makefile.in deleted file mode 100644 index b28584491..000000000 --- a/gfx/harfbuzz/src/Makefile.in +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (C) 2010 Mozilla Foundation -# -# This is used to integrate the HarfBuzz library with the Mozilla build. -# -# Permission is hereby granted, without written agreement and without -# license or royalty fees, to use, copy, modify, and distribute this -# software and its documentation for any purpose, provided that the -# above copyright notice and the following two paragraphs appear in -# all copies of this software. -# -# IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR -# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES -# ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN -# IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -# DAMAGE. -# -# THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, -# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -# FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS -# ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO -# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. -# -# Mozilla author(s): Jonathan Kew -# - -include $(topsrcdir)/config/rules.mk - -# Cancel the effect of the -DDEBUG macro if present, -# because harfbuzz uses that name for its own purposes -COMPILE_CXXFLAGS += -UDEBUG diff --git a/gfx/harfbuzz/src/check-defs.sh b/gfx/harfbuzz/src/check-defs.sh index 65a24670e..480d49992 100755 --- a/gfx/harfbuzz/src/check-defs.sh +++ b/gfx/harfbuzz/src/check-defs.sh @@ -21,7 +21,7 @@ for def in $defs; do lib=`echo "$def" | sed 's/[.]def$//;s@.*/@@'` so=.libs/lib${lib}.so - 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`" + 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`" if test -f "$so"; then diff --git a/gfx/harfbuzz/src/check-header-guards.sh b/gfx/harfbuzz/src/check-header-guards.sh index 9a3302c7f..09c5ea8b2 100755 --- a/gfx/harfbuzz/src/check-header-guards.sh +++ b/gfx/harfbuzz/src/check-header-guards.sh @@ -9,13 +9,12 @@ stat=0 test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'` test "x$HBSOURCES" = x && HBSOURCES=`cd "$srcdir"; find . -maxdepth 1 -name 'hb-*.cc' -or -name 'hb-*.hh'` - for x in $HBHEADERS $HBSOURCES; do test -f "$srcdir/$x" && x="$srcdir/$x" - echo "$x" | grep '[^h]$' -q && continue; + echo "$x" | grep -q '[^h]$' && continue; xx=`echo "$x" | sed 's@.*/@@'` tag=`echo "$xx" | tr 'a-z.-' 'A-Z_'` - lines=`grep "\<$tag\>" "$x" | wc -l | sed 's/[ ]*//g'` + lines=`grep -w "$tag" "$x" | wc -l | sed 's/[ ]*//g'` if test "x$lines" != x3; then echo "Ouch, header file $x does not have correct preprocessor guards" stat=1 diff --git a/gfx/harfbuzz/src/check-symbols.sh b/gfx/harfbuzz/src/check-symbols.sh index b2bf43fce..d4d655d26 100755 --- a/gfx/harfbuzz/src/check-symbols.sh +++ b/gfx/harfbuzz/src/check-symbols.sh @@ -19,8 +19,8 @@ tested=false 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__\>\| __gcov_flush\>\| llvm_' | 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\>\| ___gcov_flush\>\| llvm_\| _llvm_' | cut -d' ' -f3`" prefix=`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'` diff --git a/gfx/harfbuzz/src/gen-arabic-table.py b/gfx/harfbuzz/src/gen-arabic-table.py index 308435f99..59bd76012 100755 --- a/gfx/harfbuzz/src/gen-arabic-table.py +++ b/gfx/harfbuzz/src/gen-arabic-table.py @@ -134,7 +134,7 @@ def print_joining_table(f): for (start,end) in ranges: if p not in [start>>page_bits, end>>page_bits]: continue offset = "joining_offset_0x%04xu" % start - print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return joining_table[u - 0x%04Xu + %s];" % (start, end, start, offset) + print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return joining_table[u - 0x%04Xu + %s];" % (start, end, start, offset) print " break;" print "" print " default:" diff --git a/gfx/harfbuzz/src/gen-indic-table.py b/gfx/harfbuzz/src/gen-indic-table.py index f5716bda7..a849db18e 100755 --- a/gfx/harfbuzz/src/gen-indic-table.py +++ b/gfx/harfbuzz/src/gen-indic-table.py @@ -3,10 +3,32 @@ import sys if len (sys.argv) != 4: - print >>sys.stderr, "usage: ./gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt" + print >>sys.stderr, "usage: ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt" sys.exit (1) -BLACKLISTED_BLOCKS = ["Thai", "Lao", "Tibetan"] +ALLOWED_SINGLES = [0x00A0, 0x25CC] +ALLOWED_BLOCKS = [ + 'Basic Latin', + 'Latin-1 Supplement', + 'Devanagari', + 'Bengali', + 'Gurmukhi', + 'Gujarati', + 'Oriya', + 'Tamil', + 'Telugu', + 'Kannada', + 'Malayalam', + 'Sinhala', + 'Myanmar', + 'Khmer', + 'Vedic Extensions', + 'General Punctuation', + 'Superscripts and Subscripts', + 'Devanagari Extended', + 'Myanmar Extended-B', + 'Myanmar Extended-A', +] files = [file (x) for x in sys.argv[1:]] @@ -50,7 +72,7 @@ for i,d in enumerate (data): if not u in combined: combined[u] = list (defaults) combined[u][i] = v -combined = {k:v for k,v in combined.items() if v[2] not in BLACKLISTED_BLOCKS} +combined = {k:v for k,v in combined.items() if k in ALLOWED_SINGLES or v[2] in ALLOWED_BLOCKS} data = combined del combined num = len (data) @@ -61,7 +83,7 @@ for u in [0x17CD, 0x17CE, 0x17CF, 0x17D0, 0x17D3]: # Move the outliers NO-BREAK SPACE and DOTTED CIRCLE out singles = {} -for u in [0x00A0, 0x25CC]: +for u in ALLOWED_SINGLES: singles[u] = data[u] del data[u] @@ -69,7 +91,7 @@ print "/* == Start of generated table == */" print "/*" print " * The following table is generated by running:" print " *" -print " * ./gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt" +print " * ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt" print " *" print " * on files with these headers:" print " *" @@ -91,6 +113,7 @@ short = [{ "Visarga": 'Vs', "Vowel": 'Vo', "Vowel_Dependent": 'M', + "Consonant_Prefixed": 'CPrf', "Other": 'x', },{ "Not_Applicable": 'x', @@ -209,7 +232,7 @@ for p in sorted(pages): for (start,end) in zip (starts, ends): if p not in [start>>page_bits, end>>page_bits]: continue offset = "indic_offset_0x%04xu" % start - print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset) + print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset) for u,d in singles.items (): if p != u>>page_bits: continue print " if (unlikely (u == 0x%04Xu)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]]) diff --git a/gfx/harfbuzz/src/gen-use-table.py b/gfx/harfbuzz/src/gen-use-table.py index be04e4ba4..fcb66a580 100755 --- a/gfx/harfbuzz/src/gen-use-table.py +++ b/gfx/harfbuzz/src/gen-use-table.py @@ -144,36 +144,38 @@ globals().update(property_values) def is_BASE(U, UISC, UGC): return (UISC in [Number, Consonant, Consonant_Head_Letter, - #SPEC-OUTDATED Consonant_Placeholder, - Tone_Letter] or + #SPEC-DRAFT Consonant_Placeholder, + Tone_Letter, + Vowel_Independent #SPEC-DRAFT + ] or (UGC == Lo and UISC in [Avagraha, Bindu, Consonant_Final, Consonant_Medial, Consonant_Subjoined, Vowel, Vowel_Dependent])) -def is_BASE_VOWEL(U, UISC, UGC): - return UISC == Vowel_Independent def is_BASE_IND(U, UISC, UGC): - #SPEC-BROKEN return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po) + #SPEC-DRAFT return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po) return (UISC in [Consonant_Dead, Modifying_Letter] or - (UGC == Po and not is_BASE_OTHER(U, UISC, UGC))) # for 104E + (UGC == Po and not U in [0x104E, 0x2022]) or + False # SPEC-DRAFT-OUTDATED! U == 0x002D + ) def is_BASE_NUM(U, UISC, UGC): return UISC == Brahmi_Joining_Number def is_BASE_OTHER(U, UISC, UGC): - if UISC == Consonant_Placeholder: return True #SPEC-OUTDATED - return U in [0x00A0, 0x00D7, 0x2015, 0x2022, 0x25CC, - 0x25FB, 0x25FC, 0x25FD, 0x25FE] + if UISC == Consonant_Placeholder: return True #SPEC-DRAFT + #SPEC-DRAFT return U in [0x00A0, 0x00D7, 0x2015, 0x2022, 0x25CC, 0x25FB, 0x25FC, 0x25FD, 0x25FE] + return U in [0x2015, 0x2022, 0x25FB, 0x25FC, 0x25FD, 0x25FE] def is_CGJ(U, UISC, UGC): return U == 0x034F def is_CONS_FINAL(U, UISC, UGC): return ((UISC == Consonant_Final and UGC != Lo) or UISC == Consonant_Succeeding_Repha) def is_CONS_FINAL_MOD(U, UISC, UGC): - #SPEC-OUTDATED return UISC in [Consonant_Final_Modifier, Syllable_Modifier] + #SPEC-DRAFT return UISC in [Consonant_Final_Modifier, Syllable_Modifier] return UISC == Syllable_Modifier def is_CONS_MED(U, UISC, UGC): return UISC == Consonant_Medial and UGC != Lo def is_CONS_MOD(U, UISC, UGC): return UISC in [Nukta, Gemination_Mark, Consonant_Killer] def is_CONS_SUB(U, UISC, UGC): - #SPEC-OUTDATED return UISC == Consonant_Subjoined + #SPEC-DRAFT return UISC == Consonant_Subjoined return UISC == Consonant_Subjoined and UGC != Lo def is_HALANT(U, UISC, UGC): return UISC in [Virama, Invisible_Stacker] @@ -200,23 +202,24 @@ def is_REPHA(U, UISC, UGC): #SPEC-OUTDATED hack to categorize Consonant_With_Stacker and Consonant_Prefixed return UISC in [Consonant_Preceding_Repha, Consonant_With_Stacker, Consonant_Prefixed] def is_SYM(U, UISC, UGC): - if U == 0x25CC: return False #SPEC-OUTDATED - #SPEC-OUTDATED return UGC in [So, Sc] or UISC == Symbol_Letter + if U == 0x25CC: return False #SPEC-DRAFT + #SPEC-DRAFT return UGC in [So, Sc] or UISC == Symbol_Letter return UGC in [So, Sc] def is_SYM_MOD(U, UISC, UGC): return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73] def is_VARIATION_SELECTOR(U, UISC, UGC): return 0xFE00 <= U <= 0xFE0F def is_VOWEL(U, UISC, UGC): + # https://github.com/roozbehp/unicode-data/issues/6 return (UISC == Pure_Killer or - (UGC != Lo and UISC in [Vowel, Vowel_Dependent])) + (UGC != Lo and UISC in [Vowel, Vowel_Dependent] and U not in [0xAA29])) def is_VOWEL_MOD(U, UISC, UGC): + # https://github.com/roozbehp/unicode-data/issues/6 return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or - (UGC != Lo and UISC == Bindu)) + (UGC != Lo and (UISC == Bindu or U in [0xAA29]))) use_mapping = { 'B': is_BASE, - 'IV': is_BASE_VOWEL, 'IND': is_BASE_IND, 'N': is_BASE_NUM, 'GB': is_BASE_OTHER, @@ -448,7 +451,7 @@ for p in sorted(pages): for (start,end) in zip (starts, ends): if p not in [start>>page_bits, end>>page_bits]: continue offset = "use_offset_0x%04xu" % start - print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return use_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset) + print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return use_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset) for u,d in singles.items (): if p != u>>page_bits: continue print " if (unlikely (u == 0x%04Xu)) return %s;" % (u, d[0]) diff --git a/gfx/harfbuzz/src/harfbuzz-icu.pc b/gfx/harfbuzz/src/harfbuzz-icu.pc index 2926494d6..69c1cc9b5 100644 --- a/gfx/harfbuzz/src/harfbuzz-icu.pc +++ b/gfx/harfbuzz/src/harfbuzz-icu.pc @@ -5,7 +5,7 @@ includedir=/usr/local/include Name: harfbuzz Description: HarfBuzz text shaping library ICU integration -Version: 1.0.1 +Version: 1.5.1 Requires: harfbuzz Requires.private: icu-uc diff --git a/gfx/harfbuzz/src/harfbuzz.pc b/gfx/harfbuzz/src/harfbuzz.pc index 297310967..4269ed807 100644 --- a/gfx/harfbuzz/src/harfbuzz.pc +++ b/gfx/harfbuzz/src/harfbuzz.pc @@ -5,7 +5,9 @@ includedir=/usr/local/include Name: harfbuzz Description: HarfBuzz text shaping library -Version: 1.0.1 +Version: 1.5.1 Libs: -L${libdir} -lharfbuzz +Libs.private: +Requires.private: glib-2.0 >= 2.19.1 Cflags: -I${includedir}/harfbuzz diff --git a/gfx/harfbuzz/src/hb-atomic-private.hh b/gfx/harfbuzz/src/hb-atomic-private.hh index 8179571ad..2d5675792 100644 --- a/gfx/harfbuzz/src/hb-atomic-private.hh +++ b/gfx/harfbuzz/src/hb-atomic-private.hh @@ -119,6 +119,31 @@ typedef unsigned int hb_atomic_int_impl_t; #define hb_atomic_ptr_impl_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false) +#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__) + +#include + + +static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) { + __lwsync(); + int result = __fetch_and_add(AI, V); + __isync(); + return result; +} +static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) { + __sync(); + int result = __compare_and_swaplp (P, &O, N); + __sync(); + return result; +} + +typedef int hb_atomic_int_impl_t; +#define HB_ATOMIC_INT_IMPL_INIT(V) (V) +#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add (&(AI), (V)) + +#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N)) + #elif !defined(HB_NO_MT) #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ diff --git a/gfx/harfbuzz/src/hb-blob.cc b/gfx/harfbuzz/src/hb-blob.cc index b96b3158c..e28f4ea9d 100644 --- a/gfx/harfbuzz/src/hb-blob.cc +++ b/gfx/harfbuzz/src/hb-blob.cc @@ -104,7 +104,6 @@ hb_blob_create (const char *data, if (!length || length >= 1u << 31 || - data + length < data /* overflows */ || !(blob = hb_object_create ())) { if (destroy) destroy (user_data); @@ -328,7 +327,7 @@ hb_blob_is_immutable (hb_blob_t *blob) unsigned int hb_blob_get_length (hb_blob_t *blob) { -if (!blob) return 0; // wallpaper TenFourFox issue 309 + if(unlikely(!blob)) return 0; // wallpaper TenFourFox issue 309 return blob->length; } diff --git a/gfx/harfbuzz/src/hb-blob.h b/gfx/harfbuzz/src/hb-blob.h index b2419abfd..ef3fc98c0 100644 --- a/gfx/harfbuzz/src/hb-blob.h +++ b/gfx/harfbuzz/src/hb-blob.h @@ -64,7 +64,7 @@ typedef enum { typedef struct hb_blob_t hb_blob_t; -hb_blob_t * +HB_EXTERN hb_blob_t * hb_blob_create (const char *data, unsigned int length, hb_memory_mode_t mode, @@ -77,21 +77,21 @@ hb_blob_create (const char *data, * modify the parent data as that data may be * shared among multiple sub-blobs. */ -hb_blob_t * +HB_EXTERN hb_blob_t * hb_blob_create_sub_blob (hb_blob_t *parent, unsigned int offset, unsigned int length); -hb_blob_t * +HB_EXTERN hb_blob_t * hb_blob_get_empty (void); -hb_blob_t * +HB_EXTERN hb_blob_t * hb_blob_reference (hb_blob_t *blob); -void +HB_EXTERN void hb_blob_destroy (hb_blob_t *blob); -hb_bool_t +HB_EXTERN hb_bool_t hb_blob_set_user_data (hb_blob_t *blob, hb_user_data_key_t *key, void * data, @@ -99,25 +99,25 @@ hb_blob_set_user_data (hb_blob_t *blob, hb_bool_t replace); -void * +HB_EXTERN void * hb_blob_get_user_data (hb_blob_t *blob, hb_user_data_key_t *key); -void +HB_EXTERN void hb_blob_make_immutable (hb_blob_t *blob); -hb_bool_t +HB_EXTERN hb_bool_t hb_blob_is_immutable (hb_blob_t *blob); -unsigned int +HB_EXTERN unsigned int hb_blob_get_length (hb_blob_t *blob); -const char * +HB_EXTERN const char * hb_blob_get_data (hb_blob_t *blob, unsigned int *length); -char * +HB_EXTERN char * hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length); diff --git a/gfx/harfbuzz/src/hb-buffer-private.hh b/gfx/harfbuzz/src/hb-buffer-private.hh index ceccecdce..37380b40d 100644 --- a/gfx/harfbuzz/src/hb-buffer-private.hh +++ b/gfx/harfbuzz/src/hb-buffer-private.hh @@ -50,14 +50,16 @@ ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)); HB_MARK_AS_FLAG_T (hb_buffer_flags_t); HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t); +HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t); enum hb_buffer_scratch_flags_t { HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u, HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII = 0x00000001u, HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u, HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u, - HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_CURSIVE = 0x00000008u, - HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000010u, + HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u, + HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u, + /* Reserved for complex shapers' internal use. */ HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u, HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u, @@ -113,10 +115,6 @@ struct hb_buffer_t { unsigned int serial; - /* These reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ - uint8_t allocated_var_bytes[8]; - const char *allocated_var_owner[8]; - /* Text before / after the main buffer contents. * Always in Unicode, and ordered outward. * Index 0 is for "pre-context", 1 for "post-context". */ @@ -124,6 +122,52 @@ struct hb_buffer_t { hb_codepoint_t context[2][CONTEXT_LENGTH]; unsigned int context_len[2]; + /* Debugging API */ + hb_buffer_message_func_t message_func; + void *message_data; + hb_destroy_func_t message_destroy; + + /* Internal debugging. */ + /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ +#ifndef HB_NDEBUG + uint8_t allocated_var_bits; +#endif + inline void allocate_var (unsigned int start, unsigned int count) + { +#ifndef HB_NDEBUG + unsigned int end = start + count; + assert (end <= 8); + unsigned int bits = (1u<len, \ + start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \ + start < _count; \ + start = end, end = _next_cluster (buffer, start)) + +static inline unsigned int +_next_cluster (hb_buffer_t *buffer, unsigned int start) +{ + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + + unsigned int cluster = info[start].cluster; + while (++start < count && cluster == info[start].cluster) + ; + + return start; +} + + +#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \ b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \ - sizeof (b->info[0].var), owner) -#define HB_BUFFER_ALLOCATE_VAR(b, var) \ - HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var (), #var) -#define HB_BUFFER_DEALLOCATE_VAR(b, var) \ - HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var (), #var) -#define HB_BUFFER_ASSERT_VAR(b, var) \ - HB_BUFFER_XALLOCATE_VAR (b, assert_var, var (), #var) + sizeof (b->info[0].var)) +#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ()) +#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ()) +#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ()) #endif /* HB_BUFFER_PRIVATE_HH */ diff --git a/gfx/harfbuzz/src/hb-buffer-serialize.cc b/gfx/harfbuzz/src/hb-buffer-serialize.cc index 7839cbc3f..517d746ef 100644 --- a/gfx/harfbuzz/src/hb-buffer-serialize.cc +++ b/gfx/harfbuzz/src/hb-buffer-serialize.cc @@ -36,11 +36,12 @@ static const char *serialize_formats[] = { /** * hb_buffer_serialize_list_formats: * - * + * Returns a list of supported buffer serialization formats. * * Return value: (transfer none): + * A string array of buffer serialization formats. Should not be freed. * - * Since: 0.9.2 + * Since: 0.9.7 **/ const char ** hb_buffer_serialize_list_formats (void) @@ -50,14 +51,17 @@ hb_buffer_serialize_list_formats (void) /** * hb_buffer_serialize_format_from_string: - * @str: - * @len: + * @str: (array length=len) (element-type uint8_t): a string to parse + * @len: length of @str, or -1 if string is %NULL terminated * - * + * Parses a string into an #hb_buffer_serialize_format_t. Does not check if + * @str is a valid buffer serialization format, use + * hb_buffer_serialize_list_formats() to get the list of supported formats. * * Return value: + * The parsed #hb_buffer_serialize_format_t. * - * Since: 0.9.2 + * Since: 0.9.7 **/ hb_buffer_serialize_format_t hb_buffer_serialize_format_from_string (const char *str, int len) @@ -68,13 +72,15 @@ hb_buffer_serialize_format_from_string (const char *str, int len) /** * hb_buffer_serialize_format_to_string: - * @format: + * @format: an #hb_buffer_serialize_format_t to convert. * - * + * Converts @format to the string corresponding it, or %NULL if it is not a valid + * #hb_buffer_serialize_format_t. * - * Return value: + * Return value: (transfer none): + * A %NULL terminated string corresponding to @format. Should not be freed. * - * Since: 0.9.2 + * Since: 0.9.7 **/ const char * hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) @@ -139,10 +145,16 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) { - p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d", - pos[i].x_offset, pos[i].y_offset); - p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d", - pos[i].x_advance, pos[i].y_advance); + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d", + pos[i].x_offset, pos[i].y_offset)); + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d", + pos[i].x_advance, pos[i].y_advance)); + } + + if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS) + { + if (info[i].mask & HB_GLYPH_FLAG_DEFINED) + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED)); } if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) @@ -150,9 +162,9 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, hb_glyph_extents_t extents; hb_font_get_glyph_extents(font, info[i].codepoint, &extents); p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", - extents.x_bearing, extents.y_bearing)); + extents.x_bearing, extents.y_bearing)); p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", - extents.width, extents.height)); + extents.width, extents.height)); } *p++ = '}'; @@ -220,6 +232,12 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); } + if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS) + { + if (info[i].mask &HB_GLYPH_FLAG_DEFINED) + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED)); + } + if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) { hb_glyph_extents_t extents; @@ -242,24 +260,51 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, return end - start; } -/* Returns number of items, starting at start, that were serialized. */ /** * hb_buffer_serialize_glyphs: - * @buffer: a buffer. - * @start: - * @end: - * @buf: (array length=buf_size): - * @buf_size: - * @buf_consumed: (out): - * @font: - * @format: - * @flags: + * @buffer: an #hb_buffer_t buffer. + * @start: the first item in @buffer to serialize. + * @end: the last item in @buffer to serialize. + * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to + * write serialized buffer into. + * @buf_size: the size of @buf. + * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf. + * @font: (allow-none): the #hb_font_t used to shape this buffer, needed to + * read glyph names and extents. If %NULL, and empty font will be used. + * @format: the #hb_buffer_serialize_format_t to use for formatting the output. + * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties + * to serialize. * - * + * Serializes @buffer into a textual representation of its glyph content, + * useful for showing the contents of the buffer, for example during debugging. + * There are currently two supported serialization formats: + * + * ## text + * A human-readable, plain text format. + * The serialized glyphs will look something like: + * + * ``` + * [uni0651=0@518,0+0|uni0628=0+1897] + * ``` + * - The serialized glyphs are delimited with `[` and `]`. + * - Glyphs are separated with `|` + * - Each glyph starts with glyph name, or glyph index if + * #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set. Then, + * - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, `=` then #hb_glyph_info_t.cluster. + * - If #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set, the #hb_glyph_position_t in the format: + * - If both #hb_glyph_position_t.x_offset and #hb_glyph_position_t.y_offset are not 0, `@x_offset,y_offset`. Then, + * - `+x_advance`, then `,y_advance` if #hb_glyph_position_t.y_advance is not 0. Then, + * - If #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set, the + * #hb_glyph_extents_t in the format + * `<x_bearing,y_bearing,width,height>` + * + * ## json + * TODO. * * Return value: + * The number of serialized items. * - * Since: 0.9.2 + * Since: 0.9.7 **/ unsigned int hb_buffer_serialize_glyphs (hb_buffer_t *buffer, @@ -267,8 +312,8 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, unsigned int end, char *buf, unsigned int buf_size, - unsigned int *buf_consumed, /* May be NULL */ - hb_font_t *font, /* May be NULL */ + unsigned int *buf_consumed, + hb_font_t *font, hb_buffer_serialize_format_t format, hb_buffer_serialize_flags_t flags) { @@ -278,10 +323,15 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, if (!buf_consumed) buf_consumed = &sconsumed; *buf_consumed = 0; + if (buf_size) + *buf = '\0'; assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); + if (!buffer->have_positions) + flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS; + if (unlikely (start == end)) return 0; @@ -355,7 +405,7 @@ parse_int (const char *pp, const char *end, int32_t *pv) /** * hb_buffer_deserialize_glyphs: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t buffer. * @buf: (array length=buf_len): * @buf_len: * @end_ptr: (out): @@ -366,7 +416,7 @@ parse_int (const char *pp, const char *end, int32_t *pv) * * Return value: * - * Since: 0.9.2 + * Since: 0.9.7 **/ hb_bool_t hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, diff --git a/gfx/harfbuzz/src/hb-buffer.cc b/gfx/harfbuzz/src/hb-buffer.cc index 7e7dceaa6..171d1016e 100644 --- a/gfx/harfbuzz/src/hb-buffer.cc +++ b/gfx/harfbuzz/src/hb-buffer.cc @@ -31,12 +31,26 @@ #include "hb-utf-private.hh" -#ifndef HB_DEBUG_BUFFER -#define HB_DEBUG_BUFFER (HB_DEBUG+0) -#endif - +/** + * SECTION: hb-buffer + * @title: Buffers + * @short_description: Input and output buffers + * @include: hb.h + * + * Buffers serve dual role in HarfBuzz; they hold the input characters that are + * passed hb_shape(), and after shaping they hold the output glyphs. + **/ /** + * hb_segment_properties_equal: + * @a: first #hb_segment_properties_t to compare. + * @b: second #hb_segment_properties_t to compare. + * + * Checks the equality of two #hb_segment_properties_t's. + * + * Return value: + * %true if all properties of @a equal those of @b, false otherwise. + * * Since: 0.9.7 **/ hb_bool_t @@ -52,6 +66,14 @@ hb_segment_properties_equal (const hb_segment_properties_t *a, } /** + * hb_segment_properties_hash: + * @p: #hb_segment_properties_t to hash. + * + * Creates a hash representing @p. + * + * Return value: + * A hash of @p. + * * Since: 0.9.7 **/ unsigned int @@ -157,6 +179,12 @@ hb_buffer_t::shift_forward (unsigned int count) if (unlikely (!ensure (len + count))) return false; memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0])); + if (idx + count > len) + { + /* Under memory failure we might expose this area. At least + * clean it up. Oh well... */ + memset (info + len, 0, (idx + count - len) * sizeof (info[0])); + } len += count; idx += count; @@ -216,11 +244,11 @@ hb_buffer_t::clear (void) out_info = info; serial = 0; - memset (allocated_var_bytes, 0, sizeof allocated_var_bytes); - memset (allocated_var_owner, 0, sizeof allocated_var_owner); memset (context, 0, sizeof context); memset (context_len, 0, sizeof context_len); + + deallocate_var_all (); } void @@ -235,7 +263,7 @@ hb_buffer_t::add (hb_codepoint_t codepoint, memset (glyph, 0, sizeof (*glyph)); glyph->codepoint = codepoint; - glyph->mask = 1; + glyph->mask = 0; glyph->cluster = cluster; len++; @@ -324,9 +352,7 @@ hb_buffer_t::replace_glyphs (unsigned int num_in, unsigned int num_out, const uint32_t *glyph_data) { - if (unlikely (!make_room_for (num_in, num_out))) - goto done; - { + if (unlikely (!make_room_for (num_in, num_out))) return; merge_clusters (idx, idx + num_in); @@ -339,50 +365,39 @@ hb_buffer_t::replace_glyphs (unsigned int num_in, pinfo++; } - out_len += num_out; - } -done: idx += num_in; + out_len += num_out; } void hb_buffer_t::output_glyph (hb_codepoint_t glyph_index) { - if (unlikely (!make_room_for (0, 1))) - goto done; + if (unlikely (!make_room_for (0, 1))) return; out_info[out_len] = info[idx]; out_info[out_len].codepoint = glyph_index; out_len++; -done: - ; } void hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info) { - if (unlikely (!make_room_for (0, 1))) - goto done; + if (unlikely (!make_room_for (0, 1))) return; out_info[out_len] = glyph_info; out_len++; -done: - ; } void hb_buffer_t::copy_glyph (void) { - if (unlikely (!make_room_for (0, 1))) - goto done; + if (unlikely (!make_room_for (0, 1))) return; out_info[out_len] = info[idx]; out_len++; -done: - ; } bool @@ -394,13 +409,15 @@ hb_buffer_t::move_to (unsigned int i) idx = i; return true; } + if (unlikely (in_error)) + return false; assert (i <= out_len + (len - idx)); if (out_len < i) { unsigned int count = i - out_len; - if (unlikely (!make_room_for (count, count))) return false; // XXX verify bailout + if (unlikely (!make_room_for (count, count))) return false; memmove (out_info + out_len, info + idx, count * sizeof (out_info[0])); idx += count; @@ -411,6 +428,8 @@ hb_buffer_t::move_to (unsigned int i) /* Tricky part: rewinding... */ unsigned int count = out_len - i; + /* This will blow in our face if memory allocation fails later + * in this same lookup... */ if (unlikely (idx < count && !shift_forward (count + 32))) return false; assert (idx >= count); @@ -427,15 +446,13 @@ void hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index) { if (unlikely (out_info != info || out_len != idx)) { - if (unlikely (!make_room_for (1, 1))) - goto out; + if (unlikely (!make_room_for (1, 1))) return; out_info[out_len] = info[idx]; } out_info[out_len].codepoint = glyph_index; - out_len++; -out: idx++; + out_len++; } @@ -529,7 +546,10 @@ hb_buffer_t::merge_clusters_impl (unsigned int start, unsigned int end) { if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) + { + unsafe_to_break (start, end); return; + } unsigned int cluster = info[start].cluster; @@ -547,10 +567,10 @@ hb_buffer_t::merge_clusters_impl (unsigned int start, /* If we hit the start of buffer, continue in out-buffer. */ if (idx == start) for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--) - out_info[i - 1].cluster = cluster; + set_cluster (out_info[i - 1], cluster); for (unsigned int i = start; i < end; i++) - info[i].cluster = cluster; + set_cluster (info[i], cluster); } void hb_buffer_t::merge_out_clusters (unsigned int start, @@ -578,14 +598,16 @@ hb_buffer_t::merge_out_clusters (unsigned int start, /* If we hit the end of out-buffer, continue in buffer. */ if (end == out_len) for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++) - info[i].cluster = cluster; + set_cluster (info[i], cluster); for (unsigned int i = start; i < end; i++) - out_info[i].cluster = cluster; + set_cluster (out_info[i], cluster); } void hb_buffer_t::delete_glyph () { + /* The logic here is duplicated in hb_ot_hide_default_ignorables(). */ + unsigned int cluster = info[idx].cluster; if (idx + 1 < len && cluster == info[idx + 1].cluster) { @@ -598,9 +620,10 @@ hb_buffer_t::delete_glyph () /* Merge cluster backward. */ if (cluster < out_info[out_len - 1].cluster) { + unsigned int mask = info[idx].mask; unsigned int old_cluster = out_info[out_len - 1].cluster; for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--) - out_info[i - 1].cluster = cluster; + set_cluster (out_info[i - 1], cluster, mask); } goto done; } @@ -616,6 +639,32 @@ done: skip_glyph (); } +void +hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end) +{ + unsigned int cluster = (unsigned int) -1; + cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster); + _unsafe_to_break_set_mask (info, start, end, cluster); +} +void +hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end) +{ + if (!have_output) + { + unsafe_to_break_impl (start, end); + return; + } + + assert (start <= out_len); + assert (idx <= end); + + unsigned int cluster = (unsigned int) -1; + cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster); + cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster); + _unsafe_to_break_set_mask (out_info, start, out_len, cluster); + _unsafe_to_break_set_mask (info, idx, end, cluster); +} + void hb_buffer_t::guess_segment_properties (void) { @@ -648,82 +697,19 @@ hb_buffer_t::guess_segment_properties (void) } -static inline void -dump_var_allocation (const hb_buffer_t *buffer) -{ - char buf[80]; - for (unsigned int i = 0; i < 8; i++) - buf[i] = '0' + buffer->allocated_var_bytes[7 - i]; - buf[8] = '\0'; - DEBUG_MSG (BUFFER, buffer, - "Current var allocation: %s", - buf); -} - -void hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const char *owner) -{ - assert (byte_i < 8 && byte_i + count <= 8); - - if (DEBUG_ENABLED (BUFFER)) - dump_var_allocation (this); - DEBUG_MSG (BUFFER, this, - "Allocating var bytes %d..%d for %s", - byte_i, byte_i + count - 1, owner); - - for (unsigned int i = byte_i; i < byte_i + count; i++) { - assert (!allocated_var_bytes[i]); - allocated_var_bytes[i]++; - allocated_var_owner[i] = owner; - } -} - -void hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner) -{ - if (DEBUG_ENABLED (BUFFER)) - dump_var_allocation (this); - - DEBUG_MSG (BUFFER, this, - "Deallocating var bytes %d..%d for %s", - byte_i, byte_i + count - 1, owner); - - assert (byte_i < 8 && byte_i + count <= 8); - for (unsigned int i = byte_i; i < byte_i + count; i++) { - assert (allocated_var_bytes[i]); - assert (0 == strcmp (allocated_var_owner[i], owner)); - allocated_var_bytes[i]--; - } -} - -void hb_buffer_t::assert_var (unsigned int byte_i, unsigned int count, const char *owner) -{ - if (DEBUG_ENABLED (BUFFER)) - dump_var_allocation (this); - - DEBUG_MSG (BUFFER, this, - "Asserting var bytes %d..%d for %s", - byte_i, byte_i + count - 1, owner); - - assert (byte_i < 8 && byte_i + count <= 8); - for (unsigned int i = byte_i; i < byte_i + count; i++) { - assert (allocated_var_bytes[i]); - assert (0 == strcmp (allocated_var_owner[i], owner)); - } -} - -void hb_buffer_t::deallocate_var_all (void) -{ - memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes)); - memset (allocated_var_owner, 0, sizeof (allocated_var_owner)); -} - /* Public API */ /** * hb_buffer_create: (Xconstructor) * - * + * Creates a new #hb_buffer_t with all properties to defaults. * - * Return value: (transfer full) + * Return value: (transfer full): + * A newly allocated #hb_buffer_t with a reference count of 1. The initial + * reference count should be released with hb_buffer_destroy() when you are done + * using the #hb_buffer_t. This function never returns %NULL. If memory cannot + * be allocated, a special #hb_buffer_t object will be returned on which + * hb_buffer_allocation_successful() returns %false. * * Since: 0.9.2 **/ @@ -778,11 +764,13 @@ hb_buffer_get_empty (void) /** * hb_buffer_reference: (skip) - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Increases the reference count on @buffer by one. This prevents @buffer from + * being destroyed until a matching call to hb_buffer_destroy() is made. * * Return value: (transfer full): + * The referenced #hb_buffer_t. * * Since: 0.9.2 **/ @@ -794,9 +782,11 @@ hb_buffer_reference (hb_buffer_t *buffer) /** * hb_buffer_destroy: (skip) - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Deallocate the @buffer. + * Decreases the reference count on @buffer by one. If the result is zero, then + * @buffer and all associated resources are freed. See hb_buffer_reference(). * * Since: 0.9.2 **/ @@ -809,13 +799,15 @@ hb_buffer_destroy (hb_buffer_t *buffer) free (buffer->info); free (buffer->pos); + if (buffer->message_destroy) + buffer->message_destroy (buffer->message_data); free (buffer); } /** * hb_buffer_set_user_data: (skip) - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @key: * @data: * @destroy: @@ -839,7 +831,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer, /** * hb_buffer_get_user_data: (skip) - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @key: * * @@ -858,10 +850,11 @@ hb_buffer_get_user_data (hb_buffer_t *buffer, /** * hb_buffer_set_content_type: - * @buffer: a buffer. - * @content_type: + * @buffer: an #hb_buffer_t. + * @content_type: the type of buffer contents to set * - * + * Sets the type of @buffer contents, buffers are either empty, contain + * characters (before shaping) or glyphs (the result of shaping). * * Since: 0.9.5 **/ @@ -874,11 +867,12 @@ hb_buffer_set_content_type (hb_buffer_t *buffer, /** * hb_buffer_get_content_type: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * see hb_buffer_set_content_type(). * - * Return value: + * Return value: + * The type of @buffer contents. * * Since: 0.9.5 **/ @@ -891,7 +885,7 @@ hb_buffer_get_content_type (hb_buffer_t *buffer) /** * hb_buffer_set_unicode_funcs: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @unicode_funcs: * * @@ -916,7 +910,7 @@ hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, /** * hb_buffer_get_unicode_funcs: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * * * @@ -932,10 +926,16 @@ hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) /** * hb_buffer_set_direction: - * @buffer: a buffer. - * @direction: + * @buffer: an #hb_buffer_t. + * @direction: the #hb_direction_t of the @buffer * - * + * Set the text flow direction of the buffer. No shaping can happen without + * setting @buffer direction, and it controls the visual direction for the + * output glyphs; for RTL direction the glyphs will be reversed. Many layout + * features depend on the proper setting of the direction, for example, + * reversing RTL text before shaping, then shaping with LTR direction is not + * the same as keeping the text in logical order and shaping with RTL + * direction. * * Since: 0.9.2 **/ @@ -952,11 +952,12 @@ hb_buffer_set_direction (hb_buffer_t *buffer, /** * hb_buffer_get_direction: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * See hb_buffer_set_direction() * - * Return value: + * Return value: + * The direction of the @buffer. * * Since: 0.9.2 **/ @@ -968,10 +969,18 @@ hb_buffer_get_direction (hb_buffer_t *buffer) /** * hb_buffer_set_script: - * @buffer: a buffer. - * @script: + * @buffer: an #hb_buffer_t. + * @script: an #hb_script_t to set. * - * + * Sets the script of @buffer to @script. + * + * Script is crucial for choosing the proper shaping behaviour for scripts that + * require it (e.g. Arabic) and the which OpenType features defined in the font + * to be applied. + * + * You can pass one of the predefined #hb_script_t values, or use + * hb_script_from_string() or hb_script_from_iso15924_tag() to get the + * corresponding script from an ISO 15924 script tag. * * Since: 0.9.2 **/ @@ -987,11 +996,12 @@ hb_buffer_set_script (hb_buffer_t *buffer, /** * hb_buffer_get_script: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * See hb_buffer_set_script(). * - * Return value: + * Return value: + * The #hb_script_t of the @buffer. * * Since: 0.9.2 **/ @@ -1003,10 +1013,18 @@ hb_buffer_get_script (hb_buffer_t *buffer) /** * hb_buffer_set_language: - * @buffer: a buffer. - * @language: + * @buffer: an #hb_buffer_t. + * @language: an hb_language_t to set. * - * + * Sets the language of @buffer to @language. + * + * Languages are crucial for selecting which OpenType feature to apply to the + * buffer which can result in applying language-specific behaviour. Languages + * are orthogonal to the scripts, and though they are related, they are + * different concepts and should not be confused with each other. + * + * Use hb_language_from_string() to convert from ISO 639 language codes to + * #hb_language_t. * * Since: 0.9.2 **/ @@ -1022,11 +1040,12 @@ hb_buffer_set_language (hb_buffer_t *buffer, /** * hb_buffer_get_language: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * See hb_buffer_set_language(). * * Return value: (transfer none): + * The #hb_language_t of the buffer. Must not be freed by the caller. * * Since: 0.9.2 **/ @@ -1038,10 +1057,12 @@ hb_buffer_get_language (hb_buffer_t *buffer) /** * hb_buffer_set_segment_properties: - * @buffer: a buffer. - * @props: + * @buffer: an #hb_buffer_t. + * @props: an #hb_segment_properties_t to use. * - * + * Sets the segment properties of the buffer, a shortcut for calling + * hb_buffer_set_direction(), hb_buffer_set_script() and + * hb_buffer_set_language() individually. * * Since: 0.9.7 **/ @@ -1057,10 +1078,10 @@ hb_buffer_set_segment_properties (hb_buffer_t *buffer, /** * hb_buffer_get_segment_properties: - * @buffer: a buffer. - * @props: (out): + * @buffer: an #hb_buffer_t. + * @props: (out): the output #hb_segment_properties_t. * - * + * Sets @props to the #hb_segment_properties_t of @buffer. * * Since: 0.9.7 **/ @@ -1074,10 +1095,10 @@ hb_buffer_get_segment_properties (hb_buffer_t *buffer, /** * hb_buffer_set_flags: - * @buffer: a buffer. - * @flags: + * @buffer: an #hb_buffer_t. + * @flags: the buffer flags to set. * - * + * Sets @buffer flags to @flags. See #hb_buffer_flags_t. * * Since: 0.9.7 **/ @@ -1093,11 +1114,12 @@ hb_buffer_set_flags (hb_buffer_t *buffer, /** * hb_buffer_get_flags: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * See hb_buffer_set_flags(). * * Return value: + * The @buffer flags. * * Since: 0.9.7 **/ @@ -1109,7 +1131,7 @@ hb_buffer_get_flags (hb_buffer_t *buffer) /** * hb_buffer_set_cluster_level: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @cluster_level: * * @@ -1128,7 +1150,7 @@ hb_buffer_set_cluster_level (hb_buffer_t *buffer, /** * hb_buffer_get_cluster_level: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * * * @@ -1145,10 +1167,13 @@ hb_buffer_get_cluster_level (hb_buffer_t *buffer) /** * hb_buffer_set_replacement_codepoint: - * @buffer: a buffer. - * @replacement: + * @buffer: an #hb_buffer_t. + * @replacement: the replacement #hb_codepoint_t * - * + * Sets the #hb_codepoint_t that replaces invalid entries for a given encoding + * when adding text to @buffer. + * + * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT. * * Since: 0.9.31 **/ @@ -1164,11 +1189,12 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, /** * hb_buffer_get_replacement_codepoint: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * See hb_buffer_set_replacement_codepoint(). * * Return value: + * The @buffer replacement #hb_codepoint_t. * * Since: 0.9.31 **/ @@ -1181,9 +1207,10 @@ hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer) /** * hb_buffer_reset: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Resets the buffer to its initial status, as if it was just newly created + * with hb_buffer_create(). * * Since: 0.9.2 **/ @@ -1195,9 +1222,10 @@ hb_buffer_reset (hb_buffer_t *buffer) /** * hb_buffer_clear_contents: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Similar to hb_buffer_reset(), but does not clear the Unicode functions and + * the replacement code point. * * Since: 0.9.11 **/ @@ -1209,12 +1237,13 @@ hb_buffer_clear_contents (hb_buffer_t *buffer) /** * hb_buffer_pre_allocate: - * @buffer: a buffer. - * @size: + * @buffer: an #hb_buffer_t. + * @size: number of items to pre allocate. * - * + * Pre allocates memory for @buffer to fit at least @size number of items. * - * Return value: + * Return value: + * %true if @buffer memory allocation succeeded, %false otherwise. * * Since: 0.9.2 **/ @@ -1226,11 +1255,12 @@ hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) /** * hb_buffer_allocation_successful: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Check if allocating memory for the buffer succeeded. * - * Return value: + * Return value: + * %true if @buffer memory allocation succeeded, %false otherwise. * * Since: 0.9.2 **/ @@ -1242,11 +1272,18 @@ hb_buffer_allocation_successful (hb_buffer_t *buffer) /** * hb_buffer_add: - * @buffer: a buffer. - * @codepoint: - * @cluster: + * @buffer: an #hb_buffer_t. + * @codepoint: a Unicode code point. + * @cluster: the cluster value of @codepoint. * - * + * Appends a character with the Unicode value of @codepoint to @buffer, and + * gives it the initial cluster value of @cluster. Clusters can be any thing + * the client wants, they are usually used to refer to the index of the + * character in the input text stream and are output in + * #hb_glyph_info_t.cluster field. + * + * This function does not check the validity of @codepoint, it is up to the + * caller to ensure it is a valid Unicode code point. * * Since: 0.9.7 **/ @@ -1261,12 +1298,14 @@ hb_buffer_add (hb_buffer_t *buffer, /** * hb_buffer_set_length: - * @buffer: a buffer. - * @length: + * @buffer: an #hb_buffer_t. + * @length: the new length of @buffer. * - * + * Similar to hb_buffer_pre_allocate(), but clears any new items added at the + * end. * * Return value: + * %true if @buffer memory allocation succeeded, %false otherwise. * * Since: 0.9.2 **/ @@ -1301,11 +1340,13 @@ hb_buffer_set_length (hb_buffer_t *buffer, /** * hb_buffer_get_length: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * * Returns the number of items in the buffer. * - * Return value: buffer length. + * Return value: + * The @buffer length. + * The value valid as long as buffer has not been modified. * * Since: 0.9.2 **/ @@ -1317,13 +1358,15 @@ hb_buffer_get_length (hb_buffer_t *buffer) /** * hb_buffer_get_glyph_infos: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @length: (out): output array length. * - * Returns buffer glyph information array. Returned pointer - * is valid as long as buffer contents are not modified. + * Returns @buffer glyph information array. Returned pointer + * is valid as long as @buffer contents are not modified. * - * Return value: (transfer none) (array length=length): buffer glyph information array. + * Return value: (transfer none) (array length=length): + * The @buffer glyph information array. + * The value valid as long as buffer has not been modified. * * Since: 0.9.2 **/ @@ -1339,13 +1382,15 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer, /** * hb_buffer_get_glyph_positions: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @length: (out): output length. * - * Returns buffer glyph position array. Returned pointer - * is valid as long as buffer contents are not modified. + * Returns @buffer glyph position array. Returned pointer + * is valid as long as @buffer contents are not modified. * - * Return value: (transfer none) (array length=length): buffer glyph position array. + * Return value: (transfer none) (array length=length): + * The @buffer glyph position array. + * The value valid as long as buffer has not been modified. * * Since: 0.9.2 **/ @@ -1362,9 +1407,26 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer, return (hb_glyph_position_t *) buffer->pos; } +/** + * hb_glyph_info_get_glyph_flags: + * @info: a #hb_glyph_info_t. + * + * Returns glyph flags encoded within a #hb_glyph_info_t. + * + * Return value: + * The #hb_glyph_flags_t encoded within @info. + * + * Since: 1.5.0 + **/ +hb_glyph_flags_t +(hb_glyph_info_get_glyph_flags) (const hb_glyph_info_t *info) +{ + return hb_glyph_info_get_glyph_flags (info); +} + /** * hb_buffer_reverse: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * * Reverses buffer contents. * @@ -1378,7 +1440,7 @@ hb_buffer_reverse (hb_buffer_t *buffer) /** * hb_buffer_reverse_range: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @start: start index. * @end: end index. * @@ -1395,7 +1457,7 @@ hb_buffer_reverse_range (hb_buffer_t *buffer, /** * hb_buffer_reverse_clusters: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * * Reverses buffer clusters. That is, the buffer contents are * reversed, then each cluster (consecutive items having the @@ -1411,7 +1473,7 @@ hb_buffer_reverse_clusters (hb_buffer_t *buffer) /** * hb_buffer_guess_segment_properties: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * * Sets unset buffer segment properties based on buffer Unicode * contents. If buffer is not empty, it must have content type @@ -1510,13 +1572,18 @@ hb_buffer_add_utf (hb_buffer_t *buffer, /** * hb_buffer_add_utf8: - * @buffer: a buffer. - * @text: (array length=text_length) (element-type uint8_t): - * @text_length: - * @item_offset: - * @item_length: + * @buffer: an #hb_buffer_t. + * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 + * characters to append. + * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @item_offset: the offset of the first character to add to the @buffer. + * @item_length: the number of characters to add to the @buffer, or -1 for the + * end of @text (assuming it is %NULL terminated). * - * + * See hb_buffer_add_codepoints(). + * + * Replaces invalid UTF-8 characters with the @buffer replacement code point, + * see hb_buffer_set_replacement_codepoint(). * * Since: 0.9.2 **/ @@ -1532,13 +1599,17 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer, /** * hb_buffer_add_utf16: - * @buffer: a buffer. - * @text: (array length=text_length): - * @text_length: - * @item_offset: - * @item_length: + * @buffer: an #hb_buffer_t. + * @text: (array length=text_length): an array of UTF-16 characters to append. + * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @item_offset: the offset of the first character to add to the @buffer. + * @item_length: the number of characters to add to the @buffer, or -1 for the + * end of @text (assuming it is %NULL terminated). * - * + * See hb_buffer_add_codepoints(). + * + * Replaces invalid UTF-16 characters with the @buffer replacement code point, + * see hb_buffer_set_replacement_codepoint(). * * Since: 0.9.2 **/ @@ -1554,13 +1625,17 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer, /** * hb_buffer_add_utf32: - * @buffer: a buffer. - * @text: (array length=text_length): - * @text_length: - * @item_offset: - * @item_length: + * @buffer: an #hb_buffer_t. + * @text: (array length=text_length): an array of UTF-32 characters to append. + * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @item_offset: the offset of the first character to add to the @buffer. + * @item_length: the number of characters to add to the @buffer, or -1 for the + * end of @text (assuming it is %NULL terminated). * - * + * See hb_buffer_add_codepoints(). + * + * Replaces invalid UTF-32 characters with the @buffer replacement code point, + * see hb_buffer_set_replacement_codepoint(). * * Since: 0.9.2 **/ @@ -1576,13 +1651,18 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer, /** * hb_buffer_add_latin1: - * @buffer: a buffer. - * @text: (array length=text_length) (element-type uint8_t): - * @text_length: - * @item_offset: - * @item_length: + * @buffer: an #hb_buffer_t. + * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 + * characters to append. + * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @item_offset: the offset of the first character to add to the @buffer. + * @item_length: the number of characters to add to the @buffer, or -1 for the + * end of @text (assuming it is %NULL terminated). * - * + * Similar to hb_buffer_add_codepoints(), but allows only access to first 256 + * Unicode code points that can fit in 8-bit strings. + * + * Has nothing to do with non-Unicode Latin-1 encoding. * * Since: 0.9.39 **/ @@ -1598,13 +1678,25 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer, /** * hb_buffer_add_codepoints: - * @buffer: a buffer. - * @text: (array length=text_length): - * @text_length: - * @item_offset: - * @item_length: + * @buffer: a #hb_buffer_t to append characters to. + * @text: (array length=text_length): an array of Unicode code points to append. + * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @item_offset: the offset of the first code point to add to the @buffer. + * @item_length: the number of code points to add to the @buffer, or -1 for the + * end of @text (assuming it is %NULL terminated). * - * + * Appends characters from @text array to @buffer. The @item_offset is the + * position of the first character from @text that will be appended, and + * @item_length is the number of character. When shaping part of a larger text + * (e.g. a run of text from a paragraph), instead of passing just the substring + * corresponding to the run, it is preferable to pass the whole + * paragraph and specify the run start and length as @item_offset and + * @item_length, respectively, to give HarfBuzz the full context to be able, + * for example, to do cross-run Arabic shaping or properly handle combining + * marks at stat of run. + * + * This function does not check the validity of @text, it is up to the caller + * to ensure it contains a valid Unicode code points. * * Since: 0.9.31 **/ @@ -1619,6 +1711,58 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer, } +/** + * hb_buffer_append: + * @buffer: an #hb_buffer_t. + * @source: source #hb_buffer_t. + * @start: start index into source buffer to copy. Use 0 to copy from start of buffer. + * @end: end index into source buffer to copy. Use (unsigned int) -1 to copy to end of buffer. + * + * Append (part of) contents of another buffer to this buffer. + * + * Since: 1.5.0 + **/ +HB_EXTERN void +hb_buffer_append (hb_buffer_t *buffer, + hb_buffer_t *source, + unsigned int start, + unsigned int end) +{ + assert (!buffer->have_output && !source->have_output); + assert (buffer->have_positions == source->have_positions || + !buffer->len || !source->len); + assert (buffer->content_type == source->content_type || + !buffer->len || !source->len); + + if (end > source->len) + end = source->len; + if (start > end) + start = end; + if (start == end) + return; + + if (!buffer->len) + buffer->content_type = source->content_type; + if (!buffer->have_positions && source->have_positions) + buffer->clear_positions (); + + if (buffer->len + (end - start) < buffer->len) /* Overflows. */ + { + buffer->in_error = true; + return; + } + + unsigned int orig_len = buffer->len; + hb_buffer_set_length (buffer, buffer->len + (end - start)); + if (buffer->in_error) + return; + + memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0])); + if (buffer->have_positions) + memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0])); +} + + static int compare_info_codepoint (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) @@ -1676,9 +1820,12 @@ normalize_glyphs_cluster (hb_buffer_t *buffer, /** * hb_buffer_normalize_glyphs: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Reorders a glyph buffer to have canonical in-cluster glyph order / position. + * The resulting clusters should behave identical to pre-reordering clusters. + * + * This has nothing to do with Unicode normalization. * * Since: 0.9.2 **/ @@ -1686,7 +1833,8 @@ void hb_buffer_normalize_glyphs (hb_buffer_t *buffer) { assert (buffer->have_positions); - assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); + assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS || + (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID)); bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); @@ -1724,3 +1872,137 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g } } } + + +/* + * Comparing buffers. + */ + +/** + * hb_buffer_diff: + * + * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT + * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most + * callers if just comparing two buffers is needed. + * + * Since: 1.5.0 + **/ +hb_buffer_diff_flags_t +hb_buffer_diff (hb_buffer_t *buffer, + hb_buffer_t *reference, + hb_codepoint_t dottedcircle_glyph, + unsigned int position_fuzz) +{ + if (buffer->content_type != reference->content_type && buffer->len && reference->len) + return HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH; + + hb_buffer_diff_flags_t result = HB_BUFFER_DIFF_FLAG_EQUAL; + bool contains = dottedcircle_glyph != (hb_codepoint_t) -1; + + unsigned int count = reference->len; + + if (buffer->len != count) + { + /* + * we can't compare glyph-by-glyph, but we do want to know if there + * are .notdef or dottedcircle glyphs present in the reference buffer + */ + const hb_glyph_info_t *info = reference->info; + unsigned int i; + for (i = 0; i < count; i++) + { + if (contains && info[i].codepoint == dottedcircle_glyph) + result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT; + if (contains && info[i].codepoint == 0) + result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT; + } + result |= HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH; + return hb_buffer_diff_flags_t (result); + } + + if (!count) + return hb_buffer_diff_flags_t (result); + + const hb_glyph_info_t *buf_info = buffer->info; + const hb_glyph_info_t *ref_info = reference->info; + for (unsigned int i = 0; i < count; i++) + { + if (buf_info->codepoint != ref_info->codepoint) + result |= HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH; + if (buf_info->cluster != ref_info->cluster) + result |= HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH; + if ((buf_info->mask & HB_GLYPH_FLAG_DEFINED) != (ref_info->mask & HB_GLYPH_FLAG_DEFINED)) + result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH; + if (contains && ref_info->codepoint == dottedcircle_glyph) + result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT; + if (contains && ref_info->codepoint == 0) + result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT; + buf_info++; + ref_info++; + } + + if (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS) + { + assert (buffer->have_positions); + const hb_glyph_position_t *buf_pos = buffer->pos; + const hb_glyph_position_t *ref_pos = reference->pos; + for (unsigned int i = 0; i < count; i++) + { + if ((unsigned int) abs (buf_pos->x_advance - ref_pos->x_advance) > position_fuzz || + (unsigned int) abs (buf_pos->y_advance - ref_pos->y_advance) > position_fuzz || + (unsigned int) abs (buf_pos->x_offset - ref_pos->x_offset) > position_fuzz || + (unsigned int) abs (buf_pos->y_offset - ref_pos->y_offset) > position_fuzz) + { + result |= HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH; + break; + } + buf_pos++; + ref_pos++; + } + } + + return result; +} + + +/* + * Debugging. + */ + +/** + * hb_buffer_set_message_func: + * @buffer: an #hb_buffer_t. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.1.3 + **/ +void +hb_buffer_set_message_func (hb_buffer_t *buffer, + hb_buffer_message_func_t func, + void *user_data, hb_destroy_func_t destroy) +{ + if (buffer->message_destroy) + buffer->message_destroy (buffer->message_data); + + if (func) { + buffer->message_func = func; + buffer->message_data = user_data; + buffer->message_destroy = destroy; + } else { + buffer->message_func = NULL; + buffer->message_data = NULL; + buffer->message_destroy = NULL; + } +} + +bool +hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap) +{ + char buf[100]; + vsnprintf (buf, sizeof (buf), fmt, ap); + return (bool) this->message_func (this, font, buf, this->message_data); +} diff --git a/gfx/harfbuzz/src/hb-buffer.h b/gfx/harfbuzz/src/hb-buffer.h index bb89dc3de..1d633f7dc 100644 --- a/gfx/harfbuzz/src/hb-buffer.h +++ b/gfx/harfbuzz/src/hb-buffer.h @@ -40,10 +40,30 @@ HB_BEGIN_DECLS - +/** + * hb_glyph_info_t: + * @codepoint: either a Unicode code point (before shaping) or a glyph index + * (after shaping). + * @mask: + * @cluster: the index of the character in the original text that corresponds + * to this #hb_glyph_info_t, or whatever the client passes to + * hb_buffer_add(). More than one #hb_glyph_info_t can have the same + * @cluster value, if they resulted from the same character (e.g. one + * to many glyph substitution), and when more than one character gets + * merged in the same glyph (e.g. many to one glyph substitution) the + * #hb_glyph_info_t will have the smallest cluster value of them. + * By default some characters are merged into the same cluster + * (e.g. combining marks have the same cluster as their bases) + * even if they are separate glyphs, hb_buffer_set_cluster_level() + * allow selecting more fine-grained cluster handling. + * + * The #hb_glyph_info_t is the structure that holds information about the + * glyphs and their relation to input text. + * + */ typedef struct hb_glyph_info_t { hb_codepoint_t codepoint; - hb_mask_t mask; + hb_mask_t mask; /* Holds hb_glyph_flags_t after hb_shape(), plus other things. */ uint32_t cluster; /*< private >*/ @@ -51,6 +71,35 @@ typedef struct hb_glyph_info_t { hb_var_int_t var2; } hb_glyph_info_t; +typedef enum { /*< flags >*/ + HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001, + + HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */ +} hb_glyph_flags_t; + +HB_EXTERN hb_glyph_flags_t +hb_glyph_info_get_glyph_flags (const hb_glyph_info_t *info); + +#define hb_glyph_info_get_glyph_flags(info) \ + ((hb_glyph_flags_t) ((unsigned int) (info)->mask & HB_GLYPH_FLAG_DEFINED)) + + +/** + * hb_glyph_position_t: + * @x_advance: how much the line advances after drawing this glyph when setting + * text in horizontal direction. + * @y_advance: how much the line advances after drawing this glyph when setting + * text in vertical direction. + * @x_offset: how much the glyph moves on the X-axis before drawing it, this + * should not affect how much the line advances. + * @y_offset: how much the glyph moves on the Y-axis before drawing it, this + * should not affect how much the line advances. + * + * The #hb_glyph_position_t is the structure that holds the positions of the + * glyph in both horizontal and vertical directions. All positions in + * #hb_glyph_position_t are relative to the current point. + * + */ typedef struct hb_glyph_position_t { hb_position_t x_advance; hb_position_t y_advance; @@ -61,7 +110,16 @@ typedef struct hb_glyph_position_t { hb_var_int_t var; } hb_glyph_position_t; - +/** + * hb_segment_properties_t: + * @direction: the #hb_direction_t of the buffer, see hb_buffer_set_direction(). + * @script: the #hb_script_t of the buffer, see hb_buffer_set_script(). + * @language: the #hb_language_t of the buffer, see hb_buffer_set_language(). + * + * The structure that holds various text properties of an #hb_buffer_t. Can be + * set and retrieved using hb_buffer_set_segment_properties() and + * hb_buffer_get_segment_properties(), respectively. + */ typedef struct hb_segment_properties_t { hb_direction_t direction; hb_script_t script; @@ -77,101 +135,126 @@ typedef struct hb_segment_properties_t { NULL, \ NULL} -hb_bool_t +HB_EXTERN hb_bool_t hb_segment_properties_equal (const hb_segment_properties_t *a, const hb_segment_properties_t *b); -unsigned int +HB_EXTERN unsigned int hb_segment_properties_hash (const hb_segment_properties_t *p); -/* - * hb_buffer_t +/** + * hb_buffer_t: + * + * The main structure holding the input text and its properties before shaping, + * and output glyphs and their information after shaping. */ typedef struct hb_buffer_t hb_buffer_t; -hb_buffer_t * +HB_EXTERN hb_buffer_t * hb_buffer_create (void); -hb_buffer_t * +HB_EXTERN hb_buffer_t * hb_buffer_get_empty (void); -hb_buffer_t * +HB_EXTERN hb_buffer_t * hb_buffer_reference (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_destroy (hb_buffer_t *buffer); -hb_bool_t +HB_EXTERN hb_bool_t hb_buffer_set_user_data (hb_buffer_t *buffer, hb_user_data_key_t *key, void * data, hb_destroy_func_t destroy, hb_bool_t replace); -void * +HB_EXTERN void * hb_buffer_get_user_data (hb_buffer_t *buffer, hb_user_data_key_t *key); +/** + * hb_buffer_content_type_t: + * @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer. + * @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping). + * @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping). + */ typedef enum { HB_BUFFER_CONTENT_TYPE_INVALID = 0, HB_BUFFER_CONTENT_TYPE_UNICODE, HB_BUFFER_CONTENT_TYPE_GLYPHS } hb_buffer_content_type_t; -void +HB_EXTERN void hb_buffer_set_content_type (hb_buffer_t *buffer, hb_buffer_content_type_t content_type); -hb_buffer_content_type_t +HB_EXTERN hb_buffer_content_type_t hb_buffer_get_content_type (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, hb_unicode_funcs_t *unicode_funcs); -hb_unicode_funcs_t * +HB_EXTERN hb_unicode_funcs_t * hb_buffer_get_unicode_funcs (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_set_direction (hb_buffer_t *buffer, hb_direction_t direction); -hb_direction_t +HB_EXTERN hb_direction_t hb_buffer_get_direction (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_set_script (hb_buffer_t *buffer, hb_script_t script); -hb_script_t +HB_EXTERN hb_script_t hb_buffer_get_script (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_set_language (hb_buffer_t *buffer, hb_language_t language); -hb_language_t +HB_EXTERN hb_language_t hb_buffer_get_language (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_set_segment_properties (hb_buffer_t *buffer, const hb_segment_properties_t *props); -void +HB_EXTERN void hb_buffer_get_segment_properties (hb_buffer_t *buffer, hb_segment_properties_t *props); -void +HB_EXTERN void hb_buffer_guess_segment_properties (hb_buffer_t *buffer); -/* +/** + * hb_buffer_flags_t: + * @HB_BUFFER_FLAG_DEFAULT: the default buffer flag. + * @HB_BUFFER_FLAG_BOT: flag indicating that special handling of the beginning + * of text paragraph can be applied to this buffer. Should usually + * be set, unless you are passing to the buffer only part + * of the text without the full context. + * @HB_BUFFER_FLAG_EOT: flag indicating that special handling of the end of text + * paragraph can be applied to this buffer, similar to + * @HB_BUFFER_FLAG_EOT. + * @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES: + * flag indication that character with Default_Ignorable + * Unicode property should use the corresponding glyph + * from the font, instead of hiding them (currently done + * by replacing them with the space glyph and zeroing the + * advance width.) + * * Since: 0.9.20 */ typedef enum { /*< flags >*/ @@ -181,11 +264,11 @@ typedef enum { /*< flags >*/ HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u } hb_buffer_flags_t; -void +HB_EXTERN void hb_buffer_set_flags (hb_buffer_t *buffer, hb_buffer_flags_t flags); -hb_buffer_flags_t +HB_EXTERN hb_buffer_flags_t hb_buffer_get_flags (hb_buffer_t *buffer); /* @@ -198,126 +281,123 @@ typedef enum { HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES } hb_buffer_cluster_level_t; -void +HB_EXTERN void hb_buffer_set_cluster_level (hb_buffer_t *buffer, hb_buffer_cluster_level_t cluster_level); -hb_buffer_cluster_level_t +HB_EXTERN hb_buffer_cluster_level_t hb_buffer_get_cluster_level (hb_buffer_t *buffer); +/** + * HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT: + * + * The default code point for replacing invalid characters in a given encoding. + * Set to U+FFFD REPLACEMENT CHARACTER. + * + * Since: 0.9.31 + */ #define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu -/* Sets codepoint used to replace invalid UTF-8/16/32 entries. - * Default is 0xFFFDu. */ -void +HB_EXTERN void hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, hb_codepoint_t replacement); -hb_codepoint_t +HB_EXTERN hb_codepoint_t hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer); -/* Resets the buffer. Afterwards it's as if it was just created, - * except that it has a larger buffer allocated perhaps... */ -void +HB_EXTERN void hb_buffer_reset (hb_buffer_t *buffer); -/* Like reset, but does NOT clear unicode_funcs and replacement_codepoint. */ -void +HB_EXTERN void hb_buffer_clear_contents (hb_buffer_t *buffer); -/* Returns false if allocation failed */ -hb_bool_t +HB_EXTERN hb_bool_t hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size); -/* Returns false if allocation has failed before */ -hb_bool_t +HB_EXTERN hb_bool_t hb_buffer_allocation_successful (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_reverse (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_reverse_range (hb_buffer_t *buffer, unsigned int start, unsigned int end); -void +HB_EXTERN void hb_buffer_reverse_clusters (hb_buffer_t *buffer); /* Filling the buffer in */ -void +HB_EXTERN void hb_buffer_add (hb_buffer_t *buffer, hb_codepoint_t codepoint, unsigned int cluster); -void +HB_EXTERN void hb_buffer_add_utf8 (hb_buffer_t *buffer, const char *text, int text_length, unsigned int item_offset, int item_length); -void +HB_EXTERN void hb_buffer_add_utf16 (hb_buffer_t *buffer, const uint16_t *text, int text_length, unsigned int item_offset, int item_length); -void +HB_EXTERN void hb_buffer_add_utf32 (hb_buffer_t *buffer, const uint32_t *text, int text_length, unsigned int item_offset, int item_length); -/* Allows only access to first 256 Unicode codepoints. */ -void +HB_EXTERN void hb_buffer_add_latin1 (hb_buffer_t *buffer, const uint8_t *text, int text_length, unsigned int item_offset, int item_length); -/* Like add_utf32 but does NOT check for invalid Unicode codepoints. */ -void +HB_EXTERN void hb_buffer_add_codepoints (hb_buffer_t *buffer, const hb_codepoint_t *text, int text_length, unsigned int item_offset, int item_length); +HB_EXTERN void +hb_buffer_append (hb_buffer_t *buffer, + hb_buffer_t *source, + unsigned int start, + unsigned int end); -/* Clears any new items added at the end */ -hb_bool_t +HB_EXTERN hb_bool_t hb_buffer_set_length (hb_buffer_t *buffer, unsigned int length); -/* Return value valid as long as buffer not modified */ -unsigned int +HB_EXTERN unsigned int hb_buffer_get_length (hb_buffer_t *buffer); /* Getting glyphs out of the buffer */ -/* Return value valid as long as buffer not modified */ -hb_glyph_info_t * +HB_EXTERN hb_glyph_info_t * hb_buffer_get_glyph_infos (hb_buffer_t *buffer, unsigned int *length); -/* Return value valid as long as buffer not modified */ -hb_glyph_position_t * +HB_EXTERN hb_glyph_position_t * hb_buffer_get_glyph_positions (hb_buffer_t *buffer, unsigned int *length); -/* Reorders a glyph buffer to have canonical in-cluster glyph order / position. - * The resulting clusters should behave identical to pre-reordering clusters. - * NOTE: This has nothing to do with Unicode normalization. */ -void +HB_EXTERN void hb_buffer_normalize_glyphs (hb_buffer_t *buffer); @@ -325,7 +405,16 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer); * Serialize */ -/* +/** + * hb_buffer_serialize_flags_t: + * @HB_BUFFER_SERIALIZE_FLAG_DEFAULT: serialize glyph names, clusters and positions. + * @HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS: do not serialize glyph cluster. + * @HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS: do not serialize glyph position information. + * @HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES: do no serialize glyph name. + * @HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS: serialize glyph extents. + * + * Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs(). + * * Since: 0.9.20 */ typedef enum { /*< flags >*/ @@ -333,46 +422,110 @@ typedef enum { /*< flags >*/ HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u, HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u, HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u, - HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u + HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u, + HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS = 0x00000010u } hb_buffer_serialize_flags_t; +/** + * hb_buffer_serialize_format_t: + * @HB_BUFFER_SERIALIZE_FORMAT_TEXT: a human-readable, plain text format. + * @HB_BUFFER_SERIALIZE_FORMAT_JSON: a machine-readable JSON format. + * @HB_BUFFER_SERIALIZE_FORMAT_INVALID: invalid format. + * + * The buffer serialization and de-serialization format used in + * hb_buffer_serialize_glyphs() and hb_buffer_deserialize_glyphs(). + * + * Since: 0.9.2 + */ typedef enum { HB_BUFFER_SERIALIZE_FORMAT_TEXT = HB_TAG('T','E','X','T'), HB_BUFFER_SERIALIZE_FORMAT_JSON = HB_TAG('J','S','O','N'), HB_BUFFER_SERIALIZE_FORMAT_INVALID = HB_TAG_NONE } hb_buffer_serialize_format_t; -/* len=-1 means str is NUL-terminated. */ -hb_buffer_serialize_format_t +HB_EXTERN hb_buffer_serialize_format_t hb_buffer_serialize_format_from_string (const char *str, int len); -const char * +HB_EXTERN const char * hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format); -const char ** +HB_EXTERN const char ** hb_buffer_serialize_list_formats (void); -/* Returns number of items, starting at start, that were serialized. */ -unsigned int +HB_EXTERN unsigned int hb_buffer_serialize_glyphs (hb_buffer_t *buffer, unsigned int start, unsigned int end, char *buf, unsigned int buf_size, - unsigned int *buf_consumed, /* May be NULL */ - hb_font_t *font, /* May be NULL */ + unsigned int *buf_consumed, + hb_font_t *font, hb_buffer_serialize_format_t format, hb_buffer_serialize_flags_t flags); -hb_bool_t +HB_EXTERN hb_bool_t hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, const char *buf, - int buf_len, /* -1 means nul-terminated */ - const char **end_ptr, /* May be NULL */ - hb_font_t *font, /* May be NULL */ + int buf_len, + const char **end_ptr, + hb_font_t *font, hb_buffer_serialize_format_t format); +/* + * Compare buffers + */ + +typedef enum { /*< flags >*/ + HB_BUFFER_DIFF_FLAG_EQUAL = 0x0000, + + /* Buffers with different content_type cannot be meaningfully compared + * in any further detail. */ + HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH = 0x0001, + + /* For buffers with differing length, the per-glyph comparison is not + * attempted, though we do still scan reference for dottedcircle / .notdef + * glyphs. */ + HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH = 0x0002, + + /* We want to know if dottedcircle / .notdef glyphs are present in the + * reference, as we may not care so much about other differences in this + * case. */ + HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT = 0x0004, + HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT = 0x0008, + + /* If the buffers have the same length, we compare them glyph-by-glyph + * and report which aspect(s) of the glyph info/position are different. */ + HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH = 0x0010, + HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH = 0x0020, + HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH = 0x0040, + HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH = 0x0080 + +} hb_buffer_diff_flags_t; + +/* Compare the contents of two buffers, report types of differences. */ +hb_buffer_diff_flags_t +hb_buffer_diff (hb_buffer_t *buffer, + hb_buffer_t *reference, + hb_codepoint_t dottedcircle_glyph, + unsigned int position_fuzz); + + +/* + * Debugging. + */ + +typedef hb_bool_t (*hb_buffer_message_func_t) (hb_buffer_t *buffer, + hb_font_t *font, + const char *message, + void *user_data); + +HB_EXTERN void +hb_buffer_set_message_func (hb_buffer_t *buffer, + hb_buffer_message_func_t func, + void *user_data, hb_destroy_func_t destroy); + + HB_END_DECLS #endif /* HB_BUFFER_H */ diff --git a/gfx/harfbuzz/src/hb-cache-private.hh b/gfx/harfbuzz/src/hb-cache-private.hh index 19b70b7e3..24957e1e9 100644 --- a/gfx/harfbuzz/src/hb-cache-private.hh +++ b/gfx/harfbuzz/src/hb-cache-private.hh @@ -45,11 +45,11 @@ struct hb_cache_t inline bool get (unsigned int key, unsigned int *value) { - unsigned int k = key & ((1<> value_bits) != (key >> cache_bits)) return false; - *value = v & ((1<> key_bits) || (value >> value_bits))) return false; /* Overflows */ - unsigned int k = key & ((1<>cache_bits)< hb_cmap_cache_t; diff --git a/gfx/harfbuzz/src/hb-common.cc b/gfx/harfbuzz/src/hb-common.cc index e67059d10..0483816d3 100644 --- a/gfx/harfbuzz/src/hb-common.cc +++ b/gfx/harfbuzz/src/hb-common.cc @@ -88,7 +88,7 @@ hb_tag_from_string (const char *str, int len) /** * hb_tag_to_string: * @tag: - * @buf: (array fixed-size=4): + * @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t): * * * @@ -186,8 +186,10 @@ lang_equal (hb_language_t v1, const unsigned char *p1 = (const unsigned char *) v1; const unsigned char *p2 = (const unsigned char *) v2; - while (*p1 && *p1 == canon_map[*p2]) - p1++, p2++; + while (*p1 && *p1 == canon_map[*p2]) { + p1++; + p2++; + } return *p1 == canon_map[*p2]; } @@ -219,9 +221,18 @@ struct hb_language_item_t { } inline hb_language_item_t & operator = (const char *s) { - lang = (hb_language_t) strdup (s); - for (unsigned char *p = (unsigned char *) lang; *p; p++) - *p = canon_map[*p]; + /* If a custom allocated is used calling strdup() pairs + badly with a call to the custom free() in finish() below. + Therefore don't call strdup(), implement its behavior. + */ + size_t len = strlen(s) + 1; + lang = (hb_language_t) malloc(len); + if (likely (lang)) + { + memcpy((unsigned char *) lang, s, len); + for (unsigned char *p = (unsigned char *) lang; *p; p++) + *p = canon_map[*p]; + } return *this; } @@ -263,6 +274,11 @@ retry: return NULL; lang->next = first_lang; *lang = key; + if (unlikely (!lang->lang)) + { + free (lang); + return NULL; + } if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) { lang->finish (); @@ -281,12 +297,15 @@ retry: /** * hb_language_from_string: - * @str: (array length=len) (element-type uint8_t): - * @len: + * @str: (array length=len) (element-type uint8_t): a string representing + * ISO 639 language code + * @len: length of the @str, or -1 if it is %NULL-terminated. * - * + * Converts @str representing an ISO 639 language code to the corresponding + * #hb_language_t. * * Return value: (transfer none): + * The #hb_language_t corresponding to the ISO 639 language code. * * Since: 0.9.2 **/ @@ -314,11 +333,13 @@ hb_language_from_string (const char *str, int len) /** * hb_language_to_string: - * @language: + * @language: an #hb_language_t to convert. * - * + * See hb_language_from_string(). * - * Return value: (transfer none): + * Return value: (transfer none): + * A %NULL-terminated string representing the @language. Must not be freed by + * the caller. * * Since: 0.9.2 **/ @@ -357,11 +378,12 @@ hb_language_get_default (void) /** * hb_script_from_iso15924_tag: - * @tag: + * @tag: an #hb_tag_t representing an ISO 15924 tag. * - * + * Converts an ISO 15924 script tag to a corresponding #hb_script_t. * * Return value: + * An #hb_script_t corresponding to the ISO 15924 tag. * * Since: 0.9.2 **/ @@ -401,28 +423,33 @@ hb_script_from_iso15924_tag (hb_tag_t tag) /** * hb_script_from_string: - * @s: (array length=len) (element-type uint8_t): - * @len: + * @str: (array length=len) (element-type uint8_t): a string representing an + * ISO 15924 tag. + * @len: length of the @str, or -1 if it is %NULL-terminated. * - * + * Converts a string @str representing an ISO 15924 script tag to a + * corresponding #hb_script_t. Shorthand for hb_tag_from_string() then + * hb_script_from_iso15924_tag(). * * Return value: + * An #hb_script_t corresponding to the ISO 15924 tag. * * Since: 0.9.2 **/ hb_script_t -hb_script_from_string (const char *s, int len) +hb_script_from_string (const char *str, int len) { - return hb_script_from_iso15924_tag (hb_tag_from_string (s, len)); + return hb_script_from_iso15924_tag (hb_tag_from_string (str, len)); } /** * hb_script_to_iso15924_tag: - * @script: + * @script: an #hb_script_ to convert. * - * + * See hb_script_from_iso15924_tag(). * - * Return value: + * Return value: + * An #hb_tag_t representing an ISO 15924 script tag. * * Since: 0.9.2 **/ @@ -496,6 +523,9 @@ hb_script_get_horizontal_direction (hb_script_t script) /* Unicode-8.0 additions */ case HB_SCRIPT_OLD_HUNGARIAN: + /* Unicode-9.0 additions */ + case HB_SCRIPT_ADLAM: + return HB_DIRECTION_RTL; } @@ -521,7 +551,7 @@ hb_user_data_array_t::set (hb_user_data_key_t *key, } } hb_user_data_item_t item = {key, data, destroy}; - bool ret = !!items.replace_or_insert (item, lock, replace); + bool ret = !!items.replace_or_insert (item, lock, (bool) replace); return ret; } @@ -529,7 +559,7 @@ hb_user_data_array_t::set (hb_user_data_key_t *key, void * hb_user_data_array_t::get (hb_user_data_key_t *key) { - hb_user_data_item_t item = {NULL }; + hb_user_data_item_t item = {NULL, NULL, NULL}; return items.find (key, &item, lock) ? item.data : NULL; } @@ -591,3 +621,371 @@ hb_version_atleast (unsigned int major, { return HB_VERSION_ATLEAST (major, minor, micro); } + + + +/* hb_feature_t and hb_variation_t */ + +static bool +parse_space (const char **pp, const char *end) +{ + while (*pp < end && ISSPACE (**pp)) + (*pp)++; + return true; +} + +static bool +parse_char (const char **pp, const char *end, char c) +{ + parse_space (pp, end); + + if (*pp == end || **pp != c) + return false; + + (*pp)++; + return true; +} + +static bool +parse_uint (const char **pp, const char *end, unsigned int *pv) +{ + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); + strncpy (buf, *pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + unsigned int v; + + /* Intentionally use strtol instead of strtoul, such that + * -1 turns into "big number"... */ + errno = 0; + v = strtol (p, &pend, 0); + if (errno || p == pend) + return false; + + *pv = v; + *pp += pend - p; + return true; +} + +static bool +parse_uint32 (const char **pp, const char *end, uint32_t *pv) +{ + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); + strncpy (buf, *pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + unsigned int v; + + /* Intentionally use strtol instead of strtoul, such that + * -1 turns into "big number"... */ + errno = 0; + v = strtol (p, &pend, 0); + if (errno || p == pend) + return false; + + *pv = v; + *pp += pend - p; + return true; +} + +static bool +parse_float (const char **pp, const char *end, float *pv) +{ + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); + strncpy (buf, *pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + float v; + + errno = 0; + v = strtod (p, &pend); + if (errno || p == pend) + return false; + + *pv = v; + *pp += pend - p; + return true; +} + +static bool +parse_bool (const char **pp, const char *end, uint32_t *pv) +{ + parse_space (pp, end); + + const char *p = *pp; + while (*pp < end && ISALPHA(**pp)) + (*pp)++; + + /* CSS allows on/off as aliases 1/0. */ + if (*pp - p == 2 || 0 == strncmp (p, "on", 2)) + *pv = 1; + else if (*pp - p == 3 || 0 == strncmp (p, "off", 2)) + *pv = 0; + else + return false; + + return true; +} + +/* hb_feature_t */ + +static bool +parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) +{ + if (parse_char (pp, end, '-')) + feature->value = 0; + else { + parse_char (pp, end, '+'); + feature->value = 1; + } + + return true; +} + +static bool +parse_tag (const char **pp, const char *end, hb_tag_t *tag) +{ + parse_space (pp, end); + + char quote = 0; + + if (*pp < end && (**pp == '\'' || **pp == '"')) + { + quote = **pp; + (*pp)++; + } + + const char *p = *pp; + while (*pp < end && ISALNUM(**pp)) + (*pp)++; + + if (p == *pp || *pp - p > 4) + return false; + + *tag = hb_tag_from_string (p, *pp - p); + + if (quote) + { + /* CSS expects exactly four bytes. And we only allow quotations for + * CSS compatibility. So, enforce the length. */ + if (*pp - p != 4) + return false; + if (*pp == end || **pp != quote) + return false; + (*pp)++; + } + + return true; +} + +static bool +parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) +{ + parse_space (pp, end); + + bool has_start; + + feature->start = 0; + feature->end = (unsigned int) -1; + + if (!parse_char (pp, end, '[')) + return true; + + has_start = parse_uint (pp, end, &feature->start); + + if (parse_char (pp, end, ':')) { + parse_uint (pp, end, &feature->end); + } else { + if (has_start) + feature->end = feature->start + 1; + } + + return parse_char (pp, end, ']'); +} + +static bool +parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature) +{ + bool had_equal = parse_char (pp, end, '='); + bool had_value = parse_uint32 (pp, end, &feature->value) || + parse_bool (pp, end, &feature->value); + /* CSS doesn't use equal-sign between tag and value. + * If there was an equal-sign, then there *must* be a value. + * A value without an eqaul-sign is ok, but not required. */ + return !had_equal || had_value; +} + +static bool +parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) +{ + return parse_feature_value_prefix (pp, end, feature) && + parse_tag (pp, end, &feature->tag) && + parse_feature_indices (pp, end, feature) && + parse_feature_value_postfix (pp, end, feature) && + parse_space (pp, end) && + *pp == end; +} + +/** + * hb_feature_from_string: + * @str: (array length=len) (element-type uint8_t): a string to parse + * @len: length of @str, or -1 if string is %NULL terminated + * @feature: (out): the #hb_feature_t to initialize with the parsed values + * + * Parses a string into a #hb_feature_t. + * + * TODO: document the syntax here. + * + * Return value: + * %true if @str is successfully parsed, %false otherwise. + * + * Since: 0.9.5 + **/ +hb_bool_t +hb_feature_from_string (const char *str, int len, + hb_feature_t *feature) +{ + hb_feature_t feat; + + if (len < 0) + len = strlen (str); + + if (likely (parse_one_feature (&str, str + len, &feat))) + { + if (feature) + *feature = feat; + return true; + } + + if (feature) + memset (feature, 0, sizeof (*feature)); + return false; +} + +/** + * hb_feature_to_string: + * @feature: an #hb_feature_t to convert + * @buf: (array length=size) (out): output string + * @size: the allocated size of @buf + * + * Converts a #hb_feature_t into a %NULL-terminated string in the format + * understood by hb_feature_from_string(). The client in responsible for + * allocating big enough size for @buf, 128 bytes is more than enough. + * + * Since: 0.9.5 + **/ +void +hb_feature_to_string (hb_feature_t *feature, + char *buf, unsigned int size) +{ + if (unlikely (!size)) return; + + char s[128]; + unsigned int len = 0; + if (feature->value == 0) + s[len++] = '-'; + hb_tag_to_string (feature->tag, s + len); + len += 4; + while (len && s[len - 1] == ' ') + len--; + if (feature->start != 0 || feature->end != (unsigned int) -1) + { + s[len++] = '['; + if (feature->start) + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start)); + if (feature->end != feature->start + 1) { + s[len++] = ':'; + if (feature->end != (unsigned int) -1) + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end)); + } + s[len++] = ']'; + } + if (feature->value > 1) + { + s[len++] = '='; + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); + } + assert (len < ARRAY_LENGTH (s)); + len = MIN (len, size - 1); + memcpy (buf, s, len); + buf[len] = '\0'; +} + +/* hb_variation_t */ + +static bool +parse_variation_value (const char **pp, const char *end, hb_variation_t *variation) +{ + parse_char (pp, end, '='); /* Optional. */ + return parse_float (pp, end, &variation->value); +} + +static bool +parse_one_variation (const char **pp, const char *end, hb_variation_t *variation) +{ + return parse_tag (pp, end, &variation->tag) && + parse_variation_value (pp, end, variation) && + parse_space (pp, end) && + *pp == end; +} + +/** + * hb_variation_from_string: + * + * Since: 1.4.2 + */ +hb_bool_t +hb_variation_from_string (const char *str, int len, + hb_variation_t *variation) +{ + hb_variation_t var; + + if (len < 0) + len = strlen (str); + + if (likely (parse_one_variation (&str, str + len, &var))) + { + if (variation) + *variation = var; + return true; + } + + if (variation) + memset (variation, 0, sizeof (*variation)); + return false; +} + +/** + * hb_variation_to_string: + * + * Since: 1.4.2 + */ +void +hb_variation_to_string (hb_variation_t *variation, + char *buf, unsigned int size) +{ + if (unlikely (!size)) return; + + char s[128]; + unsigned int len = 0; + hb_tag_to_string (variation->tag, s + len); + len += 4; + while (len && s[len - 1] == ' ') + len--; + s[len++] = '='; + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value)); + + assert (len < ARRAY_LENGTH (s)); + len = MIN (len, size - 1); + memcpy (buf, s, len); + buf[len] = '\0'; +} diff --git a/gfx/harfbuzz/src/hb-common.h b/gfx/harfbuzz/src/hb-common.h index c291dbbe9..634cb96a6 100644 --- a/gfx/harfbuzz/src/hb-common.h +++ b/gfx/harfbuzz/src/hb-common.h @@ -98,16 +98,22 @@ typedef uint32_t hb_tag_t; #define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff) /* len=-1 means str is NUL-terminated. */ -hb_tag_t +HB_EXTERN hb_tag_t hb_tag_from_string (const char *str, int len); /* buf should have 4 bytes. */ -void +HB_EXTERN void hb_tag_to_string (hb_tag_t tag, char *buf); -/* hb_direction_t */ - +/** + * hb_direction_t: + * @HB_DIRECTION_INVALID: Initial, unset direction. + * @HB_DIRECTION_LTR: Text is set horizontally from left to right. + * @HB_DIRECTION_RTL: Text is set horizontally from right to left. + * @HB_DIRECTION_TTB: Text is set vertically from top to bottom. + * @HB_DIRECTION_BTT: Text is set vertically from bottom to top. + */ typedef enum { HB_DIRECTION_INVALID = 0, HB_DIRECTION_LTR = 4, @@ -117,10 +123,10 @@ typedef enum { } hb_direction_t; /* len=-1 means str is NUL-terminated */ -hb_direction_t +HB_EXTERN hb_direction_t hb_direction_from_string (const char *str, int len); -const char * +HB_EXTERN const char * hb_direction_to_string (hb_direction_t direction); #define HB_DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4) @@ -136,16 +142,15 @@ hb_direction_to_string (hb_direction_t direction); typedef const struct hb_language_impl_t *hb_language_t; -/* len=-1 means str is NUL-terminated */ -hb_language_t +HB_EXTERN hb_language_t hb_language_from_string (const char *str, int len); -const char * +HB_EXTERN const char * hb_language_to_string (hb_language_t language); #define HB_LANGUAGE_INVALID ((hb_language_t) NULL) -hb_language_t +HB_EXTERN hb_language_t hb_language_get_default (void); @@ -299,12 +304,22 @@ typedef enum /*7.0*/ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), - /*8.0*/ HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), - /*8.0*/ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), - /*8.0*/ HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), - /*8.0*/ HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), - /*8.0*/ HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), - /*8.0*/ HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), + /*8.0*/ HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), + /*8.0*/ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), + /*8.0*/ HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), + /*8.0*/ HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), + /*8.0*/ HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), + /*8.0*/ HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), + + /* + * Since 1.3.0 + */ + /*9.0*/ HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), + /*9.0*/ HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), + /*9.0*/ HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), + /*9.0*/ HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), + /*9.0*/ HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), + /*9.0*/ HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), /* No script set. */ HB_SCRIPT_INVALID = HB_TAG_NONE, @@ -324,18 +339,16 @@ typedef enum /* Script functions */ -hb_script_t +HB_EXTERN hb_script_t hb_script_from_iso15924_tag (hb_tag_t tag); -/* sugar for tag_from_string() then script_from_iso15924_tag */ -/* len=-1 means s is NUL-terminated */ -hb_script_t -hb_script_from_string (const char *s, int len); +HB_EXTERN hb_script_t +hb_script_from_string (const char *str, int len); -hb_tag_t +HB_EXTERN hb_tag_t hb_script_to_iso15924_tag (hb_script_t script); -hb_direction_t +HB_EXTERN hb_direction_t hb_script_get_horizontal_direction (hb_script_t script); @@ -349,6 +362,42 @@ typedef struct hb_user_data_key_t { typedef void (*hb_destroy_func_t) (void *user_data); +/* Font features and variations. */ + +typedef struct hb_feature_t { + hb_tag_t tag; + uint32_t value; + unsigned int start; + unsigned int end; +} hb_feature_t; + +HB_EXTERN hb_bool_t +hb_feature_from_string (const char *str, int len, + hb_feature_t *feature); + +HB_EXTERN void +hb_feature_to_string (hb_feature_t *feature, + char *buf, unsigned int size); + +/** + * hb_variation_t: + * + * Since: 1.4.2 + */ +typedef struct hb_variation_t { + hb_tag_t tag; + float value; +} hb_variation_t; + +HB_EXTERN hb_bool_t +hb_variation_from_string (const char *str, int len, + hb_variation_t *variation); + +HB_EXTERN void +hb_variation_to_string (hb_variation_t *variation, + char *buf, unsigned int size); + + HB_END_DECLS #endif /* HB_COMMON_H */ diff --git a/gfx/harfbuzz/src/hb-coretext.cc b/gfx/harfbuzz/src/hb-coretext.cc index 13ba5d94e..ba96d3994 100644 --- a/gfx/harfbuzz/src/hb-coretext.cc +++ b/gfx/harfbuzz/src/hb-coretext.cc @@ -27,7 +27,6 @@ */ #define HB_SHAPER coretext -#define hb_coretext_shaper_face_data_t CGFont #include "hb-shaper-impl-private.hh" #include "hb-coretext.h" @@ -70,14 +69,37 @@ hb_coretext_face_create (CGFontRef cg_font) } -HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face) -HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font) +HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face) +HB_SHAPER_DATA_ENSURE_DEFINE(coretext, font) /* * shaper face data */ +static CTFontDescriptorRef +get_last_resort_font_desc (void) +{ + // TODO Handle allocation failures? + CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0); + CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault, + (const void **) &last_resort, + 1, + &kCFTypeArrayCallBacks); + CFRelease (last_resort); + CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault, + (const void **) &kCTFontCascadeListAttribute, + (const void **) &cascade_list, + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRelease (cascade_list); + + CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes); + CFRelease (attributes); + return font_desc; +} + static void release_data (void *info, const void *data, size_t size) { @@ -87,14 +109,13 @@ release_data (void *info, const void *data, size_t size) hb_blob_destroy ((hb_blob_t *) info); } -hb_coretext_shaper_face_data_t * -_hb_coretext_shaper_face_data_create (hb_face_t *face) +static CGFontRef +create_cg_font (hb_face_t *face) { - hb_coretext_shaper_face_data_t *data = NULL; - + CGFontRef cg_font = NULL; if (face->destroy == (hb_destroy_func_t) CGFontRelease) { - data = CGFontRetain ((CGFontRef) face->user_data); + cg_font = CGFontRetain ((CGFontRef) face->user_data); } else { @@ -107,13 +128,114 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face) CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data); if (likely (provider)) { - data = CGFontCreateWithDataProvider (provider); + cg_font = CGFontCreateWithDataProvider (provider); + if (unlikely (!cg_font)) + DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed"); CGDataProviderRelease (provider); } } + return cg_font; +} - if (unlikely (!data)) { - DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed"); +static CTFontRef +create_ct_font (CGFontRef cg_font, CGFloat font_size) +{ + CTFontRef ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, NULL, NULL); + if (unlikely (!ct_font)) { + DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed"); + return NULL; + } + + /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter + * bug indicate that the cascade list reconfiguration occasionally causes + * crashes in CoreText on OS X 10.9, thus let's skip this step on older + * operating system versions. Except for the emoji font, where _not_ + * reconfiguring the cascade list causes CoreText crashes. For details, see + * crbug.com/549610 */ + // 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h + if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < 0x00070000) { + CFStringRef fontName = CTFontCopyPostScriptName (ct_font); + bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo; + CFRelease (fontName); + if (!isEmojiFont) + return ct_font; + } + + CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute); + + /* Create font copy with cascade list that has LastResort first; this speeds up CoreText + * font fallback which we don't need anyway. */ + { + CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc (); + CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, NULL, last_resort_font_desc); + CFRelease (last_resort_font_desc); + if (new_ct_font) + { + /* The CTFontCreateCopyWithAttributes call fails to stay on the same font + * when reconfiguring the cascade list and may switch to a different font + * when there are fonts that go by the same name, since the descriptor is + * just name and size. + * + * Avoid reconfiguring the cascade lists if the new font is outside the + * system locations that we cannot access from the sandboxed renderer + * process in Blink. This can be detected by the new file URL location + * that the newly found font points to. */ + CFURLRef new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute); + // Keep reconfigured font if URL cannot be retrieved (seems to be the case + // on Mac OS 10.12 Sierra), speculative fix for crbug.com/625606 + if (!original_url || !new_url || CFEqual (original_url, new_url)) { + CFRelease (ct_font); + ct_font = new_ct_font; + } else { + CFRelease (new_ct_font); + DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed."); + } + if (new_url) + CFRelease (new_url); + } + else + DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed"); + } + + if (original_url) + CFRelease (original_url); + return ct_font; +} + +struct hb_coretext_shaper_face_data_t { + CGFontRef cg_font; + CTFontRef ct_font; +}; + +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; + + data->cg_font = create_cg_font (face); + if (unlikely (!data->cg_font)) + { + DEBUG_MSG (CORETEXT, face, "CGFont creation failed.."); + free (data); + return NULL; + } + + /* We use 36pt size instead of UPEM, because CoreText implements the 'trak' table, + * which can make the font too tight at large sizes. 36pt should be a good semi-neutral + * size. + * + * Since we always create CTFont at a fixed size, our CTFont lives in face_data + * instead of font_data. Which is good, because when people change scale on + * hb_font_t, we won't need to update our CTFont. */ + data->ct_font = create_ct_font (data->cg_font, 36.); + if (unlikely (!data->ct_font)) + { + DEBUG_MSG (CORETEXT, face, "CTFont creation failed."); + CFRelease (data->cg_font); + free (data); + return NULL; } return data; @@ -122,7 +244,9 @@ _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); + CFRelease (data->ct_font); + CFRelease (data->cg_font); + free (data); } /* @@ -133,7 +257,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; + return face_data->cg_font; } @@ -141,49 +265,17 @@ hb_coretext_face_get_cg_font (hb_face_t *face) * shaper font data */ -struct hb_coretext_shaper_font_data_t { - CTFontRef ct_font; - CGFloat x_mult, y_mult; /* From CT space to HB space. */ -}; +struct hb_coretext_shaper_font_data_t {}; hb_coretext_shaper_font_data_t * -_hb_coretext_shaper_font_data_create (hb_font_t *font) +_hb_coretext_shaper_font_data_create (hb_font_t *font HB_UNUSED) { - if (unlikely (!hb_coretext_shaper_face_data_ensure (font->face))) return NULL; - - hb_coretext_shaper_font_data_t *data = (hb_coretext_shaper_font_data_t *) calloc (1, sizeof (hb_coretext_shaper_font_data_t)); - if (unlikely (!data)) - return NULL; - - hb_face_t *face = font->face; - hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - - /* Choose a CoreText font size and calculate multipliers to convert to HarfBuzz space. */ - /* TODO: use upem instead of 36? */ - CGFloat font_size = 36.; /* Default... */ - /* No idea if the following is even a good idea. */ - if (font->y_ppem) - font_size = font->y_ppem; - - if (font_size < 0) - font_size = -font_size; - data->x_mult = (CGFloat) font->x_scale / font_size; - data->y_mult = (CGFloat) font->y_scale / font_size; - data->ct_font = CTFontCreateWithGraphicsFont (face_data, font_size, NULL, NULL); - if (unlikely (!data->ct_font)) { - DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); - free (data); - return NULL; - } - - return data; + return (hb_coretext_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; } void _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) { - CFRelease (data->ct_font); - free (data); } @@ -196,7 +288,9 @@ struct hb_coretext_shaper_shape_plan_data_t {}; hb_coretext_shaper_shape_plan_data_t * _hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } @@ -209,9 +303,10 @@ _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_ CTFontRef hb_coretext_font_get_ct_font (hb_font_t *font) { - if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return NULL; - hb_coretext_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); - return font_data->ct_font; + hb_face_t *face = font->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->ct_font; } @@ -444,7 +539,10 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, { hb_face_t *face = font->face; 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); + + CGFloat ct_font_size = CTFontGetSize (face_data->ct_font); + CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size; + CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size; /* Attach marks to their bases, to match the 'ot' shaper. * Adapted from hb-ot-shape:hb_form_clusters(). @@ -453,6 +551,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, * 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... */ + if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) { hb_unicode_funcs_t *unicode = buffer->unicode; unsigned int count = buffer->len; @@ -542,22 +641,23 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, /* active_features.qsort (); */ for (unsigned int j = 0; j < active_features.len; j++) { - CFStringRef keys[2] = { + CFStringRef keys[] = { kCTFontFeatureTypeIdentifierKey, kCTFontFeatureSelectorIdentifierKey }; - CFNumberRef values[2] = { + CFNumberRef values[] = { CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature), CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting) }; + ASSERT_STATIC (ARRAY_LENGTH (keys) == ARRAY_LENGTH (values)); CFDictionaryRef dict = CFDictionaryCreate (kCFAllocatorDefault, (const void **) keys, (const void **) values, - 2, + ARRAY_LENGTH (keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFRelease (values[0]); - CFRelease (values[1]); + for (unsigned int i = 0; i < ARRAY_LENGTH (values); i++) + CFRelease (values[i]); CFArrayAppendValue (features_array, dict); CFRelease (dict); @@ -575,7 +675,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes); CFRelease (attributes); - range->font = CTFontCreateCopyWithAttributes (font_data->ct_font, 0.0, NULL, font_desc); + range->font = CTFontCreateCopyWithAttributes (face_data->ct_font, 0.0, NULL, font_desc); CFRelease (font_desc); } else @@ -600,9 +700,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, active_features.remove (feature - active_features.array); } } - - if (!range_records.len) /* No active feature found. */ - goto fail_features; } else { @@ -636,7 +733,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, pchars[chars_len++] = 0xFFFDu; else { pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10); - pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1)); + pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1)); } } @@ -693,7 +790,6 @@ resize_and_retry: scratch += old_scratch_used; scratch_size -= old_scratch_used; } -retry: { string_ref = CFStringCreateWithCharactersNoCopy (NULL, pchars, chars_len, @@ -733,9 +829,9 @@ retry: CFRelease (lang); } CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), - kCTFontAttributeName, font_data->ct_font); + kCTFontAttributeName, face_data->ct_font); - if (num_features) + if (num_features && range_records.len) { unsigned int start = 0; range_record_t *last_range = &range_records[0]; @@ -761,6 +857,30 @@ retry: CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, chars_len - start), kCTFontAttributeName, last_range->font); } + /* Enable/disable kern if requested. + * + * Note: once kern is disabled, reenabling it doesn't currently seem to work in CoreText. + */ + if (num_features) + { + unsigned int zeroint = 0; + CFNumberRef zero = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &zeroint); + for (unsigned int i = 0; i < num_features; i++) + { + const hb_feature_t &feature = features[i]; + if (feature.tag == HB_TAG('k','e','r','n') && + feature.start < chars_len && feature.start < feature.end) + { + CFRange feature_range = CFRangeMake (feature.start, + MIN (feature.end, chars_len) - feature.start); + if (feature.value) + CFAttributedStringRemoveAttribute (attr_string, feature_range, kCTKernAttributeName); + else + CFAttributedStringSetAttribute (attr_string, feature_range, kCTKernAttributeName, zero); + } + } + CFRelease (zero); + } int level = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1; CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &level); @@ -770,6 +890,7 @@ retry: 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFRelease (level_number); if (unlikely (!options)) FAIL ("CFDictionaryCreate failed"); @@ -826,7 +947,7 @@ retry: */ CFDictionaryRef attributes = CTRunGetAttributes (run); CTFontRef run_ct_font = static_cast(CFDictionaryGetValue (attributes, kCTFontAttributeName)); - if (!CFEqual (run_ct_font, font_data->ct_font)) + if (!CFEqual (run_ct_font, face_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 @@ -846,15 +967,11 @@ retry: * 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. + * construct a hb_face to begin with. * * See: http://github.com/behdad/harfbuzz/pull/36 + * + * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098 */ bool matched = false; for (unsigned int i = 0; i < range_records.len; i++) @@ -868,13 +985,13 @@ retry: CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0); if (run_cg_font) { - matched = CFEqual (run_cg_font, face_data); + matched = CFEqual (run_cg_font, face_data->cg_font); CFRelease (run_cg_font); } } if (!matched) { - CFStringRef font_ps_name = CTFontCopyName (font_data->ct_font, kCTFontPostScriptNameKey); + CFStringRef font_ps_name = CTFontCopyName (face_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); @@ -994,7 +1111,6 @@ retry: positions = position_buf; } hb_glyph_info_t *info = run_info; - CGFloat x_mult = font_data->x_mult, y_mult = font_data->y_mult; if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) { hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult; @@ -1064,6 +1180,9 @@ retry: pos->x_advance = info->mask; pos->x_offset = info->var1.i32; pos->y_offset = info->var2.i32; + + info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + info++, pos++; } else @@ -1072,6 +1191,9 @@ retry: pos->y_advance = info->mask; pos->x_offset = info->var1.i32; pos->y_offset = info->var2.i32; + + info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + info++, pos++; } @@ -1129,9 +1251,8 @@ fail: * AAT shaper */ -HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, face) -HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, font) - +HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face) +HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font) /* * shaper face data @@ -1193,7 +1314,9 @@ struct hb_coretext_aat_shaper_shape_plan_data_t {}; hb_coretext_aat_shaper_shape_plan_data_t * _hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } diff --git a/gfx/harfbuzz/src/hb-coretext.h b/gfx/harfbuzz/src/hb-coretext.h index 25267bc97..82066e4e0 100644 --- a/gfx/harfbuzz/src/hb-coretext.h +++ b/gfx/harfbuzz/src/hb-coretext.h @@ -44,14 +44,14 @@ HB_BEGIN_DECLS #define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x') -hb_face_t * +HB_EXTERN hb_face_t * hb_coretext_face_create (CGFontRef cg_font); -CGFontRef +HB_EXTERN CGFontRef hb_coretext_face_get_cg_font (hb_face_t *face); -CTFontRef +HB_EXTERN CTFontRef hb_coretext_font_get_ct_font (hb_font_t *font); diff --git a/gfx/harfbuzz/src/hb-deprecated.h b/gfx/harfbuzz/src/hb-deprecated.h index 30ae4b1ca..0398dfae6 100644 --- a/gfx/harfbuzz/src/hb-deprecated.h +++ b/gfx/harfbuzz/src/hb-deprecated.h @@ -44,6 +44,16 @@ HB_BEGIN_DECLS #define HB_BUFFER_FLAGS_DEFAULT HB_BUFFER_FLAG_DEFAULT #define HB_BUFFER_SERIALIZE_FLAGS_DEFAULT HB_BUFFER_SERIALIZE_FLAG_DEFAULT +typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data); + +HB_EXTERN void +hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_func_t func, + void *user_data, hb_destroy_func_t destroy); + #endif HB_END_DECLS diff --git a/gfx/harfbuzz/src/hb-directwrite.cc b/gfx/harfbuzz/src/hb-directwrite.cc new file mode 100644 index 000000000..14df8221b --- /dev/null +++ b/gfx/harfbuzz/src/hb-directwrite.cc @@ -0,0 +1,936 @@ +/* + * Copyright © 2015-2016 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#define HB_SHAPER directwrite +#include "hb-shaper-impl-private.hh" + +#include + +#include "hb-directwrite.h" + + +#ifndef HB_DEBUG_DIRECTWRITE +#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0) +#endif + +HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, face) +HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, font) + + +/* + * DirectWrite font stream helpers + */ + +// This is a font loader which provides only one font (unlike its original design). +// For a better implementation which was also source of this +// and DWriteFontFileStream, have a look at to NativeFontResourceDWrite.cpp in Mozilla +class DWriteFontFileLoader : public IDWriteFontFileLoader +{ +private: + IDWriteFontFileStream *mFontFileStream; +public: + DWriteFontFileLoader (IDWriteFontFileStream *fontFileStream) { + mFontFileStream = fontFileStream; + } + + // IUnknown interface + IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) { return S_OK; } + IFACEMETHOD_(ULONG, AddRef)() { return 1; } + IFACEMETHOD_(ULONG, Release)() { return 1; } + + // IDWriteFontFileLoader methods + virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const* fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + OUT IDWriteFontFileStream** fontFileStream) + { + *fontFileStream = mFontFileStream; + return S_OK; + } +}; + +class DWriteFontFileStream : public IDWriteFontFileStream +{ +private: + uint8_t *mData; + uint32_t mSize; +public: + DWriteFontFileStream(uint8_t *aData, uint32_t aSize) + { + mData = aData; + mSize = aSize; + } + + // IUnknown interface + IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) { return S_OK; } + IFACEMETHOD_(ULONG, AddRef)() { return 1; } + IFACEMETHOD_(ULONG, Release)() { return 1; } + + // IDWriteFontFileStream methods + virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart, + UINT64 fileOffset, + UINT64 fragmentSize, + OUT void** fragmentContext) + { + // We are required to do bounds checking. + if (fileOffset + fragmentSize > mSize) { + return E_FAIL; + } + + // truncate the 64 bit fileOffset to size_t sized index into mData + size_t index = static_cast (fileOffset); + + // We should be alive for the duration of this. + *fragmentStart = &mData[index]; + *fragmentContext = nullptr; + return S_OK; + } + + virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext) { } + + virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize) + { + *fileSize = mSize; + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime) + { + return E_NOTIMPL; + } +}; + + +/* +* shaper face data +*/ + +struct hb_directwrite_shaper_face_data_t { + IDWriteFactory *dwriteFactory; + IDWriteFontFile *fontFile; + IDWriteFontFileStream *fontFileStream; + IDWriteFontFileLoader *fontFileLoader; + IDWriteFontFace *fontFace; + hb_blob_t *faceBlob; +}; + +hb_directwrite_shaper_face_data_t * +_hb_directwrite_shaper_face_data_create(hb_face_t *face) +{ + hb_directwrite_shaper_face_data_t *data = + (hb_directwrite_shaper_face_data_t *) malloc (sizeof (hb_directwrite_shaper_face_data_t)); + if (unlikely (!data)) + return NULL; + + // TODO: factory and fontFileLoader should be cached separately + IDWriteFactory* dwriteFactory; + DWriteCreateFactory ( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof (IDWriteFactory), + (IUnknown**) &dwriteFactory + ); + + HRESULT hr; + hb_blob_t *blob = hb_face_reference_blob (face); + IDWriteFontFileStream *fontFileStream = new DWriteFontFileStream ( + (uint8_t*) hb_blob_get_data (blob, NULL), hb_blob_get_length (blob)); + + IDWriteFontFileLoader *fontFileLoader = new DWriteFontFileLoader (fontFileStream); + dwriteFactory->RegisterFontFileLoader (fontFileLoader); + + IDWriteFontFile *fontFile; + uint64_t fontFileKey = 0; + hr = dwriteFactory->CreateCustomFontFileReference (&fontFileKey, sizeof (fontFileKey), + fontFileLoader, &fontFile); + +#define FAIL(...) \ + HB_STMT_START { \ + DEBUG_MSG (DIRECTWRITE, NULL, __VA_ARGS__); \ + return false; \ + } HB_STMT_END; + + if (FAILED (hr)) { + FAIL ("Failed to load font file from data!"); + return false; + } + + BOOL isSupported; + DWRITE_FONT_FILE_TYPE fileType; + DWRITE_FONT_FACE_TYPE faceType; + UINT32 numberOfFaces; + hr = fontFile->Analyze (&isSupported, &fileType, &faceType, &numberOfFaces); + if (FAILED (hr) || !isSupported) { + FAIL ("Font file is not supported."); + return false; + } + +#undef FAIL + + IDWriteFontFace *fontFace; + dwriteFactory->CreateFontFace (faceType, 1, &fontFile, 0, + DWRITE_FONT_SIMULATIONS_NONE, &fontFace); + + data->dwriteFactory = dwriteFactory; + data->fontFile = fontFile; + data->fontFileStream = fontFileStream; + data->fontFileLoader = fontFileLoader; + data->fontFace = fontFace; + data->faceBlob = blob; + + return data; +} + +void +_hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data) +{ + if (data->fontFace) + data->fontFace->Release (); + if (data->fontFile) + data->fontFile->Release (); + if (data->dwriteFactory) { + if (data->fontFileLoader) + data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader); + data->dwriteFactory->Release (); + } + if (data->fontFileLoader) + delete data->fontFileLoader; + if (data->fontFileStream) + delete data->fontFileStream; + if (data->faceBlob) + hb_blob_destroy (data->faceBlob); + if (data) + free (data); +} + + +/* + * shaper font data + */ + +struct hb_directwrite_shaper_font_data_t { +}; + +hb_directwrite_shaper_font_data_t * +_hb_directwrite_shaper_font_data_create (hb_font_t *font) +{ + if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return NULL; + + hb_directwrite_shaper_font_data_t *data = + (hb_directwrite_shaper_font_data_t *) malloc (sizeof (hb_directwrite_shaper_font_data_t)); + if (unlikely (!data)) + return NULL; + + return data; +} + +void +_hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data) +{ + free (data); +} + + +/* + * shaper shape_plan data + */ + +struct hb_directwrite_shaper_shape_plan_data_t {}; + +hb_directwrite_shaper_shape_plan_data_t * +_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, + const hb_feature_t *user_features HB_UNUSED, + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) +{ + return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; +} + +void +_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan_data_t *data HB_UNUSED) +{ +} + +// Most of TextAnalysis is originally written by Bas Schouten for Mozilla project +// but now is relicensed to MIT for HarfBuzz use +class TextAnalysis + : public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink +{ +public: + + IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) { return S_OK; } + IFACEMETHOD_(ULONG, AddRef)() { return 1; } + IFACEMETHOD_(ULONG, Release)() { return 1; } + + // A single contiguous run of characters containing the same analysis + // results. + struct Run + { + uint32_t mTextStart; // starting text position of this run + uint32_t mTextLength; // number of contiguous code units covered + uint32_t mGlyphStart; // starting glyph in the glyphs array + uint32_t mGlyphCount; // number of glyphs associated with this run of + // text + DWRITE_SCRIPT_ANALYSIS mScript; + uint8_t mBidiLevel; + bool mIsSideways; + + inline bool ContainsTextPosition(uint32_t aTextPosition) const + { + return aTextPosition >= mTextStart + && aTextPosition < mTextStart + mTextLength; + } + + Run *nextRun; + }; + +public: + TextAnalysis(const wchar_t* text, + uint32_t textLength, + const wchar_t* localeName, + DWRITE_READING_DIRECTION readingDirection) + : mText(text) + , mTextLength(textLength) + , mLocaleName(localeName) + , mReadingDirection(readingDirection) + , mCurrentRun(NULL) { }; + + ~TextAnalysis() { + // delete runs, except mRunHead which is part of the TextAnalysis object + for (Run *run = mRunHead.nextRun; run;) { + Run *origRun = run; + run = run->nextRun; + free (origRun); + } + } + + STDMETHODIMP GenerateResults(IDWriteTextAnalyzer* textAnalyzer, + Run **runHead) { + // Analyzes the text using the script analyzer and returns + // the result as a series of runs. + + HRESULT hr = S_OK; + + // Initially start out with one result that covers the entire range. + // This result will be subdivided by the analysis processes. + mRunHead.mTextStart = 0; + mRunHead.mTextLength = mTextLength; + mRunHead.mBidiLevel = + (mReadingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT); + mRunHead.nextRun = NULL; + mCurrentRun = &mRunHead; + + // Call each of the analyzers in sequence, recording their results. + if (SUCCEEDED (hr = textAnalyzer->AnalyzeScript (this, 0, mTextLength, this))) { + *runHead = &mRunHead; + } + + return hr; + } + + // IDWriteTextAnalysisSource implementation + + IFACEMETHODIMP GetTextAtPosition(uint32_t textPosition, + OUT wchar_t const** textString, + OUT uint32_t* textLength) + { + if (textPosition >= mTextLength) { + // No text at this position, valid query though. + *textString = NULL; + *textLength = 0; + } + else { + *textString = mText + textPosition; + *textLength = mTextLength - textPosition; + } + return S_OK; + } + + IFACEMETHODIMP GetTextBeforePosition(uint32_t textPosition, + OUT wchar_t const** textString, + OUT uint32_t* textLength) + { + if (textPosition == 0 || textPosition > mTextLength) { + // Either there is no text before here (== 0), or this + // is an invalid position. The query is considered valid thouh. + *textString = NULL; + *textLength = 0; + } + else { + *textString = mText; + *textLength = textPosition; + } + return S_OK; + } + + IFACEMETHODIMP_(DWRITE_READING_DIRECTION) + GetParagraphReadingDirection() { return mReadingDirection; } + + IFACEMETHODIMP GetLocaleName(uint32_t textPosition, + uint32_t* textLength, + wchar_t const** localeName) + { + return S_OK; + } + + IFACEMETHODIMP + GetNumberSubstitution(uint32_t textPosition, + OUT uint32_t* textLength, + OUT IDWriteNumberSubstitution** numberSubstitution) + { + // We do not support number substitution. + *numberSubstitution = NULL; + *textLength = mTextLength - textPosition; + + return S_OK; + } + + // IDWriteTextAnalysisSink implementation + + IFACEMETHODIMP + SetScriptAnalysis(uint32_t textPosition, + uint32_t textLength, + DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis) + { + SetCurrentRun(textPosition); + SplitCurrentRun(textPosition); + while (textLength > 0) + { + Run *run = FetchNextRun(&textLength); + run->mScript = *scriptAnalysis; + } + + return S_OK; + } + + IFACEMETHODIMP + SetLineBreakpoints(uint32_t textPosition, + uint32_t textLength, + const DWRITE_LINE_BREAKPOINT* lineBreakpoints) { return S_OK; } + + IFACEMETHODIMP SetBidiLevel(uint32_t textPosition, + uint32_t textLength, + uint8_t explicitLevel, + uint8_t resolvedLevel) { return S_OK; } + + IFACEMETHODIMP + SetNumberSubstitution(uint32_t textPosition, + uint32_t textLength, + IDWriteNumberSubstitution* numberSubstitution) { return S_OK; } + +protected: + Run *FetchNextRun(IN OUT uint32_t* textLength) + { + // Used by the sink setters, this returns a reference to the next run. + // Position and length are adjusted to now point after the current run + // being returned. + + Run *origRun = mCurrentRun; + // Split the tail if needed (the length remaining is less than the + // current run's size). + if (*textLength < mCurrentRun->mTextLength) + { + SplitCurrentRun (mCurrentRun->mTextStart + *textLength); + } + else + { + // Just advance the current run. + mCurrentRun = mCurrentRun->nextRun; + } + *textLength -= origRun->mTextLength; + + // Return a reference to the run that was just current. + return origRun; + } + + void SetCurrentRun(uint32_t textPosition) + { + // Move the current run to the given position. + // Since the analyzers generally return results in a forward manner, + // this will usually just return early. If not, find the + // corresponding run for the text position. + + if (mCurrentRun && mCurrentRun->ContainsTextPosition (textPosition)) + { + return; + } + + for (Run *run = &mRunHead; run; run = run->nextRun) { + if (run->ContainsTextPosition (textPosition)) + { + mCurrentRun = run; + return; + } + } + //NS_NOTREACHED("We should always be able to find the text position in one \ + // of our runs"); + } + + void SplitCurrentRun(uint32_t splitPosition) + { + if (!mCurrentRun) + { + //NS_ASSERTION(false, "SplitCurrentRun called without current run."); + // Shouldn't be calling this when no current run is set! + return; + } + // Split the current run. + if (splitPosition <= mCurrentRun->mTextStart) + { + // No need to split, already the start of a run + // or before it. Usually the first. + return; + } + Run *newRun = (Run*) malloc (sizeof (Run)); + + *newRun = *mCurrentRun; + + // Insert the new run in our linked list. + newRun->nextRun = mCurrentRun->nextRun; + mCurrentRun->nextRun = newRun; + + // Adjust runs' text positions and lengths. + uint32_t splitPoint = splitPosition - mCurrentRun->mTextStart; + newRun->mTextStart += splitPoint; + newRun->mTextLength -= splitPoint; + mCurrentRun->mTextLength = splitPoint; + mCurrentRun = newRun; + } + +protected: + // Input + // (weak references are fine here, since this class is a transient + // stack-based helper that doesn't need to copy data) + uint32_t mTextLength; + const wchar_t* mText; + const wchar_t* mLocaleName; + DWRITE_READING_DIRECTION mReadingDirection; + + // Current processing state. + Run *mCurrentRun; + + // Output is a list of runs starting here + Run mRunHead; +}; + +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); } + +/* + * shaper + */ + +static hb_bool_t +_hb_directwrite_shape_full(hb_shape_plan_t *shape_plan, + hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + float lineWidth) +{ + hb_face_t *face = font->face; + hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); + hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); + IDWriteFactory *dwriteFactory = face_data->dwriteFactory; + IDWriteFontFace *fontFace = face_data->fontFace; + + IDWriteTextAnalyzer* analyzer; + dwriteFactory->CreateTextAnalyzer(&analyzer); + + unsigned int scratch_size; + hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size); +#define ALLOCATE_ARRAY(Type, name, len) \ + Type *name = (Type *) scratch; \ + { \ + unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \ + assert (_consumed <= scratch_size); \ + scratch += _consumed; \ + scratch_size -= _consumed; \ + } + +#define utf16_index() var1.u32 + + ALLOCATE_ARRAY(wchar_t, textString, buffer->len * 2); + + unsigned int chars_len = 0; + for (unsigned int i = 0; i < buffer->len; i++) + { + hb_codepoint_t c = buffer->info[i].codepoint; + buffer->info[i].utf16_index() = chars_len; + if (likely(c <= 0xFFFFu)) + textString[chars_len++] = c; + else if (unlikely(c > 0x10FFFFu)) + textString[chars_len++] = 0xFFFDu; + else { + textString[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10); + textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1)); + } + } + + ALLOCATE_ARRAY(WORD, log_clusters, chars_len); + // if (num_features) + { + /* Need log_clusters to assign features. */ + chars_len = 0; + for (unsigned int i = 0; i < buffer->len; i++) + { + hb_codepoint_t c = buffer->info[i].codepoint; + unsigned int cluster = buffer->info[i].cluster; + log_clusters[chars_len++] = cluster; + if (hb_in_range(c, 0x10000u, 0x10FFFFu)) + log_clusters[chars_len++] = cluster; /* Surrogates. */ + } + } + + // TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES + + DWRITE_READING_DIRECTION readingDirection = buffer->props.direction ? + DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : + DWRITE_READING_DIRECTION_LEFT_TO_RIGHT; + + /* + * There's an internal 16-bit limit on some things inside the analyzer, + * but we never attempt to shape a word longer than 64K characters + * in a single gfxShapedWord, so we cannot exceed that limit. + */ + uint32_t textLength = buffer->len; + + TextAnalysis analysis(textString, textLength, NULL, readingDirection); + TextAnalysis::Run *runHead; + HRESULT hr; + hr = analysis.GenerateResults(analyzer, &runHead); + +#define FAIL(...) \ + HB_STMT_START { \ + DEBUG_MSG (DIRECTWRITE, NULL, __VA_ARGS__); \ + return false; \ + } HB_STMT_END; + + if (FAILED (hr)) + { + FAIL ("Analyzer failed to generate results."); + return false; + } + + uint32_t maxGlyphCount = 3 * textLength / 2 + 16; + uint32_t glyphCount; + bool isRightToLeft = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); + + const wchar_t localeName[20] = {0}; + if (buffer->props.language != NULL) + { + mbstowcs ((wchar_t*) localeName, + hb_language_to_string (buffer->props.language), 20); + } + + DWRITE_TYPOGRAPHIC_FEATURES singleFeatures; + singleFeatures.featureCount = num_features; + if (num_features) + { + DWRITE_FONT_FEATURE* dwfeatureArray = (DWRITE_FONT_FEATURE*) + malloc (sizeof (DWRITE_FONT_FEATURE) * num_features); + for (unsigned int i = 0; i < num_features; ++i) + { + dwfeatureArray[i].nameTag = (DWRITE_FONT_FEATURE_TAG) + hb_uint32_swap (features[i].tag); + dwfeatureArray[i].parameter = features[i].value; + } + singleFeatures.features = dwfeatureArray; + } + const DWRITE_TYPOGRAPHIC_FEATURES* dwFeatures = + (const DWRITE_TYPOGRAPHIC_FEATURES*) &singleFeatures; + const uint32_t featureRangeLengths[] = { textLength }; + + uint16_t* clusterMap = (uint16_t*) malloc (textLength * sizeof (uint16_t)); + DWRITE_SHAPING_TEXT_PROPERTIES* textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*) + malloc (textLength * sizeof (DWRITE_SHAPING_TEXT_PROPERTIES)); +retry_getglyphs: + uint16_t* glyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t)); + DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*) + malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES)); + + hr = analyzer->GetGlyphs (textString, textLength, fontFace, false, + isRightToLeft, &runHead->mScript, localeName, NULL, &dwFeatures, + featureRangeLengths, 1, maxGlyphCount, clusterMap, textProperties, glyphIndices, + glyphProperties, &glyphCount); + + if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))) + { + free (glyphIndices); + free (glyphProperties); + + maxGlyphCount *= 2; + + goto retry_getglyphs; + } + if (FAILED (hr)) + { + FAIL ("Analyzer failed to get glyphs."); + return false; + } + + float* glyphAdvances = (float*) malloc (maxGlyphCount * sizeof (float)); + DWRITE_GLYPH_OFFSET* glyphOffsets = (DWRITE_GLYPH_OFFSET*) + malloc(maxGlyphCount * sizeof (DWRITE_GLYPH_OFFSET)); + + /* The -2 in the following is to compensate for possible + * alignment needed after the WORD array. sizeof(WORD) == 2. */ + unsigned int glyphs_size = (scratch_size * sizeof(int) - 2) + / (sizeof(WORD) + + sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES) + + sizeof(int) + + sizeof(DWRITE_GLYPH_OFFSET) + + sizeof(uint32_t)); + ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size); + +#undef ALLOCATE_ARRAY + + int fontEmSize = font->face->get_upem(); + if (fontEmSize < 0) + fontEmSize = -fontEmSize; + + if (fontEmSize < 0) + fontEmSize = -fontEmSize; + double x_mult = (double) font->x_scale / fontEmSize; + double y_mult = (double) font->y_scale / fontEmSize; + + hr = analyzer->GetGlyphPlacements (textString, + clusterMap, textProperties, textLength, glyphIndices, + glyphProperties, glyphCount, fontFace, fontEmSize, + false, isRightToLeft, &runHead->mScript, localeName, + &dwFeatures, featureRangeLengths, 1, + glyphAdvances, glyphOffsets); + + if (FAILED (hr)) + { + FAIL ("Analyzer failed to get glyph placements."); + return false; + } + + IDWriteTextAnalyzer1* analyzer1; + analyzer->QueryInterface (&analyzer1); + + if (analyzer1 && lineWidth) + { + + DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities = + (DWRITE_JUSTIFICATION_OPPORTUNITY*) + malloc (maxGlyphCount * sizeof (DWRITE_JUSTIFICATION_OPPORTUNITY)); + hr = analyzer1->GetJustificationOpportunities (fontFace, fontEmSize, + runHead->mScript, textLength, glyphCount, textString, clusterMap, + glyphProperties, justificationOpportunities); + + if (FAILED (hr)) + { + FAIL ("Analyzer failed to get justification opportunities."); + return false; + } + + float* justifiedGlyphAdvances = + (float*) malloc (maxGlyphCount * sizeof (float)); + DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*) + malloc (glyphCount * sizeof (DWRITE_GLYPH_OFFSET)); + hr = analyzer1->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities, + glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets); + + if (FAILED (hr)) + { + FAIL("Analyzer failed to get justified glyph advances."); + return false; + } + + DWRITE_SCRIPT_PROPERTIES scriptProperties; + hr = analyzer1->GetScriptProperties (runHead->mScript, &scriptProperties); + if (FAILED (hr)) + { + FAIL("Analyzer failed to get script properties."); + return false; + } + uint32_t justificationCharacter = scriptProperties.justificationCharacter; + + // if a script justificationCharacter is not space, it can have GetJustifiedGlyphs + if (justificationCharacter != 32) + { + uint16_t* modifiedClusterMap = (uint16_t*) malloc (textLength * sizeof (uint16_t)); + retry_getjustifiedglyphs: + uint16_t* modifiedGlyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t)); + float* modifiedGlyphAdvances = (float*) malloc (maxGlyphCount * sizeof (float)); + DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*) + malloc (maxGlyphCount * sizeof (DWRITE_GLYPH_OFFSET)); + uint32_t actualGlyphsCount; + hr = analyzer1->GetJustifiedGlyphs (fontFace, fontEmSize, runHead->mScript, + textLength, glyphCount, maxGlyphCount, clusterMap, glyphIndices, + glyphAdvances, justifiedGlyphAdvances, justifiedGlyphOffsets, + glyphProperties, &actualGlyphsCount, modifiedClusterMap, modifiedGlyphIndices, + modifiedGlyphAdvances, modifiedGlyphOffsets); + + if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)) + { + maxGlyphCount = actualGlyphsCount; + free (modifiedGlyphIndices); + free (modifiedGlyphAdvances); + free (modifiedGlyphOffsets); + + maxGlyphCount = actualGlyphsCount; + + goto retry_getjustifiedglyphs; + } + if (FAILED (hr)) + { + FAIL ("Analyzer failed to get justified glyphs."); + return false; + } + + free (clusterMap); + free (glyphIndices); + free (glyphAdvances); + free (glyphOffsets); + + glyphCount = actualGlyphsCount; + clusterMap = modifiedClusterMap; + glyphIndices = modifiedGlyphIndices; + glyphAdvances = modifiedGlyphAdvances; + glyphOffsets = modifiedGlyphOffsets; + + free (justifiedGlyphAdvances); + free (justifiedGlyphOffsets); + } + else + { + free (glyphAdvances); + free (glyphOffsets); + + glyphAdvances = justifiedGlyphAdvances; + glyphOffsets = justifiedGlyphOffsets; + } + + free (justificationOpportunities); + + } + + /* Ok, we've got everything we need, now compose output buffer, + * very, *very*, carefully! */ + + /* Calculate visual-clusters. That's what we ship. */ + for (unsigned int i = 0; i < glyphCount; i++) + vis_clusters[i] = -1; + for (unsigned int i = 0; i < buffer->len; i++) + { + uint32_t *p = + &vis_clusters[log_clusters[buffer->info[i].utf16_index()]]; + *p = MIN (*p, buffer->info[i].cluster); + } + for (unsigned int i = 1; i < glyphCount; i++) + if (vis_clusters[i] == -1) + vis_clusters[i] = vis_clusters[i - 1]; + +#undef utf16_index + + if (unlikely (!buffer->ensure (glyphCount))) + FAIL ("Buffer in error"); + +#undef FAIL + + /* Set glyph infos */ + buffer->len = 0; + for (unsigned int i = 0; i < glyphCount; i++) + { + hb_glyph_info_t *info = &buffer->info[buffer->len++]; + + info->codepoint = glyphIndices[i]; + info->cluster = vis_clusters[i]; + + /* The rest is crap. Let's store position info there for now. */ + info->mask = glyphAdvances[i]; + info->var1.i32 = glyphOffsets[i].advanceOffset; + info->var2.i32 = glyphOffsets[i].ascenderOffset; + } + + /* Set glyph positions */ + buffer->clear_positions (); + for (unsigned int i = 0; i < glyphCount; i++) + { + hb_glyph_info_t *info = &buffer->info[i]; + hb_glyph_position_t *pos = &buffer->pos[i]; + + /* TODO vertical */ + pos->x_advance = x_mult * (int32_t) info->mask; + pos->x_offset = + x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32); + pos->y_offset = y_mult * info->var2.i32; + + info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + } + + if (isRightToLeft) + hb_buffer_reverse (buffer); + + free (clusterMap); + free (glyphIndices); + free (textProperties); + free (glyphProperties); + free (glyphAdvances); + free (glyphOffsets); + + if (num_features) + free (singleFeatures.features); + + /* Wow, done! */ + return true; +} + +hb_bool_t +_hb_directwrite_shape(hb_shape_plan_t *shape_plan, + hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features) +{ + return _hb_directwrite_shape_full(shape_plan, font, buffer, + features, num_features, 0); +} + +/* + * Public [experimental] API + */ + +hb_bool_t +hb_directwrite_shape_experimental_width(hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + float width) +{ + static char *shapers = "directwrite"; + hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, + &buffer->props, features, num_features, &shapers); + hb_bool_t res = _hb_directwrite_shape_full (shape_plan, font, buffer, + features, num_features, width); + + if (res) + buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; + + return res; +} diff --git a/gfx/harfbuzz/src/hb-directwrite.h b/gfx/harfbuzz/src/hb-directwrite.h new file mode 100644 index 000000000..e743af214 --- /dev/null +++ b/gfx/harfbuzz/src/hb-directwrite.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2015 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_DIRECTWRITE_H +#define HB_DIRECTWRITE_H + +#include "hb.h" + +HB_BEGIN_DECLS + +HB_EXTERN hb_bool_t +hb_directwrite_shape_experimental_width(hb_font_t *font, hb_buffer_t *buffer, + const hb_feature_t *features, unsigned int num_features, float width); + +HB_END_DECLS + +#endif /* HB_DIRECTWRITE_H */ diff --git a/gfx/harfbuzz/src/hb-face-private.hh b/gfx/harfbuzz/src/hb-face-private.hh index c4266fff4..72f08a599 100644 --- a/gfx/harfbuzz/src/hb-face-private.hh +++ b/gfx/harfbuzz/src/hb-face-private.hh @@ -50,12 +50,23 @@ struct hb_face_t { void *user_data; hb_destroy_func_t destroy; - unsigned int index; - mutable unsigned int upem; - mutable unsigned int num_glyphs; + unsigned int index; /* Face index in a collection, zero-based. */ + mutable unsigned int upem; /* Units-per-EM. */ + mutable unsigned int num_glyphs; /* Number of glyphs. */ - struct hb_shaper_data_t shaper_data; + enum dirty_t { + DIRTY_NOTHING = 0x0000, + DIRTY_INDEX = 0x0001, + DIRTY_UPEM = 0x0002, + DIRTY_NUM_GLYPHS = 0x0004, + } dirty; + struct hb_shaper_data_t shaper_data; /* Various shaper data. */ + + /* Various non-shaping data. */ + /* ... */ + + /* Cache */ struct plan_node_t { hb_shape_plan_t *shape_plan; plan_node_t *next; @@ -95,6 +106,8 @@ struct hb_face_t { HB_INTERNAL void load_num_glyphs (void) const; }; +HB_MARK_AS_FLAG_T (hb_face_t::dirty_t); + extern HB_INTERNAL const hb_face_t _hb_face_nil; #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS diff --git a/gfx/harfbuzz/src/hb-face.cc b/gfx/harfbuzz/src/hb-face.cc index 9effc41c8..22998f005 100644 --- a/gfx/harfbuzz/src/hb-face.cc +++ b/gfx/harfbuzz/src/hb-face.cc @@ -28,17 +28,11 @@ #include "hb-private.hh" -#include "hb-ot-layout-private.hh" - -#include "hb-font-private.hh" +#include "hb-face-private.hh" #include "hb-open-file-private.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" -#include "hb-cache-private.hh" - -#include - /* * hb_face_t @@ -57,6 +51,8 @@ const hb_face_t _hb_face_nil = { 1000, /* upem */ 0, /* num_glyphs */ + hb_face_t::DIRTY_NOTHING, /* dirty */ + { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -177,7 +173,7 @@ hb_face_create (hb_blob_t *blob, closure, (hb_destroy_func_t) _hb_face_for_data_closure_destroy); - hb_face_set_index (face, index); + face->index = index; return face; } @@ -371,6 +367,11 @@ hb_face_set_index (hb_face_t *face, if (face->immutable) return; + if (face->index == index) + return; + + face->dirty |= face->DIRTY_INDEX; + face->index = index; } @@ -406,6 +407,11 @@ hb_face_set_upem (hb_face_t *face, if (face->immutable) return; + if (face->upem == upem) + return; + + face->dirty |= face->DIRTY_UPEM; + face->upem = upem; } @@ -450,6 +456,11 @@ hb_face_set_glyph_count (hb_face_t *face, if (face->immutable) return; + if (face->num_glyphs == glyph_count) + return; + + face->dirty |= face->DIRTY_NUM_GLYPHS; + face->num_glyphs = glyph_count; } diff --git a/gfx/harfbuzz/src/hb-face.h b/gfx/harfbuzz/src/hb-face.h index f682c468d..91237b708 100644 --- a/gfx/harfbuzz/src/hb-face.h +++ b/gfx/harfbuzz/src/hb-face.h @@ -43,28 +43,28 @@ HB_BEGIN_DECLS typedef struct hb_face_t hb_face_t; -hb_face_t * +HB_EXTERN hb_face_t * hb_face_create (hb_blob_t *blob, unsigned int index); typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag, void *user_data); /* calls destroy() when not needing user_data anymore */ -hb_face_t * +HB_EXTERN hb_face_t * hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, void *user_data, hb_destroy_func_t destroy); -hb_face_t * +HB_EXTERN hb_face_t * hb_face_get_empty (void); -hb_face_t * +HB_EXTERN hb_face_t * hb_face_reference (hb_face_t *face); -void +HB_EXTERN void hb_face_destroy (hb_face_t *face); -hb_bool_t +HB_EXTERN hb_bool_t hb_face_set_user_data (hb_face_t *face, hb_user_data_key_t *key, void * data, @@ -72,43 +72,43 @@ hb_face_set_user_data (hb_face_t *face, hb_bool_t replace); -void * +HB_EXTERN void * hb_face_get_user_data (hb_face_t *face, hb_user_data_key_t *key); -void +HB_EXTERN void hb_face_make_immutable (hb_face_t *face); -hb_bool_t +HB_EXTERN hb_bool_t hb_face_is_immutable (hb_face_t *face); -hb_blob_t * +HB_EXTERN hb_blob_t * hb_face_reference_table (hb_face_t *face, hb_tag_t tag); -hb_blob_t * +HB_EXTERN hb_blob_t * hb_face_reference_blob (hb_face_t *face); -void +HB_EXTERN void hb_face_set_index (hb_face_t *face, unsigned int index); -unsigned int +HB_EXTERN unsigned int hb_face_get_index (hb_face_t *face); -void +HB_EXTERN void hb_face_set_upem (hb_face_t *face, unsigned int upem); -unsigned int +HB_EXTERN unsigned int hb_face_get_upem (hb_face_t *face); -void +HB_EXTERN void hb_face_set_glyph_count (hb_face_t *face, unsigned int glyph_count); -unsigned int +HB_EXTERN unsigned int hb_face_get_glyph_count (hb_face_t *face); diff --git a/gfx/harfbuzz/src/hb-fallback-shape.cc b/gfx/harfbuzz/src/hb-fallback-shape.cc index 9d061a9e8..4b60c6c34 100644 --- a/gfx/harfbuzz/src/hb-fallback-shape.cc +++ b/gfx/harfbuzz/src/hb-fallback-shape.cc @@ -28,6 +28,10 @@ #include "hb-shaper-impl-private.hh" +HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face) +HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font) + + /* * shaper face data */ @@ -73,7 +77,9 @@ struct hb_fallback_shaper_shape_plan_data_t {}; hb_fallback_shaper_shape_plan_data_t * _hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } @@ -106,7 +112,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, */ hb_codepoint_t space; - bool has_space = font->get_glyph (' ', 0, &space); + bool has_space = (bool) font->get_nominal_glyph (' ', &space); buffer->clear_positions (); @@ -123,7 +129,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, pos[i].y_advance = 0; continue; } - font->get_glyph (info[i].codepoint, 0, &info[i].codepoint); + (void) font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint); font->get_glyph_advance_for_direction (info[i].codepoint, direction, &pos[i].x_advance, diff --git a/gfx/harfbuzz/src/hb-font-private.hh b/gfx/harfbuzz/src/hb-font-private.hh index 9ee9e5405..ed9f2c54a 100644 --- a/gfx/harfbuzz/src/hb-font-private.hh +++ b/gfx/harfbuzz/src/hb-font-private.hh @@ -42,7 +42,10 @@ */ #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ - HB_FONT_FUNC_IMPLEMENT (glyph) \ + HB_FONT_FUNC_IMPLEMENT (font_h_extents) \ + HB_FONT_FUNC_IMPLEMENT (font_v_extents) \ + HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \ + HB_FONT_FUNC_IMPLEMENT (variation_glyph) \ HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \ @@ -105,16 +108,36 @@ struct hb_font_t { unsigned int x_ppem; unsigned int y_ppem; + /* Font variation coordinates. */ + unsigned int num_coords; + int *coords; + hb_font_funcs_t *klass; void *user_data; hb_destroy_func_t destroy; + enum dirty_t { + DIRTY_NOTHING = 0x0000, + DIRTY_FACE = 0x0001, + DIRTY_PARENT = 0x0002, + DIRTY_FUNCS = 0x0004, + DIRTY_SCALE = 0x0008, + DIRTY_PPEM = 0x0010, + DIRTY_VARIATIONS = 0x0020, + } dirty; + struct hb_shaper_data_t shaper_data; /* Convert from font-space to user-space */ - inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); } - inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); } + inline int dir_scale (hb_direction_t direction) + { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; } + inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); } + inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); } + inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); } + inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); } + inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) + { return em_scale (v, dir_scale (direction)); } /* Convert from parent-font user-space to our user-space */ inline hb_position_t parent_scale_x_distance (hb_position_t v) { @@ -160,19 +183,43 @@ struct hb_font_t { HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT - inline hb_bool_t has_glyph (hb_codepoint_t unicode) + inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents) { - hb_codepoint_t glyph; - return get_glyph (unicode, 0, &glyph); + memset (extents, 0, sizeof (*extents)); + return klass->get.f.font_h_extents (this, user_data, + extents, + klass->user_data.font_h_extents); + } + inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents) + { + memset (extents, 0, sizeof (*extents)); + return klass->get.f.font_v_extents (this, user_data, + extents, + klass->user_data.font_v_extents); } - inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, - hb_codepoint_t *glyph) + inline bool has_glyph (hb_codepoint_t unicode) + { + hb_codepoint_t glyph; + return get_nominal_glyph (unicode, &glyph); + } + + inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, + hb_codepoint_t *glyph) { *glyph = 0; - return klass->get.f.glyph (this, user_data, - unicode, variation_selector, glyph, - klass->user_data.glyph); + return klass->get.f.nominal_glyph (this, user_data, + unicode, glyph, + klass->user_data.nominal_glyph); + } + + inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph) + { + *glyph = 0; + return klass->get.f.variation_glyph (this, user_data, + unicode, variation_selector, glyph, + klass->user_data.variation_glyph); } inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) @@ -265,6 +312,34 @@ struct hb_font_t { /* A bit higher-level, and with fallback */ + inline void get_h_extents_with_fallback (hb_font_extents_t *extents) + { + if (!get_font_h_extents (extents)) + { + extents->ascender = y_scale * .8; + extents->descender = extents->ascender - y_scale; + extents->line_gap = 0; + } + } + inline void get_v_extents_with_fallback (hb_font_extents_t *extents) + { + if (!get_font_v_extents (extents)) + { + extents->ascender = x_scale / 2; + extents->descender = extents->ascender - x_scale; + extents->line_gap = 0; + } + } + + inline void get_extents_for_direction (hb_direction_t direction, + hb_font_extents_t *extents) + { + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) + get_h_extents_with_fallback (extents); + else + get_v_extents_with_fallback (extents); + } + inline void get_glyph_advance_for_direction (hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y) @@ -278,14 +353,38 @@ struct hb_font_t { } } - /* Internal only */ inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y) { *x = get_glyph_h_advance (glyph) / 2; - /* TODO use font_metrics.ascent */ - *y = y_scale; + /* TODO cache this somehow?! */ + hb_font_extents_t extents; + get_h_extents_with_fallback (&extents); + *y = extents.ascender; + } + + inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + if (!get_glyph_h_origin (glyph, x, y) && + get_glyph_v_origin (glyph, x, y)) + { + hb_position_t dx, dy; + guess_v_origin_minus_h_origin (glyph, &dx, &dy); + *x -= dx; *y -= dy; + } + } + inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + if (!get_glyph_v_origin (glyph, x, y) && + get_glyph_h_origin (glyph, x, y)) + { + hb_position_t dx, dy; + guess_v_origin_minus_h_origin (glyph, &dx, &dy); + *x += dx; *y += dy; + } } inline void get_glyph_origin_for_direction (hb_codepoint_t glyph, @@ -293,25 +392,9 @@ struct hb_font_t { hb_position_t *x, hb_position_t *y) { if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) - { - if (!get_glyph_h_origin (glyph, x, y) && - get_glyph_v_origin (glyph, x, y)) - { - hb_position_t dx, dy; - guess_v_origin_minus_h_origin (glyph, &dx, &dy); - *x -= dx; *y -= dy; - } - } + get_glyph_h_origin_with_fallback (glyph, x, y); else - { - if (!get_glyph_v_origin (glyph, x, y) && - get_glyph_h_origin (glyph, x, y)) - { - hb_position_t dx, dy; - guess_v_origin_minus_h_origin (glyph, &dx, &dy); - *x += dx; *y += dy; - } - } + get_glyph_v_origin_with_fallback (glyph, x, y); } inline void add_glyph_h_origin (hb_codepoint_t glyph, @@ -319,7 +402,7 @@ struct hb_font_t { { hb_position_t origin_x, origin_y; - get_glyph_h_origin (glyph, &origin_x, &origin_y); + get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); *x += origin_x; *y += origin_y; @@ -329,7 +412,7 @@ struct hb_font_t { { hb_position_t origin_x, origin_y; - get_glyph_v_origin (glyph, &origin_x, &origin_y); + get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); *x += origin_x; *y += origin_y; @@ -351,7 +434,7 @@ struct hb_font_t { { hb_position_t origin_x, origin_y; - get_glyph_h_origin (glyph, &origin_x, &origin_y); + get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); *x -= origin_x; *y -= origin_y; @@ -361,7 +444,7 @@ struct hb_font_t { { hb_position_t origin_x, origin_y; - get_glyph_v_origin (glyph, &origin_x, &origin_y); + get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); *x -= origin_x; *y -= origin_y; @@ -450,17 +533,28 @@ struct hb_font_t { hb_codepoint_t unichar; if (0 == strncmp (s, "uni", 3) && hb_codepoint_parse (s + 3, len - 3, 16, &unichar) && - get_glyph (unichar, 0, glyph)) + get_nominal_glyph (unichar, glyph)) return true; } return false; } - private: - inline hb_position_t em_scale (int16_t v, int scale) { return (hb_position_t) (v * (int64_t) scale / face->get_upem ()); } + inline hb_position_t em_scale (int16_t v, int scale) + { + int upem = face->get_upem (); + int64_t scaled = v * (int64_t) scale; + scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */ + return (hb_position_t) (scaled / upem); + } + inline hb_position_t em_scalef (float v, int scale) + { + return (hb_position_t) (v * scale / face->get_upem ()); + } }; +HB_MARK_AS_FLAG_T (hb_font_t::dirty_t); + #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font); #include "hb-shaper-list.hh" diff --git a/gfx/harfbuzz/src/hb-font.cc b/gfx/harfbuzz/src/hb-font.cc index 00f9fb6d7..a684c234d 100644 --- a/gfx/harfbuzz/src/hb-font.cc +++ b/gfx/harfbuzz/src/hb-font.cc @@ -28,16 +28,7 @@ #include "hb-private.hh" -#include "hb-ot-layout-private.hh" - #include "hb-font-private.hh" -#include "hb-open-file-private.hh" -#include "hb-ot-head-table.hh" -#include "hb-ot-maxp-table.hh" - -#include "hb-cache-private.hh" - -#include /* @@ -45,27 +36,96 @@ */ static hb_bool_t -hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t unicode, - hb_codepoint_t variation_selector, - hb_codepoint_t *glyph, - void *user_data HB_UNUSED) +hb_font_get_font_h_extents_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + memset (metrics, 0, sizeof (*metrics)); + return false; +} +static hb_bool_t +hb_font_get_font_h_extents_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_font_h_extents (metrics); + if (ret) { + metrics->ascender = font->parent_scale_y_distance (metrics->ascender); + metrics->descender = font->parent_scale_y_distance (metrics->descender); + metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap); + } + return ret; +} + +static hb_bool_t +hb_font_get_font_v_extents_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + memset (metrics, 0, sizeof (*metrics)); + return false; +} +static hb_bool_t +hb_font_get_font_v_extents_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_font_v_extents (metrics); + if (ret) { + metrics->ascender = font->parent_scale_x_distance (metrics->ascender); + metrics->descender = font->parent_scale_x_distance (metrics->descender); + metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap); + } + return ret; +} + +static hb_bool_t +hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) { *glyph = 0; return false; } static hb_bool_t -hb_font_get_glyph_parent (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t unicode, - hb_codepoint_t variation_selector, - hb_codepoint_t *glyph, - void *user_data HB_UNUSED) +hb_font_get_nominal_glyph_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) { - return font->parent->get_glyph (unicode, variation_selector, glyph); + return font->parent->get_nominal_glyph (unicode, glyph); } +static hb_bool_t +hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + *glyph = 0; + return false; +} +static hb_bool_t +hb_font_get_variation_glyph_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + return font->parent->get_variation_glyph (unicode, variation_selector, glyph); +} + + static hb_position_t hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, @@ -89,6 +149,7 @@ hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED, hb_codepoint_t glyph, void *user_data HB_UNUSED) { + /* TODO use font_extents.ascender+descender */ return font->y_scale; } static hb_position_t @@ -109,7 +170,7 @@ hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { *x = *y = 0; - return false; + return true; } static hb_bool_t hb_font_get_glyph_h_origin_parent (hb_font_t *font, @@ -280,7 +341,6 @@ hb_font_get_glyph_from_name_parent (hb_font_t *font, return font->parent->get_glyph_from_name (name, len, glyph); } - static const hb_font_funcs_t _hb_font_funcs_nil = { HB_OBJECT_HEADER_STATIC, @@ -521,6 +581,42 @@ hb_font_t::has_func (unsigned int i) /* Public getters */ +/** + * hb_font_get_h_extents: + * @font: a font. + * @extents: (out): + * + * + * + * Return value: + * + * Since: 1.1.3 + **/ +hb_bool_t +hb_font_get_h_extents (hb_font_t *font, + hb_font_extents_t *extents) +{ + return font->get_font_h_extents (extents); +} + +/** + * hb_font_get_v_extents: + * @font: a font. + * @extents: (out): + * + * + * + * Return value: + * + * Since: 1.1.3 + **/ +hb_bool_t +hb_font_get_v_extents (hb_font_t *font, + hb_font_extents_t *extents) +{ + return font->get_font_v_extents (extents); +} + /** * hb_font_get_glyph: * @font: a font. @@ -539,7 +635,50 @@ hb_font_get_glyph (hb_font_t *font, hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t *glyph) { - return font->get_glyph (unicode, variation_selector, glyph); + if (unlikely (variation_selector)) + return font->get_variation_glyph (unicode, variation_selector, glyph); + return font->get_nominal_glyph (unicode, glyph); +} + +/** + * hb_font_get_nominal_glyph: + * @font: a font. + * @unicode: + * @glyph: (out): + * + * + * + * Return value: + * + * Since: 1.2.3 + **/ +hb_bool_t +hb_font_get_nominal_glyph (hb_font_t *font, + hb_codepoint_t unicode, + hb_codepoint_t *glyph) +{ + return font->get_nominal_glyph (unicode, glyph); +} + +/** + * hb_font_get_variation_glyph: + * @font: a font. + * @unicode: + * @variation_selector: + * @glyph: (out): + * + * + * + * Return value: + * + * Since: 1.2.3 + **/ +hb_bool_t +hb_font_get_variation_glyph (hb_font_t *font, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph) +{ + return font->get_variation_glyph (unicode, variation_selector, glyph); } /** @@ -745,6 +884,23 @@ hb_font_get_glyph_from_name (hb_font_t *font, /* A bit higher-level, and with fallback */ +/** + * hb_font_get_extents_for_direction: + * @font: a font. + * @direction: + * @extents: + * + * + * + * Since: 1.1.3 + **/ +void +hb_font_get_extents_for_direction (hb_font_t *font, + hb_direction_t direction, + hb_font_extents_t *extents) +{ + return font->get_extents_for_direction (direction, extents); +} /** * hb_font_get_glyph_advance_for_direction: * @font: a font. @@ -1002,6 +1158,8 @@ hb_font_create_sub_font (hb_font_t *parent) font->x_ppem = parent->x_ppem; font->y_ppem = parent->y_ppem; + /* TODO: copy variation coordinates. */ + return font; } @@ -1031,10 +1189,15 @@ hb_font_get_empty (void) 0, /* x_ppem */ 0, /* y_ppem */ + 0, /* num_coords */ + NULL, /* coords */ + const_cast (&_hb_font_funcs_nil), /* klass */ NULL, /* user_data */ NULL, /* destroy */ + hb_font_t::DIRTY_NOTHING, /* dirty */ + { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -1085,6 +1248,8 @@ hb_font_destroy (hb_font_t *font) hb_face_destroy (font->face); hb_font_funcs_destroy (font->klass); + free (font->coords); + free (font); } @@ -1185,6 +1350,11 @@ hb_font_set_parent (hb_font_t *font, if (!parent) parent = hb_font_get_empty (); + if (parent == font->parent) + return; + + font->dirty |= font->DIRTY_PARENT; + hb_font_t *old = font->parent; font->parent = hb_font_reference (parent); @@ -1208,6 +1378,37 @@ hb_font_get_parent (hb_font_t *font) return font->parent; } +/** + * hb_font_set_face: + * @font: a font. + * @face: new face. + * + * Sets font-face of @font. + * + * Since: 1.4.3 + **/ +void +hb_font_set_face (hb_font_t *font, + hb_face_t *face) +{ + if (font->immutable) + return; + + if (unlikely (!face)) + face = hb_face_get_empty (); + + if (font->face == face) + return; + + font->dirty |= font->DIRTY_FACE; + + hb_face_t *old = font->face; + + font->face = hb_face_reference (face); + + hb_face_destroy (old); +} + /** * hb_font_get_face: * @font: a font. @@ -1254,6 +1455,8 @@ hb_font_set_funcs (hb_font_t *font, if (!klass) klass = hb_font_funcs_get_empty (); + font->dirty |= font->DIRTY_FUNCS; + hb_font_funcs_reference (klass); hb_font_funcs_destroy (font->klass); font->klass = klass; @@ -1309,6 +1512,11 @@ hb_font_set_scale (hb_font_t *font, if (font->immutable) return; + if (font->x_scale == x_scale && font->y_scale == y_scale) + return; + + font->dirty |= font->DIRTY_SCALE; + font->x_scale = x_scale; font->y_scale = y_scale; } @@ -1350,6 +1558,11 @@ hb_font_set_ppem (hb_font_t *font, if (font->immutable) return; + if (font->x_ppem == x_ppem && font->y_ppem == y_ppem) + return; + + font->dirty |= font->DIRTY_PPEM; + font->x_ppem = x_ppem; font->y_ppem = y_ppem; } @@ -1372,3 +1585,249 @@ hb_font_get_ppem (hb_font_t *font, if (x_ppem) *x_ppem = font->x_ppem; if (y_ppem) *y_ppem = font->y_ppem; } + +/* + * Variations + */ + +static void +_hb_font_adopt_var_coords_normalized (hb_font_t *font, + int *coords, /* 2.14 normalized */ + unsigned int coords_length) +{ + if (font->num_coords == coords_length && + (coords_length == 0 || + 0 == memcmp (font->coords, coords, coords_length * sizeof (coords[0])))) + { + free (coords); + return; + } + + font->dirty |= font->DIRTY_VARIATIONS; + + free (font->coords); + + font->coords = coords; + font->num_coords = coords_length; +} + +/** + * hb_font_set_variations: + * + * Since: 1.4.2 + */ +void +hb_font_set_variations (hb_font_t *font, + const hb_variation_t *variations, + unsigned int variations_length) +{ + if (font->immutable) + return; + + if (!variations_length) + { + hb_font_set_var_coords_normalized (font, NULL, 0); + return; + } + + unsigned int coords_length = hb_ot_var_get_axis_count (font->face); + + int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : NULL; + if (unlikely (coords_length && !normalized)) + return; + + hb_ot_var_normalize_variations (font->face, + variations, variations_length, + normalized, coords_length); + _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); +} + +/** + * hb_font_set_var_coords_design: + * + * Since: 1.4.2 + */ +void +hb_font_set_var_coords_design (hb_font_t *font, + const float *coords, + unsigned int coords_length) +{ + if (font->immutable) + return; + + int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : NULL; + if (unlikely (coords_length && !normalized)) + return; + + hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized); + _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); +} + +/** + * hb_font_set_var_coords_normalized: + * + * Since: 1.4.2 + */ +void +hb_font_set_var_coords_normalized (hb_font_t *font, + const int *coords, /* 2.14 normalized */ + unsigned int coords_length) +{ + if (font->immutable) + return; + + int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : NULL; + if (unlikely (coords_length && !copy)) + return; + + if (coords_length) + memcpy (copy, coords, coords_length * sizeof (coords[0])); + + _hb_font_adopt_var_coords_normalized (font, copy, coords_length); +} + +/** + * hb_font_get_var_coords_normalized: + * + * Return value is valid as long as variation coordinates of the font + * are not modified. + * + * Since: 1.4.2 + */ +const int * +hb_font_get_var_coords_normalized (hb_font_t *font, + unsigned int *length) +{ + if (length) + *length = font->num_coords; + + return font->coords; +} + + +#ifndef HB_DISABLE_DEPRECATED + +/* + * Deprecated get_glyph_func(): + */ + +struct hb_trampoline_closure_t +{ + void *user_data; + hb_destroy_func_t destroy; + unsigned int ref_count; +}; + +template +struct hb_trampoline_t +{ + hb_trampoline_closure_t closure; /* Must be first. */ + FuncType func; +}; + +template +static hb_trampoline_t * +trampoline_create (FuncType func, + void *user_data, + hb_destroy_func_t destroy) +{ + typedef hb_trampoline_t trampoline_t; + + trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t)); + + if (unlikely (!trampoline)) + return NULL; + + trampoline->closure.user_data = user_data; + trampoline->closure.destroy = destroy; + trampoline->closure.ref_count = 1; + trampoline->func = func; + + return trampoline; +} + +static void +trampoline_reference (hb_trampoline_closure_t *closure) +{ + closure->ref_count++; +} + +static void +trampoline_destroy (void *user_data) +{ + hb_trampoline_closure_t *closure = (hb_trampoline_closure_t *) user_data; + + if (--closure->ref_count) + return; + + if (closure->destroy) + closure->destroy (closure->user_data); + free (closure); +} + +typedef hb_trampoline_t hb_font_get_glyph_trampoline_t; + +static hb_bool_t +hb_font_get_nominal_glyph_trampoline (hb_font_t *font, + void *font_data, + hb_codepoint_t unicode, + hb_codepoint_t *glyph, + void *user_data) +{ + hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data; + return trampoline->func (font, font_data, unicode, 0, glyph, trampoline->closure.user_data); +} + +static hb_bool_t +hb_font_get_variation_glyph_trampoline (hb_font_t *font, + void *font_data, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data) +{ + hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data; + return trampoline->func (font, font_data, unicode, variation_selector, glyph, trampoline->closure.user_data); +} + +/** + * hb_font_funcs_set_glyph_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * Deprecated. Use hb_font_funcs_set_nominal_glyph_func() and + * hb_font_funcs_set_variation_glyph_func() instead. + * + * Since: 0.9.2 + * Deprecated: 1.2.3 + **/ +void +hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_func_t func, + void *user_data, hb_destroy_func_t destroy) +{ + hb_font_get_glyph_trampoline_t *trampoline; + + trampoline = trampoline_create (func, user_data, destroy); + if (unlikely (!trampoline)) + { + if (destroy) + destroy (user_data); + return; + } + + hb_font_funcs_set_nominal_glyph_func (ffuncs, + hb_font_get_nominal_glyph_trampoline, + trampoline, + trampoline_destroy); + + trampoline_reference (&trampoline->closure); + hb_font_funcs_set_variation_glyph_func (ffuncs, + hb_font_get_variation_glyph_trampoline, + trampoline, + trampoline_destroy); +} + +#endif /* HB_DISABLE_DEPRECATED */ diff --git a/gfx/harfbuzz/src/hb-font.h b/gfx/harfbuzz/src/hb-font.h index fb4a0eab5..85fb56d5b 100644 --- a/gfx/harfbuzz/src/hb-font.h +++ b/gfx/harfbuzz/src/hb-font.h @@ -46,19 +46,19 @@ typedef struct hb_font_t hb_font_t; typedef struct hb_font_funcs_t hb_font_funcs_t; -hb_font_funcs_t * +HB_EXTERN hb_font_funcs_t * hb_font_funcs_create (void); -hb_font_funcs_t * +HB_EXTERN hb_font_funcs_t * hb_font_funcs_get_empty (void); -hb_font_funcs_t * +HB_EXTERN hb_font_funcs_t * hb_font_funcs_reference (hb_font_funcs_t *ffuncs); -void +HB_EXTERN void hb_font_funcs_destroy (hb_font_funcs_t *ffuncs); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, hb_user_data_key_t *key, void * data, @@ -66,19 +66,37 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, hb_bool_t replace); -void * +HB_EXTERN void * hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, hb_user_data_key_t *key); -void +HB_EXTERN void hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs); -/* glyph extents */ +/* font and glyph extents */ + +/* Note that typically ascender is positive and descender negative in coordinate systems that grow up. */ +typedef struct hb_font_extents_t +{ + hb_position_t ascender; /* typographic ascender. */ + hb_position_t descender; /* typographic descender. */ + hb_position_t line_gap; /* suggested line spacing gap. */ + /*< private >*/ + hb_position_t reserved9; + hb_position_t reserved8; + hb_position_t reserved7; + hb_position_t reserved6; + hb_position_t reserved5; + hb_position_t reserved4; + hb_position_t reserved3; + hb_position_t reserved2; + hb_position_t reserved1; +} hb_font_extents_t; /* Note that height is negative in coordinate systems that grow up. */ typedef struct hb_glyph_extents_t @@ -89,13 +107,23 @@ typedef struct hb_glyph_extents_t hb_position_t height; /* distance from top to bottom side. */ } hb_glyph_extents_t; - /* func types */ -typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data, - hb_codepoint_t unicode, hb_codepoint_t variation_selector, - hb_codepoint_t *glyph, - void *user_data); +typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data, + hb_font_extents_t *metrics, + void *user_data); +typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t; +typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t; + + +typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t unicode, + hb_codepoint_t *glyph, + void *user_data); +typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data); typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data, @@ -141,7 +169,39 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void * /* func setters */ /** - * hb_font_funcs_set_glyph_func: + * hb_font_funcs_set_font_h_extents_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.1.2 + **/ +HB_EXTERN void +hb_font_funcs_set_font_h_extents_func (hb_font_funcs_t *ffuncs, + hb_font_get_font_h_extents_func_t func, + void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_font_v_extents_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.1.2 + **/ +HB_EXTERN void +hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs, + hb_font_get_font_v_extents_func_t func, + void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_nominal_glyph_func: * @ffuncs: font functions. * @func: (closure user_data) (destroy destroy) (scope notified): * @user_data: @@ -149,12 +209,28 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void * * * * - * Since: 0.9.2 + * Since: 1.2.3 **/ -void -hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, - hb_font_get_glyph_func_t func, - void *user_data, hb_destroy_func_t destroy); +HB_EXTERN void +hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_get_nominal_glyph_func_t func, + void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_variation_glyph_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.2.3 + **/ +HB_EXTERN void +hb_font_funcs_set_variation_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_get_variation_glyph_func_t func, + void *user_data, hb_destroy_func_t destroy); /** * hb_font_funcs_set_glyph_h_advance_func: @@ -167,7 +243,7 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_h_advance_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -183,7 +259,7 @@ hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_v_advance_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -199,7 +275,7 @@ hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_h_origin_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -215,7 +291,7 @@ hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_v_origin_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -231,7 +307,7 @@ hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_h_kerning_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -247,7 +323,7 @@ hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_v_kerning_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -263,7 +339,7 @@ hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_extents_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -279,7 +355,7 @@ hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_contour_point_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -295,7 +371,7 @@ hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_name_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -311,57 +387,67 @@ hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_from_name_func_t func, void *user_data, hb_destroy_func_t destroy); - /* func dispatch */ -hb_bool_t -hb_font_get_glyph (hb_font_t *font, - hb_codepoint_t unicode, hb_codepoint_t variation_selector, - hb_codepoint_t *glyph); +HB_EXTERN hb_bool_t +hb_font_get_h_extents (hb_font_t *font, + hb_font_extents_t *extents); +HB_EXTERN hb_bool_t +hb_font_get_v_extents (hb_font_t *font, + hb_font_extents_t *extents); -hb_position_t +HB_EXTERN hb_bool_t +hb_font_get_nominal_glyph (hb_font_t *font, + hb_codepoint_t unicode, + hb_codepoint_t *glyph); +HB_EXTERN hb_bool_t +hb_font_get_variation_glyph (hb_font_t *font, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph); + +HB_EXTERN hb_position_t hb_font_get_glyph_h_advance (hb_font_t *font, hb_codepoint_t glyph); -hb_position_t +HB_EXTERN hb_position_t hb_font_get_glyph_v_advance (hb_font_t *font, hb_codepoint_t glyph); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_h_origin (hb_font_t *font, hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_v_origin (hb_font_t *font, hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y); -hb_position_t +HB_EXTERN hb_position_t hb_font_get_glyph_h_kerning (hb_font_t *font, hb_codepoint_t left_glyph, hb_codepoint_t right_glyph); -hb_position_t +HB_EXTERN hb_position_t hb_font_get_glyph_v_kerning (hb_font_t *font, hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_contour_point (hb_font_t *font, hb_codepoint_t glyph, unsigned int point_index, hb_position_t *x, hb_position_t *y); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_name (hb_font_t *font, hb_codepoint_t glyph, char *name, unsigned int size); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_from_name (hb_font_t *font, const char *name, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); @@ -369,52 +455,63 @@ hb_font_get_glyph_from_name (hb_font_t *font, /* high-level funcs, with fallback */ -void +/* Calls either hb_font_get_nominal_glyph() if variation_selector is 0, + * otherwise callse hb_font_get_variation_glyph(). */ +HB_EXTERN hb_bool_t +hb_font_get_glyph (hb_font_t *font, + hb_codepoint_t unicode, hb_codepoint_t variation_selector, + hb_codepoint_t *glyph); + +HB_EXTERN void +hb_font_get_extents_for_direction (hb_font_t *font, + hb_direction_t direction, + hb_font_extents_t *extents); +HB_EXTERN void hb_font_get_glyph_advance_for_direction (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y); -void +HB_EXTERN void hb_font_get_glyph_origin_for_direction (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y); -void +HB_EXTERN void hb_font_add_glyph_origin_for_direction (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y); -void +HB_EXTERN void hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y); -void +HB_EXTERN void hb_font_get_glyph_kerning_for_direction (hb_font_t *font, hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_extents_for_origin (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, hb_glyph_extents_t *extents); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, hb_codepoint_t glyph, unsigned int point_index, hb_direction_t direction, hb_position_t *x, hb_position_t *y); /* Generates gidDDD if glyph has no name. */ -void +HB_EXTERN void hb_font_glyph_to_string (hb_font_t *font, hb_codepoint_t glyph, char *s, unsigned int size); /* Parses gidDDD and uniUUUU strings automatically. */ -hb_bool_t +HB_EXTERN hb_bool_t hb_font_glyph_from_string (hb_font_t *font, const char *s, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); @@ -426,22 +523,22 @@ hb_font_glyph_from_string (hb_font_t *font, /* Fonts are very light-weight objects */ -hb_font_t * +HB_EXTERN hb_font_t * hb_font_create (hb_face_t *face); -hb_font_t * +HB_EXTERN hb_font_t * hb_font_create_sub_font (hb_font_t *parent); -hb_font_t * +HB_EXTERN hb_font_t * hb_font_get_empty (void); -hb_font_t * +HB_EXTERN hb_font_t * hb_font_reference (hb_font_t *font); -void +HB_EXTERN void hb_font_destroy (hb_font_t *font); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_set_user_data (hb_font_t *font, hb_user_data_key_t *key, void * data, @@ -449,46 +546,50 @@ hb_font_set_user_data (hb_font_t *font, hb_bool_t replace); -void * +HB_EXTERN void * hb_font_get_user_data (hb_font_t *font, hb_user_data_key_t *key); -void +HB_EXTERN void hb_font_make_immutable (hb_font_t *font); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_is_immutable (hb_font_t *font); -void +HB_EXTERN void hb_font_set_parent (hb_font_t *font, hb_font_t *parent); -hb_font_t * +HB_EXTERN hb_font_t * hb_font_get_parent (hb_font_t *font); -hb_face_t * +HB_EXTERN void +hb_font_set_face (hb_font_t *font, + hb_face_t *face); + +HB_EXTERN hb_face_t * hb_font_get_face (hb_font_t *font); -void +HB_EXTERN void hb_font_set_funcs (hb_font_t *font, hb_font_funcs_t *klass, void *font_data, hb_destroy_func_t destroy); /* Be *very* careful with this function! */ -void +HB_EXTERN void hb_font_set_funcs_data (hb_font_t *font, void *font_data, hb_destroy_func_t destroy); -void +HB_EXTERN void hb_font_set_scale (hb_font_t *font, int x_scale, int y_scale); -void +HB_EXTERN void hb_font_get_scale (hb_font_t *font, int *x_scale, int *y_scale); @@ -496,16 +597,34 @@ hb_font_get_scale (hb_font_t *font, /* * A zero value means "no hinting in that direction" */ -void +HB_EXTERN void hb_font_set_ppem (hb_font_t *font, unsigned int x_ppem, unsigned int y_ppem); -void +HB_EXTERN void hb_font_get_ppem (hb_font_t *font, unsigned int *x_ppem, unsigned int *y_ppem); +HB_EXTERN void +hb_font_set_variations (hb_font_t *font, + const hb_variation_t *variations, + unsigned int variations_length); + +HB_EXTERN void +hb_font_set_var_coords_design (hb_font_t *font, + const float *coords, + unsigned int coords_length); + +HB_EXTERN void +hb_font_set_var_coords_normalized (hb_font_t *font, + const int *coords, /* 2.14 normalized */ + unsigned int coords_length); + +HB_EXTERN const int * +hb_font_get_var_coords_normalized (hb_font_t *font, + unsigned int *length); HB_END_DECLS diff --git a/gfx/harfbuzz/src/hb-ft.cc b/gfx/harfbuzz/src/hb-ft.cc index 9b872ea58..492992ee4 100644 --- a/gfx/harfbuzz/src/hb-ft.cc +++ b/gfx/harfbuzz/src/hb-ft.cc @@ -33,7 +33,10 @@ #include "hb-font-private.hh" +#include "hb-cache-private.hh" // Maybe use in the future? + #include FT_ADVANCES_H +#include FT_MULTIPLE_MASTERS_H #include FT_TRUETYPE_TABLES_H @@ -70,11 +73,12 @@ struct hb_ft_font_t { FT_Face ft_face; int load_flags; + bool symbol; /* Whether selected cmap is symbol cmap. */ bool unref; /* Whether to destroy ft_face when done. */ }; static hb_ft_font_t * -_hb_ft_font_create (FT_Face ft_face, bool unref) +_hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) { hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); @@ -82,6 +86,7 @@ _hb_ft_font_create (FT_Face ft_face, bool unref) return NULL; ft_font->ft_face = ft_face; + ft_font->symbol = symbol; ft_font->unref = unref; ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; @@ -89,11 +94,17 @@ _hb_ft_font_create (FT_Face ft_face, bool unref) return ft_font; } +static void +_hb_ft_face_destroy (FT_Face ft_face) +{ + FT_Done_Face (ft_face); +} + static void _hb_ft_font_destroy (hb_ft_font_t *ft_font) { if (ft_font->unref) - FT_Done_Face (ft_font->ft_face); + _hb_ft_face_destroy (ft_font->ft_face); free (ft_font); } @@ -155,21 +166,46 @@ hb_ft_font_get_face (hb_font_t *font) static hb_bool_t -hb_ft_get_glyph (hb_font_t *font HB_UNUSED, - void *font_data, - hb_codepoint_t unicode, - hb_codepoint_t variation_selector, - hb_codepoint_t *glyph, - void *user_data HB_UNUSED) - +hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t unicode, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; - unsigned int g; + unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode); - if (likely (!variation_selector)) - g = FT_Get_Char_Index (ft_font->ft_face, unicode); - else - g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector); + if (unlikely (!g)) + { + if (unlikely (ft_font->symbol) && unicode <= 0x00FFu) + { + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * http://www.microsoft.com/typography/otspec/recom.htm + * under "Non-Standard (Symbol) Fonts". */ + g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode); + if (!g) + return false; + } + else + return false; + } + + *glyph = g; + return true; +} + +static hb_bool_t +hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector); if (unlikely (!g)) return false; @@ -366,6 +402,25 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED, return *glyph != 0; } +static hb_bool_t +hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED, + void *font_data, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; + metrics->ascender = ft_face->size->metrics.ascender; + metrics->descender = ft_face->size->metrics.descender; + metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender); + if (font->y_scale < 0) + { + metrics->ascender = -metrics->ascender; + metrics->descender = -metrics->descender; + metrics->line_gap = -metrics->line_gap; + } + return true; +} static hb_font_funcs_t *static_ft_funcs = NULL; @@ -387,7 +442,10 @@ retry: { funcs = hb_font_funcs_create (); - hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL); + hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, NULL, NULL); + //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, NULL, NULL); + hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, NULL, NULL); + hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, NULL, NULL); hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL); hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL); //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL); @@ -411,9 +469,11 @@ retry: #endif }; + bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL; + hb_font_set_funcs (font, funcs, - _hb_ft_font_create (ft_face, unref), + _hb_ft_font_create (ft_face, symbol, unref), (hb_destroy_func_t) _hb_ft_font_destroy); } @@ -433,7 +493,7 @@ reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) return NULL; buffer = (FT_Byte *) malloc (length); - if (buffer == NULL) + if (!buffer) return NULL; error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length); @@ -461,7 +521,7 @@ hb_ft_face_create (FT_Face ft_face, { hb_face_t *face; - if (ft_face->stream->read == NULL) { + if (!ft_face->stream->read) { hb_blob_t *blob; blob = hb_blob_create ((const char *) ft_face->stream->base, @@ -493,7 +553,7 @@ hb_face_t * hb_ft_face_create_referenced (FT_Face ft_face) { FT_Reference_Face (ft_face); - return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face); + return hb_ft_face_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy); } static void @@ -549,14 +609,36 @@ hb_ft_font_create (FT_Face ft_face, hb_face_destroy (face); _hb_ft_font_set_funcs (font, ft_face, false); hb_font_set_scale (font, - (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16), - (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16)); + (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16), + (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16)); #if 0 /* hb-ft works in no-hinting model */ hb_font_set_ppem (font, ft_face->size->metrics.x_ppem, ft_face->size->metrics.y_ppem); #endif +#ifdef HAVE_FT_GET_VAR_BLEND_COORDINATES + FT_MM_Var *mm_var = NULL; + if (!FT_Get_MM_Var (ft_face, &mm_var)) + { + FT_Fixed *ft_coords = (FT_Fixed *) calloc (mm_var->num_axis, sizeof (FT_Fixed)); + int *coords = (int *) calloc (mm_var->num_axis, sizeof (int)); + if (coords && ft_coords) + { + if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords)) + { + for (unsigned int i = 0; i < mm_var->num_axis; ++i) + coords[i] = ft_coords[i] >>= 2; + + hb_font_set_var_coords_normalized (font, coords, mm_var->num_axis); + } + } + free (coords); + free (ft_coords); + free (mm_var); + } +#endif + return font; } @@ -573,7 +655,7 @@ hb_font_t * hb_ft_font_create_referenced (FT_Face ft_face) { FT_Reference_Face (ft_face); - return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face); + return hb_ft_font_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy); } @@ -642,7 +724,8 @@ hb_ft_font_set_funcs (hb_font_t *font) return; } - FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE); + if (FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE)) + FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL); FT_Set_Char_Size (ft_face, abs (font->x_scale), abs (font->y_scale), @@ -658,6 +741,20 @@ hb_ft_font_set_funcs (hb_font_t *font) FT_Set_Transform (ft_face, &matrix, NULL); } + unsigned int num_coords; + const int *coords = hb_font_get_var_coords_normalized (font, &num_coords); + if (num_coords) + { + FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed)); + if (ft_coords) + { + for (unsigned int i = 0; i < num_coords; i++) + ft_coords[i] = coords[i] << 2; + FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords); + free (ft_coords); + } + } + ft_face->generic.data = blob; ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; diff --git a/gfx/harfbuzz/src/hb-ft.h b/gfx/harfbuzz/src/hb-ft.h index 4bbc82658..dc8ef8558 100644 --- a/gfx/harfbuzz/src/hb-ft.h +++ b/gfx/harfbuzz/src/hb-ft.h @@ -59,7 +59,7 @@ HB_BEGIN_DECLS * probably should use (the more recent) hb_ft_face_create_referenced() * instead. */ -hb_face_t * +HB_EXTERN hb_face_t * hb_ft_face_create (FT_Face ft_face, hb_destroy_func_t destroy); @@ -71,7 +71,7 @@ hb_ft_face_create (FT_Face ft_face, * Client is still responsible for making sure that ft-face is destroyed * after hb-face is. */ -hb_face_t * +HB_EXTERN hb_face_t * hb_ft_face_create_cached (FT_Face ft_face); /* This version is like hb_ft_face_create(), except that it calls @@ -81,7 +81,7 @@ hb_ft_face_create_cached (FT_Face ft_face); * This is the most convenient version to use. Use it unless you have * very good reasons not to. */ -hb_face_t * +HB_EXTERN hb_face_t * hb_ft_face_create_referenced (FT_Face ft_face); @@ -98,26 +98,26 @@ hb_ft_face_create_referenced (FT_Face ft_face); /* See notes on hb_ft_face_create(). Same issues re lifecycle-management * apply here. Use hb_ft_font_create_referenced() if you can. */ -hb_font_t * +HB_EXTERN hb_font_t * hb_ft_font_create (FT_Face ft_face, hb_destroy_func_t destroy); /* See notes on hb_ft_face_create_referenced() re lifecycle-management * issues. */ -hb_font_t * +HB_EXTERN hb_font_t * hb_ft_font_create_referenced (FT_Face ft_face); -FT_Face +HB_EXTERN FT_Face hb_ft_font_get_face (hb_font_t *font); -void +HB_EXTERN void hb_ft_font_set_load_flags (hb_font_t *font, int load_flags); -int +HB_EXTERN int hb_ft_font_get_load_flags (hb_font_t *font); /* Makes an hb_font_t use FreeType internally to implement font functions. */ -void +HB_EXTERN void hb_ft_font_set_funcs (hb_font_t *font); diff --git a/gfx/harfbuzz/src/hb-glib.cc b/gfx/harfbuzz/src/hb-glib.cc index 7dbd83d29..2b91b5b65 100644 --- a/gfx/harfbuzz/src/hb-glib.cc +++ b/gfx/harfbuzz/src/hb-glib.cc @@ -382,7 +382,10 @@ hb_glib_get_unicode_funcs (void) return const_cast (&_hb_glib_unicode_funcs); } +#if GLIB_CHECK_VERSION(2,31,10) /** + * hb_glib_blob_create: + * * Since: 0.9.38 **/ hb_blob_t * @@ -396,3 +399,4 @@ hb_glib_blob_create (GBytes *gbytes) g_bytes_ref (gbytes), (hb_destroy_func_t) g_bytes_unref); } +#endif diff --git a/gfx/harfbuzz/src/hb-glib.h b/gfx/harfbuzz/src/hb-glib.h index 1a8f42ea5..5f04183ba 100644 --- a/gfx/harfbuzz/src/hb-glib.h +++ b/gfx/harfbuzz/src/hb-glib.h @@ -36,19 +36,20 @@ HB_BEGIN_DECLS -hb_script_t +HB_EXTERN hb_script_t hb_glib_script_to_script (GUnicodeScript script); -GUnicodeScript +HB_EXTERN GUnicodeScript hb_glib_script_from_script (hb_script_t script); -hb_unicode_funcs_t * +HB_EXTERN hb_unicode_funcs_t * hb_glib_get_unicode_funcs (void); -hb_blob_t * +#if GLIB_CHECK_VERSION(2,31,10) +HB_EXTERN hb_blob_t * hb_glib_blob_create (GBytes *gbytes); - +#endif HB_END_DECLS diff --git a/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl b/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl index 6ecda06c2..e28510c22 100644 --- a/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl +++ b/gfx/harfbuzz/src/hb-gobject-enums.h.tmpl @@ -42,7 +42,7 @@ HB_BEGIN_DECLS /*** END file-header ***/ /*** BEGIN value-header ***/ -GType @enum_name@_get_type (void) G_GNUC_CONST; +HB_EXTERN GType @enum_name@_get_type (void) G_GNUC_CONST; #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) /*** END value-header ***/ diff --git a/gfx/harfbuzz/src/hb-gobject-structs.cc b/gfx/harfbuzz/src/hb-gobject-structs.cc index 6bd63368b..fef00245b 100644 --- a/gfx/harfbuzz/src/hb-gobject-structs.cc +++ b/gfx/harfbuzz/src/hb-gobject-structs.cc @@ -78,3 +78,6 @@ HB_DEFINE_VALUE_TYPE (glyph_info) HB_DEFINE_VALUE_TYPE (glyph_position) HB_DEFINE_VALUE_TYPE (segment_properties) HB_DEFINE_VALUE_TYPE (user_data_key) + +HB_DEFINE_VALUE_TYPE (ot_math_glyph_variant) +HB_DEFINE_VALUE_TYPE (ot_math_glyph_part) diff --git a/gfx/harfbuzz/src/hb-gobject-structs.h b/gfx/harfbuzz/src/hb-gobject-structs.h index 0a0387dce..1c303219b 100644 --- a/gfx/harfbuzz/src/hb-gobject-structs.h +++ b/gfx/harfbuzz/src/hb-gobject-structs.h @@ -41,62 +41,74 @@ HB_BEGIN_DECLS /* Object types */ /** + * hb_gobject_blob_get_type: + * * Since: 0.9.2 **/ -GType hb_gobject_blob_get_type (void); +HB_EXTERN GType hb_gobject_blob_get_type (void); #define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ()) /** + * hb_gobject_buffer_get_type: + * * Since: 0.9.2 **/ -GType hb_gobject_buffer_get_type (void); +HB_EXTERN GType hb_gobject_buffer_get_type (void); #define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ()) /** + * hb_gobject_face_get_type: + * * Since: 0.9.2 **/ -GType hb_gobject_face_get_type (void); +HB_EXTERN GType hb_gobject_face_get_type (void); #define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ()) /** + * hb_gobject_font_get_type: + * * Since: 0.9.2 **/ -GType hb_gobject_font_get_type (void); +HB_EXTERN GType hb_gobject_font_get_type (void); #define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ()) /** + * hb_gobject_font_funcs_get_type: + * * Since: 0.9.2 **/ -GType hb_gobject_font_funcs_get_type (void); +HB_EXTERN GType hb_gobject_font_funcs_get_type (void); #define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ()) -GType hb_gobject_set_get_type (void); +HB_EXTERN GType hb_gobject_set_get_type (void); #define HB_GOBJECT_TYPE_SET (hb_gobject_set_get_type ()) -GType hb_gobject_shape_plan_get_type (void); +HB_EXTERN GType hb_gobject_shape_plan_get_type (void); #define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ()) /** + * hb_gobject_unicode_funcs_get_type: + * * Since: 0.9.2 **/ -GType hb_gobject_unicode_funcs_get_type (void); +HB_EXTERN GType hb_gobject_unicode_funcs_get_type (void); #define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ()) /* Value types */ -GType hb_gobject_feature_get_type (void); +HB_EXTERN GType hb_gobject_feature_get_type (void); #define HB_GOBJECT_TYPE_FEATURE (hb_gobject_feature_get_type ()) -GType hb_gobject_glyph_info_get_type (void); +HB_EXTERN GType hb_gobject_glyph_info_get_type (void); #define HB_GOBJECT_TYPE_GLYPH_INFO (hb_gobject_glyph_info_get_type ()) -GType hb_gobject_glyph_position_get_type (void); +HB_EXTERN GType hb_gobject_glyph_position_get_type (void); #define HB_GOBJECT_TYPE_GLYPH_POSITION (hb_gobject_glyph_position_get_type ()) -GType hb_gobject_segment_properties_get_type (void); +HB_EXTERN GType hb_gobject_segment_properties_get_type (void); #define HB_GOBJECT_TYPE_SEGMENT_PROPERTIES (hb_gobject_segment_properties_get_type ()) -GType hb_gobject_user_data_key_get_type (void); +HB_EXTERN GType hb_gobject_user_data_key_get_type (void); #define HB_GOBJECT_TYPE_USER_DATA_KEY (hb_gobject_user_data_key_get_type ()) diff --git a/gfx/harfbuzz/src/hb-graphite2.cc b/gfx/harfbuzz/src/hb-graphite2.cc index cd694c140..9e0761e63 100644 --- a/gfx/harfbuzz/src/hb-graphite2.cc +++ b/gfx/harfbuzz/src/hb-graphite2.cc @@ -27,7 +27,6 @@ */ #define HB_SHAPER graphite2 -#define hb_graphite2_shaper_font_data_t gr_font #include "hb-shaper-impl-private.hh" #include "hb-graphite2.h" @@ -35,8 +34,8 @@ #include -HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, face) -HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, font) +HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, face) +HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, font) /* @@ -153,26 +152,17 @@ hb_graphite2_face_get_gr_face (hb_face_t *face) * shaper font data */ -static float hb_graphite2_get_advance (const void *hb_font, unsigned short gid) -{ - return ((hb_font_t *) hb_font)->get_glyph_h_advance (gid); -} +struct hb_graphite2_shaper_font_data_t {}; hb_graphite2_shaper_font_data_t * -_hb_graphite2_shaper_font_data_create (hb_font_t *font) +_hb_graphite2_shaper_font_data_create (hb_font_t *font HB_UNUSED) { - if (unlikely (!hb_graphite2_shaper_face_data_ensure (font->face))) return NULL; - - hb_face_t *face = font->face; - hb_graphite2_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - - return gr_make_font_with_advance_fn (font->x_scale, font, &hb_graphite2_get_advance, face_data->grface); + return (hb_graphite2_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; } void -_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data) +_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data HB_UNUSED) { - gr_font_destroy (data); } /* @@ -181,8 +171,7 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data) gr_font * hb_graphite2_font_get_gr_font (hb_font_t *font) { - if (unlikely (!hb_graphite2_shaper_font_data_ensure (font))) return NULL; - return HB_SHAPER_DATA_GET (font); + return NULL; } @@ -195,7 +184,9 @@ struct hb_graphite2_shaper_shape_plan_data_t {}; hb_graphite2_shaper_shape_plan_data_t * _hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } @@ -216,6 +207,7 @@ struct hb_graphite2_cluster_t { unsigned int base_glyph; unsigned int num_glyphs; unsigned int cluster; + float advance; }; hb_bool_t @@ -227,7 +219,6 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, { hb_face_t *face = font->face; gr_face *grface = HB_SHAPER_DATA_GET (face)->grface; - gr_font *grfont = HB_SHAPER_DATA_GET (font); const char *lang = hb_language_to_string (hb_buffer_get_language (buffer)); const char *lang_end = lang ? strchr (lang, '-') : NULL; @@ -259,7 +250,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, hb_tag_t script_tag[2]; hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]); - seg = gr_make_seg (grfont, grface, + seg = gr_make_seg (NULL, grface, script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1], feats, gr_utf32, chars, buffer->len, @@ -310,6 +301,12 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, hb_codepoint_t *pg = gids; clusters[0].cluster = buffer->info[0].cluster; + float curradv = 0.; + if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + { + curradv = gr_slot_origin_X(gr_seg_first_slot(seg)); + clusters[0].advance = gr_seg_advance_X(seg) - curradv; + } for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (is), ic++) { unsigned int before = gr_slot_before (is); @@ -320,6 +317,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, { clusters[ci-1].num_chars += clusters[ci].num_chars; clusters[ci-1].num_glyphs += clusters[ci].num_glyphs; + clusters[ci-1].advance += clusters[ci].advance; ci--; } @@ -331,13 +329,23 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, c->num_chars = before - c->base_char; c->base_glyph = ic; c->num_glyphs = 0; + if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + c->advance = curradv - gr_slot_origin_X(is); + else + clusters[ci].advance = gr_slot_origin_X(is) - curradv; ci++; + curradv = gr_slot_origin_X(is); } clusters[ci].num_glyphs++; if (clusters[ci].base_char + clusters[ci].num_chars < after + 1) clusters[ci].num_chars = after + 1 - clusters[ci].base_char; } + + if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + clusters[ci].advance += curradv; + else + clusters[ci].advance = gr_seg_advance_X(seg) - curradv; ci++; for (unsigned int i = 0; i < ci; ++i) @@ -347,57 +355,55 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j]; info->codepoint = gids[clusters[i].base_glyph + j]; info->cluster = clusters[i].cluster; + info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + info->var1.i32 = clusters[i].advance; // all glyphs in the cluster get the same advance } } buffer->len = glyph_count; + unsigned int upem = hb_face_get_upem (face); + float xscale = (float) font->x_scale / upem; + float yscale = (float) font->y_scale / upem; + yscale *= yscale / xscale; /* Positioning. */ + unsigned int currclus = (unsigned int) -1; + const hb_glyph_info_t *info = buffer->info; + hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL); if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) { - hb_glyph_position_t *pPos; - for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_slot (seg); - is; pPos++, is = gr_slot_next_in_segment (is)) + curradvx = 0; + for (is = gr_seg_first_slot (seg); is; pPos++, ++info, is = gr_slot_next_in_segment (is)) { - pPos->x_offset = gr_slot_origin_X (is) - curradvx; - pPos->y_offset = gr_slot_origin_Y (is) - curradvy; - pPos->x_advance = gr_slot_advance_X (is, grface, grfont); - pPos->y_advance = gr_slot_advance_Y (is, grface, grfont); - curradvx += pPos->x_advance; + pPos->x_offset = gr_slot_origin_X (is) * xscale - curradvx; + pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; + if (info->cluster != currclus) { + pPos->x_advance = info->var1.i32 * xscale; + curradvx += pPos->x_advance; + currclus = info->cluster; + } else + pPos->x_advance = 0.; + + pPos->y_advance = gr_slot_advance_Y (is, grface, NULL) * yscale; curradvy += pPos->y_advance; } - pPos[-1].x_advance += gr_seg_advance_X(seg) - curradvx; } else { - hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL) + buffer->len - 1; - const hb_glyph_info_t *info = buffer->info + buffer->len - 1; - const hb_glyph_info_t *tinfo; - const gr_slot *tis; - int currclus = -1; - float clusx = 0., clusy = 0.; - for (is = gr_seg_last_slot (seg); is; pPos--, info--, is = gr_slot_prev_in_segment (is)) + curradvx = gr_seg_advance_X(seg); + for (is = gr_seg_first_slot (seg); is; pPos++, info++, is = gr_slot_next_in_segment (is)) { if (info->cluster != currclus) { - curradvx += clusx; - curradvy += clusy; + pPos->x_advance = info->var1.i32 * xscale; + curradvx -= pPos->x_advance; currclus = info->cluster; - clusx = 0.; - clusy = 0.; - for (tis = is, tinfo = info; tis && tinfo->cluster == currclus; tis = gr_slot_prev_in_segment (tis), tinfo--) - { - clusx += gr_slot_advance_X (tis, grface, grfont); - clusy += gr_slot_advance_Y (tis, grface, grfont); - } - curradvx += clusx; - curradvy += clusy; - } - pPos->x_advance = gr_slot_advance_X (is, grface, grfont); - pPos->y_advance = gr_slot_advance_Y (is, grface, grfont); - curradvx -= pPos->x_advance; + } else + pPos->x_advance = 0.; + + pPos->y_advance = gr_slot_advance_Y (is, grface, NULL) * yscale; curradvy -= pPos->y_advance; - pPos->x_offset = gr_slot_origin_X (is) - curradvx; - pPos->y_offset = gr_slot_origin_Y (is) - curradvy; + pPos->x_offset = (gr_slot_origin_X (is) - info->var1.i32) * xscale - curradvx + pPos->x_advance; + pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; } hb_buffer_reverse_clusters (buffer); } diff --git a/gfx/harfbuzz/src/hb-graphite2.h b/gfx/harfbuzz/src/hb-graphite2.h index 3eae54acb..82b1e64cd 100644 --- a/gfx/harfbuzz/src/hb-graphite2.h +++ b/gfx/harfbuzz/src/hb-graphite2.h @@ -36,12 +36,16 @@ HB_BEGIN_DECLS #define HB_GRAPHITE2_TAG_SILF HB_TAG('S','i','l','f') -gr_face * +HB_EXTERN gr_face * hb_graphite2_face_get_gr_face (hb_face_t *face); -gr_font * +#ifndef HB_DISABLE_DEPRECATED + +HB_EXTERN gr_font * hb_graphite2_font_get_gr_font (hb_font_t *font); +#endif + HB_END_DECLS diff --git a/gfx/harfbuzz/src/hb-icu.cc b/gfx/harfbuzz/src/hb-icu.cc index 24cec9d72..ee54721fd 100644 --- a/gfx/harfbuzz/src/hb-icu.cc +++ b/gfx/harfbuzz/src/hb-icu.cc @@ -36,6 +36,7 @@ #include #include #include +#include #include diff --git a/gfx/harfbuzz/src/hb-icu.h b/gfx/harfbuzz/src/hb-icu.h index f2f35f0f2..2db6a7b67 100644 --- a/gfx/harfbuzz/src/hb-icu.h +++ b/gfx/harfbuzz/src/hb-icu.h @@ -36,14 +36,14 @@ HB_BEGIN_DECLS -hb_script_t +HB_EXTERN hb_script_t hb_icu_script_to_script (UScriptCode script); -UScriptCode +HB_EXTERN UScriptCode hb_icu_script_from_script (hb_script_t script); -hb_unicode_funcs_t * +HB_EXTERN hb_unicode_funcs_t * hb_icu_get_unicode_funcs (void); diff --git a/gfx/harfbuzz/src/hb-open-file-private.hh b/gfx/harfbuzz/src/hb-open-file-private.hh index 152230a0e..f208419aa 100644 --- a/gfx/harfbuzz/src/hb-open-file-private.hh +++ b/gfx/harfbuzz/src/hb-open-file-private.hh @@ -140,9 +140,9 @@ struct TTCHeaderVersion1 protected: Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ - FixedVersion version; /* Version of the TTC Header (1.0), + FixedVersion<>version; /* Version of the TTC Header (1.0), * 0x00010000u */ - ArrayOf, ULONG> + ArrayOf, ULONG> table; /* Array of offsets to the OffsetTable for each font * from the beginning of the file */ public: @@ -187,7 +187,7 @@ struct TTCHeader union { struct { Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ - FixedVersion version; /* Version of the TTC Header (1.0 or 2.0), + FixedVersion<>version; /* Version of the TTC Header (1.0 or 2.0), * 0x00010000u or 0x00020000u */ } header; TTCHeaderVersion1 version1; diff --git a/gfx/harfbuzz/src/hb-open-type-private.hh b/gfx/harfbuzz/src/hb-open-type-private.hh index 1e4037805..d90d68c59 100644 --- a/gfx/harfbuzz/src/hb-open-type-private.hh +++ b/gfx/harfbuzz/src/hb-open-type-private.hh @@ -30,6 +30,7 @@ #define HB_OPEN_TYPE_PRIVATE_HH #include "hb-private.hh" +#include "hb-face-private.hh" namespace OT { @@ -101,10 +102,11 @@ static inline Type& StructAfter(TObject &X) #define DEFINE_SIZE_STATIC(size) \ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \ static const unsigned int static_size = (size); \ - static const unsigned int min_size = (size) + static const unsigned int min_size = (size); \ + inline unsigned int get_size (void) const { return (size); } #define DEFINE_SIZE_UNION(size, _member) \ - DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \ + DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \ static const unsigned int min_size = (size) #define DEFINE_SIZE_MIN(size) \ @@ -182,7 +184,7 @@ struct hb_dispatch_context_t /* This limits sanitizing time on really broken fonts. */ #ifndef HB_SANITIZE_MAX_EDITS -#define HB_SANITIZE_MAX_EDITS 8 +#define HB_SANITIZE_MAX_EDITS 32 #endif struct hb_sanitize_context_t : @@ -649,7 +651,9 @@ struct IntType DEFINE_SIZE_STATIC (Size); }; +typedef IntType CHAR; /* 8-bit signed integer. */ typedef IntType BYTE; /* 8-bit unsigned integer. */ +typedef IntType INT8; /* 8-bit signed integer. */ typedef IntType USHORT; /* 16-bit unsigned integer. */ typedef IntType SHORT; /* 16-bit signed integer. */ typedef IntType ULONG; /* 32-bit unsigned integer. */ @@ -662,6 +666,24 @@ typedef SHORT FWORD; /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ typedef USHORT UFWORD; +/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */ +struct F2DOT14 : SHORT +{ + //inline float to_float (void) const { return ???; } + //inline void set_float (float f) { v.set (f * ???); } + public: + DEFINE_SIZE_STATIC (2); +}; + +/* 32-bit signed fixed-point number (16.16). */ +struct Fixed: LONG +{ + //inline float to_float (void) const { return ???; } + //inline void set_float (float f) { v.set (f * ???); } + public: + DEFINE_SIZE_STATIC (4); +}; + /* Date represented in number of seconds since 12:00 midnight, January 1, * 1904. The value is represented as a signed 64-bit integer. */ struct LONGDATETIME @@ -739,9 +761,10 @@ struct CheckSum : ULONG * Version Numbers */ +template struct FixedVersion { - inline uint32_t to_int (void) const { return (major << 16) + minor; } + inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -749,10 +772,10 @@ struct FixedVersion return_trace (c->check_struct (this)); } - USHORT major; - USHORT minor; + FixedType major; + FixedType minor; public: - DEFINE_SIZE_STATIC (4); + DEFINE_SIZE_STATIC (2 * sizeof(FixedType)); }; @@ -785,6 +808,7 @@ struct OffsetTo : Offset if (unlikely (!c->check_struct (this))) return_trace (false); unsigned int offset = *this; if (unlikely (!offset)) return_trace (true); + if (unlikely (!c->check_range (base, offset))) return_trace (false); const Type &obj = StructAtOffset (base, offset); return_trace (likely (obj.sanitize (c)) || neuter (c)); } @@ -795,6 +819,7 @@ struct OffsetTo : Offset if (unlikely (!c->check_struct (this))) return_trace (false); unsigned int offset = *this; if (unlikely (!offset)) return_trace (true); + if (unlikely (!c->check_range (base, offset))) return_trace (false); const Type &obj = StructAtOffset (base, offset); return_trace (likely (obj.sanitize (c, user_data)) || neuter (c)); } @@ -805,6 +830,7 @@ struct OffsetTo : Offset } DEFINE_SIZE_STATIC (sizeof(OffsetType)); }; +template struct LOffsetTo : OffsetTo {}; template static inline const Type& operator + (const Base &base, const OffsetTo &offset) { return offset (base); } template @@ -926,10 +952,11 @@ struct ArrayOf public: DEFINE_SIZE_ARRAY (sizeof (LenType), array); }; +template struct LArrayOf : ArrayOf {}; /* Array of Offset's */ -template -struct OffsetArrayOf : ArrayOf > {}; +template +struct OffsetArrayOf : ArrayOf > {}; /* Array of offsets relative to the beginning of the array itself. */ template @@ -1037,6 +1064,104 @@ struct SortedArrayOf : ArrayOf }; +/* Lazy struct and blob loaders. */ + +/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */ +template +struct hb_lazy_loader_t +{ + inline void init (hb_face_t *face_) + { + face = face_; + instance = NULL; + } + + inline void fini (void) + { + if (instance && instance != &OT::Null(T)) + { + instance->fini(); + free (instance); + } + } + + inline const T* get (void) const + { + retry: + T *p = (T *) hb_atomic_ptr_get (&instance); + if (unlikely (!p)) + { + p = (T *) calloc (1, sizeof (T)); + if (unlikely (!p)) + p = const_cast (&OT::Null(T)); + else + p->init (face); + if (unlikely (!hb_atomic_ptr_cmpexch (const_cast(&instance), NULL, p))) + { + if (p != &OT::Null(T)) + p->fini (); + goto retry; + } + } + return p; + } + + inline const T* operator-> (void) const + { + return get (); + } + + private: + hb_face_t *face; + T *instance; +}; + +/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */ +template +struct hb_lazy_table_loader_t +{ + inline void init (hb_face_t *face_) + { + face = face_; + instance = NULL; + blob = NULL; + } + + inline void fini (void) + { + hb_blob_destroy (blob); + } + + inline const T* get (void) const + { + retry: + T *p = (T *) hb_atomic_ptr_get (&instance); + if (unlikely (!p)) + { + hb_blob_t *blob_ = OT::Sanitizer::sanitize (face->reference_table (T::tableTag)); + p = const_cast(OT::Sanitizer::lock_instance (blob_)); + if (!hb_atomic_ptr_cmpexch (const_cast(&instance), NULL, p)) + { + hb_blob_destroy (blob_); + goto retry; + } + blob = blob_; + } + return p; + } + + inline const T* operator-> (void) const + { + return get(); + } + + private: + hb_face_t *face; + T *instance; + mutable hb_blob_t *blob; +}; + + } /* namespace OT */ diff --git a/gfx/harfbuzz/src/hb-ot-cbdt-table.hh b/gfx/harfbuzz/src/hb-ot-cbdt-table.hh new file mode 100644 index 000000000..0a7fbf5b7 --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-cbdt-table.hh @@ -0,0 +1,384 @@ +/* + * Copyright © 2016 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Seigo Nonaka + */ + +#ifndef HB_OT_CBDT_TABLE_HH +#define HB_OT_CBDT_TABLE_HH + +#include "hb-open-type-private.hh" + +namespace OT { + +struct SmallGlyphMetrics +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + inline void get_extents (hb_glyph_extents_t *extents) const + { + extents->x_bearing = bearingX; + extents->y_bearing = bearingY; + extents->width = width; + extents->height = -height; + } + + BYTE height; + BYTE width; + CHAR bearingX; + CHAR bearingY; + BYTE advance; + + DEFINE_SIZE_STATIC(5); +}; + +struct BigGlyphMetrics : SmallGlyphMetrics +{ + CHAR vertBearingX; + CHAR vertBearingY; + BYTE vertAdvance; + + DEFINE_SIZE_STATIC(8); +}; + +struct SBitLineMetrics +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + CHAR ascender; + CHAR decender; + BYTE widthMax; + CHAR caretSlopeNumerator; + CHAR caretSlopeDenominator; + CHAR caretOffset; + CHAR minOriginSB; + CHAR minAdvanceSB; + CHAR maxBeforeBL; + CHAR minAfterBL; + CHAR padding1; + CHAR padding2; + + DEFINE_SIZE_STATIC(12); +}; + + +/* + * Index Subtables. + */ + +struct IndexSubtableHeader +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + USHORT indexFormat; + USHORT imageFormat; + ULONG imageDataOffset; + + DEFINE_SIZE_STATIC(8); +}; + +template +struct IndexSubtableFormat1Or3 +{ + inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1)); + } + + bool get_image_data (unsigned int idx, + unsigned int *offset, + unsigned int *length) const + { + if (unlikely (offsetArrayZ[idx + 1] <= offsetArrayZ[idx])) + return false; + + *offset = header.imageDataOffset + offsetArrayZ[idx]; + *length = offsetArrayZ[idx + 1] - offsetArrayZ[idx]; + return true; + } + + IndexSubtableHeader header; + Offset offsetArrayZ[VAR]; + + DEFINE_SIZE_ARRAY(8, offsetArrayZ); +}; + +struct IndexSubtableFormat1 : IndexSubtableFormat1Or3 {}; +struct IndexSubtableFormat3 : IndexSubtableFormat1Or3 {}; + +struct IndexSubtable +{ + inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const + { + TRACE_SANITIZE (this); + if (!u.header.sanitize (c)) return_trace (false); + switch (u.header.indexFormat) { + case 1: return_trace (u.format1.sanitize (c, glyph_count)); + case 3: return_trace (u.format3.sanitize (c, glyph_count)); + default:return_trace (true); + } + } + + inline bool get_extents (hb_glyph_extents_t *extents) const + { + switch (u.header.indexFormat) { + case 2: case 5: /* TODO */ + case 1: case 3: case 4: /* Variable-metrics formats do not have metrics here. */ + default:return (false); + } + } + + bool get_image_data (unsigned int idx, + unsigned int *offset, + unsigned int *length, + unsigned int *format) const + { + *format = u.header.imageFormat; + switch (u.header.indexFormat) { + case 1: return u.format1.get_image_data (idx, offset, length); + case 3: return u.format3.get_image_data (idx, offset, length); + default: return false; + } + } + + protected: + union { + IndexSubtableHeader header; + IndexSubtableFormat1 format1; + IndexSubtableFormat3 format3; + /* TODO: Format 2, 4, 5. */ + } u; + public: + DEFINE_SIZE_UNION (8, header); +}; + +struct IndexSubtableRecord +{ + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + firstGlyphIndex <= lastGlyphIndex && + offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1)); + } + + inline bool get_extents (hb_glyph_extents_t *extents) const + { + return (this+offsetToSubtable).get_extents (extents); + } + + bool get_image_data (unsigned int gid, + unsigned int *offset, + unsigned int *length, + unsigned int *format) const + { + if (gid < firstGlyphIndex || gid > lastGlyphIndex) + { + return false; + } + return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex, + offset, length, format); + } + + USHORT firstGlyphIndex; + USHORT lastGlyphIndex; + LOffsetTo offsetToSubtable; + + DEFINE_SIZE_STATIC(8); +}; + +struct IndexSubtableArray +{ + inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const + { + TRACE_SANITIZE (this); + if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count))) + return_trace (false); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!indexSubtablesZ[i].sanitize (c, this))) + return_trace (false); + return_trace (true); + } + + public: + const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const + { + for (unsigned int i = 0; i < numTables; ++i) + { + unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex; + unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex; + if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) { + return &indexSubtablesZ[i]; + } + } + return NULL; + } + + protected: + IndexSubtableRecord indexSubtablesZ[VAR]; + + public: + DEFINE_SIZE_ARRAY(0, indexSubtablesZ); +}; + +struct BitmapSizeTable +{ + friend struct CBLC; + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) && + c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) && + horizontal.sanitize (c) && + vertical.sanitize (c)); + } + + const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const + { + return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables); + } + + protected: + LOffsetTo indexSubtableArrayOffset; + ULONG indexTablesSize; + ULONG numberOfIndexSubtables; + ULONG colorRef; + SBitLineMetrics horizontal; + SBitLineMetrics vertical; + USHORT startGlyphIndex; + USHORT endGlyphIndex; + BYTE ppemX; + BYTE ppemY; + BYTE bitDepth; + CHAR flags; + +public: + DEFINE_SIZE_STATIC(48); +}; + + +/* + * Glyph Bitmap Data Formats. + */ + +struct GlyphBitmapDataFormat17 +{ + SmallGlyphMetrics glyphMetrics; + ULONG dataLen; + BYTE dataZ[VAR]; + + DEFINE_SIZE_ARRAY(9, dataZ); +}; + + +/* + * CBLC -- Color Bitmap Location Table + */ + +#define HB_OT_TAG_CBLC HB_TAG('C','B','L','C') + +struct CBLC +{ + static const hb_tag_t tableTag = HB_OT_TAG_CBLC; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + likely (version.major == 2 || version.major == 3) && + sizeTables.sanitize (c, this)); + } + + public: + const IndexSubtableRecord *find_table (hb_codepoint_t glyph, + unsigned int *x_ppem, unsigned int *y_ppem) const + { + /* TODO: Make it possible to select strike. */ + + unsigned int count = sizeTables.len; + for (uint32_t i = 0; i < count; ++i) + { + unsigned int startGlyphIndex = sizeTables.array[i].startGlyphIndex; + unsigned int endGlyphIndex = sizeTables.array[i].endGlyphIndex; + if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) + { + *x_ppem = sizeTables[i].ppemX; + *y_ppem = sizeTables[i].ppemY; + return sizeTables[i].find_table (glyph, this); + } + } + + return NULL; + } + + protected: + FixedVersion<> version; + LArrayOf sizeTables; + + public: + DEFINE_SIZE_ARRAY(8, sizeTables); +}; + +/* + * CBDT -- Color Bitmap Data Table + */ +#define HB_OT_TAG_CBDT HB_TAG('C','B','D','T') + +struct CBDT +{ + static const hb_tag_t tableTag = HB_OT_TAG_CBDT; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + likely (version.major == 2 || version.major == 3)); + } + + protected: + FixedVersion<>version; + BYTE dataZ[VAR]; + + public: + DEFINE_SIZE_ARRAY(4, dataZ); +}; + +} /* namespace OT */ + +#endif /* HB_OT_CBDT_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-cmap-table.hh b/gfx/harfbuzz/src/hb-ot-cmap-table.hh index c9161f0ef..3a53a1cb5 100644 --- a/gfx/harfbuzz/src/hb-ot-cmap-table.hh +++ b/gfx/harfbuzz/src/hb-ot-cmap-table.hh @@ -69,61 +69,78 @@ struct CmapSubtableFormat0 struct CmapSubtableFormat4 { - inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const + struct accelerator_t { - unsigned int segCount; + inline void init (const CmapSubtableFormat4 *subtable) + { + segCount = subtable->segCountX2 / 2; + endCount = subtable->values; + startCount = endCount + segCount + 1; + idDelta = startCount + segCount; + idRangeOffset = idDelta + segCount; + glyphIdArray = idRangeOffset + segCount; + glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2; + } + + static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph) + { + const accelerator_t *thiz = (const accelerator_t *) obj; + + /* Custom two-array bsearch. */ + int min = 0, max = (int) thiz->segCount - 1; + const USHORT *startCount = thiz->startCount; + const USHORT *endCount = thiz->endCount; + unsigned int i; + while (min <= max) + { + int mid = (min + max) / 2; + if (codepoint < startCount[mid]) + max = mid - 1; + else if (codepoint > endCount[mid]) + min = mid + 1; + else + { + i = mid; + goto found; + } + } + return false; + + found: + hb_codepoint_t gid; + unsigned int rangeOffset = thiz->idRangeOffset[i]; + if (rangeOffset == 0) + gid = codepoint + thiz->idDelta[i]; + else + { + /* Somebody has been smoking... */ + unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount; + if (unlikely (index >= thiz->glyphIdArrayLength)) + return false; + gid = thiz->glyphIdArray[index]; + if (unlikely (!gid)) + return false; + gid += thiz->idDelta[i]; + } + + *glyph = gid & 0xFFFFu; + return true; + } + const USHORT *endCount; const USHORT *startCount; const USHORT *idDelta; const USHORT *idRangeOffset; const USHORT *glyphIdArray; + unsigned int segCount; unsigned int glyphIdArrayLength; + }; - segCount = this->segCountX2 / 2; - endCount = this->values; - startCount = endCount + segCount + 1; - idDelta = startCount + segCount; - idRangeOffset = idDelta + segCount; - glyphIdArray = idRangeOffset + segCount; - glyphIdArrayLength = (this->length - 16 - 8 * segCount) / 2; - - /* Custom two-array bsearch. */ - int min = 0, max = (int) segCount - 1; - unsigned int i; - while (min <= max) - { - int mid = (min + max) / 2; - if (codepoint < startCount[mid]) - max = mid - 1; - else if (codepoint > endCount[mid]) - min = mid + 1; - else - { - i = mid; - goto found; - } - } - return false; - - found: - hb_codepoint_t gid; - unsigned int rangeOffset = idRangeOffset[i]; - if (rangeOffset == 0) - gid = codepoint + idDelta[i]; - else - { - /* Somebody has been smoking... */ - unsigned int index = rangeOffset / 2 + (codepoint - startCount[i]) + i - segCount; - if (unlikely (index >= glyphIdArrayLength)) - return false; - gid = glyphIdArray[index]; - if (unlikely (!gid)) - return false; - gid += idDelta[i]; - } - - *glyph = gid & 0xFFFFu; - return true; + inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const + { + accelerator_t accel; + accel.init (this); + return accel.get_glyph_func (&accel, codepoint, glyph); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -363,9 +380,9 @@ struct VariationSelectorRecord } UINT24 varSelector; /* Variation selector. */ - OffsetTo + LOffsetTo defaultUVS; /* Offset to Default UVS Table. May be 0. */ - OffsetTo + LOffsetTo nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */ public: DEFINE_SIZE_STATIC (11); @@ -388,7 +405,7 @@ struct CmapSubtableFormat14 } protected: - USHORT format; /* Format number is set to 0. */ + USHORT format; /* Format number is set to 14. */ ULONG lengthZ; /* Byte length of this subtable. */ SortedArrayOf record; /* Variation selector records; sorted @@ -416,16 +433,6 @@ struct CmapSubtable } } - inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint, - hb_codepoint_t variation_selector, - hb_codepoint_t *glyph) const - { - switch (u.format) { - case 14: return u.format14.get_glyph_variant(codepoint, variation_selector, glyph); - default: return GLYPH_VARIANT_NOT_FOUND; - } - } - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -442,7 +449,7 @@ struct CmapSubtable } } - protected: + public: union { USHORT format; /* Format identifier */ CmapSubtableFormat0 format0; @@ -479,7 +486,7 @@ struct EncodingRecord USHORT platformID; /* Platform ID. */ USHORT encodingID; /* Platform-specific encoding ID. */ - OffsetTo + LOffsetTo subtable; /* Byte offset from beginning of table to the subtable for this encoding. */ public: DEFINE_SIZE_STATIC (8); diff --git a/gfx/harfbuzz/src/hb-ot-font.cc b/gfx/harfbuzz/src/hb-ot-font.cc index 8d3330070..d3251caf7 100644 --- a/gfx/harfbuzz/src/hb-ot-font.cc +++ b/gfx/harfbuzz/src/hb-ot-font.cc @@ -31,10 +31,14 @@ #include "hb-font-private.hh" #include "hb-ot-cmap-table.hh" +#include "hb-ot-cbdt-table.hh" #include "hb-ot-glyf-table.hh" #include "hb-ot-head-table.hh" #include "hb-ot-hhea-table.hh" #include "hb-ot-hmtx-table.hh" +#include "hb-ot-os2-table.hh" +#include "hb-ot-var-hvar-table.hh" +//#include "hb-ot-post-table.hh" struct hb_ot_face_metrics_accelerator_t @@ -42,20 +46,57 @@ struct hb_ot_face_metrics_accelerator_t unsigned int num_metrics; unsigned int num_advances; unsigned int default_advance; - const OT::_mtx *table; + unsigned short ascender; + unsigned short descender; + unsigned short line_gap; + bool has_font_extents; + + const OT::hmtxvmtx *table; hb_blob_t *blob; + const OT::HVARVVAR *var; + hb_blob_t *var_blob; + inline void init (hb_face_t *face, - hb_tag_t _hea_tag, hb_tag_t _mtx_tag) + hb_tag_t _hea_tag, + hb_tag_t _mtx_tag, + hb_tag_t _var_tag, + hb_tag_t os2_tag, + unsigned int default_advance = 0) { - this->default_advance = face->get_upem (); + this->default_advance = default_advance ? default_advance : face->get_upem (); + + bool got_font_extents = false; + if (os2_tag) + { + hb_blob_t *os2_blob = OT::Sanitizer::sanitize (face->reference_table (os2_tag)); + const OT::os2 *os2 = OT::Sanitizer::lock_instance (os2_blob); +#define USE_TYPO_METRICS (1u<<7) + if (0 != (os2->fsSelection & USE_TYPO_METRICS)) + { + this->ascender = os2->sTypoAscender; + this->descender = os2->sTypoDescender; + this->line_gap = os2->sTypoLineGap; + got_font_extents = (this->ascender | this->descender) != 0; + } + hb_blob_destroy (os2_blob); + } hb_blob_t *_hea_blob = OT::Sanitizer::sanitize (face->reference_table (_hea_tag)); const OT::_hea *_hea = OT::Sanitizer::lock_instance (_hea_blob); this->num_advances = _hea->numberOfLongMetrics; + if (!got_font_extents) + { + this->ascender = _hea->ascender; + this->descender = _hea->descender; + this->line_gap = _hea->lineGap; + got_font_extents = (this->ascender | this->descender) != 0; + } hb_blob_destroy (_hea_blob); - this->blob = OT::Sanitizer::sanitize (face->reference_table (_mtx_tag)); + this->has_font_extents = got_font_extents; + + this->blob = OT::Sanitizer::sanitize (face->reference_table (_mtx_tag)); /* Cap num_metrics() and num_advances() based on table length. */ unsigned int len = hb_blob_get_length (this->blob); @@ -71,15 +112,20 @@ struct hb_ot_face_metrics_accelerator_t hb_blob_destroy (this->blob); this->blob = hb_blob_get_empty (); } - this->table = OT::Sanitizer::lock_instance (this->blob); + this->table = OT::Sanitizer::lock_instance (this->blob); + + this->var_blob = OT::Sanitizer::sanitize (face->reference_table (_var_tag)); + this->var = OT::Sanitizer::lock_instance (this->var_blob); } inline void fini (void) { hb_blob_destroy (this->blob); + hb_blob_destroy (this->var_blob); } - inline unsigned int get_advance (hb_codepoint_t glyph) const + inline unsigned int get_advance (hb_codepoint_t glyph, + hb_font_t *font) const { if (unlikely (glyph >= this->num_metrics)) { @@ -92,10 +138,8 @@ struct hb_ot_face_metrics_accelerator_t return this->default_advance; } - if (glyph >= this->num_advances) - glyph = this->num_advances - 1; - - return this->table->longMetric[glyph].advance; + return this->table->longMetric[MIN (glyph, (uint32_t) this->num_advances - 1)].advance + + this->var->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?! } }; @@ -172,10 +216,133 @@ struct hb_ot_face_glyf_accelerator_t } }; +struct hb_ot_face_cbdt_accelerator_t +{ + hb_blob_t *cblc_blob; + hb_blob_t *cbdt_blob; + const OT::CBLC *cblc; + const OT::CBDT *cbdt; + + unsigned int cbdt_len; + unsigned int upem; + + inline void init (hb_face_t *face) + { + upem = face->get_upem(); + + cblc_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_CBLC)); + cbdt_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_CBDT)); + cbdt_len = hb_blob_get_length (cbdt_blob); + + if (hb_blob_get_length (cblc_blob) == 0) { + cblc = NULL; + cbdt = NULL; + return; /* Not a bitmap font. */ + } + cblc = OT::Sanitizer::lock_instance (cblc_blob); + cbdt = OT::Sanitizer::lock_instance (cbdt_blob); + + } + + inline void fini (void) + { + hb_blob_destroy (this->cblc_blob); + hb_blob_destroy (this->cbdt_blob); + } + + inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const + { + unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */ + + if (!cblc) + return false; // Not a color bitmap font. + + const OT::IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem); + if (!subtable_record || !x_ppem || !y_ppem) + return false; + + if (subtable_record->get_extents (extents)) + return true; + + unsigned int image_offset = 0, image_length = 0, image_format = 0; + if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format)) + return false; + + { + /* TODO Move the following into CBDT struct when adding more formats. */ + + if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length)) + return false; + + switch (image_format) + { + case 17: { + if (unlikely (image_length < OT::GlyphBitmapDataFormat17::min_size)) + return false; + + const OT::GlyphBitmapDataFormat17& glyphFormat17 = + OT::StructAtOffset (this->cbdt, image_offset); + glyphFormat17.glyphMetrics.get_extents (extents); + } + break; + default: + // TODO: Support other image formats. + return false; + } + } + + /* Convert to the font units. */ + extents->x_bearing *= upem / (float) x_ppem; + extents->y_bearing *= upem / (float) y_ppem; + extents->width *= upem / (float) x_ppem; + extents->height *= upem / (float) y_ppem; + + return true; + } +}; + +typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj, + hb_codepoint_t codepoint, + hb_codepoint_t *glyph); + +template +static inline bool get_glyph_from (const void *obj, + hb_codepoint_t codepoint, + hb_codepoint_t *glyph) +{ + const Type *typed_obj = (const Type *) obj; + return typed_obj->get_glyph (codepoint, glyph); +} + +template +static inline bool get_glyph_from_symbol (const void *obj, + hb_codepoint_t codepoint, + hb_codepoint_t *glyph) +{ + const Type *typed_obj = (const Type *) obj; + if (likely (typed_obj->get_glyph (codepoint, glyph))) + return true; + + if (codepoint <= 0x00FFu) + { + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * http://www.microsoft.com/typography/otspec/recom.htm + * under "Non-Standard (Symbol) Fonts". */ + return typed_obj->get_glyph (0xF000u + codepoint, glyph); + } + + return false; +} + struct hb_ot_face_cmap_accelerator_t { - const OT::CmapSubtable *table; - const OT::CmapSubtable *uvs_table; + hb_cmap_get_glyph_func_t get_glyph_func; + const void *get_glyph_data; + OT::CmapSubtableFormat4::accelerator_t format4_accel; + + const OT::CmapSubtableFormat14 *uvs_table; hb_blob_t *blob; inline void init (hb_face_t *face) @@ -183,8 +350,9 @@ struct hb_ot_face_cmap_accelerator_t 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; + const OT::CmapSubtableFormat14 *subtable_uvs = NULL; + bool symbol = false; /* 32-bit subtables. */ if (!subtable) subtable = cmap->find_subtable (3, 10); if (!subtable) subtable = cmap->find_subtable (0, 6); @@ -195,17 +363,42 @@ struct hb_ot_face_cmap_accelerator_t if (!subtable) subtable = cmap->find_subtable (0, 2); if (!subtable) subtable = cmap->find_subtable (0, 1); if (!subtable) subtable = cmap->find_subtable (0, 0); - if (!subtable) subtable = cmap->find_subtable (3, 0); + if (!subtable) + { + subtable = cmap->find_subtable (3, 0); + if (subtable) symbol = true; + } /* Meh. */ if (!subtable) subtable = &OT::Null(OT::CmapSubtable); /* UVS subtable. */ - if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5); + if (!subtable_uvs) + { + const OT::CmapSubtable *st = cmap->find_subtable (0, 5); + if (st && st->u.format == 14) + subtable_uvs = &st->u.format14; + } /* Meh. */ - if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable); + if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtableFormat14); - this->table = subtable; this->uvs_table = subtable_uvs; + + this->get_glyph_data = subtable; + if (unlikely (symbol)) + this->get_glyph_func = get_glyph_from_symbol; + else + switch (subtable->u.format) { + /* Accelerate format 4 and format 12. */ + default: this->get_glyph_func = get_glyph_from; break; + case 12: this->get_glyph_func = get_glyph_from; break; + case 4: + { + this->format4_accel.init (&subtable->u.format4); + this->get_glyph_data = &this->format4_accel; + this->get_glyph_func = this->format4_accel.get_glyph_func; + } + break; + } } inline void fini (void) @@ -213,33 +406,36 @@ struct hb_ot_face_cmap_accelerator_t hb_blob_destroy (this->blob); } - inline bool get_glyph (hb_codepoint_t unicode, - hb_codepoint_t variation_selector, - hb_codepoint_t *glyph) const + inline bool get_nominal_glyph (hb_codepoint_t unicode, + hb_codepoint_t *glyph) const { - if (unlikely (variation_selector)) + return this->get_glyph_func (this->get_glyph_data, unicode, glyph); + } + + inline bool get_variation_glyph (hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph) const + { + switch (this->uvs_table->get_glyph_variant (unicode, + variation_selector, + glyph)) { - switch (this->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; - } + 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); + return get_nominal_glyph (unicode, glyph); } }; - struct hb_ot_font_t { hb_ot_face_cmap_accelerator_t cmap; hb_ot_face_metrics_accelerator_t h_metrics; hb_ot_face_metrics_accelerator_t v_metrics; - hb_ot_face_glyf_accelerator_t glyf; + OT::hb_lazy_loader_t glyf; + OT::hb_lazy_loader_t cbdt; }; @@ -252,9 +448,11 @@ _hb_ot_font_create (hb_face_t *face) return NULL; ot_font->cmap.init (face); - ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx); - ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx); /* TODO Can we do this lazily? */ + ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_HVAR, HB_OT_TAG_os2); + ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_OT_TAG_VVAR, HB_TAG_NONE, + ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */ ot_font->glyf.init (face); + ot_font->cbdt.init (face); return ot_font; } @@ -266,42 +464,54 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font) ot_font->h_metrics.fini (); ot_font->v_metrics.fini (); ot_font->glyf.fini (); + ot_font->cbdt.fini (); free (ot_font); } static hb_bool_t -hb_ot_get_glyph (hb_font_t *font HB_UNUSED, - void *font_data, - hb_codepoint_t unicode, - hb_codepoint_t variation_selector, - hb_codepoint_t *glyph, - void *user_data HB_UNUSED) +hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t unicode, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return ot_font->cmap.get_glyph (unicode, variation_selector, glyph); + return ot_font->cmap.get_nominal_glyph (unicode, glyph); +} + +static hb_bool_t +hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph); } static hb_position_t -hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED, +hb_ot_get_glyph_h_advance (hb_font_t *font, void *font_data, hb_codepoint_t glyph, void *user_data HB_UNUSED) { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return font->em_scale_x (ot_font->h_metrics.get_advance (glyph)); + return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font)); } static hb_position_t -hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, +hb_ot_get_glyph_v_advance (hb_font_t *font, void *font_data, hb_codepoint_t glyph, void *user_data HB_UNUSED) { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph)); + return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font)); } static hb_bool_t @@ -312,7 +522,10 @@ hb_ot_get_glyph_extents (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; - bool ret = ot_font->glyf.get_extents (glyph, extents); + bool ret = ot_font->glyf->get_extents (glyph, extents); + if (!ret) + ret = ot_font->cbdt->get_extents (glyph, extents); + // TODO Hook up side-bearings variations. extents->x_bearing = font->em_scale_x (extents->x_bearing); extents->y_bearing = font->em_scale_y (extents->y_bearing); extents->width = font->em_scale_x (extents->width); @@ -320,6 +533,33 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, return ret; } +static hb_bool_t +hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED, + void *font_data, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender); + metrics->descender = font->em_scale_y (ot_font->h_metrics.descender); + metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap); + // TODO Hook up variations. + return ot_font->h_metrics.has_font_extents; +} + +static hb_bool_t +hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED, + void *font_data, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender); + metrics->descender = font->em_scale_x (ot_font->v_metrics.descender); + metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap); + // TODO Hook up variations. + return ot_font->v_metrics.has_font_extents; +} static hb_font_funcs_t *static_ot_funcs = NULL; @@ -341,7 +581,10 @@ retry: { funcs = hb_font_funcs_create (); - hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL); + hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, NULL, NULL); + hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, NULL, NULL); + hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, NULL, NULL); + hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, NULL, NULL); hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL); hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL); //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL); @@ -370,6 +613,8 @@ retry: /** + * hb_ot_font_set_funcs: + * * Since: 0.9.28 **/ void diff --git a/gfx/harfbuzz/src/hb-ot-font.h b/gfx/harfbuzz/src/hb-ot-font.h index b9947a16b..80eaa54b1 100644 --- a/gfx/harfbuzz/src/hb-ot-font.h +++ b/gfx/harfbuzz/src/hb-ot-font.h @@ -36,7 +36,7 @@ HB_BEGIN_DECLS -void +HB_EXTERN void hb_ot_font_set_funcs (hb_font_t *font); diff --git a/gfx/harfbuzz/src/hb-ot-glyf-table.hh b/gfx/harfbuzz/src/hb-ot-glyf-table.hh index 9e5af6d10..dc7aa8469 100644 --- a/gfx/harfbuzz/src/hb-ot-glyf-table.hh +++ b/gfx/harfbuzz/src/hb-ot-glyf-table.hh @@ -90,10 +90,10 @@ struct glyfGlyphHeader * greater than or equal to zero, * this is a simple glyph; if negative, * this is a composite glyph. */ - SHORT xMin; /* Minimum x for coordinate data. */ - SHORT yMin; /* Minimum y for coordinate data. */ - SHORT xMax; /* Maximum x for coordinate data. */ - SHORT yMax; /* Maximum y for coordinate data. */ + FWORD xMin; /* Minimum x for coordinate data. */ + FWORD yMin; /* Minimum y for coordinate data. */ + FWORD xMax; /* Maximum x for coordinate data. */ + FWORD yMax; /* Maximum y for coordinate data. */ DEFINE_SIZE_STATIC (10); }; diff --git a/gfx/harfbuzz/src/hb-ot-head-table.hh b/gfx/harfbuzz/src/hb-ot-head-table.hh index fc351cfb4..9c3e51eb0 100644 --- a/gfx/harfbuzz/src/hb-ot-head-table.hh +++ b/gfx/harfbuzz/src/hb-ot-head-table.hh @@ -55,13 +55,15 @@ struct head inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && likely (version.major == 1)); + return_trace (c->check_struct (this) && + version.major == 1 && + magicNumber == 0x5F0F3CF5u); } protected: - FixedVersion version; /* Version of the head table--currently + FixedVersion<>version; /* Version of the head table--currently * 0x00010000u for version 1.0. */ - FixedVersion fontRevision; /* Set by font manufacturer. */ + FixedVersion<>fontRevision; /* Set by font manufacturer. */ ULONG checkSumAdjustment; /* To compute: set it to 0, sum the * entire font as ULONG, then store * 0xB1B0AFBAu - sum. */ diff --git a/gfx/harfbuzz/src/hb-ot-hhea-table.hh b/gfx/harfbuzz/src/hb-ot-hhea-table.hh index 24114534a..c8e9536cf 100644 --- a/gfx/harfbuzz/src/hb-ot-hhea-table.hh +++ b/gfx/harfbuzz/src/hb-ot-hhea-table.hh @@ -56,7 +56,7 @@ struct _hea } public: - FixedVersion version; /* 0x00010000u for version 1.0. */ + FixedVersion<>version; /* 0x00010000u for version 1.0. */ FWORD ascender; /* Typographic ascent. */ FWORD descender; /* Typographic descent. */ FWORD lineGap; /* Typographic line gap. */ diff --git a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh index 49056e676..30aa62534 100644 --- a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh +++ b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh @@ -44,16 +44,14 @@ namespace OT { struct LongMetric { - USHORT advance; /* Advance width/height. */ - SHORT lsb; /* Leading (left/top) side bearing. */ + UFWORD advance; /* Advance width/height. */ + FWORD lsb; /* Leading (left/top) side bearing. */ public: DEFINE_SIZE_STATIC (4); }; -struct _mtx +struct hmtxvmtx { - 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; @@ -74,7 +72,7 @@ struct _mtx * be in the array, but that entry is * required. The last entry applies to * all subsequent glyphs. */ - SHORT leadingBearingX[VAR]; /* Here the advance is assumed + FWORD 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 @@ -91,10 +89,10 @@ struct _mtx DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX); }; -struct hmtx : _mtx { +struct hmtx : hmtxvmtx { static const hb_tag_t tableTag = HB_OT_TAG_hmtx; }; -struct vmtx : _mtx { +struct vmtx : hmtxvmtx { static const hb_tag_t tableTag = HB_OT_TAG_vmtx; }; diff --git a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh index 5b21f1427..578d850c1 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh @@ -507,7 +507,7 @@ struct Feature { return this+featureParams; } inline bool sanitize (hb_sanitize_context_t *c, - const Record::sanitize_closure_t *closure) const + const Record::sanitize_closure_t *closure = NULL) const { TRACE_SANITIZE (this); if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c)))) @@ -545,6 +545,9 @@ struct Feature c->try_set (&featureParams, new_offset) && !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)) return_trace (false); + + if (c->edit_count > 1) + c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */ } return_trace (true); @@ -728,8 +731,8 @@ struct CoverageFormat1 inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }; inline bool more (void) { return i < c->glyphArray.len; } inline void next (void) { i++; } - inline uint16_t get_glyph (void) { return c->glyphArray[i]; } - inline uint16_t get_coverage (void) { return i; } + inline hb_codepoint_t get_glyph (void) { return c->glyphArray[i]; } + inline unsigned int get_coverage (void) { return i; } private: const struct CoverageFormat1 *c; @@ -767,7 +770,11 @@ struct CoverageFormat2 TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!num_glyphs)) return_trace (true); + if (unlikely (!num_glyphs)) + { + rangeRecord.len.set (0); + return_trace (true); + } unsigned int num_ranges = 1; for (unsigned int i = 1; i < num_glyphs; i++) @@ -822,26 +829,33 @@ struct CoverageFormat2 public: /* Older compilers need this to be public. */ - struct Iter { - inline void init (const CoverageFormat2 &c_) { + struct Iter + { + inline void init (const CoverageFormat2 &c_) + { c = &c_; coverage = 0; i = 0; j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0; } inline bool more (void) { return i < c->rangeRecord.len; } - inline void next (void) { - coverage++; - if (j == c->rangeRecord[i].end) { + inline void next (void) + { + if (j >= c->rangeRecord[i].end) + { i++; if (more ()) + { j = c->rangeRecord[i].start; + coverage = c->rangeRecord[i].value; + } return; } + coverage++; j++; } - inline uint16_t get_glyph (void) { return j; } - inline uint16_t get_coverage (void) { return coverage; } + inline hb_codepoint_t get_glyph (void) { return j; } + inline unsigned int get_coverage (void) { return coverage; } private: const struct CoverageFormat2 *c; @@ -927,7 +941,7 @@ struct Coverage } struct Iter { - Iter (void) : format (0) {}; + Iter (void) : format (0), u () {}; inline void init (const Coverage &c_) { format = c_.u.format; switch (format) { @@ -950,14 +964,14 @@ struct Coverage default: break; } } - inline uint16_t get_glyph (void) { + inline hb_codepoint_t get_glyph (void) { switch (format) { case 1: return u.format1.get_glyph (); case 2: return u.format2.get_glyph (); default:return 0; } } - inline uint16_t get_coverage (void) { + inline unsigned int get_coverage (void) { switch (format) { case 1: return u.format1.get_coverage (); case 2: return u.format2.get_coverage (); @@ -968,8 +982,8 @@ struct Coverage private: unsigned int format; union { + CoverageFormat2::Iter format2; /* Put this one first since it's larger; helps shut up compiler. */ CoverageFormat1::Iter format1; - CoverageFormat2::Iter format2; } u; }; @@ -1154,12 +1168,389 @@ struct ClassDef }; +/* + * Item Variation Store + */ + +struct VarRegionAxis +{ + inline float evaluate (int coord) const + { + int start = startCoord, peak = peakCoord, end = endCoord; + + /* TODO Move these to sanitize(). */ + if (unlikely (start > peak || peak > end)) + return 1.; + if (unlikely (start < 0 && end > 0 && peak != 0)) + return 1.; + + if (peak == 0 || coord == peak) + return 1.; + + if (coord <= start || end <= coord) + return 0.; + + /* Interpolate */ + if (coord < peak) + return float (coord - start) / (peak - start); + else + return float (end - coord) / (end - peak); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + /* TODO Handle invalid start/peak/end configs, so we don't + * have to do that at runtime. */ + } + + public: + F2DOT14 startCoord; + F2DOT14 peakCoord; + F2DOT14 endCoord; + public: + DEFINE_SIZE_STATIC (6); +}; + +struct VarRegionList +{ + inline float evaluate (unsigned int region_index, + int *coords, unsigned int coord_len) const + { + if (unlikely (region_index >= regionCount)) + return 0.; + + const VarRegionAxis *axes = axesZ + (region_index * axisCount); + + float v = 1.; + unsigned int count = MIN (coord_len, (unsigned int) axisCount); + for (unsigned int i = 0; i < count; i++) + { + float factor = axes[i].evaluate (coords[i]); + if (factor == 0.) + return 0.; + v *= factor; + } + return v; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (axesZ, axesZ[0].static_size, + (unsigned int) axisCount * (unsigned int) regionCount)); + } + + protected: + USHORT axisCount; + USHORT regionCount; + VarRegionAxis axesZ[VAR]; + public: + DEFINE_SIZE_ARRAY (4, axesZ); +}; + +struct VarData +{ + inline unsigned int get_row_size (void) const + { return shortCount + regionIndices.len; } + + inline unsigned int get_size (void) const + { return itemCount * get_row_size (); } + + inline float get_delta (unsigned int inner, + int *coords, unsigned int coord_count, + const VarRegionList ®ions) const + { + if (unlikely (inner >= itemCount)) + return 0.; + + unsigned int count = regionIndices.len; + unsigned int scount = shortCount; + + const BYTE *bytes = &StructAfter (regionIndices); + const BYTE *row = bytes + inner * (scount + count); + + float delta = 0.; + unsigned int i = 0; + + const SHORT *scursor = reinterpret_cast (row); + for (; i < scount; i++) + { + float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count); + delta += scalar * *scursor++; + } + const INT8 *bcursor = reinterpret_cast (scursor); + for (; i < count; i++) + { + float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count); + delta += scalar * *bcursor++; + } + + return delta; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + regionIndices.sanitize(c) && + shortCount <= regionIndices.len && + c->check_array (&StructAfter (regionIndices), + get_row_size (), itemCount)); + } + + protected: + USHORT itemCount; + USHORT shortCount; + ArrayOf regionIndices; + BYTE bytesX[VAR]; + public: + DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX); +}; + +struct VariationStore +{ + inline float get_delta (unsigned int outer, unsigned int inner, + int *coords, unsigned int coord_count) const + { + if (unlikely (outer >= dataSets.len)) + return 0.; + + return (this+dataSets[outer]).get_delta (inner, + coords, coord_count, + this+regions); + } + + inline float get_delta (unsigned int index, + int *coords, unsigned int coord_count) const + { + unsigned int outer = index >> 16; + unsigned int inner = index & 0xFFFF; + return get_delta (outer, inner, coords, coord_count); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + format == 1 && + regions.sanitize (c, this) && + dataSets.sanitize (c, this)); + } + + protected: + USHORT format; + LOffsetTo regions; + OffsetArrayOf dataSets; + public: + DEFINE_SIZE_ARRAY (8, dataSets); +}; + +/* + * Feature Variations + */ + +struct ConditionFormat1 +{ + friend struct Condition; + + private: + inline bool evaluate (const int *coords, unsigned int coord_len) const + { + int coord = axisIndex < coord_len ? coords[axisIndex] : 0; + return filterRangeMinValue <= coord && coord <= filterRangeMaxValue; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + USHORT format; /* Format identifier--format = 1 */ + USHORT axisIndex; + F2DOT14 filterRangeMinValue; + F2DOT14 filterRangeMaxValue; + public: + DEFINE_SIZE_STATIC (8); +}; + +struct Condition +{ + inline bool evaluate (const int *coords, unsigned int coord_len) const + { + switch (u.format) { + case 1: return u.format1.evaluate (coords, coord_len); + default:return false; + } + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) { + case 1: return_trace (u.format1.sanitize (c)); + default:return_trace (true); + } + } + + protected: + union { + USHORT format; /* Format identifier */ + ConditionFormat1 format1; + } u; + public: + DEFINE_SIZE_UNION (2, format); +}; + +struct ConditionSet +{ + inline bool evaluate (const int *coords, unsigned int coord_len) const + { + unsigned int count = conditions.len; + for (unsigned int i = 0; i < count; i++) + if (!(this+conditions.array[i]).evaluate (coords, coord_len)) + return false; + return true; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (conditions.sanitize (c, this)); + } + + protected: + OffsetArrayOf conditions; + public: + DEFINE_SIZE_ARRAY (2, conditions); +}; + +struct FeatureTableSubstitutionRecord +{ + friend struct FeatureTableSubstitution; + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && feature.sanitize (c, base)); + } + + protected: + USHORT featureIndex; + LOffsetTo feature; + public: + DEFINE_SIZE_STATIC (6); +}; + +struct FeatureTableSubstitution +{ + inline const Feature *find_substitute (unsigned int feature_index) const + { + unsigned int count = substitutions.len; + for (unsigned int i = 0; i < count; i++) + { + const FeatureTableSubstitutionRecord &record = substitutions.array[i]; + if (record.featureIndex == feature_index) + return &(this+record.feature); + } + return NULL; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + substitutions.sanitize (c, this)); + } + + protected: + FixedVersion<> version; /* Version--0x00010000u */ + ArrayOf + substitutions; + public: + DEFINE_SIZE_ARRAY (6, substitutions); +}; + +struct FeatureVariationRecord +{ + friend struct FeatureVariations; + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (conditions.sanitize (c, base) && + substitutions.sanitize (c, base)); + } + + protected: + LOffsetTo + conditions; + LOffsetTo + substitutions; + public: + DEFINE_SIZE_STATIC (8); +}; + +struct FeatureVariations +{ + static const unsigned int NOT_FOUND_INDEX = 0xFFFFFFFFu; + + inline bool find_index (const int *coords, unsigned int coord_len, + unsigned int *index) const + { + unsigned int count = varRecords.len; + for (unsigned int i = 0; i < count; i++) + { + const FeatureVariationRecord &record = varRecords.array[i]; + if ((this+record.conditions).evaluate (coords, coord_len)) + { + *index = i; + return true; + } + } + *index = NOT_FOUND_INDEX; + return false; + } + + inline const Feature *find_substitute (unsigned int variations_index, + unsigned int feature_index) const + { + const FeatureVariationRecord &record = varRecords[variations_index]; + return (this+record.substitutions).find_substitute (feature_index); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + varRecords.sanitize (c, this)); + } + + protected: + FixedVersion<> version; /* Version--0x00010000u */ + LArrayOf + varRecords; + public: + DEFINE_SIZE_ARRAY (8, varRecords); +}; + + /* * Device Tables */ -struct Device +struct HintingDevice { + friend struct Device; + + private: inline hb_position_t get_x_delta (hb_font_t *font) const { return get_delta (font->x_ppem, font->x_scale); } @@ -1167,6 +1558,21 @@ struct Device inline hb_position_t get_y_delta (hb_font_t *font) const { return get_delta (font->y_ppem, font->y_scale); } + inline unsigned int get_size (void) const + { + unsigned int f = deltaFormat; + if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size; + return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f))); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && c->check_range (this, this->get_size ())); + } + + private: + inline int get_delta (unsigned int ppem, int scale) const { if (!ppem) return 0; @@ -1177,8 +1583,6 @@ struct Device return (int) (pixels * (int64_t) scale / ppem); } - - inline int get_delta_pixels (unsigned int ppem_size) const { unsigned int f = deltaFormat; @@ -1202,19 +1606,6 @@ struct Device return delta; } - inline unsigned int get_size (void) const - { - unsigned int f = deltaFormat; - if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size; - return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f))); - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && c->check_range (this, this->get_size ())); - } - protected: USHORT startSize; /* Smallest size to correct--in ppem */ USHORT endSize; /* Largest size to correct--in ppem */ @@ -1228,6 +1619,101 @@ struct Device DEFINE_SIZE_ARRAY (6, deltaValue); }; +struct VariationDevice +{ + friend struct Device; + + private: + + inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const + { return font->em_scalef_x (get_delta (font, store)); } + + inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const + { return font->em_scalef_y (get_delta (font, store)); } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + private: + + inline float get_delta (hb_font_t *font, const VariationStore &store) const + { + return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords); + } + + protected: + USHORT outerIndex; + USHORT innerIndex; + USHORT deltaFormat; /* Format identifier for this table: 0x0x8000 */ + public: + DEFINE_SIZE_STATIC (6); +}; + +struct DeviceHeader +{ + protected: + USHORT reserved1; + USHORT reserved2; + public: + USHORT format; /* Format identifier */ + public: + DEFINE_SIZE_STATIC (6); +}; + +struct Device +{ + inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const + { + switch (u.b.format) + { + case 1: case 2: case 3: + return u.hinting.get_x_delta (font); + case 0x8000: + return u.variation.get_x_delta (font, store); + default: + return 0; + } + } + inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const + { + switch (u.b.format) + { + case 1: case 2: case 3: + return u.hinting.get_y_delta (font); + case 0x8000: + return u.variation.get_y_delta (font, store); + default: + return 0; + } + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.b.format.sanitize (c)) return_trace (false); + switch (u.b.format) { + case 1: case 2: case 3: + return_trace (u.hinting.sanitize (c)); + case 0x8000: + return_trace (u.variation.sanitize (c)); + default: + return_trace (true); + } + } + + protected: + union { + DeviceHeader b; + HintingDevice hinting; + VariationDevice variation; + } u; + public: + DEFINE_SIZE_UNION (6, b); +}; + } /* namespace OT */ diff --git a/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh index bc36436be..552df0fd8 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh @@ -97,7 +97,7 @@ struct CaretValueFormat1 friend struct CaretValue; private: - inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const + inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const { return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate); } @@ -146,11 +146,11 @@ struct CaretValueFormat3 { friend struct CaretValue; - inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const + inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VariationStore &var_store) const { return HB_DIRECTION_IS_HORIZONTAL (direction) ? - font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) : - font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font); + font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) : + font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -172,12 +172,15 @@ struct CaretValueFormat3 struct CaretValue { - inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const + inline hb_position_t get_caret_value (hb_font_t *font, + hb_direction_t direction, + hb_codepoint_t glyph_id, + const VariationStore &var_store) const { switch (u.format) { - case 1: return u.format1.get_caret_value (font, direction, glyph_id); + case 1: return u.format1.get_caret_value (font, direction); case 2: return u.format2.get_caret_value (font, direction, glyph_id); - case 3: return u.format3.get_caret_value (font, direction, glyph_id); + case 3: return u.format3.get_caret_value (font, direction, var_store); default:return 0; } } @@ -210,6 +213,7 @@ struct LigGlyph inline unsigned int get_lig_carets (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, + const VariationStore &var_store, unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const @@ -218,7 +222,7 @@ struct LigGlyph const OffsetTo *array = carets.sub_array (start_offset, caret_count); unsigned int count = *caret_count; for (unsigned int i = 0; i < count; i++) - caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id); + caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store); } return carets.len; @@ -244,6 +248,7 @@ struct LigCaretList inline unsigned int get_lig_carets (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, + const VariationStore &var_store, unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const @@ -256,7 +261,7 @@ struct LigCaretList return 0; } const LigGlyph &lig_glyph = this+ligGlyph[index]; - return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); + return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -290,7 +295,7 @@ struct MarkGlyphSetsFormat1 protected: USHORT format; /* Format identifier--format = 1 */ - ArrayOf > + ArrayOf > coverage; /* Array of long offsets to mark set * coverage tables */ public: @@ -367,11 +372,17 @@ struct GDEF unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const - { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); } + { return (this+ligCaretList).get_lig_carets (font, + direction, glyph_id, get_var_store(), + start_offset, caret_count, caret_array); } - inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef[0] != 0; } + inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; } inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const - { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); } + { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); } + + inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; } + inline const VariationStore &get_var_store (void) const + { return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -382,10 +393,10 @@ struct GDEF attachList.sanitize (c, this) && ligCaretList.sanitize (c, this) && markAttachClassDef.sanitize (c, this) && - (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this))); + (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) && + (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); } - /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing * glyph class and other bits, and high 8-bit gthe mark attachment type (if any). * Not to be confused with lookup_props which is very similar. */ @@ -409,8 +420,8 @@ struct GDEF protected: - FixedVersion version; /* Version of the GDEF table--currently - * 0x00010002u */ + FixedVersion<>version; /* Version of the GDEF table--currently + * 0x00010003u */ OffsetTo glyphClassDef; /* Offset to class definition table * for glyph type--from beginning of @@ -428,12 +439,17 @@ struct GDEF * mark attachment type--from beginning * of GDEF header (may be Null) */ OffsetTo - markGlyphSetsDef[VAR]; /* Offset to the table of mark set + markGlyphSetsDef; /* Offset to the table of mark set * definitions--from beginning of GDEF * header (may be NULL). Introduced - * in version 00010002. */ + * in version 0x00010002. */ + LOffsetTo + varStore; /* Offset to the table of Item Variation + * Store--from beginning of GDEF + * header (may be NULL). Introduced + * in version 0x00010003. */ public: - DEFINE_SIZE_ARRAY (12, markGlyphSetsDef); + DEFINE_SIZE_MIN (12); }; diff --git a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh index 8bb91071d..738ca8c44 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh @@ -36,8 +36,17 @@ namespace OT { /* buffer **position** var allocations */ -#define attach_lookback() var.u16[0] /* number of glyphs to go back to attach this glyph to its base */ -#define cursive_chain() var.i16[1] /* character to which this connects, may be positive or negative */ +#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */ +#define attach_type() var.u8[2] /* attachment type */ +/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */ + +enum attach_type_t { + ATTACH_TYPE_NONE = 0X00, + + /* Each attachment should be either a mark or a cursive; can't be both. */ + ATTACH_TYPE_MARK = 0X01, + ATTACH_TYPE_CURSIVE = 0X02, +}; /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */ @@ -94,18 +103,17 @@ struct ValueFormat : USHORT inline unsigned int get_size (void) const { return get_len () * Value::static_size; } - void apply_value (hb_font_t *font, - hb_direction_t direction, + void apply_value (hb_apply_context_t *c, const void *base, const Value *values, hb_glyph_position_t &glyph_pos) const { - unsigned int x_ppem, y_ppem; unsigned int format = *this; - hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (direction); - if (!format) return; + hb_font_t *font = c->font; + hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction); + if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++)); if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++)); if (format & xAdvance) { @@ -120,27 +128,29 @@ struct ValueFormat : USHORT if (!has_device ()) return; - x_ppem = font->x_ppem; - y_ppem = font->y_ppem; + bool use_x_device = font->x_ppem || font->num_coords; + bool use_y_device = font->y_ppem || font->num_coords; - if (!x_ppem && !y_ppem) return; + if (!use_x_device && !use_y_device) return; + + const VariationStore &store = c->var_store; /* pixel -> fractional pixel */ if (format & xPlaDevice) { - if (x_ppem) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font); + if (use_x_device) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font, store); values++; } if (format & yPlaDevice) { - if (y_ppem) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font); + if (use_y_device) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font, store); values++; } if (format & xAdvDevice) { - if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font); + if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store); values++; } if (format & yAdvDevice) { /* y_advance values grow downward but font-space grows upward, hence negation */ - if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font); + if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store); values++; } } @@ -222,11 +232,12 @@ struct ValueFormat : USHORT struct AnchorFormat1 { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, hb_position_t *x, hb_position_t *y) const { - *x = font->em_scale_x (xCoordinate); - *y = font->em_scale_y (yCoordinate); + hb_font_t *font = c->font; + *x = font->em_scale_x (xCoordinate); + *y = font->em_scale_y (yCoordinate); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -245,18 +256,19 @@ struct AnchorFormat1 struct AnchorFormat2 { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id, hb_position_t *x, hb_position_t *y) const { - unsigned int x_ppem = font->x_ppem; - unsigned int y_ppem = font->y_ppem; - hb_position_t cx, cy; - hb_bool_t ret; + hb_font_t *font = c->font; + unsigned int x_ppem = font->x_ppem; + unsigned int y_ppem = font->y_ppem; + hb_position_t cx, cy; + hb_bool_t ret; - ret = (x_ppem || y_ppem) && - font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); - *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate); - *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate); + ret = (x_ppem || y_ppem) && + font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); + *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate); + *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -276,16 +288,17 @@ struct AnchorFormat2 struct AnchorFormat3 { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, hb_position_t *x, hb_position_t *y) const { - *x = font->em_scale_x (xCoordinate); - *y = font->em_scale_y (yCoordinate); + hb_font_t *font = c->font; + *x = font->em_scale_x (xCoordinate); + *y = font->em_scale_y (yCoordinate); - if (font->x_ppem) - *x += (this+xDeviceTable).get_x_delta (font); - if (font->y_ppem) - *y += (this+yDeviceTable).get_x_delta (font); + if (font->x_ppem || font->num_coords) + *x += (this+xDeviceTable).get_x_delta (font, c->var_store); + if (font->y_ppem || font->num_coords) + *y += (this+yDeviceTable).get_y_delta (font, c->var_store); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -312,14 +325,14 @@ struct AnchorFormat3 struct Anchor { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id, hb_position_t *x, hb_position_t *y) const { *x = *y = 0; switch (u.format) { - case 1: u.format1.get_anchor (font, glyph_id, x, y); return; - case 2: u.format2.get_anchor (font, glyph_id, x, y); return; - case 3: u.format3.get_anchor (font, glyph_id, x, y); return; + case 1: u.format1.get_anchor (c, glyph_id, x, y); return; + case 2: u.format2.get_anchor (c, glyph_id, x, y); return; + case 3: u.format3.get_anchor (c, glyph_id, x, y); return; default: return; } } @@ -361,7 +374,7 @@ struct AnchorMatrix { TRACE_SANITIZE (this); if (!c->check_struct (this)) return_trace (false); - if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return_trace (false); + if (unlikely (_hb_unsigned_int_mul_overflows (rows, cols))) return_trace (false); unsigned int count = rows * cols; if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false); for (unsigned int i = 0; i < count; i++) @@ -419,13 +432,15 @@ struct MarkArray : ArrayOf /* Array of MarkRecords--in Coverage orde hb_position_t mark_x, mark_y, base_x, base_y; - mark_anchor.get_anchor (c->font, buffer->cur().codepoint, &mark_x, &mark_y); - glyph_anchor.get_anchor (c->font, buffer->info[glyph_pos].codepoint, &base_x, &base_y); + buffer->unsafe_to_break (glyph_pos, buffer->idx); + mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y); + glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y); hb_glyph_position_t &o = buffer->cur_pos(); o.x_offset = base_x - mark_x; o.y_offset = base_y - mark_y; - o.attach_lookback() = buffer->idx - glyph_pos; + o.attach_type() = ATTACH_TYPE_MARK; + o.attach_chain() = (int) glyph_pos - (int) buffer->idx; buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; buffer->idx++; @@ -462,8 +477,7 @@ struct SinglePosFormat1 unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - valueFormat.apply_value (c->font, c->direction, this, - values, buffer->cur_pos()); + valueFormat.apply_value (c, this, values, buffer->cur_pos()); buffer->idx++; return_trace (true); @@ -513,7 +527,7 @@ struct SinglePosFormat2 if (likely (index >= valueCount)) return_trace (false); - valueFormat.apply_value (c->font, c->direction, this, + valueFormat.apply_value (c, this, &values[index * valueFormat.get_len ()], buffer->cur_pos()); @@ -630,10 +644,9 @@ struct PairSet min = mid + 1; else { - valueFormats[0].apply_value (c->font, c->direction, this, - &record->values[0], buffer->cur_pos()); - valueFormats[1].apply_value (c->font, c->direction, this, - &record->values[len1], buffer->pos[pos]); + buffer->unsafe_to_break (buffer->idx, pos + 1); + valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); + valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); if (len2) pos++; buffer->idx = pos; @@ -679,7 +692,7 @@ struct PairPosFormat1 (this+coverage).add_coverage (c->input); unsigned int count = pairSet.len; for (unsigned int i = 0; i < count; i++) - (this+pairSet[i]).collect_glyphs (c, &valueFormat1); + (this+pairSet[i]).collect_glyphs (c, valueFormat); } inline const Coverage &get_coverage (void) const @@ -698,7 +711,7 @@ struct PairPosFormat1 skippy_iter.reset (buffer->idx, 1); if (!skippy_iter.next ()) return_trace (false); - return_trace ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx)); + return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx)); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -707,11 +720,11 @@ struct PairPosFormat1 if (!c->check_struct (this)) return_trace (false); - unsigned int len1 = valueFormat1.get_len (); - unsigned int len2 = valueFormat2.get_len (); + unsigned int len1 = valueFormat[0].get_len (); + unsigned int len2 = valueFormat[1].get_len (); PairSet::sanitize_closure_t closure = { this, - &valueFormat1, + valueFormat, len1, 1 + len1 + len2 }; @@ -724,10 +737,10 @@ struct PairPosFormat1 OffsetTo coverage; /* Offset to Coverage table--from * beginning of subtable */ - ValueFormat valueFormat1; /* Defines the types of data in + ValueFormat valueFormat[2]; /* [0] Defines the types of data in * ValueRecord1--for the first glyph * in the pair--may be zero (0) */ - ValueFormat valueFormat2; /* Defines the types of data in + /* [1] Defines the types of data in * ValueRecord2--for the second glyph * in the pair--may be zero (0) */ OffsetArrayOf @@ -742,7 +755,7 @@ struct PairPosFormat2 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - /* (this+coverage).add_coverage (c->input); // Don't need this. */ + (this+coverage).add_coverage (c->input); unsigned int count1 = class1Count; const ClassDef &klass1 = this+classDef1; @@ -779,11 +792,10 @@ struct PairPosFormat2 unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false); + buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1); const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; - valueFormat1.apply_value (c->font, c->direction, this, - v, buffer->cur_pos()); - valueFormat2.apply_value (c->font, c->direction, this, - v + len1, buffer->pos[skippy_iter.idx]); + valueFormat1.apply_value (c, this, v, buffer->cur_pos()); + valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); buffer->idx = skippy_iter.idx; if (len2) @@ -907,9 +919,6 @@ struct CursivePosFormat1 TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; - /* We don't handle mark glyphs here. */ - if (unlikely (_hb_glyph_info_is_mark (&buffer->cur()))) return_trace (false); - const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)]; if (!this_record.exitAnchor) return_trace (false); @@ -923,9 +932,10 @@ struct CursivePosFormat1 unsigned int i = buffer->idx; unsigned int j = skippy_iter.idx; + buffer->unsafe_to_break (i, j); hb_position_t entry_x, entry_y, exit_x, exit_y; - (this+this_record.exitAnchor).get_anchor (c->font, buffer->info[i].codepoint, &exit_x, &exit_y); - (this+next_record.entryAnchor).get_anchor (c->font, buffer->info[j].codepoint, &entry_x, &entry_y); + (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y); + (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y); hb_glyph_position_t *pos = buffer->pos; @@ -993,8 +1003,9 @@ struct CursivePosFormat1 */ reverse_cursive_minor_offset (pos, child, c->direction, parent); - pos[child].cursive_chain() = parent - child; - buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_CURSIVE; + pos[child].attach_type() = ATTACH_TYPE_CURSIVE; + pos[child].attach_chain() = (int) parent - (int) child; + buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) pos[child].y_offset = y_offset; else @@ -1069,7 +1080,7 @@ struct MarkBasePosFormat1 unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); if (likely (mark_index == NOT_COVERED)) return_trace (false); - /* now we search backwards for a non-mark glyph */ + /* Now we search backwards for a non-mark glyph */ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, 1); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); @@ -1081,7 +1092,7 @@ struct MarkBasePosFormat1 } while (1); /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */ - if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { /*return_trace (false);*/ } + //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); } unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint); if (base_index == NOT_COVERED) return_trace (false); @@ -1170,14 +1181,14 @@ struct MarkLigPosFormat1 unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); if (likely (mark_index == NOT_COVERED)) return_trace (false); - /* now we search backwards for a non-mark glyph */ + /* Now we search backwards for a non-mark glyph */ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, 1); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); if (!skippy_iter.prev ()) return_trace (false); /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */ - if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { /*return_trace (false);*/ } + //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); } unsigned int j = skippy_iter.idx; unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint); @@ -1501,7 +1512,8 @@ struct GPOS : GSUBGPOS { return CastR (GSUBGPOS::get_lookup (i)); } static inline void position_start (hb_font_t *font, hb_buffer_t *buffer); - static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer); + static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer); + static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer); inline bool sanitize (hb_sanitize_context_t *c) const { @@ -1510,21 +1522,19 @@ struct GPOS : GSUBGPOS const OffsetTo &list = CastR > (lookupList); return_trace (list.sanitize (c, this)); } - public: - DEFINE_SIZE_STATIC (10); }; static void reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) { - unsigned int j = pos[i].cursive_chain(); - if (likely (!j)) + int chain = pos[i].attach_chain(), type = pos[i].attach_type(); + if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE))) return; - j += i; + pos[i].attach_chain() = 0; - pos[i].cursive_chain() = 0; + unsigned int j = (int) i + chain; /* Stop if we see new parent in the chain. */ if (j == new_parent) @@ -1537,62 +1547,68 @@ reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direc else pos[j].x_offset = -pos[i].x_offset; - pos[j].cursive_chain() = i - j; + pos[j].attach_chain() = -chain; + pos[j].attach_type() = type; } static void -fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) +propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) { - unsigned int j = pos[i].cursive_chain(); - if (likely (!j)) + /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate + * offset of glyph they are attached to. */ + int chain = pos[i].attach_chain(), type = pos[i].attach_type(); + if (likely (!chain)) return; - j += i; + unsigned int j = (int) i + chain; - pos[i].cursive_chain() = 0; + pos[i].attach_chain() = 0; - fix_cursive_minor_offset (pos, j, direction); + propagate_attachment_offsets (pos, j, direction); - if (HB_DIRECTION_IS_HORIZONTAL (direction)) - pos[i].y_offset += pos[j].y_offset; - else + assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE)); + + if (type & ATTACH_TYPE_CURSIVE) + { + if (HB_DIRECTION_IS_HORIZONTAL (direction)) + pos[i].y_offset += pos[j].y_offset; + else + pos[i].x_offset += pos[j].x_offset; + } + else /*if (type & ATTACH_TYPE_MARK)*/ + { pos[i].x_offset += pos[j].x_offset; -} + pos[i].y_offset += pos[j].y_offset; -static void -fix_mark_attachment (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) -{ - if (likely (!(pos[i].attach_lookback()))) - return; - - unsigned int j = i - pos[i].attach_lookback(); - - pos[i].x_offset += pos[j].x_offset; - pos[i].y_offset += pos[j].y_offset; - - if (HB_DIRECTION_IS_FORWARD (direction)) - for (unsigned int k = j; k < i; k++) { - pos[i].x_offset -= pos[k].x_advance; - pos[i].y_offset -= pos[k].y_advance; - } - else - for (unsigned int k = j + 1; k < i + 1; k++) { - pos[i].x_offset += pos[k].x_advance; - pos[i].y_offset += pos[k].y_advance; - } + assert (j < i); + if (HB_DIRECTION_IS_FORWARD (direction)) + for (unsigned int k = j; k < i; k++) { + pos[i].x_offset -= pos[k].x_advance; + pos[i].y_offset -= pos[k].y_advance; + } + else + for (unsigned int k = j + 1; k < i + 1; k++) { + pos[i].x_offset += pos[k].x_advance; + pos[i].y_offset += pos[k].y_advance; + } + } } void GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { - buffer->clear_positions (); - unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) - buffer->pos[i].attach_lookback() = buffer->pos[i].cursive_chain() = 0; + buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0; } void -GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) +GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) +{ + //_hb_buffer_assert_gsubgpos_vars (buffer); +} + +void +GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { _hb_buffer_assert_gsubgpos_vars (buffer); @@ -1600,15 +1616,10 @@ GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len); hb_direction_t direction = buffer->props.direction; - /* Handle cursive connections */ - if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_CURSIVE) - for (unsigned int i = 0; i < len; i++) - fix_cursive_minor_offset (pos, i, direction); - /* Handle attachments */ if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT) for (unsigned int i = 0; i < len; i++) - fix_mark_attachment (pos, i, direction); + propagate_attachment_offsets (pos, i, direction); } @@ -1637,8 +1648,8 @@ template } -#undef attach_lookback -#undef cursive_chain +#undef attach_chain +#undef attach_type } /* namespace OT */ diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh index 459a1a3dd..85be7e7ea 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh @@ -41,7 +41,10 @@ struct SingleSubstFormat1 { TRACE_CLOSURE (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + /* TODO Switch to range-based API to work around malicious fonts. + * https://github.com/behdad/harfbuzz/issues/363 */ hb_codepoint_t glyph_id = iter.get_glyph (); if (c->glyphs->has (glyph_id)) c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu); @@ -52,7 +55,10 @@ struct SingleSubstFormat1 { TRACE_COLLECT_GLYPHS (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + /* TODO Switch to range-based API to work around malicious fonts. + * https://github.com/behdad/harfbuzz/issues/363 */ hb_codepoint_t glyph_id = iter.get_glyph (); c->input->add (glyph_id); c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu); @@ -120,7 +126,11 @@ struct SingleSubstFormat2 { TRACE_CLOSURE (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = substitute.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) c->glyphs->add (substitute[iter.get_coverage ()]); } @@ -130,7 +140,11 @@ struct SingleSubstFormat2 { TRACE_COLLECT_GLYPHS (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = substitute.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ c->input->add (iter.get_glyph ()); c->output->add (substitute[iter.get_coverage ()]); } @@ -265,16 +279,6 @@ struct Sequence TRACE_APPLY (this); unsigned int count = substitute.len; - /* TODO: - * Testing shows that Uniscribe actually allows zero-len susbstitute, - * which essentially deletes a glyph. We don't allow for now. It - * can be confusing to the client since the cluster from the deleted - * glyph won't be merged with any output cluster... Also, currently - * buffer->move_to() makes assumptions about this too. Perhaps fix - * in the future after figuring out what to do with the clusters. - */ - if (unlikely (!count)) return_trace (false); - /* Special-case to make it in-place and not consider this * as a "multiplied" substitution. */ if (unlikely (count == 1)) @@ -282,6 +286,13 @@ struct Sequence c->replace_glyph (substitute.array[0]); return_trace (true); } + /* Spec disallows this, but Uniscribe allows it. + * https://github.com/behdad/harfbuzz/issues/253 */ + else if (unlikely (count == 0)) + { + c->buffer->delete_glyph (); + return_trace (true); + } unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ? HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; @@ -324,7 +335,11 @@ struct MultipleSubstFormat1 { TRACE_CLOSURE (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = sequence.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) (this+sequence[iter.get_coverage ()]).closure (c); } @@ -442,7 +457,11 @@ struct AlternateSubstFormat1 { TRACE_CLOSURE (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = alternateSet.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) { const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; unsigned int count = alt_set.len; @@ -456,7 +475,11 @@ struct AlternateSubstFormat1 { TRACE_COLLECT_GLYPHS (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = alternateSet.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ c->input->add (iter.get_glyph ()); const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; unsigned int count = alt_set.len; @@ -765,7 +788,11 @@ struct LigatureSubstFormat1 { TRACE_CLOSURE (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = ligatureSet.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) (this+ligatureSet[iter.get_coverage ()]).closure (c); } @@ -775,7 +802,11 @@ struct LigatureSubstFormat1 { TRACE_COLLECT_GLYPHS (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = ligatureSet.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ c->input->add (iter.get_glyph ()); (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c); } @@ -926,7 +957,11 @@ struct ReverseChainSingleSubstFormat1 const ArrayOf &substitute = StructAfter > (lookahead); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + count = substitute.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) c->glyphs->add (substitute[iter.get_coverage ()]); } @@ -979,14 +1014,17 @@ struct ReverseChainSingleSubstFormat1 const OffsetArrayOf &lookahead = StructAfter > (backtrack); const ArrayOf &substitute = StructAfter > (lookahead); + unsigned int start_index = 0, end_index = 0; if (match_backtrack (c, backtrack.len, (USHORT *) backtrack.array, - match_coverage, this) && + match_coverage, this, + &start_index) && match_lookahead (c, lookahead.len, (USHORT *) lookahead.array, match_coverage, this, - 1)) + 1, &end_index)) { + c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index); c->replace_glyph_inplace (substitute[index]); /* Note: We DON'T decrease buffer->idx. The main loop does it * for us. This is useful for preventing surprises if someone @@ -1268,7 +1306,6 @@ struct GSUB : GSUBGPOS { return CastR (GSUBGPOS::get_lookup (i)); } static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer); - static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer); inline bool sanitize (hb_sanitize_context_t *c) const { @@ -1277,8 +1314,6 @@ struct GSUB : GSUBGPOS const OffsetTo &list = CastR > (lookupList); return_trace (list.sanitize (c, this)); } - public: - DEFINE_SIZE_STATIC (10); }; @@ -1297,11 +1332,6 @@ GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer) } } -void -GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED) -{ -} - /* Out-of-class implementation for methods recursing */ diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh index 36f6dd405..472628a39 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh @@ -319,7 +319,7 @@ struct hb_apply_context_t : if (!c->check_glyph_property (&info, lookup_props)) return SKIP_YES; - if (unlikely (_hb_glyph_info_is_default_ignorable (&info) && + if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) && (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && (ignore_zwj || !_hb_glyph_info_is_zwj (&info)))) return SKIP_MAYBE; @@ -342,13 +342,13 @@ struct hb_apply_context_t : inline void init (hb_apply_context_t *c_, bool context_match = false) { c = c_; - match_glyph_data = NULL, + match_glyph_data = NULL; matcher.set_match_func (NULL, NULL); matcher.set_lookup_props (c->lookup_props); /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ - matcher.set_ignore_zwnj (context_match || c->table_index == 1); + matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj)); /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */ - matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj); + matcher.set_ignore_zwj (c->table_index == 1 || (context_match || c->auto_zwj)); matcher.set_mask (context_match ? -1 : c->lookup_mask); } inline void set_lookup_props (unsigned int lookup_props) @@ -457,43 +457,50 @@ struct hb_apply_context_t : return ret; } - unsigned int table_index; /* GSUB/GPOS */ + skipping_iterator_t iter_input, iter_context; + hb_font_t *font; hb_face_t *face; hb_buffer_t *buffer; + recurse_func_t recurse_func; + const GDEF &gdef; + const VariationStore &var_store; + hb_direction_t direction; hb_mask_t lookup_mask; - bool auto_zwj; - recurse_func_t recurse_func; - unsigned int nesting_level_left; - unsigned int lookup_props; - const GDEF &gdef; - bool has_glyph_classes; - skipping_iterator_t iter_input, iter_context; + unsigned int table_index; /* GSUB/GPOS */ unsigned int lookup_index; + unsigned int lookup_props; + unsigned int nesting_level_left; unsigned int debug_depth; + bool auto_zwnj; + bool auto_zwj; + bool has_glyph_classes; + hb_apply_context_t (unsigned int table_index_, hb_font_t *font_, hb_buffer_t *buffer_) : - table_index (table_index_), + iter_input (), iter_context (), font (font_), face (font->face), buffer (buffer_), + recurse_func (NULL), + gdef (*hb_ot_layout_from_face (face)->gdef), + var_store (gdef.get_var_store ()), direction (buffer_->props.direction), lookup_mask (1), - auto_zwj (true), - recurse_func (NULL), - nesting_level_left (HB_MAX_NESTING_LEVEL), - lookup_props (0), - gdef (*hb_ot_layout_from_face (face)->gdef), - has_glyph_classes (gdef.has_glyph_classes ()), - iter_input (), - iter_context (), + table_index (table_index_), lookup_index ((unsigned int) -1), - debug_depth (0) {} + lookup_props (0), + nesting_level_left (HB_MAX_NESTING_LEVEL), + debug_depth (0), + auto_zwnj (true), + auto_zwj (true), + has_glyph_classes (gdef.has_glyph_classes ()) {} inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } + inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; } inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; } inline void set_lookup_props (unsigned int lookup_props_) @@ -845,9 +852,12 @@ static inline bool ligate_input (hb_apply_context_t *c, while (buffer->idx < match_positions[i] && !buffer->in_error) { if (!is_mark_ligature) { + unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); + if (this_comp == 0) + this_comp = last_num_components; unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->cur()), 1u), last_num_components); - _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); + MIN (this_comp, last_num_components); + _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); } buffer->next_glyph (); } @@ -864,8 +874,11 @@ static inline bool ligate_input (hb_apply_context_t *c, /* Re-adjust components for any marks following. */ for (unsigned int i = buffer->idx; i < buffer->len; i++) { if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) { + unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]); + if (!this_comp) + break; unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->info[i]), 1u), last_num_components); + MIN (this_comp, last_num_components); _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp); } else break; @@ -878,7 +891,8 @@ static inline bool match_backtrack (hb_apply_context_t *c, unsigned int count, const USHORT backtrack[], match_func_t match_func, - const void *match_data) + const void *match_data, + unsigned int *match_start) { TRACE_APPLY (NULL); @@ -890,6 +904,8 @@ static inline bool match_backtrack (hb_apply_context_t *c, if (!skippy_iter.prev ()) return_trace (false); + *match_start = skippy_iter.idx; + return_trace (true); } @@ -898,7 +914,8 @@ static inline bool match_lookahead (hb_apply_context_t *c, const USHORT lookahead[], match_func_t match_func, const void *match_data, - unsigned int offset) + unsigned int offset, + unsigned int *end_index) { TRACE_APPLY (NULL); @@ -910,6 +927,8 @@ static inline bool match_lookahead (hb_apply_context_t *c, if (!skippy_iter.next ()) return_trace (false); + *end_index = skippy_iter.idx + 1; + return_trace (true); } @@ -951,7 +970,7 @@ static inline bool apply_lookup (hb_apply_context_t *c, TRACE_APPLY (NULL); hb_buffer_t *buffer = c->buffer; - unsigned int end; + int end; /* All positions are distance from beginning of *output* buffer. * Adjust. */ @@ -965,12 +984,17 @@ static inline bool apply_lookup (hb_apply_context_t *c, match_positions[j] += delta; } - for (unsigned int i = 0; i < lookupCount; i++) + for (unsigned int i = 0; i < lookupCount && !buffer->in_error; i++) { unsigned int idx = lookupRecord[i].sequenceIndex; if (idx >= count) continue; + /* Don't recurse to ourself at same position. + * Note that this test is too naive, it doesn't catch longer loops. */ + if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index) + continue; + buffer->move_to (match_positions[idx]); unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len (); @@ -983,12 +1007,41 @@ static inline bool apply_lookup (hb_apply_context_t *c, if (!delta) continue; - /* Recursed lookup changed buffer len. Adjust. */ + /* Recursed lookup changed buffer len. Adjust. + * + * TODO: + * + * Right now, if buffer length increased by n, we assume n new glyphs + * were added right after the current position, and if buffer length + * was decreased by n, we assume n match positions after the current + * one where removed. The former (buffer length increased) case is + * fine, but the decrease case can be improved in at least two ways, + * both of which are significant: + * + * - If recursed-to lookup is MultipleSubst and buffer length + * decreased, then it's current match position that was deleted, + * NOT the one after it. + * + * - If buffer length was decreased by n, it does not necessarily + * mean that n match positions where removed, as there might + * have been marks and default-ignorables in the sequence. We + * should instead drop match positions between current-position + * and current-position + n instead. + * + * It should be possible to construct tests for both of these cases. + */ - /* end can't go back past the current match position. - * Note: this is only true because we do NOT allow MultipleSubst - * with zero sequence len. */ - end = MAX (MIN((int) match_positions[idx] + 1, (int) new_len), int (end) + delta); + end += delta; + if (end <= int (match_positions[idx])) + { + /* End might end up being smaller than match_positions[idx] if the recursed + * lookup ended up removing many items, more than we have had matched. + * Just never rewind end back and get out of here. + * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */ + end = match_positions[idx]; + /* There can't be any further changes. */ + break; + } unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */ @@ -1098,10 +1151,11 @@ static inline bool context_apply_lookup (hb_apply_context_t *c, inputCount, input, lookup_context.funcs.match, lookup_context.match_data, &match_length, match_positions) - && apply_lookup (c, + && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length), + apply_lookup (c, inputCount, match_positions, lookupCount, lookupRecord, - match_length); + match_length)); } struct Rule @@ -1619,7 +1673,7 @@ static inline bool chain_context_apply_lookup (hb_apply_context_t *c, const LookupRecord lookupRecord[], ChainContextApplyLookupContext &lookup_context) { - unsigned int match_length = 0; + unsigned int start_index = 0, match_length = 0, end_index = 0; unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; return match_input (c, inputCount, input, @@ -1627,15 +1681,17 @@ static inline bool chain_context_apply_lookup (hb_apply_context_t *c, &match_length, match_positions) && match_backtrack (c, backtrackCount, backtrack, - lookup_context.funcs.match, lookup_context.match_data[0]) + lookup_context.funcs.match, lookup_context.match_data[0], + &start_index) && match_lookahead (c, lookaheadCount, lookahead, lookup_context.funcs.match, lookup_context.match_data[2], - match_length) - && apply_lookup (c, + match_length, &end_index) + && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index), + apply_lookup (c, inputCount, match_positions, lookupCount, lookupRecord, - match_length); + match_length)); } struct ChainRule @@ -2255,6 +2311,24 @@ struct GSUBGPOS inline const Lookup& get_lookup (unsigned int i) const { return (this+lookupList)[i]; } + inline bool find_variations_index (const int *coords, unsigned int num_coords, + unsigned int *index) const + { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations)) + .find_index (coords, num_coords, index); } + inline const Feature& get_feature_variation (unsigned int feature_index, + unsigned int variations_index) const + { + if (FeatureVariations::NOT_FOUND_INDEX != variations_index && + version.to_int () >= 0x00010001u) + { + const Feature *feature = (this+featureVars).find_substitute (variations_index, + feature_index); + if (feature) + return *feature; + } + return get_feature (feature_index); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -2262,11 +2336,12 @@ struct GSUBGPOS likely (version.major == 1) && scriptList.sanitize (c, this) && featureList.sanitize (c, this) && - lookupList.sanitize (c, this)); + lookupList.sanitize (c, this) && + (version.to_int () < 0x00010001u || featureVars.sanitize (c, this))); } protected: - FixedVersion version; /* Version of the GSUB/GPOS table--initially set + FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set * to 0x00010000u */ OffsetTo scriptList; /* ScriptList table */ @@ -2274,8 +2349,13 @@ struct GSUBGPOS featureList; /* FeatureList table */ OffsetTo lookupList; /* LookupList table */ + LOffsetTo + featureVars; /* Offset to Feature Variations + table--from beginning of table + * (may be NULL). Introduced + * in version 0x00010001. */ public: - DEFINE_SIZE_STATIC (10); + DEFINE_SIZE_MIN (10); }; diff --git a/gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh b/gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh index 7e199c2e1..c3068491b 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-jstf-table.hh @@ -218,7 +218,7 @@ struct JSTF } protected: - FixedVersion version; /* Version of the JSTF table--initially set + FixedVersion<>version; /* Version of the JSTF table--initially set * to 0x00010000u */ RecordArrayOf scriptList; /* Array of JstfScripts--listed diff --git a/gfx/harfbuzz/src/hb-ot-layout-private.hh b/gfx/harfbuzz/src/hb-ot-layout-private.hh index 45897ed5a..d4ac60b06 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-private.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-private.hh @@ -34,6 +34,7 @@ #include "hb-font-private.hh" #include "hb-buffer-private.hh" #include "hb-set-private.hh" +#include "hb-open-type-private.hh" /* Private API corresponding to hb-ot-layout.h: */ @@ -99,21 +100,20 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, const hb_ot_layout_lookup_accelerator_t &accel); -/* Should be called after all the substitute_lookup's are done */ -HB_INTERNAL void -hb_ot_layout_substitute_finish (hb_font_t *font, - hb_buffer_t *buffer); - - -/* Should be called before all the position_lookup's are done. Resets positions to zero. */ +/* Should be called before all the position_lookup's are done. */ HB_INTERNAL void hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer); -/* Should be called after all the position_lookup's are done */ +/* Should be called after all the position_lookup's are done, to finish advances. */ HB_INTERNAL void -hb_ot_layout_position_finish (hb_font_t *font, - hb_buffer_t *buffer); +hb_ot_layout_position_finish_advances (hb_font_t *font, + hb_buffer_t *buffer); + +/* Should be called after hb_ot_layout_position_finish_advances, to finish offsets. */ +HB_INTERNAL void +hb_ot_layout_position_finish_offsets (hb_font_t *font, + hb_buffer_t *buffer); @@ -125,6 +125,9 @@ namespace OT { struct GDEF; struct GSUB; struct GPOS; + struct MATH; + struct fvar; + struct avar; } struct hb_ot_layout_lookup_accelerator_t @@ -158,6 +161,11 @@ struct hb_ot_layout_t const struct OT::GSUB *gsub; const struct OT::GPOS *gpos; + /* TODO Move the following out of this struct. */ + OT::hb_lazy_table_loader_t math; + OT::hb_lazy_table_loader_t fvar; + OT::hb_lazy_table_loader_t avar; + unsigned int gsub_lookup_count; unsigned int gpos_lookup_count; @@ -189,8 +197,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout); #define syllable() var1.u8[3] /* GSUB/GPOS shaping boundaries */ -/* loop over syllables */ - +/* Loop over syllables. Based on foreach_cluster(). */ #define foreach_syllable(buffer, start, end) \ for (unsigned int \ _count = buffer->len, \ @@ -219,23 +226,25 @@ _next_syllable (hb_buffer_t *buffer, unsigned int start) * - General_Category: 5 bits. * - A bit each for: * * Is it Default_Ignorable(); we have a modified Default_Ignorable(). - * * Is it U+200D ZWJ? - * * Is it U+200C ZWNJ? + * * Whether it's one of the three Mongolian Free Variation Selectors. + * * One free bit right now. * * The high-byte has different meanings, switched by the Gen-Cat: * - For Mn,Mc,Me: the modified Combining_Class. + * - For Cf: whether it's ZWJ, ZWNJ, or something else. * - For Ws: index of which space character this is, if space fallback * is needed, ie. we don't set this by default, only if asked to. - * - * If needed, we can use the ZWJ/ZWNJ to use the high byte as well, - * freeing two more bits. */ enum hb_unicode_props_flags_t { - UPROPS_MASK_ZWJ = 0x20u, - UPROPS_MASK_ZWNJ = 0x40u, - UPROPS_MASK_IGNORABLE = 0x80u, - UPROPS_MASK_GEN_CAT = 0x1Fu + UPROPS_MASK_GEN_CAT = 0x001Fu, + UPROPS_MASK_IGNORABLE = 0x0020u, + UPROPS_MASK_HIDDEN = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3, + * or TAG characters */ + + /* If GEN_CAT=FORMAT, top byte masks: */ + UPROPS_MASK_Cf_ZWJ = 0x0100u, + UPROPS_MASK_Cf_ZWNJ = 0x0200u }; HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t); @@ -254,11 +263,27 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer) { buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES; props |= UPROPS_MASK_IGNORABLE; - if (u == 0x200Cu) props |= UPROPS_MASK_ZWNJ; - if (u == 0x200Du) props |= UPROPS_MASK_ZWJ; + if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ; + if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ; + /* Mongolian Free Variation Selectors need to be remembered + * because although we need to hide them like default-ignorables, + * they need to non-ignorable during shaping. This is similar to + * what we do for joiners in Indic-like shapers, but since the + * FVSes are GC=Mn, we have use a separate bit to remember them. + * Fixes: + * https://github.com/behdad/harfbuzz/issues/234 + */ + if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN; + /* TAG characters need similar treatment. Fixes: + * https://github.com/behdad/harfbuzz/issues/463 + */ + if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN; } - else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK (gen_cat))) + else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat))) { + /* The above check is just an optimization to let in only things we need further + * processing on. */ + /* Only Mn and Mc can have non-zero ccc: * http://www.unicode.org/policies/stability_policy.html#Property_Value * """ @@ -273,6 +298,16 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer) * the "else if". */ props |= unicode->modified_combining_class (info->codepoint)<<8; + + /* Recategorize emoji skin-tone modifiers as Unicode mark, so they + * behave correctly in non-native directionality. They originally + * are MODIFIER_SYMBOL. Fixes: + * https://github.com/behdad/harfbuzz/issues/169 + */ + if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu))) + { + props = gen_cat = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK; + } } } @@ -338,25 +373,44 @@ static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info); static inline hb_bool_t _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info) { - return (info->unicode_props() & UPROPS_MASK_IGNORABLE) && !_hb_glyph_info_ligated (info); + return (info->unicode_props() & UPROPS_MASK_IGNORABLE) && + !_hb_glyph_info_ligated (info); +} +static inline hb_bool_t +_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info) +{ + return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN)) + == UPROPS_MASK_IGNORABLE) && + !_hb_glyph_info_ligated (info); } +static inline bool +_hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info) +{ + return _hb_glyph_info_get_general_category (info) == + HB_UNICODE_GENERAL_CATEGORY_FORMAT; +} static inline hb_bool_t _hb_glyph_info_is_zwnj (const hb_glyph_info_t *info) { - return !!(info->unicode_props() & UPROPS_MASK_ZWNJ); + return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ); } - static inline hb_bool_t _hb_glyph_info_is_zwj (const hb_glyph_info_t *info) { - return !!(info->unicode_props() & UPROPS_MASK_ZWJ); + return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ); +} +static inline hb_bool_t +_hb_glyph_info_is_joiner (const hb_glyph_info_t *info) +{ + return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ)); } - static inline void _hb_glyph_info_flip_joiners (hb_glyph_info_t *info) { - info->unicode_props() ^= UPROPS_MASK_ZWNJ | UPROPS_MASK_ZWJ; + if (!_hb_glyph_info_is_unicode_format (info)) + return; + info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ; } /* lig_props: aka lig_id / lig_comp @@ -517,11 +571,9 @@ _hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info) } static inline void -_hb_glyph_info_clear_substituted_and_ligated_and_multiplied (hb_glyph_info_t *info) +_hb_glyph_info_clear_substituted (hb_glyph_info_t *info) { - info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED | - HB_OT_LAYOUT_GLYPH_PROPS_LIGATED | - HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED); + info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED); } @@ -575,5 +627,4 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer) #undef lig_props #undef glyph_props - #endif /* HB_OT_LAYOUT_PRIVATE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-layout.cc b/gfx/harfbuzz/src/hb-ot-layout.cc index 66aa35ad7..977e58301 100644 --- a/gfx/harfbuzz/src/hb-ot-layout.cc +++ b/gfx/harfbuzz/src/hb-ot-layout.cc @@ -34,15 +34,10 @@ #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" -#include "hb-ot-layout-jstf-table.hh" +#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise. #include "hb-ot-map-private.hh" -#include -#include - - -HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) hb_ot_layout_t * _hb_ot_layout_create (hb_face_t *face) @@ -60,6 +55,117 @@ _hb_ot_layout_create (hb_face_t *face) layout->gpos_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GPOS)); layout->gpos = OT::Sanitizer::lock_instance (layout->gpos_blob); + layout->math.init (face); + layout->fvar.init (face); + layout->avar.init (face); + + { + /* + * The ugly business of blacklisting individual fonts' tables happen here! + * See this thread for why we finally had to bend in and do this: + * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html + */ + unsigned int gdef_len = hb_blob_get_length (layout->gdef_blob); + unsigned int gsub_len = hb_blob_get_length (layout->gsub_blob); + unsigned int gpos_len = hb_blob_get_length (layout->gpos_blob); + if (0 + /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */ + || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len) + /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */ + || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len) + /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */ + || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len) + /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */ + || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len) + /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */ + || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len) + /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */ + || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len) + ) + { + /* In certain versions of Times New Roman Italic and Bold Italic, + * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong + * glyph class 3 (mark) in GDEF. Nuke the GDEF to avoid zero-width + * double-quote. See: + * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html + */ + if (3 == layout->gdef->get_glyph_class (5)) + layout->gdef = &OT::Null(OT::GDEF); + } + else if (0 + /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */ + || (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len) + /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */ + || (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len) + /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */ + || (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len) + /* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */ + || (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len) + /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + || (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len) + /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + || (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len) + /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */ + || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len) + /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */ + || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len) + /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + || (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len) + /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + || (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len) + /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */ + || (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len) + /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */ + || (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len) + /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */ + || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len) + /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */ + || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len) + /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */ + || (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len) + /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */ + || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len) + /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */ + || (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len) + /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */ + /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */ + || (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len) + /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */ + /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */ + || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len) + /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */ + || (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len) + /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/ + || (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len) + /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */ + || (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len) + /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */ + || (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len) + /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */ + || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len) + /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */ + || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len) + /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */ + || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len) + /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */ + || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len) + /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf + * "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */ + || (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len) + ) + { + /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks + * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya, + * and the version of Cantarell shipped by Ubuntu 16.04. + * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing. + * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 + * https://bugzilla.mozilla.org/show_bug.cgi?id=1279693 + * https://bugzilla.mozilla.org/show_bug.cgi?id=1279875 + */ + layout->gdef = &OT::Null(OT::GDEF); + } + } + layout->gsub_lookup_count = layout->gsub->get_lookup_count (); layout->gpos_lookup_count = layout->gpos->get_lookup_count (); @@ -96,6 +202,10 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) hb_blob_destroy (layout->gsub_blob); hb_blob_destroy (layout->gpos_blob); + layout->math.fini (); + layout->fvar.fini (); + layout->avar.fini (); + free (layout); } @@ -118,7 +228,6 @@ _get_gpos (hb_face_t *face) return *hb_ot_layout_from_face (face)->gpos; } - /* * GDEF */ @@ -130,6 +239,8 @@ hb_ot_layout_has_glyph_classes (hb_face_t *face) } /** + * hb_ot_layout_get_glyph_class: + * * Since: 0.9.7 **/ hb_ot_layout_glyph_class_t @@ -140,6 +251,8 @@ hb_ot_layout_get_glyph_class (hb_face_t *face, } /** + * hb_ot_layout_get_glyphs_in_class: + * * Since: 0.9.7 **/ void @@ -166,7 +279,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, hb_codepoint_t glyph, unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, - int *caret_array /* OUT */) + hb_position_t *caret_array /* OUT */) { return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array); } @@ -365,6 +478,8 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face, } /** + * hb_ot_layout_language_get_required_feature: + * * Since: 0.9.30 **/ hb_bool_t @@ -452,6 +567,8 @@ hb_ot_layout_language_find_feature (hb_face_t *face, } /** + * hb_ot_layout_feature_get_lookups: + * * Since: 0.9.7 **/ unsigned int @@ -462,13 +579,18 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face, unsigned int *lookup_count /* IN/OUT */, unsigned int *lookup_indexes /* OUT */) { - const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - const OT::Feature &f = g.get_feature (feature_index); - - return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); + return hb_ot_layout_feature_with_variations_get_lookups (face, + table_tag, + feature_index, + HB_OT_LAYOUT_NO_VARIATIONS_INDEX, + start_offset, + lookup_count, + lookup_indexes); } /** + * hb_ot_layout_table_get_lookup_count: + * * Since: 0.9.22 **/ unsigned int @@ -629,6 +751,8 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t *face, } /** + * hb_ot_layout_collect_lookups: + * * Since: 0.9.8 **/ void @@ -673,6 +797,8 @@ hb_ot_layout_collect_lookups (hb_face_t *face, } /** + * hb_ot_layout_lookup_collect_glyphs: + * * Since: 0.9.7 **/ void @@ -710,6 +836,38 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, } +/* Variations support */ + +hb_bool_t +hb_ot_layout_table_find_feature_variations (hb_face_t *face, + hb_tag_t table_tag, + const int *coords, + unsigned int num_coords, + unsigned int *variations_index /* out */) +{ + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + return g.find_variations_index (coords, num_coords, variations_index); +} + +unsigned int +hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + unsigned int variations_index, + unsigned int start_offset, + unsigned int *lookup_count /* IN/OUT */, + unsigned int *lookup_indexes /* OUT */) +{ + ASSERT_STATIC (OT::FeatureVariations::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_VARIATIONS_INDEX); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + const OT::Feature &f = g.get_feature_variation (feature_index, variations_index); + + return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); +} + + /* * OT::GSUB */ @@ -721,6 +879,8 @@ hb_ot_layout_has_substitution (hb_face_t *face) } /** + * hb_ot_layout_lookup_would_substitute: + * * Since: 0.9.7 **/ hb_bool_t @@ -742,7 +902,7 @@ hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face, hb_bool_t zero_context) { if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false; - OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context); + OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context); const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); @@ -755,13 +915,9 @@ hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer) OT::GSUB::substitute_start (font, buffer); } -void -hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer) -{ - OT::GSUB::substitute_finish (font, buffer); -} - /** + * hb_ot_layout_lookup_substitute_closure: + * * Since: 0.9.7 **/ void @@ -793,12 +949,20 @@ hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer) } void -hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer) +hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer) { - OT::GPOS::position_finish (font, buffer); + OT::GPOS::position_finish_advances (font, buffer); +} + +void +hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) +{ + OT::GPOS::position_finish_offsets (font, buffer); } /** + * hb_ot_layout_get_size_params: + * * Since: 0.9.10 **/ hb_bool_t @@ -882,20 +1046,79 @@ struct GPOSProxy }; -template +struct hb_get_subtables_context_t : + OT::hb_dispatch_context_t +{ + template + static inline bool apply_to (const void *obj, OT::hb_apply_context_t *c) + { + const Type *typed_obj = (const Type *) obj; + return typed_obj->apply (c); + } + + typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_apply_context_t *c); + + struct hb_applicable_t + { + inline void init (const void *obj_, hb_apply_func_t apply_func_) + { + obj = obj_; + apply_func = apply_func_; + } + + inline bool apply (OT::hb_apply_context_t *c) const { return apply_func (obj, c); } + + private: + const void *obj; + hb_apply_func_t apply_func; + }; + + typedef hb_auto_array_t array_t; + + /* Dispatch interface. */ + inline const char *get_name (void) { return "GET_SUBTABLES"; } + template + inline return_t dispatch (const T &obj) + { + hb_applicable_t *entry = array.push(); + if (likely (entry)) + entry->init (&obj, apply_to); + return HB_VOID; + } + static return_t default_return_value (void) { return HB_VOID; } + bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; } + + hb_get_subtables_context_t (array_t &array_) : + array (array_), + debug_depth (0) {} + + array_t &array; + unsigned int debug_depth; +}; + static inline bool apply_forward (OT::hb_apply_context_t *c, - const Obj &obj, - const hb_ot_layout_lookup_accelerator_t &accel) + const hb_ot_layout_lookup_accelerator_t &accel, + const hb_get_subtables_context_t::array_t &subtables) { bool ret = false; hb_buffer_t *buffer = c->buffer; while (buffer->idx < buffer->len && !buffer->in_error) { + bool applied = false; if (accel.may_have (buffer->cur().codepoint) && (buffer->cur().mask & c->lookup_mask) && - c->check_glyph_property (&buffer->cur(), c->lookup_props) && - obj.apply (c)) + c->check_glyph_property (&buffer->cur(), c->lookup_props)) + { + for (unsigned int i = 0; i < subtables.len; i++) + if (subtables[i].apply (c)) + { + applied = true; + break; + } + } + + if (applied) ret = true; else buffer->next_glyph (); @@ -903,11 +1126,10 @@ apply_forward (OT::hb_apply_context_t *c, return ret; } -template static inline bool apply_backward (OT::hb_apply_context_t *c, - const Obj &obj, - const hb_ot_layout_lookup_accelerator_t &accel) + const hb_ot_layout_lookup_accelerator_t &accel, + const hb_get_subtables_context_t::array_t &subtables) { bool ret = false; hb_buffer_t *buffer = c->buffer; @@ -915,9 +1137,15 @@ apply_backward (OT::hb_apply_context_t *c, { if (accel.may_have (buffer->cur().codepoint) && (buffer->cur().mask & c->lookup_mask) && - c->check_glyph_property (&buffer->cur(), c->lookup_props) && - obj.apply (c)) - ret = true; + c->check_glyph_property (&buffer->cur(), c->lookup_props)) + { + for (unsigned int i = 0; i < subtables.len; i++) + if (subtables[i].apply (c)) + { + ret = true; + break; + } + } /* The reverse lookup doesn't "advance" cursor (for good reason). */ buffer->idx--; @@ -926,26 +1154,6 @@ apply_backward (OT::hb_apply_context_t *c, return ret; } -struct hb_apply_forward_context_t : - OT::hb_dispatch_context_t -{ - inline const char *get_name (void) { return "APPLY_FWD"; } - template - inline return_t dispatch (const T &obj) { return apply_forward (c, obj, accel); } - static return_t default_return_value (void) { return false; } - bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return true; } - - hb_apply_forward_context_t (OT::hb_apply_context_t *c_, - const hb_ot_layout_lookup_accelerator_t &accel_) : - c (c_), - accel (accel_), - debug_depth (0) {} - - OT::hb_apply_context_t *c; - const hb_ot_layout_lookup_accelerator_t &accel; - unsigned int debug_depth; -}; - template static inline void apply_string (OT::hb_apply_context_t *c, @@ -959,6 +1167,10 @@ apply_string (OT::hb_apply_context_t *c, c->set_lookup_props (lookup.get_props ()); + hb_get_subtables_context_t::array_t subtables; + hb_get_subtables_context_t c_get_subtables (subtables); + lookup.dispatch (&c_get_subtables); + if (likely (!lookup.is_reverse ())) { /* in/out forward substitution/positioning */ @@ -967,13 +1179,7 @@ apply_string (OT::hb_apply_context_t *c, buffer->idx = 0; bool ret; - if (lookup.get_subtable_count () == 1) - { - hb_apply_forward_context_t c_forward (c, accel); - ret = lookup.dispatch (&c_forward); - } - else - ret = apply_forward (c, lookup, accel); + ret = apply_forward (c, accel, subtables); if (ret) { if (!Proxy::inplace) @@ -989,7 +1195,7 @@ apply_string (OT::hb_apply_context_t *c, buffer->remove_output (); buffer->idx = buffer->len - 1; - apply_backward (c, lookup, accel); + apply_backward (c, accel, subtables); } } @@ -1008,25 +1214,16 @@ inline void hb_ot_map_t::apply (const Proxy &proxy, const stage_map_t *stage = &stages[table_index][stage_index]; for (; i < stage->last_lookup; i++) { -#if 0 - char buf[4096]; - hb_buffer_serialize_glyphs (buffer, 0, buffer->len, - buf, sizeof (buf), NULL, - font, - HB_BUFFER_SERIALIZE_FORMAT_TEXT, - Proxy::table_index == 0 ? - HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS : - HB_BUFFER_SERIALIZE_FLAG_DEFAULT); - printf ("buf: [%s]\n", buf); -#endif - unsigned int lookup_index = lookups[table_index][i].index; + if (!buffer->message (font, "start lookup %d", lookup_index)) continue; c.set_lookup_index (lookup_index); c.set_lookup_mask (lookups[table_index][i].mask); c.set_auto_zwj (lookups[table_index][i].auto_zwj); + c.set_auto_zwnj (lookups[table_index][i].auto_zwnj); apply_string (&c, proxy.table.get_lookup (lookup_index), proxy.accels[lookup_index]); + (void) buffer->message (font, "end lookup %d", lookup_index); } if (stage->pause_func) diff --git a/gfx/harfbuzz/src/hb-ot-layout.h b/gfx/harfbuzz/src/hb-ot-layout.h index 949678ac4..9861f0fc7 100644 --- a/gfx/harfbuzz/src/hb-ot-layout.h +++ b/gfx/harfbuzz/src/hb-ot-layout.h @@ -48,7 +48,7 @@ HB_BEGIN_DECLS * GDEF */ -hb_bool_t +HB_EXTERN hb_bool_t hb_ot_layout_has_glyph_classes (hb_face_t *face); typedef enum { @@ -59,11 +59,11 @@ typedef enum { HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT = 4 } hb_ot_layout_glyph_class_t; -hb_ot_layout_glyph_class_t +HB_EXTERN hb_ot_layout_glyph_class_t hb_ot_layout_get_glyph_class (hb_face_t *face, hb_codepoint_t glyph); -void +HB_EXTERN void hb_ot_layout_get_glyphs_in_class (hb_face_t *face, hb_ot_layout_glyph_class_t klass, hb_set_t *glyphs /* OUT */); @@ -71,7 +71,7 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face, /* Not that useful. Provides list of attach points for a glyph that a * client may want to cache */ -unsigned int +HB_EXTERN unsigned int hb_ot_layout_get_attach_points (hb_face_t *face, hb_codepoint_t glyph, unsigned int start_offset, @@ -79,7 +79,7 @@ hb_ot_layout_get_attach_points (hb_face_t *face, unsigned int *point_array /* OUT */); /* Ligature caret positions */ -unsigned int +HB_EXTERN unsigned int hb_ot_layout_get_ligature_carets (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph, @@ -95,36 +95,37 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, #define HB_OT_LAYOUT_NO_SCRIPT_INDEX 0xFFFFu #define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu #define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu +#define HB_OT_LAYOUT_NO_VARIATIONS_INDEX 0xFFFFFFFFu -unsigned int +HB_EXTERN unsigned int hb_ot_layout_table_get_script_tags (hb_face_t *face, hb_tag_t table_tag, unsigned int start_offset, unsigned int *script_count /* IN/OUT */, hb_tag_t *script_tags /* OUT */); -hb_bool_t +HB_EXTERN hb_bool_t hb_ot_layout_table_find_script (hb_face_t *face, hb_tag_t table_tag, hb_tag_t script_tag, unsigned int *script_index); /* Like find_script, but takes zero-terminated array of scripts to test */ -hb_bool_t +HB_EXTERN hb_bool_t hb_ot_layout_table_choose_script (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *script_tags, unsigned int *script_index, hb_tag_t *chosen_script); -unsigned int +HB_EXTERN unsigned int hb_ot_layout_table_get_feature_tags (hb_face_t *face, hb_tag_t table_tag, unsigned int start_offset, unsigned int *feature_count /* IN/OUT */, hb_tag_t *feature_tags /* OUT */); -unsigned int +HB_EXTERN unsigned int hb_ot_layout_script_get_language_tags (hb_face_t *face, hb_tag_t table_tag, unsigned int script_index, @@ -132,21 +133,21 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face, unsigned int *language_count /* IN/OUT */, hb_tag_t *language_tags /* OUT */); -hb_bool_t +HB_EXTERN hb_bool_t hb_ot_layout_script_find_language (hb_face_t *face, hb_tag_t table_tag, unsigned int script_index, hb_tag_t language_tag, unsigned int *language_index); -hb_bool_t +HB_EXTERN hb_bool_t hb_ot_layout_language_get_required_feature_index (hb_face_t *face, hb_tag_t table_tag, unsigned int script_index, unsigned int language_index, unsigned int *feature_index); -hb_bool_t +HB_EXTERN hb_bool_t hb_ot_layout_language_get_required_feature (hb_face_t *face, hb_tag_t table_tag, unsigned int script_index, @@ -154,7 +155,7 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face, unsigned int *feature_index, hb_tag_t *feature_tag); -unsigned int +HB_EXTERN unsigned int hb_ot_layout_language_get_feature_indexes (hb_face_t *face, hb_tag_t table_tag, unsigned int script_index, @@ -163,7 +164,7 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t *face, unsigned int *feature_count /* IN/OUT */, unsigned int *feature_indexes /* OUT */); -unsigned int +HB_EXTERN unsigned int hb_ot_layout_language_get_feature_tags (hb_face_t *face, hb_tag_t table_tag, unsigned int script_index, @@ -172,7 +173,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face, unsigned int *feature_count /* IN/OUT */, hb_tag_t *feature_tags /* OUT */); -hb_bool_t +HB_EXTERN hb_bool_t hb_ot_layout_language_find_feature (hb_face_t *face, hb_tag_t table_tag, unsigned int script_index, @@ -180,7 +181,7 @@ hb_ot_layout_language_find_feature (hb_face_t *face, hb_tag_t feature_tag, unsigned int *feature_index); -unsigned int +HB_EXTERN unsigned int hb_ot_layout_feature_get_lookups (hb_face_t *face, hb_tag_t table_tag, unsigned int feature_index, @@ -188,12 +189,12 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face, unsigned int *lookup_count /* IN/OUT */, unsigned int *lookup_indexes /* OUT */); -unsigned int +HB_EXTERN unsigned int hb_ot_layout_table_get_lookup_count (hb_face_t *face, hb_tag_t table_tag); -void +HB_EXTERN void hb_ot_layout_collect_lookups (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *scripts, @@ -201,7 +202,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */); -void +HB_EXTERN void hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, hb_tag_t table_tag, unsigned int lookup_index, @@ -228,7 +229,7 @@ typedef hb_bool_t const hb_ot_layout_glyph_sequence_t *sequence, void *user_data); -void +HB_EXTERN void Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face, hb_tag_t table_tag, unsigned int lookup_index, @@ -236,22 +237,40 @@ Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face, void *user_data); #endif +/* Variations support */ + +HB_EXTERN hb_bool_t +hb_ot_layout_table_find_feature_variations (hb_face_t *face, + hb_tag_t table_tag, + const int *coords, + unsigned int num_coords, + unsigned int *variations_index /* out */); + +HB_EXTERN unsigned int +hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + unsigned int variations_index, + unsigned int start_offset, + unsigned int *lookup_count /* IN/OUT */, + unsigned int *lookup_indexes /* OUT */); + /* * GSUB */ -hb_bool_t +HB_EXTERN hb_bool_t hb_ot_layout_has_substitution (hb_face_t *face); -hb_bool_t +HB_EXTERN hb_bool_t hb_ot_layout_lookup_would_substitute (hb_face_t *face, unsigned int lookup_index, const hb_codepoint_t *glyphs, unsigned int glyphs_length, hb_bool_t zero_context); -void +HB_EXTERN void hb_ot_layout_lookup_substitute_closure (hb_face_t *face, unsigned int lookup_index, hb_set_t *glyphs @@ -259,7 +278,7 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face, #ifdef HB_NOT_IMPLEMENTED /* Note: You better have GDEF when using this API, or marks won't do much. */ -hb_bool_t +HB_EXTERN hb_bool_t Xhb_ot_layout_lookup_substitute (hb_font_t *font, unsigned int lookup_index, const hb_ot_layout_glyph_sequence_t *sequence, @@ -274,12 +293,12 @@ Xhb_ot_layout_lookup_substitute (hb_font_t *font, * GPOS */ -hb_bool_t +HB_EXTERN hb_bool_t hb_ot_layout_has_positioning (hb_face_t *face); #ifdef HB_NOT_IMPLEMENTED /* Note: You better have GDEF when using this API, or marks won't do much. */ -hb_bool_t +HB_EXTERN hb_bool_t Xhb_ot_layout_lookup_position (hb_font_t *font, unsigned int lookup_index, const hb_ot_layout_glyph_sequence_t *sequence, @@ -288,7 +307,7 @@ Xhb_ot_layout_lookup_position (hb_font_t *font, /* Optical 'size' feature info. Returns true if found. * http://www.microsoft.com/typography/otspec/features_pt.htm#size */ -hb_bool_t +HB_EXTERN hb_bool_t hb_ot_layout_get_size_params (hb_face_t *face, unsigned int *design_size, /* OUT. May be NULL */ unsigned int *subfamily_id, /* OUT. May be NULL */ diff --git a/gfx/harfbuzz/src/hb-ot-map-private.hh b/gfx/harfbuzz/src/hb-ot-map-private.hh index 6f62c77de..6f774dde0 100644 --- a/gfx/harfbuzz/src/hb-ot-map-private.hh +++ b/gfx/harfbuzz/src/hb-ot-map-private.hh @@ -50,6 +50,7 @@ struct hb_ot_map_t hb_mask_t mask; hb_mask_t _1_mask; /* mask for value=1, for quick access */ unsigned int needs_fallback : 1; + unsigned int auto_zwnj : 1; unsigned int auto_zwj : 1; static int cmp (const feature_map_t *a, const feature_map_t *b) @@ -58,6 +59,7 @@ struct hb_ot_map_t struct lookup_map_t { unsigned short index; + unsigned short auto_zwnj : 1; unsigned short auto_zwj : 1; hb_mask_t mask; @@ -113,7 +115,7 @@ struct hb_ot_map_t assert (stage <= stages[table_index].len); unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0; unsigned int end = stage < stages[table_index].len ? stages[table_index][stage].last_lookup : lookups[table_index].len; - *plookups = &lookups[table_index][start]; + *plookups = end == start ? NULL : &lookups[table_index][start]; *lookup_count = end - start; } @@ -139,12 +141,6 @@ struct hb_ot_map_t private: - HB_INTERNAL void add_lookups (hb_face_t *face, - unsigned int table_index, - unsigned int feature_index, - hb_mask_t mask, - bool auto_zwj); - hb_mask_t global_mask; hb_prealloced_array_t features; @@ -156,8 +152,9 @@ enum hb_ot_map_feature_flags_t { F_NONE = 0x0000u, F_GLOBAL = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */ F_HAS_FALLBACK = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */ - F_MANUAL_ZWJ = 0x0004u, /* Don't skip over ZWJ when matching. */ - F_GLOBAL_SEARCH = 0x0008u /* If feature not found in LangSys, look for it in global feature list and pick one. */ + F_MANUAL_ZWNJ = 0x0004u, /* Don't skip over ZWNJ when matching **context**. */ + F_MANUAL_ZWJ = 0x0008u, /* Don't skip over ZWJ when matching **input**. */ + F_GLOBAL_SEARCH = 0x0010u /* If feature not found in LangSys, look for it in global feature list and pick one. */ }; HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t); /* Macro version for where const is desired. */ @@ -182,7 +179,9 @@ struct hb_ot_map_builder_t inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func) { add_pause (1, pause_func); } - HB_INTERNAL void compile (struct hb_ot_map_t &m); + HB_INTERNAL void compile (hb_ot_map_t &m, + const int *coords, + unsigned int num_coords); inline void finish (void) { feature_infos.finish (); @@ -194,6 +193,15 @@ struct hb_ot_map_builder_t private: + HB_INTERNAL void add_lookups (hb_ot_map_t &m, + hb_face_t *face, + unsigned int table_index, + unsigned int feature_index, + unsigned int variations_index, + hb_mask_t mask, + bool auto_zwnj = true, + bool auto_zwj = true); + struct feature_info_t { hb_tag_t tag; unsigned int seq; /* sequence#, used for stable sorting only */ @@ -203,7 +211,8 @@ struct hb_ot_map_builder_t unsigned int stage[2]; /* GSUB/GPOS */ static int cmp (const feature_info_t *a, const feature_info_t *b) - { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); } + { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : + (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); } }; struct stage_info_t { diff --git a/gfx/harfbuzz/src/hb-ot-map.cc b/gfx/harfbuzz/src/hb-ot-map.cc index 95bd04ee8..5764a1104 100644 --- a/gfx/harfbuzz/src/hb-ot-map.cc +++ b/gfx/harfbuzz/src/hb-ot-map.cc @@ -31,44 +31,13 @@ #include "hb-ot-layout-private.hh" -void -hb_ot_map_t::add_lookups (hb_face_t *face, - unsigned int table_index, - unsigned int feature_index, - hb_mask_t mask, - bool auto_zwj) +void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const { - unsigned int lookup_indices[32]; - unsigned int offset, len; - unsigned int table_lookup_count; - - table_lookup_count = hb_ot_layout_table_get_lookup_count (face, table_tags[table_index]); - - offset = 0; - do { - len = ARRAY_LENGTH (lookup_indices); - hb_ot_layout_feature_get_lookups (face, - table_tags[table_index], - feature_index, - offset, &len, - lookup_indices); - - for (unsigned int i = 0; i < len; i++) - { - if (lookup_indices[i] >= table_lookup_count) - continue; - hb_ot_map_t::lookup_map_t *lookup = lookups[table_index].push (); - if (unlikely (!lookup)) - return; - lookup->mask = mask; - lookup->index = lookup_indices[i]; - lookup->auto_zwj = auto_zwj; - } - - offset += len; - } while (len == ARRAY_LENGTH (lookup_indices)); + for (unsigned int i = 0; i < lookups[table_index].len; i++) + hb_set_add (lookups_out, lookups[table_index][i].index); } + hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_, const hb_segment_properties_t *props_) { @@ -89,7 +58,7 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_, for (unsigned int table_index = 0; table_index < 2; table_index++) { hb_tag_t table_tag = table_tags[table_index]; - found_script[table_index] = hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]); + found_script[table_index] = (bool) hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]); hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]); } } @@ -109,13 +78,50 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, info->stage[1] = current_stage[1]; } - -void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const +void +hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, + hb_face_t *face, + unsigned int table_index, + unsigned int feature_index, + unsigned int variations_index, + hb_mask_t mask, + bool auto_zwnj, + bool auto_zwj) { - for (unsigned int i = 0; i < lookups[table_index].len; i++) - hb_set_add (lookups_out, lookups[table_index][i].index); + unsigned int lookup_indices[32]; + unsigned int offset, len; + unsigned int table_lookup_count; + + table_lookup_count = hb_ot_layout_table_get_lookup_count (face, table_tags[table_index]); + + offset = 0; + do { + len = ARRAY_LENGTH (lookup_indices); + hb_ot_layout_feature_with_variations_get_lookups (face, + table_tags[table_index], + feature_index, + variations_index, + offset, &len, + lookup_indices); + + for (unsigned int i = 0; i < len; i++) + { + if (lookup_indices[i] >= table_lookup_count) + continue; + hb_ot_map_t::lookup_map_t *lookup = m.lookups[table_index].push (); + if (unlikely (!lookup)) + return; + lookup->mask = mask; + lookup->index = lookup_indices[i]; + lookup->auto_zwnj = auto_zwnj; + lookup->auto_zwj = auto_zwj; + } + + offset += len; + } while (len == ARRAY_LENGTH (lookup_indices)); } + void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func) { stage_info_t *s = stages[table_index].push (); @@ -128,9 +134,15 @@ void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::paus } void -hb_ot_map_builder_t::compile (hb_ot_map_t &m) +hb_ot_map_builder_t::compile (hb_ot_map_t &m, + const int *coords, + unsigned int num_coords) { - m.global_mask = 1; + ASSERT_STATIC (!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))); + unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1; + unsigned int global_bit_shift = _hb_popcount32 (HB_GLYPH_FLAG_DEFINED); + + m.global_mask = global_bit_mask; unsigned int required_feature_index[2]; hb_tag_t required_feature_tag[2]; @@ -182,7 +194,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) /* Allocate bits now */ - unsigned int next_bit = 1; + unsigned int next_bit = global_bit_shift + 1; + for (unsigned int i = 0; i < feature_infos.len; i++) { const feature_info_t *info = &feature_infos[i]; @@ -193,7 +206,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) /* Uses the global bit */ bits_needed = 0; else - bits_needed = _hb_bit_storage (info->max_value); + /* Limit to 8 bits per feature. */ + bits_needed = MIN(8u, _hb_bit_storage (info->max_value)); if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t)) continue; /* Feature disabled, or not enough bits. */ @@ -204,11 +218,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) for (unsigned int table_index = 0; table_index < 2; table_index++) { if (required_feature_tag[table_index] == info->tag) - { required_feature_stage[table_index] = info->stage[table_index]; - found = true; - continue; - } + found |= hb_ot_layout_language_find_feature (face, table_tags[table_index], script_index[table_index], @@ -239,18 +250,19 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) map->index[1] = feature_index[1]; map->stage[0] = info->stage[0]; map->stage[1] = info->stage[1]; + map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ); map->auto_zwj = !(info->flags & F_MANUAL_ZWJ); if ((info->flags & F_GLOBAL) && info->max_value == 1) { /* Uses the global bit */ - map->shift = 0; - map->mask = 1; + map->shift = global_bit_shift; + map->mask = global_bit_mask; } else { map->shift = next_bit; - map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit); + map->mask = (1u << (next_bit + bits_needed)) - (1u << next_bit); next_bit += bits_needed; m.global_mask |= (info->default_value << map->shift) & map->mask; } - map->_1_mask = (1 << map->shift) & map->mask; + map->_1_mask = (1u << map->shift) & map->mask; map->needs_fallback = !found; } @@ -264,23 +276,32 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) { /* Collect lookup indices for features */ + unsigned int variations_index; + hb_ot_layout_table_find_feature_variations (face, + table_tags[table_index], + coords, + num_coords, + &variations_index); + unsigned int stage_index = 0; unsigned int last_num_lookups = 0; for (unsigned stage = 0; stage < current_stage[table_index]; stage++) { if (required_feature_index[table_index] != HB_OT_LAYOUT_NO_FEATURE_INDEX && required_feature_stage[table_index] == stage) - m.add_lookups (face, table_index, - required_feature_index[table_index], - 1 /* mask */, - true /* auto_zwj */); + add_lookups (m, face, table_index, + required_feature_index[table_index], + variations_index, + global_bit_mask); for (unsigned i = 0; i < m.features.len; i++) if (m.features[i].stage[table_index] == stage) - m.add_lookups (face, table_index, - m.features[i].index[table_index], - m.features[i].mask, - m.features[i].auto_zwj); + add_lookups (m, face, table_index, + m.features[i].index[table_index], + variations_index, + m.features[i].mask, + m.features[i].auto_zwnj, + m.features[i].auto_zwj); /* Sort lookups and merge duplicates */ if (last_num_lookups < m.lookups[table_index].len) @@ -294,6 +315,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) else { m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask; + m.lookups[table_index][j].auto_zwnj &= m.lookups[table_index][i].auto_zwnj; m.lookups[table_index][j].auto_zwj &= m.lookups[table_index][i].auto_zwj; } m.lookups[table_index].shrink (j + 1); diff --git a/gfx/harfbuzz/src/hb-ot-math-table.hh b/gfx/harfbuzz/src/hb-ot-math-table.hh new file mode 100644 index 000000000..191d79e98 --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-math-table.hh @@ -0,0 +1,722 @@ +/* + * Copyright © 2016 Igalia S.L. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Igalia Author(s): Frédéric Wang + */ + +#ifndef HB_OT_MATH_TABLE_HH +#define HB_OT_MATH_TABLE_HH + +#include "hb-open-type-private.hh" +#include "hb-ot-layout-common-private.hh" +#include "hb-ot-math.h" + +namespace OT { + + +struct MathValueRecord +{ + inline hb_position_t get_x_value (hb_font_t *font, const void *base) const + { return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); } + inline hb_position_t get_y_value (hb_font_t *font, const void *base) const + { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); } + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && deviceTable.sanitize (c, base)); + } + + protected: + SHORT value; /* The X or Y value in design units */ + OffsetTo deviceTable; /* Offset to the device table - from the + * beginning of parent table. May be NULL. + * Suggested format for device table is 1. */ + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct MathConstants +{ + inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + + unsigned int count = ARRAY_LENGTH (mathValueRecords); + for (unsigned int i = 0; i < count; i++) + if (!mathValueRecords[i].sanitize (c, this)) + return_trace (false); + + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && sanitize_math_value_records(c)); + } + + inline hb_position_t get_value (hb_ot_math_constant_t constant, + hb_font_t *font) const + { + switch (constant) { + + case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: + case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: + return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN]; + + case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: + case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: + return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]); + + case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE: + case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: + case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: + case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value(font, this); + + case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: + case HB_OT_MATH_CONSTANT_AXIS_HEIGHT: + case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP: + case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN: + case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN: + case HB_OT_MATH_CONSTANT_MATH_LEADING: + case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER: + case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER: + case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_STACK_GAP_MIN: + case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP: + case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX: + case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED: + case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER: + case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: + case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this); + + case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: + return radicalDegreeBottomRaisePercent; + + default: + return 0; + } + } + + protected: + SHORT percentScaleDown[2]; + USHORT minHeight[2]; + MathValueRecord mathValueRecords[51]; + SHORT radicalDegreeBottomRaisePercent; + + public: + DEFINE_SIZE_STATIC (214); +}; + +struct MathItalicsCorrectionInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + coverage.sanitize (c, this) && + italicsCorrection.sanitize (c, this)); + } + + inline hb_position_t get_value (hb_codepoint_t glyph, + hb_font_t *font) const + { + unsigned int index = (this+coverage).get_coverage (glyph); + return italicsCorrection[index].get_x_value (font, this); + } + + protected: + OffsetTo coverage; /* Offset to Coverage table - + * from the beginning of + * MathItalicsCorrectionInfo + * table. */ + ArrayOf italicsCorrection; /* Array of MathValueRecords + * defining italics correction + * values for each + * covered glyph. */ + + public: + DEFINE_SIZE_ARRAY (4, italicsCorrection); +}; + +struct MathTopAccentAttachment +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + topAccentCoverage.sanitize (c, this) && + topAccentAttachment.sanitize (c, this)); + } + + inline hb_position_t get_value (hb_codepoint_t glyph, + hb_font_t *font) const + { + unsigned int index = (this+topAccentCoverage).get_coverage (glyph); + if (index == NOT_COVERED) + return font->get_glyph_h_advance (glyph) / 2; + return topAccentAttachment[index].get_x_value(font, this); + } + + protected: + OffsetTo topAccentCoverage; /* Offset to Coverage table - + * from the beginning of + * MathTopAccentAttachment + * table. */ + ArrayOf topAccentAttachment; /* Array of MathValueRecords + * defining top accent + * attachment points for each + * covered glyph. */ + + public: + DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment); +}; + +struct MathKern +{ + inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + unsigned int count = 2 * heightCount + 1; + for (unsigned int i = 0; i < count; i++) + if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (mathValueRecords, + mathValueRecords[0].static_size, + 2 * heightCount + 1) && + sanitize_math_value_records (c)); + } + + inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const + { + const MathValueRecord* correctionHeight = mathValueRecords; + const MathValueRecord* kernValue = mathValueRecords + heightCount; + int sign = font->y_scale < 0 ? -1 : +1; + + /* The description of the MathKern table is a ambiguous, but interpreting + * "between the two heights found at those indexes" for 0 < i < len as + * + * correctionHeight[i-1] < correction_height <= correctionHeight[i] + * + * makes the result consistent with the limit cases and we can just use the + * binary search algorithm of std::upper_bound: + */ + unsigned int i = 0; + unsigned int count = heightCount; + while (count > 0) + { + unsigned int half = count / 2; + hb_position_t height = correctionHeight[i + half].get_y_value(font, this); + if (sign * height < sign * correction_height) + { + i += half + 1; + count -= half + 1; + } else + count = half; + } + return kernValue[i].get_x_value(font, this); + } + + protected: + USHORT heightCount; + MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at + * which the kern value changes. + * Sorted by the height value in + * design units (heightCount entries), + * Followed by: + * Array of kern values corresponding + * to heights. (heightCount+1 entries). + */ + + public: + DEFINE_SIZE_ARRAY (2, mathValueRecords); +}; + +struct MathKernInfoRecord +{ + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + + unsigned int count = ARRAY_LENGTH (mathKern); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!mathKern[i].sanitize (c, base))) + return_trace (false); + + return_trace (true); + } + + inline hb_position_t get_kerning (hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font, + const void *base) const + { + unsigned int idx = kern; + if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0; + return (base+mathKern[idx]).get_value (correction_height, font); + } + + protected: + /* Offset to MathKern table for each corner - + * from the beginning of MathKernInfo table. May be NULL. */ + OffsetTo mathKern[4]; + + public: + DEFINE_SIZE_STATIC (8); +}; + +struct MathKernInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathKernCoverage.sanitize (c, this) && + mathKernInfoRecords.sanitize (c, this)); + } + + inline hb_position_t get_kerning (hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font) const + { + unsigned int index = (this+mathKernCoverage).get_coverage (glyph); + return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this); + } + + protected: + OffsetTo mathKernCoverage; /* Offset to Coverage table - + * from the beginning of the + * MathKernInfo table. */ + ArrayOf mathKernInfoRecords; /* Array of + * MathKernInfoRecords, + * per-glyph information for + * mathematical positioning + * of subscripts and + * superscripts. */ + + public: + DEFINE_SIZE_ARRAY (4, mathKernInfoRecords); +}; + +struct MathGlyphInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathItalicsCorrectionInfo.sanitize (c, this) && + mathTopAccentAttachment.sanitize (c, this) && + extendedShapeCoverage.sanitize (c, this) && + mathKernInfo.sanitize(c, this)); + } + + inline hb_position_t + get_italics_correction (hb_codepoint_t glyph, hb_font_t *font) const + { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); } + + inline hb_position_t + get_top_accent_attachment (hb_codepoint_t glyph, hb_font_t *font) const + { return (this+mathTopAccentAttachment).get_value (glyph, font); } + + inline bool is_extended_shape (hb_codepoint_t glyph) const + { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; } + + inline hb_position_t get_kerning (hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font) const + { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); } + + protected: + /* Offset to MathItalicsCorrectionInfo table - + * from the beginning of MathGlyphInfo table. */ + OffsetTo mathItalicsCorrectionInfo; + + /* Offset to MathTopAccentAttachment table - + * from the beginning of MathGlyphInfo table. */ + OffsetTo mathTopAccentAttachment; + + /* Offset to coverage table for Extended Shape glyphs - + * from the beginning of MathGlyphInfo table. When the left or right glyph of + * a box is an extended shape variant, the (ink) box (and not the default + * position defined by values in MathConstants table) should be used for + * vertical positioning purposes. May be NULL.. */ + OffsetTo extendedShapeCoverage; + + /* Offset to MathKernInfo table - + * from the beginning of MathGlyphInfo table. */ + OffsetTo mathKernInfo; + + public: + DEFINE_SIZE_STATIC (8); +}; + +struct MathGlyphVariantRecord +{ + friend struct MathGlyphConstruction; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + GlyphID variantGlyph; /* Glyph ID for the variant. */ + USHORT advanceMeasurement; /* Advance width/height, in design units, of the + * variant, in the direction of requested + * glyph extension. */ + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct PartFlags : USHORT +{ + enum Flags { + Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ + + Defined = 0x0001u, /* All defined flags. */ + }; + + public: + DEFINE_SIZE_STATIC (2); +}; + +struct MathGlyphPartRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + inline void extract (hb_ot_math_glyph_part_t &out, + int scale, + hb_font_t *font) const + { + out.glyph = glyph; + + out.start_connector_length = font->em_scale (startConnectorLength, scale); + out.end_connector_length = font->em_scale (endConnectorLength, scale); + out.full_advance = font->em_scale (fullAdvance, scale); + + ASSERT_STATIC ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER == + (unsigned int) PartFlags::Extender); + + out.flags = (hb_ot_math_glyph_part_flags_t) + (unsigned int) + (partFlags & PartFlags::Defined); + } + + protected: + GlyphID glyph; /* Glyph ID for the part. */ + USHORT startConnectorLength; /* Advance width/ height of the straight bar + * connector material, in design units, is at + * the beginning of the glyph, in the + * direction of the extension. */ + USHORT endConnectorLength; /* Advance width/ height of the straight bar + * connector material, in design units, is at + * the end of the glyph, in the direction of + * the extension. */ + USHORT fullAdvance; /* Full advance width/height for this part, + * in the direction of the extension. + * In design units. */ + PartFlags partFlags; /* Part qualifiers. */ + + public: + DEFINE_SIZE_STATIC (10); +}; + +struct MathGlyphAssembly +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + italicsCorrection.sanitize(c, this) && + partRecords.sanitize(c)); + } + + inline unsigned int get_parts (hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_ot_math_glyph_part_t *parts /* OUT */, + hb_position_t *italics_correction /* OUT */) const + { + if (parts_count) + { + int scale = font->dir_scale (direction); + const MathGlyphPartRecord *arr = + partRecords.sub_array (start_offset, parts_count); + unsigned int count = *parts_count; + for (unsigned int i = 0; i < count; i++) + arr[i].extract (parts[i], scale, font); + } + + if (italics_correction) + *italics_correction = italicsCorrection.get_x_value (font, this); + + return partRecords.len; + } + + protected: + MathValueRecord italicsCorrection; /* Italics correction of this + * MathGlyphAssembly. Should not + * depend on the assembly size. */ + ArrayOf partRecords; /* Array of part records, from + * left to right and bottom to + * top. */ + + public: + DEFINE_SIZE_ARRAY (6, partRecords); +}; + +struct MathGlyphConstruction +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + glyphAssembly.sanitize(c, this) && + mathGlyphVariantRecord.sanitize(c)); + } + + inline const MathGlyphAssembly &get_assembly (void) const + { return this+glyphAssembly; } + + inline unsigned int get_variants (hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_ot_math_glyph_variant_t *variants /* OUT */) const + { + if (variants_count) + { + int scale = font->dir_scale (direction); + const MathGlyphVariantRecord *arr = + mathGlyphVariantRecord.sub_array (start_offset, variants_count); + unsigned int count = *variants_count; + for (unsigned int i = 0; i < count; i++) + { + variants[i].glyph = arr[i].variantGlyph; + variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale); + } + } + return mathGlyphVariantRecord.len; + } + + protected: + /* Offset to MathGlyphAssembly table for this shape - from the beginning of + MathGlyphConstruction table. May be NULL. */ + OffsetTo glyphAssembly; + + /* MathGlyphVariantRecords for alternative variants of the glyphs. */ + ArrayOf mathGlyphVariantRecord; + + public: + DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord); +}; + +struct MathVariants +{ + inline bool sanitize_offsets (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + unsigned int count = vertGlyphCount + horizGlyphCount; + for (unsigned int i = 0; i < count; i++) + if (!glyphConstruction[i].sanitize (c, this)) return_trace (false); + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + vertGlyphCoverage.sanitize (c, this) && + horizGlyphCoverage.sanitize (c, this) && + c->check_array (glyphConstruction, + glyphConstruction[0].static_size, + vertGlyphCount + horizGlyphCount) && + sanitize_offsets (c)); + } + + inline hb_position_t get_min_connector_overlap (hb_direction_t direction, + hb_font_t *font) const + { return font->em_scale_dir (minConnectorOverlap, direction); } + + inline unsigned int get_glyph_variants (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_ot_math_glyph_variant_t *variants /* OUT */) const + { return get_glyph_construction (glyph, direction, font) + .get_variants (direction, font, start_offset, variants_count, variants); } + + inline unsigned int get_glyph_parts (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_ot_math_glyph_part_t *parts /* OUT */, + hb_position_t *italics_correction /* OUT */) const + { return get_glyph_construction (glyph, direction, font) + .get_assembly () + .get_parts (direction, font, + start_offset, parts_count, parts, + italics_correction); } + + private: + inline const MathGlyphConstruction & + get_glyph_construction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font) const + { + bool vertical = HB_DIRECTION_IS_VERTICAL (direction); + unsigned int count = vertical ? vertGlyphCount : horizGlyphCount; + const OffsetTo &coverage = vertical ? vertGlyphCoverage + : horizGlyphCoverage; + + unsigned int index = (this+coverage).get_coverage (glyph); + if (unlikely (index >= count)) return Null(MathGlyphConstruction); + + if (!vertical) + index += vertGlyphCount; + + return this+glyphConstruction[index]; + } + + protected: + USHORT minConnectorOverlap; /* Minimum overlap of connecting + * glyphs during glyph construction, + * in design units. */ + OffsetTo vertGlyphCoverage; /* Offset to Coverage table - + * from the beginning of MathVariants + * table. */ + OffsetTo horizGlyphCoverage; /* Offset to Coverage table - + * from the beginning of MathVariants + * table. */ + USHORT vertGlyphCount; /* Number of glyphs for which + * information is provided for + * vertically growing variants. */ + USHORT horizGlyphCount; /* Number of glyphs for which + * information is provided for + * horizontally growing variants. */ + + /* Array of offsets to MathGlyphConstruction tables - from the beginning of + the MathVariants table, for shapes growing in vertical/horizontal + direction. */ + OffsetTo glyphConstruction[VAR]; + + public: + DEFINE_SIZE_ARRAY (10, glyphConstruction); +}; + + +/* + * MATH -- The MATH Table + */ + +struct MATH +{ + static const hb_tag_t tableTag = HB_OT_TAG_MATH; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + mathConstants.sanitize (c, this) && + mathGlyphInfo.sanitize (c, this) && + mathVariants.sanitize (c, this)); + } + + inline hb_position_t get_constant (hb_ot_math_constant_t constant, + hb_font_t *font) const + { return (this+mathConstants).get_value (constant, font); } + + inline const MathGlyphInfo &get_math_glyph_info (void) const + { return this+mathGlyphInfo; } + + inline const MathVariants &get_math_variants (void) const + { return this+mathVariants; } + + protected: + FixedVersion<>version; /* Version of the MATH table + * initially set to 0x00010000u */ + OffsetTo mathConstants;/* MathConstants table */ + OffsetTo mathGlyphInfo;/* MathGlyphInfo table */ + OffsetTo mathVariants; /* MathVariants table */ + + public: + DEFINE_SIZE_STATIC (10); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_MATH_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-math.cc b/gfx/harfbuzz/src/hb-ot-math.cc new file mode 100644 index 000000000..f82a07353 --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-math.cc @@ -0,0 +1,253 @@ +/* + * Copyright © 2016 Igalia S.L. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Igalia Author(s): Frédéric Wang + */ + +#include "hb-open-type-private.hh" + +#include "hb-ot-layout-private.hh" +#include "hb-ot-math-table.hh" + +static inline const OT::MATH& +_get_math (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH); + hb_ot_layout_t * layout = hb_ot_layout_from_face (face); + return *(layout->math.get ()); +} + +/* + * OT::MATH + */ + +/** + * hb_ot_math_has_data: + * @face: #hb_face_t to test + * + * This function allows to verify the presence of an OpenType MATH table on the + * face. + * + * Return value: true if face has a MATH table, false otherwise + * + * Since: 1.3.3 + **/ +hb_bool_t +hb_ot_math_has_data (hb_face_t *face) +{ + return &_get_math (face) != &OT::Null(OT::MATH); +} + +/** + * hb_ot_math_get_constant: + * @font: #hb_font_t from which to retrieve the value + * @constant: #hb_ot_math_constant_t the constant to retrieve + * + * This function returns the requested math constants as a #hb_position_t. + * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, + * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or + * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is + * actually an integer between 0 and 100 representing that percentage. + * + * Return value: the requested constant or 0 + * + * Since: 1.3.3 + **/ +hb_position_t +hb_ot_math_get_constant (hb_font_t *font, + hb_ot_math_constant_t constant) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_constant(constant, font); +} + +/** + * hb_ot_math_get_glyph_italics_correction: + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * + * Return value: the italics correction of the glyph or 0 + * + * Since: 1.3.3 + **/ +hb_position_t +hb_ot_math_get_glyph_italics_correction (hb_font_t *font, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_glyph_info().get_italics_correction (glyph, font); +} + +/** + * hb_ot_math_get_glyph_top_accent_attachment: + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * + * Return value: the top accent attachment of the glyph or 0 + * + * Since: 1.3.3 + **/ +hb_position_t +hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_glyph_info().get_top_accent_attachment (glyph, font); +} + +/** + * hb_ot_math_is_glyph_extended_shape: + * @face: a #hb_face_t to test + * @glyph: a glyph index to test + * + * Return value: true if the glyph is an extended shape, false otherwise + * + * Since: 1.3.3 + **/ +hb_bool_t +hb_ot_math_is_glyph_extended_shape (hb_face_t *face, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (face); + return math.get_math_glyph_info().is_extended_shape (glyph); +} + +/** + * hb_ot_math_get_glyph_kerning: + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * @kern: the #hb_ot_math_kern_t from which to retrieve the value + * @correction_height: the correction height to use to determine the kerning. + * + * This function tries to retrieve the MathKern table for the specified font, + * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the + * MathKern table to find one value that is greater or equal to specified + * correction_height. If one is found the corresponding value from the list of + * kerns is returned and otherwise the last kern value is returned. + * + * Return value: requested kerning or 0 + * + * Since: 1.3.3 + **/ +hb_position_t +hb_ot_math_get_glyph_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); +} + +/** + * hb_ot_math_get_glyph_variants: + * @font: #hb_font_t from which to retrieve the values + * @glyph: index of the glyph to stretch + * @direction: direction of the stretching + * @start_offset: offset of the first variant to retrieve + * @variants_count: maximum number of variants to retrieve after start_offset + * (IN) and actual number of variants retrieved (OUT) + * @variants: array of size at least @variants_count to store the result + * + * This function tries to retrieve the MathGlyphConstruction for the specified + * font, glyph and direction. Note that only the value of + * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list + * of size variants as an array of hb_ot_math_glyph_variant_t structs. + * + * Return value: the total number of size variants available or 0 + * + * Since: 1.3.3 + **/ +unsigned int +hb_ot_math_get_glyph_variants (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_ot_math_glyph_variant_t *variants /* OUT */) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_variants().get_glyph_variants (glyph, direction, font, + start_offset, + variants_count, + variants); +} + +/** + * hb_ot_math_get_min_connector_overlap: + * @font: #hb_font_t from which to retrieve the value + * @direction: direction of the stretching + * + * This function tries to retrieve the MathVariants table for the specified + * font and returns the minimum overlap of connecting glyphs to draw a glyph + * assembly in the specified direction. Note that only the value of + * #HB_DIRECTION_IS_HORIZONTAL is considered. + * + * Return value: requested min connector overlap or 0 + * + * Since: 1.3.3 + **/ +hb_position_t +hb_ot_math_get_min_connector_overlap (hb_font_t *font, + hb_direction_t direction) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_variants().get_min_connector_overlap (direction, font); +} + +/** + * hb_ot_math_get_glyph_assembly: + * @font: #hb_font_t from which to retrieve the values + * @glyph: index of the glyph to stretch + * @direction: direction of the stretching + * @start_offset: offset of the first glyph part to retrieve + * @parts_count: maximum number of glyph parts to retrieve after start_offset + * (IN) and actual number of parts retrieved (OUT) + * @parts: array of size at least @parts_count to store the result + * @italics_correction: italic correction of the glyph assembly + * + * This function tries to retrieve the GlyphAssembly for the specified font, + * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL + * is considered. It provides the information necessary to draw the glyph + * assembly as an array of #hb_ot_math_glyph_part_t. + * + * Return value: the total number of parts in the glyph assembly + * + * Since: 1.3.3 + **/ +unsigned int +hb_ot_math_get_glyph_assembly (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_ot_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_variants().get_glyph_parts (glyph, direction, font, + start_offset, + parts_count, + parts, + italics_correction); +} diff --git a/gfx/harfbuzz/src/hb-ot-math.h b/gfx/harfbuzz/src/hb-ot-math.h new file mode 100644 index 000000000..521a5ca03 --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-math.h @@ -0,0 +1,209 @@ +/* + * Copyright © 2016 Igalia S.L. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Igalia Author(s): Frédéric Wang + */ + +#ifndef HB_OT_H_IN +#error "Include instead." +#endif + +#ifndef HB_OT_MATH_H +#define HB_OT_MATH_H + +#include "hb.h" + +HB_BEGIN_DECLS + + +/* + * MATH + */ + +#define HB_OT_TAG_MATH HB_TAG('M','A','T','H') + +/* Use with hb_buffer_set_script() for math shaping. */ +#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h') + +/* Types */ + +/** + * hb_ot_math_constant_t: + * + * Since: 1.3.3 + */ +typedef enum { + HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0, + HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1, + HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT = 2, + HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT = 3, + HB_OT_MATH_CONSTANT_MATH_LEADING = 4, + HB_OT_MATH_CONSTANT_AXIS_HEIGHT = 5, + HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT = 6, + HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT = 7, + HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN = 8, + HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX = 9, + HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN = 10, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP = 11, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED = 12, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN = 13, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX = 14, + HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN = 15, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT = 16, + HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT = 17, + HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN = 18, + HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN = 19, + HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN = 20, + HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN = 21, + HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP = 22, + HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP = 23, + HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN = 24, + HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN = 25, + HB_OT_MATH_CONSTANT_STACK_GAP_MIN = 26, + HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN = 27, + HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP = 28, + HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN = 29, + HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN = 30, + HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN = 31, + HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP = 32, + HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP = 33, + HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN = 34, + HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN = 35, + HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN = 36, + HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN = 37, + HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS = 38, + HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN = 39, + HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN = 40, + HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP = 41, + HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP = 42, + HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP = 43, + HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS = 44, + HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER = 45, + HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP = 46, + HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS = 47, + HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER = 48, + HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP = 49, + HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP = 50, + HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS = 51, + HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER = 52, + HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE = 53, + HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE = 54, + HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55 +} hb_ot_math_constant_t; + +/** + * hb_ot_math_kern_t: + * + * Since: 1.3.3 + */ +typedef enum { + HB_OT_MATH_KERN_TOP_RIGHT = 0, + HB_OT_MATH_KERN_TOP_LEFT = 1, + HB_OT_MATH_KERN_BOTTOM_RIGHT = 2, + HB_OT_MATH_KERN_BOTTOM_LEFT = 3 +} hb_ot_math_kern_t; + +/** + * hb_ot_math_glyph_variant_t: + * + * Since: 1.3.3 + */ +typedef struct hb_ot_math_glyph_variant_t { + hb_codepoint_t glyph; + hb_position_t advance; +} hb_ot_math_glyph_variant_t; + +/** + * hb_ot_math_glyph_part_flags_t: + * + * Since: 1.3.3 + */ +typedef enum { /*< flags >*/ + HB_MATH_GLYPH_PART_FLAG_EXTENDER = 0x00000001u /* Extender glyph */ +} hb_ot_math_glyph_part_flags_t; + +/** + * hb_ot_math_glyph_part_t: + * + * Since: 1.3.3 + */ +typedef struct hb_ot_math_glyph_part_t { + hb_codepoint_t glyph; + hb_position_t start_connector_length; + hb_position_t end_connector_length; + hb_position_t full_advance; + hb_ot_math_glyph_part_flags_t flags; +} hb_ot_math_glyph_part_t; + +/* Methods */ + +HB_EXTERN hb_bool_t +hb_ot_math_has_data (hb_face_t *face); + +HB_EXTERN hb_position_t +hb_ot_math_get_constant (hb_font_t *font, + hb_ot_math_constant_t constant); + +HB_EXTERN hb_position_t +hb_ot_math_get_glyph_italics_correction (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_bool_t +hb_ot_math_is_glyph_extended_shape (hb_face_t *face, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_math_get_glyph_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height); + +HB_EXTERN unsigned int +hb_ot_math_get_glyph_variants (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_ot_math_glyph_variant_t *variants /* OUT */); + +HB_EXTERN hb_position_t +hb_ot_math_get_min_connector_overlap (hb_font_t *font, + hb_direction_t direction); + +HB_EXTERN unsigned int +hb_ot_math_get_glyph_assembly (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_ot_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */); + + +HB_END_DECLS + +#endif /* HB_OT_MATH_H */ diff --git a/gfx/harfbuzz/src/hb-ot-maxp-table.hh b/gfx/harfbuzz/src/hb-ot-maxp-table.hh index 27105af13..943e3908c 100644 --- a/gfx/harfbuzz/src/hb-ot-maxp-table.hh +++ b/gfx/harfbuzz/src/hb-ot-maxp-table.hh @@ -58,7 +58,7 @@ struct maxp /* We only implement version 0.5 as none of the extra fields in version 1.0 are useful. */ protected: - FixedVersion version; /* Version of the maxp table (0.5 or 1.0), + FixedVersion<>version; /* Version of the maxp table (0.5 or 1.0), * 0x00005000u or 0x00010000u. */ USHORT numGlyphs; /* The number of glyphs in the font. */ public: diff --git a/gfx/harfbuzz/src/hb-ot-os2-table.hh b/gfx/harfbuzz/src/hb-ot-os2-table.hh new file mode 100644 index 000000000..4709cd6e8 --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-os2-table.hh @@ -0,0 +1,105 @@ +/* + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_OS2_TABLE_HH +#define HB_OT_OS2_TABLE_HH + +#include "hb-open-type-private.hh" + + +namespace OT { + +/* + * OS/2 and Windows Metrics + * http://www.microsoft.com/typography/otspec/os2.htm + */ + +#define HB_OT_TAG_os2 HB_TAG('O','S','/','2') + +struct os2 +{ + static const hb_tag_t tableTag = HB_OT_TAG_os2; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + USHORT version; + + /* Version 0 */ + SHORT xAvgCharWidth; + USHORT usWeightClass; + USHORT usWidthClass; + USHORT fsType; + SHORT ySubscriptXSize; + SHORT ySubscriptYSize; + SHORT ySubscriptXOffset; + SHORT ySubscriptYOffset; + SHORT ySuperscriptXSize; + SHORT ySuperscriptYSize; + SHORT ySuperscriptXOffset; + SHORT ySuperscriptYOffset; + SHORT yStrikeoutSize; + SHORT yStrikeoutPosition; + SHORT sFamilyClass; + BYTE panose[10]; + ULONG ulUnicodeRange[4]; + Tag achVendID; + USHORT fsSelection; + USHORT usFirstCharIndex; + USHORT usLastCharIndex; + SHORT sTypoAscender; + SHORT sTypoDescender; + SHORT sTypoLineGap; + USHORT usWinAscent; + USHORT usWinDescent; + + /* Version 1 */ + //ULONG ulCodePageRange1; + //ULONG ulCodePageRange2; + + /* Version 2 */ + //SHORT sxHeight; + //SHORT sCapHeight; + //USHORT usDefaultChar; + //USHORT usBreakChar; + //USHORT usMaxContext; + + /* Version 5 */ + //USHORT usLowerOpticalPointSize; + //USHORT usUpperOpticalPointSize; + + public: + DEFINE_SIZE_STATIC (78); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_OS2_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-post-table.hh b/gfx/harfbuzz/src/hb-ot-post-table.hh new file mode 100644 index 000000000..82ab3882a --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-post-table.hh @@ -0,0 +1,119 @@ +/* + * Copyright © 2016 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_POST_TABLE_HH +#define HB_OT_POST_TABLE_HH + +#include "hb-open-type-private.hh" + + +namespace OT { + + +/* + * post -- PostScript + */ + +#define HB_OT_TAG_post HB_TAG('p','o','s','t') + + +struct postV2Tail +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (numberOfGlyphs.sanitize (c) && + c->check_array (glyphNameIndex, sizeof (USHORT), numberOfGlyphs)); + } + + USHORT numberOfGlyphs; /* Number of glyphs (this should be the + * same as numGlyphs in 'maxp' table). */ + USHORT glyphNameIndex[VAR]; /* This is not an offset, but is the + * ordinal number of the glyph in 'post' + * string tables. */ + BYTE namesX[VAR]; /* Glyph names with length bytes [variable] + * (a Pascal string). */ + + DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX); +}; + +struct post +{ + static const hb_tag_t tableTag = HB_OT_TAG_post; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!c->check_struct (this))) + return_trace (false); + if (version.to_int () == 0x00020000) + { + const postV2Tail &v2 = StructAfter(*this); + return_trace (v2.sanitize (c)); + } + return_trace (true); + } + + public: + FixedVersion<>version; /* 0x00010000 for version 1.0 + * 0x00020000 for version 2.0 + * 0x00025000 for version 2.5 (deprecated) + * 0x00030000 for version 3.0 */ + Fixed italicAngle; /* Italic angle in counter-clockwise degrees + * from the vertical. Zero for upright text, + * negative for text that leans to the right + * (forward). */ + FWORD underlinePosition; /* This is the suggested distance of the top + * of the underline from the baseline + * (negative values indicate below baseline). + * The PostScript definition of this FontInfo + * dictionary key (the y coordinate of the + * center of the stroke) is not used for + * historical reasons. The value of the + * PostScript key may be calculated by + * subtracting half the underlineThickness + * from the value of this field. */ + FWORD underlineThickness; /* Suggested values for the underline + thickness. */ + ULONG isFixedPitch; /* Set to 0 if the font is proportionally + * spaced, non-zero if the font is not + * proportionally spaced (i.e. monospaced). */ + ULONG minMemType42; /* Minimum memory usage when an OpenType font + * is downloaded. */ + ULONG maxMemType42; /* Maximum memory usage when an OpenType font + * is downloaded. */ + ULONG minMemType1; /* Minimum memory usage when an OpenType font + * is downloaded as a Type 1 font. */ + ULONG maxMemType1; /* Maximum memory usage when an OpenType font + * is downloaded as a Type 1 font. */ +/*postV2Tail v2[VAR];*/ + DEFINE_SIZE_STATIC (32); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_POST_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh index 80d504435..228f36659 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh @@ -6,10 +6,10 @@ * * on files with these headers: * - * # ArabicShaping-8.0.0.txt - * # Date: 2015-02-17, 23:33:00 GMT [RP] - * # Blocks-8.0.0.txt - * # Date: 2014-11-10, 23:04:00 GMT [KW] + * # ArabicShaping-9.0.0.txt + * # Date: 2016-02-24, 22:25:00 GMT [RP] + * # Blocks-9.0.0.txt + * # Date: 2016-02-05, 23:48:00 GMT [KW] * UnicodeData.txt does not have a header. */ @@ -19,6 +19,7 @@ #define X JOINING_TYPE_X #define R JOINING_TYPE_R +#define T JOINING_TYPE_T #define U JOINING_TYPE_U #define A JOINING_GROUP_ALAPH #define DR JOINING_GROUP_DALATH_RISH @@ -76,9 +77,11 @@ static const uint8_t joining_table[] = /* Arabic Extended-A */ - /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D, + /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,X,D,D,D,R,D,D,D,D,X,X, + /* 08C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, + /* 08E0 */ X,X,U, -#define joining_offset_0x1806u 693 +#define joining_offset_0x1806u 739 /* Mongolian */ @@ -86,43 +89,48 @@ static const uint8_t joining_table[] = /* 1820 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, /* 1840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, /* 1860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X, - /* 1880 */ U,U,U,U,U,U,U,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, + /* 1880 */ U,U,U,U,U,T,T,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, /* 18A0 */ D,D,D,D,D,D,D,D,D,X,D, -#define joining_offset_0x200cu 858 +#define joining_offset_0x200cu 904 /* General Punctuation */ - /* 2000 */ U,C, + /* 2000 */ U,C,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, + /* 2020 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, + /* 2040 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, + /* 2060 */ X,X,X,X,X,X,U,U,U,U, -#define joining_offset_0x2066u 860 - - /* General Punctuation */ - - /* 2060 */ U,U,U,U, - -#define joining_offset_0xa840u 864 +#define joining_offset_0xa840u 998 /* Phags-pa */ /* A840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, /* A860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,L,U, -#define joining_offset_0x10ac0u 916 +#define joining_offset_0x10ac0u 1050 /* Manichaean */ /* 10AC0 */ D,D,D,D,D,R,U,R,U,R,R,U,U,L,R,R,R,R,R,D,D,D,D,L,D,D,D,D,D,R,D,D, /* 10AE0 */ D,R,U,U,R,X,X,X,X,X,X,D,D,D,D,R, -#define joining_offset_0x10b80u 964 +#define joining_offset_0x10b80u 1098 /* Psalter Pahlavi */ /* 10B80 */ D,R,D,R,R,R,D,D,D,R,D,D,R,D,R,R,D,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X, /* 10BA0 */ X,X,X,X,X,X,X,X,X,R,R,R,R,D,D,U, -}; /* Table items: 1012; occupancy: 57% */ +#define joining_offset_0x1e900u 1146 + + /* Adlam */ + + /* 1E900 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, + /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, + /* 1E940 */ D,D,D,D, + +}; /* Table items: 1214; occupancy: 54% */ static unsigned int @@ -131,25 +139,28 @@ joining_type (hb_codepoint_t u) switch (u >> 12) { case 0x0u: - if (hb_in_range (u, 0x0600u, 0x08B4u)) return joining_table[u - 0x0600u + joining_offset_0x0600u]; + if (hb_in_range (u, 0x0600u, 0x08E2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u]; break; case 0x1u: - if (hb_in_range (u, 0x1806u, 0x18AAu)) return joining_table[u - 0x1806u + joining_offset_0x1806u]; + if (hb_in_range (u, 0x1806u, 0x18AAu)) return joining_table[u - 0x1806u + joining_offset_0x1806u]; break; case 0x2u: - if (hb_in_range (u, 0x200Cu, 0x200Du)) return joining_table[u - 0x200Cu + joining_offset_0x200cu]; - if (hb_in_range (u, 0x2066u, 0x2069u)) return joining_table[u - 0x2066u + joining_offset_0x2066u]; + if (hb_in_range (u, 0x200Cu, 0x2069u)) return joining_table[u - 0x200Cu + joining_offset_0x200cu]; break; case 0xAu: - if (hb_in_range (u, 0xA840u, 0xA873u)) return joining_table[u - 0xA840u + joining_offset_0xa840u]; + if (hb_in_range (u, 0xA840u, 0xA873u)) return joining_table[u - 0xA840u + joining_offset_0xa840u]; break; case 0x10u: - if (hb_in_range (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u]; - if (hb_in_range (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u]; + if (hb_in_range (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u]; + if (hb_in_range (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u]; + break; + + case 0x1Eu: + if (hb_in_range (u, 0x1E900u, 0x1E943u)) return joining_table[u - 0x1E900u + joining_offset_0x1e900u]; break; default: @@ -160,6 +171,7 @@ joining_type (hb_codepoint_t u) #undef X #undef R +#undef T #undef U #undef A #undef DR diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc index 507547714..ed7b3f2dd 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc @@ -199,6 +199,9 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) * work. However, testing shows that rlig and calt are applied * together for Mongolian in Uniscribe. As such, we only add a * pause for Arabic, not other scripts. + * + * A pause after calt is required to make KFGQPC Uthmanic Script HAFS + * work correctly. See https://github.com/behdad/harfbuzz/issues/505 */ map->add_gsub_pause (nuke_joiners); @@ -222,6 +225,8 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) if (plan->props.script == HB_SCRIPT_ARABIC) map->add_gsub_pause (arabic_fallback_shape); + /* No pause after rclt. See 98460779bae19e4d64d29461ff154b3527bf8420. */ + map->add_global_bool_feature (HB_TAG('r','c','l','t')); map->add_global_bool_feature (HB_TAG('c','a','l','t')); map->add_gsub_pause (NULL); @@ -316,7 +321,10 @@ arabic_joining (hb_buffer_t *buffer) const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; if (entry->prev_action != NONE && prev != (unsigned int) -1) + { info[prev].arabic_shaping_action() = entry->prev_action; + buffer->unsafe_to_break (prev, i + 1); + } info[i].arabic_shaping_action() = entry->curr_action; @@ -345,7 +353,7 @@ mongolian_variation_selectors (hb_buffer_t *buffer) unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 1; i < count; i++) - if (unlikely (hb_in_range (info[i].codepoint, 0x180Bu, 0x180Du))) + if (unlikely (hb_in_range (info[i].codepoint, 0x180Bu, 0x180Du))) info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action(); } @@ -463,10 +471,6 @@ apply_stch (const hb_ot_shape_plan_t *plan, * Second pass applies the stretch, copying things to the end of buffer. */ - /* 30 = 2048 / 70. - * https://www.microsoft.com/typography/cursivescriptguidelines.mspx */ - hb_position_t overlap = font->x_scale / 30; - DEBUG_MSG (ARABIC, NULL, "overlap for stretching is %d", overlap); int sign = font->x_scale < 0 ? -1 : +1; unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT typedef enum { MEASURE, CUT } step_t; @@ -504,18 +508,15 @@ apply_stch (const hb_ot_shape_plan_t *plan, hb_in_range (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING)) { i--; - hb_glyph_extents_t extents; - if (!font->get_glyph_extents (info[i].codepoint, &extents)) - extents.width = 0; - extents.width -= overlap; + hb_position_t width = font->get_glyph_h_advance (info[i].codepoint); if (info[i].arabic_shaping_action() == STCH_FIXED) { - w_fixed += extents.width; + w_fixed += width; n_fixed++; } else { - w_repeating += extents.width; + w_repeating += width; n_repeating++; } } @@ -540,9 +541,20 @@ apply_stch (const hb_ot_shape_plan_t *plan, /* Number of additional times to repeat each repeating tile. */ int n_copies = 0; - hb_position_t w_remaining = w_total - w_fixed - overlap; + hb_position_t w_remaining = w_total - w_fixed; if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0) - n_copies = (sign * w_remaining + sign * w_repeating / 4) / (sign * w_repeating) - 1; + n_copies = (sign * w_remaining) / (sign * w_repeating) - 1; + + /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */ + hb_position_t extra_repeat_overlap = 0; + hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1); + if (shortfall > 0 && n_repeating > 0) + { + ++n_copies; + hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining; + if (excess > 0) + extra_repeat_overlap = excess / (n_copies * n_repeating); + } if (step == MEASURE) { @@ -551,13 +563,10 @@ apply_stch (const hb_ot_shape_plan_t *plan, } else { - hb_position_t x_offset = -overlap; + hb_position_t x_offset = 0; for (unsigned int k = end; k > start; k--) { - hb_glyph_extents_t extents; - if (!font->get_glyph_extents (info[k - 1].codepoint, &extents)) - extents.width = 0; - extents.width -= overlap; + hb_position_t width = font->get_glyph_h_advance (info[k - 1].codepoint); unsigned int repeat = 1; if (info[k - 1].arabic_shaping_action() == STCH_REPEATING) @@ -567,7 +576,9 @@ apply_stch (const hb_ot_shape_plan_t *plan, repeat, info[k - 1].codepoint, j); for (unsigned int n = 0; n < repeat; n++) { - x_offset -= extents.width; + x_offset -= width; + if (n > 0) + x_offset += extra_repeat_overlap; pos[k - 1].x_offset = x_offset; /* Append copy. */ --j; @@ -615,6 +626,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = NULL, /* decompose */ NULL, /* compose */ setup_masks_arabic, + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc index 1e441fa55..42830ab61 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc @@ -40,6 +40,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default = NULL, /* decompose */ NULL, /* compose */ NULL, /* setup_masks */ - HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, + NULL, /* disable_otl */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc index 5f4d98b70..0e74802ee 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc @@ -32,7 +32,7 @@ /* Same order as the feature array below */ enum { - NONE, + _JMO, LJMO, VJMO, @@ -105,16 +105,16 @@ data_destroy_hangul (void *data) #define NCount (VCount * TCount) #define SCount (LCount * NCount) -#define isCombiningL(u) (hb_in_range ((u), LBase, LBase+LCount-1)) -#define isCombiningV(u) (hb_in_range ((u), VBase, VBase+VCount-1)) -#define isCombiningT(u) (hb_in_range ((u), TBase+1, TBase+TCount-1)) -#define isCombinedS(u) (hb_in_range ((u), SBase, SBase+SCount-1)) +#define isCombiningL(u) (hb_in_range ((u), LBase, LBase+LCount-1)) +#define isCombiningV(u) (hb_in_range ((u), VBase, VBase+VCount-1)) +#define isCombiningT(u) (hb_in_range ((u), TBase+1, TBase+TCount-1)) +#define isCombinedS(u) (hb_in_range ((u), SBase, SBase+SCount-1)) -#define isL(u) (hb_in_ranges ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu)) -#define isV(u) (hb_in_ranges ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u)) -#define isT(u) (hb_in_ranges ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu)) +#define isL(u) (hb_in_ranges ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu)) +#define isV(u) (hb_in_ranges ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u)) +#define isT(u) (hb_in_ranges ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu)) -#define isHangulTone(u) (hb_in_range ((u), 0x302Eu, 0x302Fu)) +#define isHangulTone(u) (hb_in_range ((u), 0x302Eu, 0x302Fu)) /* buffer var allocations */ #define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */ @@ -202,6 +202,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan, if (start < end && end == buffer->out_len) { /* Tone mark follows a valid syllable; move it in front, unless it's zero width. */ + buffer->unsafe_to_break_from_outbuffer (start, buffer->idx); buffer->next_glyph (); if (!is_zero_width_char (font, u)) { @@ -258,6 +259,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan, else t = 0; /* The next character was not a trailing jamo. */ } + buffer->unsafe_to_break (buffer->idx, buffer->idx + (t ? 3 : 2)); /* We've got a syllable ; see if it can potentially be composed. */ if (isCombiningL (l) && isCombiningV (v) && (t == 0 || isCombiningT (t))) @@ -322,6 +324,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan, end = start + 1; continue; } + else + buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */ } /* Otherwise, decompose if font doesn't support or , @@ -368,6 +372,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan, buffer->merge_out_clusters (start, end); continue; } + else if ((!tindex && buffer->idx + 1 < count && isT (buffer->cur(+1).codepoint))) + buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */ } if (has_glyph) @@ -419,6 +425,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul = NULL, /* decompose */ NULL, /* compose */ setup_masks_hangul, + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc index 62825fa86..96f249461 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc @@ -68,7 +68,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c, 0xFB4Au /* TAV */ }; - bool found = c->unicode->compose (a, b, ab); + bool found = (bool) c->unicode->compose (a, b, ab); if (!found && !c->plan->has_mark) { @@ -154,6 +154,18 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c, return found; } +static bool +disable_otl_hebrew (const hb_ot_shape_plan_t *plan) +{ + /* For Hebrew shaper, use fallback if GPOS does not have 'hebr' + * script. This matches Uniscribe better, and makes fonts like + * Arial that have GSUB/GPOS/GDEF but no data for Hebrew work. + * See: + * https://github.com/behdad/harfbuzz/issues/347#issuecomment-267838368 + */ + return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r'); +} + const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = { @@ -168,6 +180,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = NULL, /* decompose */ compose_hebrew, NULL, /* setup_masks */ + disable_otl_hebrew, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; 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 f652d4fda..5a7a265c8 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh @@ -56,52 +56,52 @@ static const unsigned char _indic_syllable_machine_trans_keys[] = { 5u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 8u, 8u, 1u, 16u, 8u, 13u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, - 16u, 16u, 8u, 8u, 1u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, - 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, - 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, + 16u, 16u, 8u, 8u, 1u, 18u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, + 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, + 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 14u, 5u, 14u, 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, 3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, - 5u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, - 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, - 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, - 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, - 1u, 16u, 3u, 31u, 3u, 31u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, - 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, - 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, - 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, - 3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, - 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, - 5u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, - 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, - 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, - 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, - 4u, 14u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, - 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, - 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, 5u, 10u, + 5u, 14u, 3u, 14u, 1u, 16u, 4u, 14u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, + 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, + 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 14u, 5u, 14u, 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, 3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, - 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, - 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, - 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, - 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, - 4u, 14u, 3u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, - 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, - 3u, 31u, 4u, 31u, 1u, 16u, 3u, 31u, 3u, 31u, 4u, 31u, 5u, 14u, 5u, 14u, - 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, - 3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, + 3u, 14u, 1u, 16u, 4u, 14u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 14u, 1u, 16u, + 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, + 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, + 3u, 17u, 3u, 17u, 4u, 17u, 5u, 14u, 5u, 14u, 5u, 10u, 9u, 10u, 9u, 9u, + 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, 3u, 10u, 5u, 10u, 3u, 10u, + 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, + 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 1u, 16u, + 4u, 14u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, + 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, + 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 14u, 3u, 17u, 4u, 14u, + 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, + 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, + 3u, 17u, 3u, 17u, 4u, 17u, 5u, 14u, 5u, 14u, 5u, 10u, 9u, 10u, 9u, 9u, + 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, 3u, 10u, 5u, 10u, 3u, 10u, + 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, + 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 1u, 16u, + 4u, 14u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, + 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, + 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, + 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 1u, 17u, 3u, 17u, + 1u, 17u, 4u, 14u, 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, + 5u, 10u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 3u, 17u, 3u, 17u, 1u, 16u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, - 5u, 14u, 3u, 14u, 1u, 16u, 4u, 31u, 4u, 14u, 3u, 31u, 3u, 31u, 1u, 16u, - 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, - 1u, 16u, 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, - 1u, 16u, 1u, 16u, 3u, 31u, 3u, 31u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, - 1u, 16u, 3u, 31u, 1u, 31u, 3u, 31u, 1u, 31u, 4u, 14u, 5u, 10u, 9u, 10u, - 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 1u, 16u, 3u, 31u, 3u, 31u, - 4u, 31u, 3u, 31u, 3u, 31u, 1u, 16u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, - 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, - 3u, 13u, 3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 3u, 10u, 5u, 10u, - 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 0 + 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 13u, 3u, 10u, 5u, 10u, 3u, 10u, + 3u, 13u, 1u, 16u, 3u, 10u, 5u, 10u, 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, + 9u, 10u, 9u, 9u, 5u, 10u, 0 }; static const char _indic_syllable_machine_key_spans[] = { @@ -127,52 +127,52 @@ static const char _indic_syllable_machine_key_spans[] = { 3, 4, 3, 1, 4, 3, 1, 4, 3, 1, 1, 16, 6, 5, 1, 1, 5, 1, 1, 5, 1, 1, 5, 1, - 1, 1, 31, 29, 29, 28, 16, 29, - 29, 28, 16, 29, 29, 28, 16, 29, - 29, 28, 16, 29, 29, 28, 10, 10, + 1, 1, 18, 15, 15, 14, 16, 15, + 15, 14, 16, 15, 15, 14, 16, 15, + 15, 14, 16, 15, 15, 14, 10, 10, 6, 2, 1, 2, 2, 1, 6, 11, 8, 6, 8, 11, 12, 12, 11, 10, 12, 11, 10, 12, 11, 10, 12, 11, - 10, 12, 16, 28, 11, 29, 29, 16, - 16, 16, 16, 16, 29, 29, 16, 16, - 16, 16, 16, 29, 29, 16, 16, 16, - 16, 16, 29, 29, 16, 16, 16, 16, - 16, 29, 29, 29, 29, 28, 16, 29, - 29, 28, 16, 29, 29, 28, 16, 29, - 29, 28, 16, 29, 29, 28, 10, 10, - 6, 2, 1, 2, 2, 1, 6, 11, - 8, 6, 8, 11, 12, 12, 11, 10, - 12, 11, 10, 12, 11, 10, 12, 11, - 10, 12, 16, 28, 11, 29, 29, 16, - 16, 16, 16, 16, 29, 29, 16, 16, - 16, 16, 16, 29, 29, 16, 16, 16, - 16, 16, 29, 29, 16, 16, 16, 16, - 11, 16, 29, 29, 28, 16, 29, 29, - 28, 16, 29, 29, 28, 16, 29, 29, - 28, 16, 29, 29, 28, 10, 10, 6, + 10, 12, 16, 11, 15, 15, 16, 16, + 16, 16, 16, 15, 15, 16, 16, 16, + 16, 16, 15, 15, 16, 16, 16, 16, + 16, 15, 15, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 14, 16, 15, 15, + 14, 16, 15, 15, 14, 16, 15, 15, + 14, 16, 15, 15, 14, 10, 10, 6, 2, 1, 2, 2, 1, 6, 11, 8, 6, 8, 11, 12, 12, 11, 10, 12, 11, 10, 12, 11, 10, 12, 11, 10, - 12, 16, 28, 11, 29, 29, 16, 16, - 16, 16, 16, 29, 29, 16, 16, 16, - 16, 16, 29, 29, 16, 16, 16, 16, - 16, 29, 29, 16, 16, 16, 16, 16, - 11, 29, 11, 29, 29, 28, 16, 29, - 29, 28, 16, 29, 29, 28, 16, 29, - 29, 28, 16, 29, 29, 28, 10, 10, - 6, 2, 1, 2, 2, 1, 6, 11, - 8, 6, 8, 11, 12, 12, 11, 10, + 12, 16, 11, 15, 15, 16, 16, 16, + 16, 16, 15, 15, 16, 16, 16, 16, + 16, 15, 15, 16, 16, 16, 16, 16, + 15, 15, 16, 16, 16, 16, 11, 16, + 15, 15, 14, 16, 15, 15, 14, 16, + 15, 15, 14, 16, 15, 15, 14, 16, + 15, 15, 14, 10, 10, 6, 2, 1, + 2, 2, 1, 6, 11, 8, 6, 8, + 11, 12, 12, 11, 10, 12, 11, 10, + 12, 11, 10, 12, 11, 10, 12, 16, + 11, 15, 15, 16, 16, 16, 16, 16, + 15, 15, 16, 16, 16, 16, 16, 15, + 15, 16, 16, 16, 16, 16, 15, 15, + 16, 16, 16, 16, 16, 11, 15, 11, + 15, 15, 14, 16, 15, 15, 14, 16, + 15, 15, 14, 16, 15, 15, 14, 16, + 15, 15, 14, 10, 10, 6, 2, 1, + 2, 2, 1, 6, 11, 8, 6, 8, + 11, 12, 12, 11, 10, 12, 11, 10, + 12, 11, 10, 12, 11, 10, 12, 16, + 11, 15, 15, 16, 16, 16, 16, 16, + 15, 15, 16, 16, 16, 16, 16, 15, + 15, 16, 16, 16, 16, 16, 15, 15, + 16, 16, 16, 16, 16, 15, 17, 15, + 17, 11, 6, 2, 1, 2, 2, 1, + 6, 16, 15, 15, 14, 15, 15, 16, 12, 11, 10, 12, 11, 10, 12, 11, - 10, 12, 16, 28, 11, 29, 29, 16, - 16, 16, 16, 16, 29, 29, 16, 16, - 16, 16, 16, 29, 29, 16, 16, 16, - 16, 16, 29, 29, 16, 16, 16, 16, - 16, 29, 31, 29, 31, 11, 6, 2, - 1, 2, 2, 1, 6, 16, 29, 29, - 28, 29, 29, 16, 12, 11, 10, 12, - 11, 10, 12, 11, 10, 12, 11, 10, - 11, 8, 6, 8, 11, 16, 8, 6, - 6, 2, 1, 2, 2, 1, 6 + 10, 12, 11, 10, 11, 8, 6, 8, + 11, 16, 8, 6, 6, 2, 1, 2, + 2, 1, 6 }; static const short _indic_syllable_machine_index_offsets[] = { @@ -198,52 +198,52 @@ static const short _indic_syllable_machine_index_offsets[] = { 954, 958, 963, 967, 969, 974, 978, 980, 985, 989, 991, 993, 1010, 1017, 1023, 1025, 1027, 1033, 1035, 1037, 1043, 1045, 1047, 1053, - 1055, 1057, 1059, 1091, 1121, 1151, 1180, 1197, - 1227, 1257, 1286, 1303, 1333, 1363, 1392, 1409, - 1439, 1469, 1498, 1515, 1545, 1575, 1604, 1615, - 1626, 1633, 1636, 1638, 1641, 1644, 1646, 1653, - 1665, 1674, 1681, 1690, 1702, 1715, 1728, 1740, - 1751, 1764, 1776, 1787, 1800, 1812, 1823, 1836, - 1848, 1859, 1872, 1889, 1918, 1930, 1960, 1990, - 2007, 2024, 2041, 2058, 2075, 2105, 2135, 2152, - 2169, 2186, 2203, 2220, 2250, 2280, 2297, 2314, - 2331, 2348, 2365, 2395, 2425, 2442, 2459, 2476, - 2493, 2510, 2540, 2570, 2600, 2630, 2659, 2676, - 2706, 2736, 2765, 2782, 2812, 2842, 2871, 2888, - 2918, 2948, 2977, 2994, 3024, 3054, 3083, 3094, - 3105, 3112, 3115, 3117, 3120, 3123, 3125, 3132, - 3144, 3153, 3160, 3169, 3181, 3194, 3207, 3219, - 3230, 3243, 3255, 3266, 3279, 3291, 3302, 3315, - 3327, 3338, 3351, 3368, 3397, 3409, 3439, 3469, - 3486, 3503, 3520, 3537, 3554, 3584, 3614, 3631, - 3648, 3665, 3682, 3699, 3729, 3759, 3776, 3793, - 3810, 3827, 3844, 3874, 3904, 3921, 3938, 3955, - 3972, 3984, 4001, 4031, 4061, 4090, 4107, 4137, - 4167, 4196, 4213, 4243, 4273, 4302, 4319, 4349, - 4379, 4408, 4425, 4455, 4485, 4514, 4525, 4536, - 4543, 4546, 4548, 4551, 4554, 4556, 4563, 4575, - 4584, 4591, 4600, 4612, 4625, 4638, 4650, 4661, - 4674, 4686, 4697, 4710, 4722, 4733, 4746, 4758, - 4769, 4782, 4799, 4828, 4840, 4870, 4900, 4917, - 4934, 4951, 4968, 4985, 5015, 5045, 5062, 5079, - 5096, 5113, 5130, 5160, 5190, 5207, 5224, 5241, - 5258, 5275, 5305, 5335, 5352, 5369, 5386, 5403, - 5420, 5432, 5462, 5474, 5504, 5534, 5563, 5580, - 5610, 5640, 5669, 5686, 5716, 5746, 5775, 5792, - 5822, 5852, 5881, 5898, 5928, 5958, 5987, 5998, - 6009, 6016, 6019, 6021, 6024, 6027, 6029, 6036, - 6048, 6057, 6064, 6073, 6085, 6098, 6111, 6123, - 6134, 6147, 6159, 6170, 6183, 6195, 6206, 6219, - 6231, 6242, 6255, 6272, 6301, 6313, 6343, 6373, - 6390, 6407, 6424, 6441, 6458, 6488, 6518, 6535, - 6552, 6569, 6586, 6603, 6633, 6663, 6680, 6697, - 6714, 6731, 6748, 6778, 6808, 6825, 6842, 6859, - 6876, 6893, 6923, 6955, 6985, 7017, 7029, 7036, - 7039, 7041, 7044, 7047, 7049, 7056, 7073, 7103, - 7133, 7162, 7192, 7222, 7239, 7252, 7264, 7275, - 7288, 7300, 7311, 7324, 7336, 7347, 7360, 7372, - 7383, 7395, 7404, 7411, 7420, 7432, 7449, 7458, - 7465, 7472, 7475, 7477, 7480, 7483, 7485 + 1055, 1057, 1059, 1078, 1094, 1110, 1125, 1142, + 1158, 1174, 1189, 1206, 1222, 1238, 1253, 1270, + 1286, 1302, 1317, 1334, 1350, 1366, 1381, 1392, + 1403, 1410, 1413, 1415, 1418, 1421, 1423, 1430, + 1442, 1451, 1458, 1467, 1479, 1492, 1505, 1517, + 1528, 1541, 1553, 1564, 1577, 1589, 1600, 1613, + 1625, 1636, 1649, 1666, 1678, 1694, 1710, 1727, + 1744, 1761, 1778, 1795, 1811, 1827, 1844, 1861, + 1878, 1895, 1912, 1928, 1944, 1961, 1978, 1995, + 2012, 2029, 2045, 2061, 2078, 2095, 2112, 2129, + 2146, 2162, 2178, 2194, 2210, 2225, 2242, 2258, + 2274, 2289, 2306, 2322, 2338, 2353, 2370, 2386, + 2402, 2417, 2434, 2450, 2466, 2481, 2492, 2503, + 2510, 2513, 2515, 2518, 2521, 2523, 2530, 2542, + 2551, 2558, 2567, 2579, 2592, 2605, 2617, 2628, + 2641, 2653, 2664, 2677, 2689, 2700, 2713, 2725, + 2736, 2749, 2766, 2778, 2794, 2810, 2827, 2844, + 2861, 2878, 2895, 2911, 2927, 2944, 2961, 2978, + 2995, 3012, 3028, 3044, 3061, 3078, 3095, 3112, + 3129, 3145, 3161, 3178, 3195, 3212, 3229, 3241, + 3258, 3274, 3290, 3305, 3322, 3338, 3354, 3369, + 3386, 3402, 3418, 3433, 3450, 3466, 3482, 3497, + 3514, 3530, 3546, 3561, 3572, 3583, 3590, 3593, + 3595, 3598, 3601, 3603, 3610, 3622, 3631, 3638, + 3647, 3659, 3672, 3685, 3697, 3708, 3721, 3733, + 3744, 3757, 3769, 3780, 3793, 3805, 3816, 3829, + 3846, 3858, 3874, 3890, 3907, 3924, 3941, 3958, + 3975, 3991, 4007, 4024, 4041, 4058, 4075, 4092, + 4108, 4124, 4141, 4158, 4175, 4192, 4209, 4225, + 4241, 4258, 4275, 4292, 4309, 4326, 4338, 4354, + 4366, 4382, 4398, 4413, 4430, 4446, 4462, 4477, + 4494, 4510, 4526, 4541, 4558, 4574, 4590, 4605, + 4622, 4638, 4654, 4669, 4680, 4691, 4698, 4701, + 4703, 4706, 4709, 4711, 4718, 4730, 4739, 4746, + 4755, 4767, 4780, 4793, 4805, 4816, 4829, 4841, + 4852, 4865, 4877, 4888, 4901, 4913, 4924, 4937, + 4954, 4966, 4982, 4998, 5015, 5032, 5049, 5066, + 5083, 5099, 5115, 5132, 5149, 5166, 5183, 5200, + 5216, 5232, 5249, 5266, 5283, 5300, 5317, 5333, + 5349, 5366, 5383, 5400, 5417, 5434, 5450, 5468, + 5484, 5502, 5514, 5521, 5524, 5526, 5529, 5532, + 5534, 5541, 5558, 5574, 5590, 5605, 5621, 5637, + 5654, 5667, 5679, 5690, 5703, 5715, 5726, 5739, + 5751, 5762, 5775, 5787, 5798, 5810, 5819, 5826, + 5835, 5847, 5864, 5873, 5880, 5887, 5890, 5892, + 5895, 5898, 5900 }; static const short _indic_syllable_machine_indicies[] = { @@ -381,882 +381,684 @@ static const short _indic_syllable_machine_indicies[] = { 161, 161, 162, 157, 0, 183, 0, 184, 0, 186, 185, 188, 189, 190, 191, 192, 193, 84, 79, 194, 195, 196, 196, 156, - 197, 198, 199, 200, 201, 187, 187, 187, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 202, 187, 204, 205, 206, 207, 6, - 1, 208, 209, 203, 203, 38, 210, 203, - 203, 211, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 212, - 203, 213, 205, 214, 214, 6, 1, 208, - 209, 203, 203, 203, 210, 203, 203, 211, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 212, 203, 205, - 214, 214, 6, 1, 208, 209, 203, 203, - 203, 210, 203, 203, 211, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 212, 203, 215, 203, 203, 203, - 19, 216, 203, 1, 208, 209, 203, 203, - 203, 217, 203, 215, 203, 218, 219, 220, - 221, 6, 1, 208, 209, 203, 203, 36, - 222, 203, 203, 211, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 212, 203, 223, 219, 224, 224, 6, - 1, 208, 209, 203, 203, 203, 222, 203, - 203, 211, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 212, - 203, 219, 224, 224, 6, 1, 208, 209, - 203, 203, 203, 222, 203, 203, 211, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 212, 203, 225, 203, - 203, 203, 19, 226, 203, 1, 208, 209, - 203, 203, 203, 217, 203, 225, 203, 227, - 228, 229, 230, 6, 1, 208, 209, 203, - 203, 34, 231, 203, 203, 211, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 212, 203, 232, 228, 233, - 233, 6, 1, 208, 209, 203, 203, 203, - 231, 203, 203, 211, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 212, 203, 228, 233, 233, 6, 1, - 208, 209, 203, 203, 203, 231, 203, 203, - 211, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 212, 203, - 234, 203, 203, 203, 19, 235, 203, 1, - 208, 209, 203, 203, 203, 217, 203, 234, - 203, 236, 237, 238, 239, 6, 1, 208, - 209, 203, 203, 32, 240, 203, 203, 211, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 212, 203, 241, - 237, 242, 242, 6, 1, 208, 209, 203, - 203, 203, 240, 203, 203, 211, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 212, 203, 237, 242, 242, - 6, 1, 208, 209, 203, 203, 203, 240, - 203, 203, 211, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 212, 203, 243, 203, 203, 203, 19, 244, - 203, 1, 208, 209, 203, 203, 203, 217, - 203, 243, 203, 245, 246, 247, 248, 6, - 1, 208, 209, 203, 203, 30, 249, 203, - 203, 211, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 212, - 203, 250, 246, 251, 251, 6, 1, 208, - 209, 203, 203, 203, 249, 203, 203, 211, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 212, 203, 246, - 251, 251, 6, 1, 208, 209, 203, 203, - 203, 249, 203, 203, 211, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 212, 203, 19, 252, 203, 1, - 208, 209, 203, 203, 203, 217, 203, 253, - 253, 203, 1, 208, 209, 203, 203, 203, - 217, 203, 254, 203, 203, 255, 208, 209, - 203, 208, 209, 203, 256, 203, 208, 257, - 203, 208, 258, 203, 208, 203, 254, 203, - 203, 203, 208, 209, 203, 259, 203, 260, - 261, 203, 1, 208, 209, 203, 203, 4, - 203, 3, 203, 253, 253, 203, 1, 208, - 209, 203, 253, 253, 203, 1, 208, 209, - 203, 259, 203, 253, 253, 203, 1, 208, - 209, 203, 259, 203, 260, 253, 203, 1, - 208, 209, 203, 203, 4, 203, 19, 203, - 262, 262, 6, 1, 208, 209, 203, 203, - 203, 217, 203, 263, 28, 264, 265, 9, - 1, 208, 209, 203, 203, 203, 217, 203, - 28, 264, 265, 9, 1, 208, 209, 203, - 203, 203, 217, 203, 264, 264, 9, 1, - 208, 209, 203, 203, 203, 217, 203, 266, - 25, 267, 268, 12, 1, 208, 209, 203, - 203, 203, 217, 203, 25, 267, 268, 12, - 1, 208, 209, 203, 203, 203, 217, 203, - 267, 267, 12, 1, 208, 209, 203, 203, - 203, 217, 203, 269, 22, 270, 271, 15, - 1, 208, 209, 203, 203, 203, 217, 203, - 22, 270, 271, 15, 1, 208, 209, 203, - 203, 203, 217, 203, 270, 270, 15, 1, - 208, 209, 203, 203, 203, 217, 203, 272, - 19, 253, 273, 203, 1, 208, 209, 203, - 203, 203, 217, 203, 19, 253, 273, 203, - 1, 208, 209, 203, 203, 203, 217, 203, - 253, 274, 203, 1, 208, 209, 203, 203, - 203, 217, 203, 19, 203, 253, 253, 203, - 1, 208, 209, 203, 203, 203, 217, 203, - 2, 3, 203, 203, 19, 252, 203, 1, - 208, 209, 203, 203, 203, 217, 203, 2, - 203, 246, 251, 251, 6, 1, 208, 209, - 203, 203, 203, 249, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 212, 203, 246, 251, - 251, 6, 1, 208, 209, 203, 203, 203, - 249, 203, 245, 246, 251, 251, 6, 1, - 208, 209, 203, 203, 203, 249, 203, 203, - 211, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 212, 203, - 245, 246, 247, 251, 6, 1, 208, 209, - 203, 203, 30, 249, 203, 203, 211, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 212, 203, 243, 203, - 275, 203, 262, 262, 6, 1, 208, 209, - 203, 203, 203, 217, 203, 243, 203, 243, - 203, 203, 203, 253, 253, 203, 1, 208, - 209, 203, 203, 203, 217, 203, 243, 203, - 243, 203, 203, 203, 253, 276, 203, 1, - 208, 209, 203, 203, 203, 217, 203, 243, - 203, 243, 203, 275, 203, 253, 253, 203, - 1, 208, 209, 203, 203, 203, 217, 203, - 243, 203, 243, 3, 203, 203, 19, 244, - 203, 1, 208, 209, 203, 203, 203, 217, - 203, 243, 203, 236, 237, 242, 242, 6, - 1, 208, 209, 203, 203, 203, 240, 203, - 203, 211, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 212, - 203, 236, 237, 238, 242, 6, 1, 208, - 209, 203, 203, 32, 240, 203, 203, 211, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 212, 203, 234, - 203, 277, 203, 262, 262, 6, 1, 208, - 209, 203, 203, 203, 217, 203, 234, 203, - 234, 203, 203, 203, 253, 253, 203, 1, - 208, 209, 203, 203, 203, 217, 203, 234, - 203, 234, 203, 203, 203, 253, 278, 203, - 1, 208, 209, 203, 203, 203, 217, 203, - 234, 203, 234, 203, 277, 203, 253, 253, - 203, 1, 208, 209, 203, 203, 203, 217, - 203, 234, 203, 234, 3, 203, 203, 19, - 235, 203, 1, 208, 209, 203, 203, 203, - 217, 203, 234, 203, 227, 228, 233, 233, - 6, 1, 208, 209, 203, 203, 203, 231, - 203, 203, 211, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 212, 203, 227, 228, 229, 233, 6, 1, - 208, 209, 203, 203, 34, 231, 203, 203, - 211, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 212, 203, - 225, 203, 279, 203, 262, 262, 6, 1, - 208, 209, 203, 203, 203, 217, 203, 225, - 203, 225, 203, 203, 203, 253, 253, 203, - 1, 208, 209, 203, 203, 203, 217, 203, - 225, 203, 225, 203, 203, 203, 253, 280, - 203, 1, 208, 209, 203, 203, 203, 217, - 203, 225, 203, 225, 203, 279, 203, 253, - 253, 203, 1, 208, 209, 203, 203, 203, - 217, 203, 225, 203, 225, 3, 203, 203, - 19, 226, 203, 1, 208, 209, 203, 203, - 203, 217, 203, 225, 203, 218, 219, 224, - 224, 6, 1, 208, 209, 203, 203, 203, - 222, 203, 203, 211, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 212, 203, 218, 219, 220, 224, 6, - 1, 208, 209, 203, 203, 36, 222, 203, - 203, 211, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 212, - 203, 215, 203, 281, 203, 262, 262, 6, - 1, 208, 209, 203, 203, 203, 217, 203, - 215, 203, 215, 203, 203, 203, 253, 253, - 203, 1, 208, 209, 203, 203, 203, 217, - 203, 215, 203, 215, 203, 203, 203, 253, - 282, 203, 1, 208, 209, 203, 203, 203, - 217, 203, 215, 203, 215, 203, 281, 203, - 253, 253, 203, 1, 208, 209, 203, 203, - 203, 217, 203, 215, 203, 215, 3, 203, - 203, 19, 216, 203, 1, 208, 209, 203, - 203, 203, 217, 203, 215, 203, 204, 205, - 214, 214, 6, 1, 208, 209, 203, 203, - 203, 210, 203, 203, 211, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 212, 203, 204, 205, 206, 214, - 6, 1, 208, 209, 203, 203, 38, 210, - 203, 203, 211, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 212, 203, 284, 285, 286, 287, 45, 40, - 288, 289, 283, 283, 77, 290, 283, 283, - 291, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 292, 283, - 293, 285, 294, 287, 45, 40, 288, 289, - 283, 283, 283, 290, 283, 283, 291, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 292, 283, 285, 294, - 287, 45, 40, 288, 289, 283, 283, 283, - 290, 283, 283, 291, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 292, 283, 295, 283, 283, 283, 58, - 296, 283, 40, 288, 289, 283, 283, 283, - 297, 283, 295, 283, 298, 299, 300, 301, - 45, 40, 288, 289, 283, 283, 75, 302, - 283, 283, 291, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 292, 283, 303, 299, 304, 304, 45, 40, - 288, 289, 283, 283, 283, 302, 283, 283, - 291, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 292, 283, - 299, 304, 304, 45, 40, 288, 289, 283, - 283, 283, 302, 283, 283, 291, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 292, 283, 305, 283, 283, - 283, 58, 306, 283, 40, 288, 289, 283, - 283, 283, 297, 283, 305, 283, 307, 308, - 309, 310, 45, 40, 288, 289, 283, 283, - 73, 311, 283, 283, 291, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 292, 283, 312, 308, 313, 313, - 45, 40, 288, 289, 283, 283, 283, 311, - 283, 283, 291, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 292, 283, 308, 313, 313, 45, 40, 288, - 289, 283, 283, 283, 311, 283, 283, 291, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 292, 283, 314, - 283, 283, 283, 58, 315, 283, 40, 288, - 289, 283, 283, 283, 297, 283, 314, 283, - 316, 317, 318, 319, 45, 40, 288, 289, - 283, 283, 71, 320, 283, 283, 291, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 292, 283, 321, 317, - 322, 322, 45, 40, 288, 289, 283, 283, - 283, 320, 283, 283, 291, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 292, 283, 317, 322, 322, 45, - 40, 288, 289, 283, 283, 283, 320, 283, - 283, 291, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 292, - 283, 323, 283, 283, 283, 58, 324, 283, - 40, 288, 289, 283, 283, 283, 297, 283, - 323, 283, 325, 326, 327, 328, 45, 40, - 288, 289, 283, 283, 69, 329, 283, 283, - 291, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 292, 283, - 330, 326, 331, 331, 45, 40, 288, 289, - 283, 283, 283, 329, 283, 283, 291, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 292, 283, 326, 331, - 331, 45, 40, 288, 289, 283, 283, 283, - 329, 283, 283, 291, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 292, 283, 58, 332, 283, 40, 288, - 289, 283, 283, 283, 297, 283, 333, 333, - 283, 40, 288, 289, 283, 283, 283, 297, - 283, 334, 283, 283, 335, 288, 289, 283, - 288, 289, 283, 336, 283, 288, 337, 283, - 288, 338, 283, 288, 283, 334, 283, 283, - 283, 288, 289, 283, 339, 283, 340, 341, - 283, 40, 288, 289, 283, 283, 43, 283, - 42, 283, 333, 333, 283, 40, 288, 289, - 283, 333, 333, 283, 40, 288, 289, 283, - 339, 283, 333, 333, 283, 40, 288, 289, - 283, 339, 283, 340, 333, 283, 40, 288, - 289, 283, 283, 43, 283, 58, 283, 342, - 342, 45, 40, 288, 289, 283, 283, 283, - 297, 283, 343, 67, 344, 345, 48, 40, - 288, 289, 283, 283, 283, 297, 283, 67, - 344, 345, 48, 40, 288, 289, 283, 283, - 283, 297, 283, 344, 344, 48, 40, 288, - 289, 283, 283, 283, 297, 283, 346, 64, - 347, 348, 51, 40, 288, 289, 283, 283, - 283, 297, 283, 64, 347, 348, 51, 40, - 288, 289, 283, 283, 283, 297, 283, 347, - 347, 51, 40, 288, 289, 283, 283, 283, - 297, 283, 349, 61, 350, 351, 54, 40, - 288, 289, 283, 283, 283, 297, 283, 61, - 350, 351, 54, 40, 288, 289, 283, 283, - 283, 297, 283, 350, 350, 54, 40, 288, - 289, 283, 283, 283, 297, 283, 352, 58, - 333, 353, 283, 40, 288, 289, 283, 283, - 283, 297, 283, 58, 333, 353, 283, 40, - 288, 289, 283, 283, 283, 297, 283, 333, - 354, 283, 40, 288, 289, 283, 283, 283, - 297, 283, 58, 283, 333, 333, 283, 40, - 288, 289, 283, 283, 283, 297, 283, 41, - 42, 283, 283, 58, 332, 283, 40, 288, - 289, 283, 283, 283, 297, 283, 41, 283, - 326, 331, 331, 45, 40, 288, 289, 283, - 283, 283, 329, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 292, 283, 326, 331, 331, - 45, 40, 288, 289, 283, 283, 283, 329, - 283, 325, 326, 331, 331, 45, 40, 288, - 289, 283, 283, 283, 329, 283, 283, 291, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 292, 283, 325, - 326, 327, 331, 45, 40, 288, 289, 283, - 283, 69, 329, 283, 283, 291, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 292, 283, 323, 283, 355, - 283, 342, 342, 45, 40, 288, 289, 283, - 283, 283, 297, 283, 323, 283, 323, 283, - 283, 283, 333, 333, 283, 40, 288, 289, - 283, 283, 283, 297, 283, 323, 283, 323, - 283, 283, 283, 333, 356, 283, 40, 288, - 289, 283, 283, 283, 297, 283, 323, 283, - 323, 283, 355, 283, 333, 333, 283, 40, - 288, 289, 283, 283, 283, 297, 283, 323, - 283, 323, 42, 283, 283, 58, 324, 283, - 40, 288, 289, 283, 283, 283, 297, 283, - 323, 283, 316, 317, 322, 322, 45, 40, - 288, 289, 283, 283, 283, 320, 283, 283, - 291, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 292, 283, - 316, 317, 318, 322, 45, 40, 288, 289, - 283, 283, 71, 320, 283, 283, 291, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 292, 283, 314, 283, - 357, 283, 342, 342, 45, 40, 288, 289, - 283, 283, 283, 297, 283, 314, 283, 314, - 283, 283, 283, 333, 333, 283, 40, 288, - 289, 283, 283, 283, 297, 283, 314, 283, - 314, 283, 283, 283, 333, 358, 283, 40, - 288, 289, 283, 283, 283, 297, 283, 314, - 283, 314, 283, 357, 283, 333, 333, 283, - 40, 288, 289, 283, 283, 283, 297, 283, - 314, 283, 314, 42, 283, 283, 58, 315, - 283, 40, 288, 289, 283, 283, 283, 297, - 283, 314, 283, 307, 308, 313, 313, 45, - 40, 288, 289, 283, 283, 283, 311, 283, - 283, 291, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 292, - 283, 307, 308, 309, 313, 45, 40, 288, - 289, 283, 283, 73, 311, 283, 283, 291, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 292, 283, 305, - 283, 359, 283, 342, 342, 45, 40, 288, - 289, 283, 283, 283, 297, 283, 305, 283, - 305, 283, 283, 283, 333, 333, 283, 40, - 288, 289, 283, 283, 283, 297, 283, 305, - 283, 305, 283, 283, 283, 333, 360, 283, - 40, 288, 289, 283, 283, 283, 297, 283, - 305, 283, 305, 283, 359, 283, 333, 333, - 283, 40, 288, 289, 283, 283, 283, 297, - 283, 305, 283, 305, 42, 283, 283, 58, - 306, 283, 40, 288, 289, 283, 283, 283, - 297, 283, 305, 283, 298, 299, 304, 304, - 45, 40, 288, 289, 283, 283, 283, 302, - 283, 283, 291, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, - 292, 283, 298, 299, 300, 304, 45, 40, - 288, 289, 283, 283, 75, 302, 283, 283, - 291, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 292, 283, - 295, 283, 361, 283, 342, 342, 45, 40, - 288, 289, 283, 283, 283, 297, 283, 295, - 283, 295, 283, 283, 283, 333, 333, 283, - 40, 288, 289, 283, 283, 283, 297, 283, - 295, 283, 295, 283, 283, 283, 333, 362, - 283, 40, 288, 289, 283, 283, 283, 297, - 283, 295, 283, 295, 283, 361, 283, 333, - 333, 283, 40, 288, 289, 283, 283, 283, - 297, 283, 295, 283, 76, 44, 44, 45, - 40, 283, 283, 283, 283, 283, 76, 283, - 295, 42, 283, 283, 58, 296, 283, 40, - 288, 289, 283, 283, 283, 297, 283, 295, - 283, 284, 285, 294, 287, 45, 40, 288, - 289, 283, 283, 283, 290, 283, 283, 291, - 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 292, 283, 364, - 191, 365, 365, 84, 79, 194, 195, 363, - 363, 363, 197, 363, 363, 200, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 202, 363, 191, 365, 365, - 84, 79, 194, 195, 363, 363, 363, 197, - 363, 363, 200, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 202, 363, 366, 363, 363, 363, 98, 367, - 363, 79, 194, 195, 363, 363, 363, 368, - 363, 366, 363, 369, 370, 371, 372, 84, - 79, 194, 195, 363, 363, 115, 373, 363, - 363, 200, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 202, - 363, 374, 370, 375, 375, 84, 79, 194, - 195, 363, 363, 363, 373, 363, 363, 200, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 202, 363, 370, - 375, 375, 84, 79, 194, 195, 363, 363, - 363, 373, 363, 363, 200, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 202, 363, 376, 363, 363, 363, - 98, 377, 363, 79, 194, 195, 363, 363, - 363, 368, 363, 376, 363, 378, 379, 380, - 381, 84, 79, 194, 195, 363, 363, 113, - 382, 363, 363, 200, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 202, 363, 383, 379, 384, 384, 84, - 79, 194, 195, 363, 363, 363, 382, 363, - 363, 200, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 202, - 363, 379, 384, 384, 84, 79, 194, 195, - 363, 363, 363, 382, 363, 363, 200, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 202, 363, 385, 363, - 363, 363, 98, 386, 363, 79, 194, 195, - 363, 363, 363, 368, 363, 385, 363, 387, - 388, 389, 390, 84, 79, 194, 195, 363, - 363, 111, 391, 363, 363, 200, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 202, 363, 392, 388, 393, - 393, 84, 79, 194, 195, 363, 363, 363, - 391, 363, 363, 200, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 202, 363, 388, 393, 393, 84, 79, - 194, 195, 363, 363, 363, 391, 363, 363, - 200, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 202, 363, - 394, 363, 363, 363, 98, 395, 363, 79, - 194, 195, 363, 363, 363, 368, 363, 394, - 363, 396, 397, 398, 399, 84, 79, 194, - 195, 363, 363, 109, 400, 363, 363, 200, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 202, 363, 401, - 397, 402, 402, 84, 79, 194, 195, 363, - 363, 363, 400, 363, 363, 200, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 202, 363, 397, 402, 402, - 84, 79, 194, 195, 363, 363, 363, 400, - 363, 363, 200, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 202, 363, 98, 403, 363, 79, 194, 195, - 363, 363, 363, 368, 363, 404, 404, 363, - 79, 194, 195, 363, 363, 363, 368, 363, - 405, 363, 363, 406, 194, 195, 363, 194, - 195, 363, 407, 363, 194, 408, 363, 194, - 409, 363, 194, 363, 405, 363, 363, 363, - 194, 195, 363, 410, 363, 411, 412, 363, - 79, 194, 195, 363, 363, 82, 363, 81, - 363, 404, 404, 363, 79, 194, 195, 363, - 404, 404, 363, 79, 194, 195, 363, 410, - 363, 404, 404, 363, 79, 194, 195, 363, - 410, 363, 411, 404, 363, 79, 194, 195, - 363, 363, 82, 363, 98, 363, 413, 413, - 84, 79, 194, 195, 363, 363, 363, 368, - 363, 414, 107, 415, 416, 88, 79, 194, - 195, 363, 363, 363, 368, 363, 107, 415, - 416, 88, 79, 194, 195, 363, 363, 363, - 368, 363, 415, 415, 88, 79, 194, 195, - 363, 363, 363, 368, 363, 417, 104, 418, - 419, 91, 79, 194, 195, 363, 363, 363, - 368, 363, 104, 418, 419, 91, 79, 194, - 195, 363, 363, 363, 368, 363, 418, 418, - 91, 79, 194, 195, 363, 363, 363, 368, - 363, 420, 101, 421, 422, 94, 79, 194, - 195, 363, 363, 363, 368, 363, 101, 421, - 422, 94, 79, 194, 195, 363, 363, 363, - 368, 363, 421, 421, 94, 79, 194, 195, - 363, 363, 363, 368, 363, 423, 98, 404, - 424, 363, 79, 194, 195, 363, 363, 363, - 368, 363, 98, 404, 424, 363, 79, 194, - 195, 363, 363, 363, 368, 363, 404, 425, - 363, 79, 194, 195, 363, 363, 363, 368, - 363, 98, 363, 404, 404, 363, 79, 194, - 195, 363, 363, 363, 368, 363, 80, 81, - 363, 363, 98, 403, 363, 79, 194, 195, - 363, 363, 363, 368, 363, 80, 363, 397, - 402, 402, 84, 79, 194, 195, 363, 363, - 363, 400, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 202, 363, 397, 402, 402, 84, - 79, 194, 195, 363, 363, 363, 400, 363, - 396, 397, 402, 402, 84, 79, 194, 195, - 363, 363, 363, 400, 363, 363, 200, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 202, 363, 396, 397, - 398, 402, 84, 79, 194, 195, 363, 363, - 109, 400, 363, 363, 200, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 202, 363, 394, 363, 426, 363, - 413, 413, 84, 79, 194, 195, 363, 363, - 363, 368, 363, 394, 363, 394, 363, 363, - 363, 404, 404, 363, 79, 194, 195, 363, - 363, 363, 368, 363, 394, 363, 394, 363, - 363, 363, 404, 427, 363, 79, 194, 195, - 363, 363, 363, 368, 363, 394, 363, 394, - 363, 426, 363, 404, 404, 363, 79, 194, - 195, 363, 363, 363, 368, 363, 394, 363, - 394, 81, 363, 363, 98, 395, 363, 79, - 194, 195, 363, 363, 363, 368, 363, 394, - 363, 387, 388, 393, 393, 84, 79, 194, - 195, 363, 363, 363, 391, 363, 363, 200, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 202, 363, 387, - 388, 389, 393, 84, 79, 194, 195, 363, - 363, 111, 391, 363, 363, 200, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 202, 363, 385, 363, 428, - 363, 413, 413, 84, 79, 194, 195, 363, - 363, 363, 368, 363, 385, 363, 385, 363, - 363, 363, 404, 404, 363, 79, 194, 195, - 363, 363, 363, 368, 363, 385, 363, 385, - 363, 363, 363, 404, 429, 363, 79, 194, - 195, 363, 363, 363, 368, 363, 385, 363, - 385, 363, 428, 363, 404, 404, 363, 79, - 194, 195, 363, 363, 363, 368, 363, 385, - 363, 385, 81, 363, 363, 98, 386, 363, - 79, 194, 195, 363, 363, 363, 368, 363, - 385, 363, 378, 379, 384, 384, 84, 79, - 194, 195, 363, 363, 363, 382, 363, 363, - 200, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 202, 363, - 378, 379, 380, 384, 84, 79, 194, 195, - 363, 363, 113, 382, 363, 363, 200, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 202, 363, 376, 363, - 430, 363, 413, 413, 84, 79, 194, 195, - 363, 363, 363, 368, 363, 376, 363, 376, - 363, 363, 363, 404, 404, 363, 79, 194, - 195, 363, 363, 363, 368, 363, 376, 363, - 376, 363, 363, 363, 404, 431, 363, 79, - 194, 195, 363, 363, 363, 368, 363, 376, - 363, 376, 363, 430, 363, 404, 404, 363, - 79, 194, 195, 363, 363, 363, 368, 363, - 376, 363, 376, 81, 363, 363, 98, 377, - 363, 79, 194, 195, 363, 363, 363, 368, - 363, 376, 363, 369, 370, 375, 375, 84, - 79, 194, 195, 363, 363, 363, 373, 363, - 363, 200, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 202, - 363, 369, 370, 371, 375, 84, 79, 194, - 195, 363, 363, 115, 373, 363, 363, 200, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 202, 363, 366, - 363, 432, 363, 413, 413, 84, 79, 194, - 195, 363, 363, 363, 368, 363, 366, 363, - 366, 363, 363, 363, 404, 404, 363, 79, - 194, 195, 363, 363, 363, 368, 363, 366, - 363, 366, 363, 363, 363, 404, 433, 363, - 79, 194, 195, 363, 363, 363, 368, 363, - 366, 363, 366, 363, 432, 363, 404, 404, - 363, 79, 194, 195, 363, 363, 363, 368, - 363, 366, 363, 366, 81, 363, 363, 98, - 367, 363, 79, 194, 195, 363, 363, 363, - 368, 363, 366, 363, 116, 83, 83, 84, - 79, 434, 434, 434, 434, 156, 116, 434, - 190, 191, 365, 365, 84, 79, 194, 195, - 363, 363, 363, 197, 363, 363, 200, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 202, 363, 116, 83, - 83, 84, 79, 434, 434, 434, 434, 434, - 116, 434, 436, 437, 438, 439, 123, 118, - 440, 441, 435, 435, 155, 442, 435, 435, - 443, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 444, 435, - 445, 437, 439, 439, 123, 118, 440, 441, - 435, 435, 435, 442, 435, 435, 443, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 444, 435, 437, 439, - 439, 123, 118, 440, 441, 435, 435, 435, - 442, 435, 435, 443, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 444, 435, 446, 435, 435, 435, 136, - 447, 435, 118, 440, 441, 435, 435, 435, - 448, 435, 446, 435, 449, 450, 451, 452, - 123, 118, 440, 441, 435, 435, 153, 453, - 435, 435, 443, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 444, 435, 454, 450, 455, 455, 123, 118, - 440, 441, 435, 435, 435, 453, 435, 435, - 443, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 444, 435, - 450, 455, 455, 123, 118, 440, 441, 435, - 435, 435, 453, 435, 435, 443, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 444, 435, 456, 435, 435, - 435, 136, 457, 435, 118, 440, 441, 435, - 435, 435, 448, 435, 456, 435, 458, 459, - 460, 461, 123, 118, 440, 441, 435, 435, - 151, 462, 435, 435, 443, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 444, 435, 463, 459, 464, 464, - 123, 118, 440, 441, 435, 435, 435, 462, - 435, 435, 443, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 444, 435, 459, 464, 464, 123, 118, 440, - 441, 435, 435, 435, 462, 435, 435, 443, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 444, 435, 465, - 435, 435, 435, 136, 466, 435, 118, 440, - 441, 435, 435, 435, 448, 435, 465, 435, - 467, 468, 469, 470, 123, 118, 440, 441, - 435, 435, 149, 471, 435, 435, 443, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 444, 435, 472, 468, - 473, 473, 123, 118, 440, 441, 435, 435, - 435, 471, 435, 435, 443, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 444, 435, 468, 473, 473, 123, - 118, 440, 441, 435, 435, 435, 471, 435, - 435, 443, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 444, - 435, 474, 435, 435, 435, 136, 475, 435, - 118, 440, 441, 435, 435, 435, 448, 435, - 474, 435, 476, 477, 478, 479, 123, 118, - 440, 441, 435, 435, 147, 480, 435, 435, - 443, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 444, 435, - 481, 477, 482, 482, 123, 118, 440, 441, - 435, 435, 435, 480, 435, 435, 443, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 444, 435, 477, 482, - 482, 123, 118, 440, 441, 435, 435, 435, - 480, 435, 435, 443, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 444, 435, 136, 483, 435, 118, 440, - 441, 435, 435, 435, 448, 435, 484, 484, - 435, 118, 440, 441, 435, 435, 435, 448, - 435, 485, 435, 435, 486, 440, 441, 435, - 440, 441, 435, 487, 435, 440, 488, 435, - 440, 489, 435, 440, 435, 485, 435, 435, - 435, 440, 441, 435, 490, 435, 491, 492, - 435, 118, 440, 441, 435, 435, 121, 435, - 120, 435, 484, 484, 435, 118, 440, 441, - 435, 484, 484, 435, 118, 440, 441, 435, - 490, 435, 484, 484, 435, 118, 440, 441, - 435, 490, 435, 491, 484, 435, 118, 440, - 441, 435, 435, 121, 435, 136, 435, 493, - 493, 123, 118, 440, 441, 435, 435, 435, - 448, 435, 494, 145, 495, 496, 126, 118, - 440, 441, 435, 435, 435, 448, 435, 145, - 495, 496, 126, 118, 440, 441, 435, 435, - 435, 448, 435, 495, 495, 126, 118, 440, - 441, 435, 435, 435, 448, 435, 497, 142, - 498, 499, 129, 118, 440, 441, 435, 435, - 435, 448, 435, 142, 498, 499, 129, 118, - 440, 441, 435, 435, 435, 448, 435, 498, - 498, 129, 118, 440, 441, 435, 435, 435, - 448, 435, 500, 139, 501, 502, 132, 118, - 440, 441, 435, 435, 435, 448, 435, 139, - 501, 502, 132, 118, 440, 441, 435, 435, - 435, 448, 435, 501, 501, 132, 118, 440, - 441, 435, 435, 435, 448, 435, 503, 136, - 484, 504, 435, 118, 440, 441, 435, 435, - 435, 448, 435, 136, 484, 504, 435, 118, - 440, 441, 435, 435, 435, 448, 435, 484, - 505, 435, 118, 440, 441, 435, 435, 435, - 448, 435, 136, 435, 484, 484, 435, 118, - 440, 441, 435, 435, 435, 448, 435, 119, - 120, 435, 435, 136, 483, 435, 118, 440, - 441, 435, 435, 435, 448, 435, 119, 435, - 477, 482, 482, 123, 118, 440, 441, 435, - 435, 435, 480, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 444, 435, 477, 482, 482, - 123, 118, 440, 441, 435, 435, 435, 480, - 435, 476, 477, 482, 482, 123, 118, 440, - 441, 435, 435, 435, 480, 435, 435, 443, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 444, 435, 476, - 477, 478, 482, 123, 118, 440, 441, 435, - 435, 147, 480, 435, 435, 443, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 444, 435, 474, 435, 506, - 435, 493, 493, 123, 118, 440, 441, 435, - 435, 435, 448, 435, 474, 435, 474, 435, - 435, 435, 484, 484, 435, 118, 440, 441, - 435, 435, 435, 448, 435, 474, 435, 474, - 435, 435, 435, 484, 507, 435, 118, 440, - 441, 435, 435, 435, 448, 435, 474, 435, - 474, 435, 506, 435, 484, 484, 435, 118, - 440, 441, 435, 435, 435, 448, 435, 474, - 435, 474, 120, 435, 435, 136, 475, 435, - 118, 440, 441, 435, 435, 435, 448, 435, - 474, 435, 467, 468, 473, 473, 123, 118, - 440, 441, 435, 435, 435, 471, 435, 435, - 443, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 444, 435, - 467, 468, 469, 473, 123, 118, 440, 441, - 435, 435, 149, 471, 435, 435, 443, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 444, 435, 465, 435, - 508, 435, 493, 493, 123, 118, 440, 441, - 435, 435, 435, 448, 435, 465, 435, 465, - 435, 435, 435, 484, 484, 435, 118, 440, - 441, 435, 435, 435, 448, 435, 465, 435, - 465, 435, 435, 435, 484, 509, 435, 118, - 440, 441, 435, 435, 435, 448, 435, 465, - 435, 465, 435, 508, 435, 484, 484, 435, - 118, 440, 441, 435, 435, 435, 448, 435, - 465, 435, 465, 120, 435, 435, 136, 466, - 435, 118, 440, 441, 435, 435, 435, 448, - 435, 465, 435, 458, 459, 464, 464, 123, - 118, 440, 441, 435, 435, 435, 462, 435, - 435, 443, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 444, - 435, 458, 459, 460, 464, 123, 118, 440, - 441, 435, 435, 151, 462, 435, 435, 443, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 444, 435, 456, - 435, 510, 435, 493, 493, 123, 118, 440, - 441, 435, 435, 435, 448, 435, 456, 435, - 456, 435, 435, 435, 484, 484, 435, 118, - 440, 441, 435, 435, 435, 448, 435, 456, - 435, 456, 435, 435, 435, 484, 511, 435, - 118, 440, 441, 435, 435, 435, 448, 435, - 456, 435, 456, 435, 510, 435, 484, 484, - 435, 118, 440, 441, 435, 435, 435, 448, - 435, 456, 435, 456, 120, 435, 435, 136, - 457, 435, 118, 440, 441, 435, 435, 435, - 448, 435, 456, 435, 449, 450, 455, 455, - 123, 118, 440, 441, 435, 435, 435, 453, - 435, 435, 443, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 444, 435, 449, 450, 451, 455, 123, 118, - 440, 441, 435, 435, 153, 453, 435, 435, - 443, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 444, 435, - 446, 435, 512, 435, 493, 493, 123, 118, - 440, 441, 435, 435, 435, 448, 435, 446, - 435, 446, 435, 435, 435, 484, 484, 435, - 118, 440, 441, 435, 435, 435, 448, 435, - 446, 435, 446, 435, 435, 435, 484, 513, - 435, 118, 440, 441, 435, 435, 435, 448, - 435, 446, 435, 446, 435, 512, 435, 484, - 484, 435, 118, 440, 441, 435, 435, 435, - 448, 435, 446, 435, 446, 120, 435, 435, - 136, 447, 435, 118, 440, 441, 435, 435, - 435, 448, 435, 446, 435, 436, 437, 439, - 439, 123, 118, 440, 441, 435, 435, 435, - 442, 435, 435, 443, 435, 435, 435, 435, - 435, 435, 435, 435, 435, 435, 435, 435, - 435, 444, 435, 188, 189, 190, 191, 514, - 365, 84, 79, 194, 195, 196, 196, 156, - 197, 363, 188, 200, 363, 363, 363, 363, - 363, 363, 363, 363, 363, 363, 363, 363, - 363, 202, 363, 204, 515, 206, 207, 6, - 1, 208, 209, 203, 203, 38, 210, 203, - 203, 211, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 212, - 203, 215, 189, 190, 191, 516, 517, 84, - 157, 518, 519, 203, 196, 156, 520, 203, - 215, 200, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 202, - 203, 116, 521, 521, 84, 157, 208, 209, - 203, 203, 156, 522, 203, 523, 203, 203, - 524, 518, 519, 203, 518, 519, 203, 256, - 203, 518, 525, 203, 518, 526, 203, 518, - 203, 523, 203, 203, 203, 518, 519, 203, - 527, 3, 363, 363, 404, 433, 363, 79, - 194, 195, 363, 363, 363, 368, 363, 527, - 363, 528, 370, 529, 530, 84, 157, 518, - 519, 203, 203, 158, 373, 203, 203, 200, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 202, 203, 531, - 370, 532, 532, 84, 157, 518, 519, 203, - 203, 203, 373, 203, 203, 200, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 202, 203, 370, 532, 532, - 84, 157, 518, 519, 203, 203, 203, 373, - 203, 203, 200, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 202, 203, 528, 370, 532, 532, 84, 157, - 518, 519, 203, 203, 203, 373, 203, 203, - 200, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 202, 203, - 528, 370, 529, 532, 84, 157, 518, 519, - 203, 203, 158, 373, 203, 203, 200, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 202, 203, 215, 203, - 281, 116, 533, 533, 160, 157, 208, 209, - 203, 203, 203, 522, 203, 215, 203, 534, - 184, 535, 536, 162, 157, 518, 519, 203, - 203, 203, 537, 203, 184, 535, 536, 162, - 157, 518, 519, 203, 203, 203, 537, 203, - 535, 535, 162, 157, 518, 519, 203, 203, - 203, 537, 203, 538, 181, 539, 540, 165, - 157, 518, 519, 203, 203, 203, 537, 203, - 181, 539, 540, 165, 157, 518, 519, 203, - 203, 203, 537, 203, 539, 539, 165, 157, - 518, 519, 203, 203, 203, 537, 203, 541, - 178, 542, 543, 168, 157, 518, 519, 203, - 203, 203, 537, 203, 178, 542, 543, 168, - 157, 518, 519, 203, 203, 203, 537, 203, - 542, 542, 168, 157, 518, 519, 203, 203, - 203, 537, 203, 544, 175, 545, 546, 203, - 157, 518, 519, 203, 203, 203, 537, 203, - 175, 545, 546, 203, 157, 518, 519, 203, - 203, 203, 537, 203, 545, 545, 203, 157, - 518, 519, 203, 203, 203, 537, 203, 547, - 203, 548, 549, 203, 157, 518, 519, 203, - 203, 172, 203, 171, 203, 545, 545, 203, - 157, 518, 519, 203, 545, 545, 203, 157, - 518, 519, 203, 547, 203, 545, 545, 203, - 157, 518, 519, 203, 547, 203, 548, 545, - 203, 157, 518, 519, 203, 203, 172, 203, - 527, 171, 363, 363, 98, 367, 363, 79, - 194, 195, 363, 363, 363, 368, 363, 527, - 363, 551, 550, 552, 552, 550, 186, 553, - 554, 550, 552, 552, 550, 186, 553, 554, - 550, 555, 550, 550, 556, 553, 554, 550, - 553, 554, 550, 557, 550, 553, 558, 550, - 553, 559, 550, 553, 550, 555, 550, 550, - 550, 553, 554, 550, 0 + 197, 198, 199, 200, 201, 187, 203, 204, + 205, 206, 6, 1, 207, 208, 202, 202, + 38, 209, 202, 202, 210, 202, 211, 204, + 212, 212, 6, 1, 207, 208, 202, 202, + 202, 209, 202, 202, 210, 202, 204, 212, + 212, 6, 1, 207, 208, 202, 202, 202, + 209, 202, 202, 210, 202, 213, 202, 202, + 202, 19, 214, 202, 1, 207, 208, 202, + 202, 202, 215, 202, 213, 202, 216, 217, + 218, 219, 6, 1, 207, 208, 202, 202, + 36, 220, 202, 202, 210, 202, 221, 217, + 222, 222, 6, 1, 207, 208, 202, 202, + 202, 220, 202, 202, 210, 202, 217, 222, + 222, 6, 1, 207, 208, 202, 202, 202, + 220, 202, 202, 210, 202, 223, 202, 202, + 202, 19, 224, 202, 1, 207, 208, 202, + 202, 202, 215, 202, 223, 202, 225, 226, + 227, 228, 6, 1, 207, 208, 202, 202, + 34, 229, 202, 202, 210, 202, 230, 226, + 231, 231, 6, 1, 207, 208, 202, 202, + 202, 229, 202, 202, 210, 202, 226, 231, + 231, 6, 1, 207, 208, 202, 202, 202, + 229, 202, 202, 210, 202, 232, 202, 202, + 202, 19, 233, 202, 1, 207, 208, 202, + 202, 202, 215, 202, 232, 202, 234, 235, + 236, 237, 6, 1, 207, 208, 202, 202, + 32, 238, 202, 202, 210, 202, 239, 235, + 240, 240, 6, 1, 207, 208, 202, 202, + 202, 238, 202, 202, 210, 202, 235, 240, + 240, 6, 1, 207, 208, 202, 202, 202, + 238, 202, 202, 210, 202, 241, 202, 202, + 202, 19, 242, 202, 1, 207, 208, 202, + 202, 202, 215, 202, 241, 202, 243, 244, + 245, 246, 6, 1, 207, 208, 202, 202, + 30, 247, 202, 202, 210, 202, 248, 244, + 249, 249, 6, 1, 207, 208, 202, 202, + 202, 247, 202, 202, 210, 202, 244, 249, + 249, 6, 1, 207, 208, 202, 202, 202, + 247, 202, 202, 210, 202, 19, 250, 202, + 1, 207, 208, 202, 202, 202, 215, 202, + 251, 251, 202, 1, 207, 208, 202, 202, + 202, 215, 202, 252, 202, 202, 253, 207, + 208, 202, 207, 208, 202, 254, 202, 207, + 255, 202, 207, 256, 202, 207, 202, 252, + 202, 202, 202, 207, 208, 202, 257, 202, + 258, 259, 202, 1, 207, 208, 202, 202, + 4, 202, 3, 202, 251, 251, 202, 1, + 207, 208, 202, 251, 251, 202, 1, 207, + 208, 202, 257, 202, 251, 251, 202, 1, + 207, 208, 202, 257, 202, 258, 251, 202, + 1, 207, 208, 202, 202, 4, 202, 19, + 202, 260, 260, 6, 1, 207, 208, 202, + 202, 202, 215, 202, 261, 28, 262, 263, + 9, 1, 207, 208, 202, 202, 202, 215, + 202, 28, 262, 263, 9, 1, 207, 208, + 202, 202, 202, 215, 202, 262, 262, 9, + 1, 207, 208, 202, 202, 202, 215, 202, + 264, 25, 265, 266, 12, 1, 207, 208, + 202, 202, 202, 215, 202, 25, 265, 266, + 12, 1, 207, 208, 202, 202, 202, 215, + 202, 265, 265, 12, 1, 207, 208, 202, + 202, 202, 215, 202, 267, 22, 268, 269, + 15, 1, 207, 208, 202, 202, 202, 215, + 202, 22, 268, 269, 15, 1, 207, 208, + 202, 202, 202, 215, 202, 268, 268, 15, + 1, 207, 208, 202, 202, 202, 215, 202, + 270, 19, 251, 271, 202, 1, 207, 208, + 202, 202, 202, 215, 202, 19, 251, 271, + 202, 1, 207, 208, 202, 202, 202, 215, + 202, 251, 272, 202, 1, 207, 208, 202, + 202, 202, 215, 202, 19, 202, 251, 251, + 202, 1, 207, 208, 202, 202, 202, 215, + 202, 2, 3, 202, 202, 19, 250, 202, + 1, 207, 208, 202, 202, 202, 215, 202, + 2, 202, 244, 249, 249, 6, 1, 207, + 208, 202, 202, 202, 247, 202, 243, 244, + 249, 249, 6, 1, 207, 208, 202, 202, + 202, 247, 202, 202, 210, 202, 243, 244, + 245, 249, 6, 1, 207, 208, 202, 202, + 30, 247, 202, 202, 210, 202, 241, 202, + 273, 202, 260, 260, 6, 1, 207, 208, + 202, 202, 202, 215, 202, 241, 202, 241, + 202, 202, 202, 251, 251, 202, 1, 207, + 208, 202, 202, 202, 215, 202, 241, 202, + 241, 202, 202, 202, 251, 274, 202, 1, + 207, 208, 202, 202, 202, 215, 202, 241, + 202, 241, 202, 273, 202, 251, 251, 202, + 1, 207, 208, 202, 202, 202, 215, 202, + 241, 202, 241, 3, 202, 202, 19, 242, + 202, 1, 207, 208, 202, 202, 202, 215, + 202, 241, 202, 234, 235, 240, 240, 6, + 1, 207, 208, 202, 202, 202, 238, 202, + 202, 210, 202, 234, 235, 236, 240, 6, + 1, 207, 208, 202, 202, 32, 238, 202, + 202, 210, 202, 232, 202, 275, 202, 260, + 260, 6, 1, 207, 208, 202, 202, 202, + 215, 202, 232, 202, 232, 202, 202, 202, + 251, 251, 202, 1, 207, 208, 202, 202, + 202, 215, 202, 232, 202, 232, 202, 202, + 202, 251, 276, 202, 1, 207, 208, 202, + 202, 202, 215, 202, 232, 202, 232, 202, + 275, 202, 251, 251, 202, 1, 207, 208, + 202, 202, 202, 215, 202, 232, 202, 232, + 3, 202, 202, 19, 233, 202, 1, 207, + 208, 202, 202, 202, 215, 202, 232, 202, + 225, 226, 231, 231, 6, 1, 207, 208, + 202, 202, 202, 229, 202, 202, 210, 202, + 225, 226, 227, 231, 6, 1, 207, 208, + 202, 202, 34, 229, 202, 202, 210, 202, + 223, 202, 277, 202, 260, 260, 6, 1, + 207, 208, 202, 202, 202, 215, 202, 223, + 202, 223, 202, 202, 202, 251, 251, 202, + 1, 207, 208, 202, 202, 202, 215, 202, + 223, 202, 223, 202, 202, 202, 251, 278, + 202, 1, 207, 208, 202, 202, 202, 215, + 202, 223, 202, 223, 202, 277, 202, 251, + 251, 202, 1, 207, 208, 202, 202, 202, + 215, 202, 223, 202, 223, 3, 202, 202, + 19, 224, 202, 1, 207, 208, 202, 202, + 202, 215, 202, 223, 202, 216, 217, 222, + 222, 6, 1, 207, 208, 202, 202, 202, + 220, 202, 202, 210, 202, 216, 217, 218, + 222, 6, 1, 207, 208, 202, 202, 36, + 220, 202, 202, 210, 202, 213, 202, 279, + 202, 260, 260, 6, 1, 207, 208, 202, + 202, 202, 215, 202, 213, 202, 213, 202, + 202, 202, 251, 251, 202, 1, 207, 208, + 202, 202, 202, 215, 202, 213, 202, 213, + 202, 202, 202, 251, 280, 202, 1, 207, + 208, 202, 202, 202, 215, 202, 213, 202, + 213, 202, 279, 202, 251, 251, 202, 1, + 207, 208, 202, 202, 202, 215, 202, 213, + 202, 213, 3, 202, 202, 19, 214, 202, + 1, 207, 208, 202, 202, 202, 215, 202, + 213, 202, 203, 204, 212, 212, 6, 1, + 207, 208, 202, 202, 202, 209, 202, 202, + 210, 202, 203, 204, 205, 212, 6, 1, + 207, 208, 202, 202, 38, 209, 202, 202, + 210, 202, 282, 283, 284, 285, 45, 40, + 286, 287, 281, 281, 77, 288, 281, 281, + 289, 281, 290, 283, 291, 285, 45, 40, + 286, 287, 281, 281, 281, 288, 281, 281, + 289, 281, 283, 291, 285, 45, 40, 286, + 287, 281, 281, 281, 288, 281, 281, 289, + 281, 292, 281, 281, 281, 58, 293, 281, + 40, 286, 287, 281, 281, 281, 294, 281, + 292, 281, 295, 296, 297, 298, 45, 40, + 286, 287, 281, 281, 75, 299, 281, 281, + 289, 281, 300, 296, 301, 301, 45, 40, + 286, 287, 281, 281, 281, 299, 281, 281, + 289, 281, 296, 301, 301, 45, 40, 286, + 287, 281, 281, 281, 299, 281, 281, 289, + 281, 302, 281, 281, 281, 58, 303, 281, + 40, 286, 287, 281, 281, 281, 294, 281, + 302, 281, 304, 305, 306, 307, 45, 40, + 286, 287, 281, 281, 73, 308, 281, 281, + 289, 281, 309, 305, 310, 310, 45, 40, + 286, 287, 281, 281, 281, 308, 281, 281, + 289, 281, 305, 310, 310, 45, 40, 286, + 287, 281, 281, 281, 308, 281, 281, 289, + 281, 311, 281, 281, 281, 58, 312, 281, + 40, 286, 287, 281, 281, 281, 294, 281, + 311, 281, 313, 314, 315, 316, 45, 40, + 286, 287, 281, 281, 71, 317, 281, 281, + 289, 281, 318, 314, 319, 319, 45, 40, + 286, 287, 281, 281, 281, 317, 281, 281, + 289, 281, 314, 319, 319, 45, 40, 286, + 287, 281, 281, 281, 317, 281, 281, 289, + 281, 320, 281, 281, 281, 58, 321, 281, + 40, 286, 287, 281, 281, 281, 294, 281, + 320, 281, 322, 323, 324, 325, 45, 40, + 286, 287, 281, 281, 69, 326, 281, 281, + 289, 281, 327, 323, 328, 328, 45, 40, + 286, 287, 281, 281, 281, 326, 281, 281, + 289, 281, 323, 328, 328, 45, 40, 286, + 287, 281, 281, 281, 326, 281, 281, 289, + 281, 58, 329, 281, 40, 286, 287, 281, + 281, 281, 294, 281, 330, 330, 281, 40, + 286, 287, 281, 281, 281, 294, 281, 331, + 281, 281, 332, 286, 287, 281, 286, 287, + 281, 333, 281, 286, 334, 281, 286, 335, + 281, 286, 281, 331, 281, 281, 281, 286, + 287, 281, 336, 281, 337, 338, 281, 40, + 286, 287, 281, 281, 43, 281, 42, 281, + 330, 330, 281, 40, 286, 287, 281, 330, + 330, 281, 40, 286, 287, 281, 336, 281, + 330, 330, 281, 40, 286, 287, 281, 336, + 281, 337, 330, 281, 40, 286, 287, 281, + 281, 43, 281, 58, 281, 339, 339, 45, + 40, 286, 287, 281, 281, 281, 294, 281, + 340, 67, 341, 342, 48, 40, 286, 287, + 281, 281, 281, 294, 281, 67, 341, 342, + 48, 40, 286, 287, 281, 281, 281, 294, + 281, 341, 341, 48, 40, 286, 287, 281, + 281, 281, 294, 281, 343, 64, 344, 345, + 51, 40, 286, 287, 281, 281, 281, 294, + 281, 64, 344, 345, 51, 40, 286, 287, + 281, 281, 281, 294, 281, 344, 344, 51, + 40, 286, 287, 281, 281, 281, 294, 281, + 346, 61, 347, 348, 54, 40, 286, 287, + 281, 281, 281, 294, 281, 61, 347, 348, + 54, 40, 286, 287, 281, 281, 281, 294, + 281, 347, 347, 54, 40, 286, 287, 281, + 281, 281, 294, 281, 349, 58, 330, 350, + 281, 40, 286, 287, 281, 281, 281, 294, + 281, 58, 330, 350, 281, 40, 286, 287, + 281, 281, 281, 294, 281, 330, 351, 281, + 40, 286, 287, 281, 281, 281, 294, 281, + 58, 281, 330, 330, 281, 40, 286, 287, + 281, 281, 281, 294, 281, 41, 42, 281, + 281, 58, 329, 281, 40, 286, 287, 281, + 281, 281, 294, 281, 41, 281, 323, 328, + 328, 45, 40, 286, 287, 281, 281, 281, + 326, 281, 322, 323, 328, 328, 45, 40, + 286, 287, 281, 281, 281, 326, 281, 281, + 289, 281, 322, 323, 324, 328, 45, 40, + 286, 287, 281, 281, 69, 326, 281, 281, + 289, 281, 320, 281, 352, 281, 339, 339, + 45, 40, 286, 287, 281, 281, 281, 294, + 281, 320, 281, 320, 281, 281, 281, 330, + 330, 281, 40, 286, 287, 281, 281, 281, + 294, 281, 320, 281, 320, 281, 281, 281, + 330, 353, 281, 40, 286, 287, 281, 281, + 281, 294, 281, 320, 281, 320, 281, 352, + 281, 330, 330, 281, 40, 286, 287, 281, + 281, 281, 294, 281, 320, 281, 320, 42, + 281, 281, 58, 321, 281, 40, 286, 287, + 281, 281, 281, 294, 281, 320, 281, 313, + 314, 319, 319, 45, 40, 286, 287, 281, + 281, 281, 317, 281, 281, 289, 281, 313, + 314, 315, 319, 45, 40, 286, 287, 281, + 281, 71, 317, 281, 281, 289, 281, 311, + 281, 354, 281, 339, 339, 45, 40, 286, + 287, 281, 281, 281, 294, 281, 311, 281, + 311, 281, 281, 281, 330, 330, 281, 40, + 286, 287, 281, 281, 281, 294, 281, 311, + 281, 311, 281, 281, 281, 330, 355, 281, + 40, 286, 287, 281, 281, 281, 294, 281, + 311, 281, 311, 281, 354, 281, 330, 330, + 281, 40, 286, 287, 281, 281, 281, 294, + 281, 311, 281, 311, 42, 281, 281, 58, + 312, 281, 40, 286, 287, 281, 281, 281, + 294, 281, 311, 281, 304, 305, 310, 310, + 45, 40, 286, 287, 281, 281, 281, 308, + 281, 281, 289, 281, 304, 305, 306, 310, + 45, 40, 286, 287, 281, 281, 73, 308, + 281, 281, 289, 281, 302, 281, 356, 281, + 339, 339, 45, 40, 286, 287, 281, 281, + 281, 294, 281, 302, 281, 302, 281, 281, + 281, 330, 330, 281, 40, 286, 287, 281, + 281, 281, 294, 281, 302, 281, 302, 281, + 281, 281, 330, 357, 281, 40, 286, 287, + 281, 281, 281, 294, 281, 302, 281, 302, + 281, 356, 281, 330, 330, 281, 40, 286, + 287, 281, 281, 281, 294, 281, 302, 281, + 302, 42, 281, 281, 58, 303, 281, 40, + 286, 287, 281, 281, 281, 294, 281, 302, + 281, 295, 296, 301, 301, 45, 40, 286, + 287, 281, 281, 281, 299, 281, 281, 289, + 281, 295, 296, 297, 301, 45, 40, 286, + 287, 281, 281, 75, 299, 281, 281, 289, + 281, 292, 281, 358, 281, 339, 339, 45, + 40, 286, 287, 281, 281, 281, 294, 281, + 292, 281, 292, 281, 281, 281, 330, 330, + 281, 40, 286, 287, 281, 281, 281, 294, + 281, 292, 281, 292, 281, 281, 281, 330, + 359, 281, 40, 286, 287, 281, 281, 281, + 294, 281, 292, 281, 292, 281, 358, 281, + 330, 330, 281, 40, 286, 287, 281, 281, + 281, 294, 281, 292, 281, 76, 44, 44, + 45, 40, 281, 281, 281, 281, 281, 76, + 281, 292, 42, 281, 281, 58, 293, 281, + 40, 286, 287, 281, 281, 281, 294, 281, + 292, 281, 282, 283, 291, 285, 45, 40, + 286, 287, 281, 281, 281, 288, 281, 281, + 289, 281, 361, 191, 362, 362, 84, 79, + 194, 195, 360, 360, 360, 197, 360, 360, + 200, 360, 191, 362, 362, 84, 79, 194, + 195, 360, 360, 360, 197, 360, 360, 200, + 360, 363, 360, 360, 360, 98, 364, 360, + 79, 194, 195, 360, 360, 360, 365, 360, + 363, 360, 366, 367, 368, 369, 84, 79, + 194, 195, 360, 360, 115, 370, 360, 360, + 200, 360, 371, 367, 372, 372, 84, 79, + 194, 195, 360, 360, 360, 370, 360, 360, + 200, 360, 367, 372, 372, 84, 79, 194, + 195, 360, 360, 360, 370, 360, 360, 200, + 360, 373, 360, 360, 360, 98, 374, 360, + 79, 194, 195, 360, 360, 360, 365, 360, + 373, 360, 375, 376, 377, 378, 84, 79, + 194, 195, 360, 360, 113, 379, 360, 360, + 200, 360, 380, 376, 381, 381, 84, 79, + 194, 195, 360, 360, 360, 379, 360, 360, + 200, 360, 376, 381, 381, 84, 79, 194, + 195, 360, 360, 360, 379, 360, 360, 200, + 360, 382, 360, 360, 360, 98, 383, 360, + 79, 194, 195, 360, 360, 360, 365, 360, + 382, 360, 384, 385, 386, 387, 84, 79, + 194, 195, 360, 360, 111, 388, 360, 360, + 200, 360, 389, 385, 390, 390, 84, 79, + 194, 195, 360, 360, 360, 388, 360, 360, + 200, 360, 385, 390, 390, 84, 79, 194, + 195, 360, 360, 360, 388, 360, 360, 200, + 360, 391, 360, 360, 360, 98, 392, 360, + 79, 194, 195, 360, 360, 360, 365, 360, + 391, 360, 393, 394, 395, 396, 84, 79, + 194, 195, 360, 360, 109, 397, 360, 360, + 200, 360, 398, 394, 399, 399, 84, 79, + 194, 195, 360, 360, 360, 397, 360, 360, + 200, 360, 394, 399, 399, 84, 79, 194, + 195, 360, 360, 360, 397, 360, 360, 200, + 360, 98, 400, 360, 79, 194, 195, 360, + 360, 360, 365, 360, 401, 401, 360, 79, + 194, 195, 360, 360, 360, 365, 360, 402, + 360, 360, 403, 194, 195, 360, 194, 195, + 360, 404, 360, 194, 405, 360, 194, 406, + 360, 194, 360, 402, 360, 360, 360, 194, + 195, 360, 407, 360, 408, 409, 360, 79, + 194, 195, 360, 360, 82, 360, 81, 360, + 401, 401, 360, 79, 194, 195, 360, 401, + 401, 360, 79, 194, 195, 360, 407, 360, + 401, 401, 360, 79, 194, 195, 360, 407, + 360, 408, 401, 360, 79, 194, 195, 360, + 360, 82, 360, 98, 360, 410, 410, 84, + 79, 194, 195, 360, 360, 360, 365, 360, + 411, 107, 412, 413, 88, 79, 194, 195, + 360, 360, 360, 365, 360, 107, 412, 413, + 88, 79, 194, 195, 360, 360, 360, 365, + 360, 412, 412, 88, 79, 194, 195, 360, + 360, 360, 365, 360, 414, 104, 415, 416, + 91, 79, 194, 195, 360, 360, 360, 365, + 360, 104, 415, 416, 91, 79, 194, 195, + 360, 360, 360, 365, 360, 415, 415, 91, + 79, 194, 195, 360, 360, 360, 365, 360, + 417, 101, 418, 419, 94, 79, 194, 195, + 360, 360, 360, 365, 360, 101, 418, 419, + 94, 79, 194, 195, 360, 360, 360, 365, + 360, 418, 418, 94, 79, 194, 195, 360, + 360, 360, 365, 360, 420, 98, 401, 421, + 360, 79, 194, 195, 360, 360, 360, 365, + 360, 98, 401, 421, 360, 79, 194, 195, + 360, 360, 360, 365, 360, 401, 422, 360, + 79, 194, 195, 360, 360, 360, 365, 360, + 98, 360, 401, 401, 360, 79, 194, 195, + 360, 360, 360, 365, 360, 80, 81, 360, + 360, 98, 400, 360, 79, 194, 195, 360, + 360, 360, 365, 360, 80, 360, 394, 399, + 399, 84, 79, 194, 195, 360, 360, 360, + 397, 360, 393, 394, 399, 399, 84, 79, + 194, 195, 360, 360, 360, 397, 360, 360, + 200, 360, 393, 394, 395, 399, 84, 79, + 194, 195, 360, 360, 109, 397, 360, 360, + 200, 360, 391, 360, 423, 360, 410, 410, + 84, 79, 194, 195, 360, 360, 360, 365, + 360, 391, 360, 391, 360, 360, 360, 401, + 401, 360, 79, 194, 195, 360, 360, 360, + 365, 360, 391, 360, 391, 360, 360, 360, + 401, 424, 360, 79, 194, 195, 360, 360, + 360, 365, 360, 391, 360, 391, 360, 423, + 360, 401, 401, 360, 79, 194, 195, 360, + 360, 360, 365, 360, 391, 360, 391, 81, + 360, 360, 98, 392, 360, 79, 194, 195, + 360, 360, 360, 365, 360, 391, 360, 384, + 385, 390, 390, 84, 79, 194, 195, 360, + 360, 360, 388, 360, 360, 200, 360, 384, + 385, 386, 390, 84, 79, 194, 195, 360, + 360, 111, 388, 360, 360, 200, 360, 382, + 360, 425, 360, 410, 410, 84, 79, 194, + 195, 360, 360, 360, 365, 360, 382, 360, + 382, 360, 360, 360, 401, 401, 360, 79, + 194, 195, 360, 360, 360, 365, 360, 382, + 360, 382, 360, 360, 360, 401, 426, 360, + 79, 194, 195, 360, 360, 360, 365, 360, + 382, 360, 382, 360, 425, 360, 401, 401, + 360, 79, 194, 195, 360, 360, 360, 365, + 360, 382, 360, 382, 81, 360, 360, 98, + 383, 360, 79, 194, 195, 360, 360, 360, + 365, 360, 382, 360, 375, 376, 381, 381, + 84, 79, 194, 195, 360, 360, 360, 379, + 360, 360, 200, 360, 375, 376, 377, 381, + 84, 79, 194, 195, 360, 360, 113, 379, + 360, 360, 200, 360, 373, 360, 427, 360, + 410, 410, 84, 79, 194, 195, 360, 360, + 360, 365, 360, 373, 360, 373, 360, 360, + 360, 401, 401, 360, 79, 194, 195, 360, + 360, 360, 365, 360, 373, 360, 373, 360, + 360, 360, 401, 428, 360, 79, 194, 195, + 360, 360, 360, 365, 360, 373, 360, 373, + 360, 427, 360, 401, 401, 360, 79, 194, + 195, 360, 360, 360, 365, 360, 373, 360, + 373, 81, 360, 360, 98, 374, 360, 79, + 194, 195, 360, 360, 360, 365, 360, 373, + 360, 366, 367, 372, 372, 84, 79, 194, + 195, 360, 360, 360, 370, 360, 360, 200, + 360, 366, 367, 368, 372, 84, 79, 194, + 195, 360, 360, 115, 370, 360, 360, 200, + 360, 363, 360, 429, 360, 410, 410, 84, + 79, 194, 195, 360, 360, 360, 365, 360, + 363, 360, 363, 360, 360, 360, 401, 401, + 360, 79, 194, 195, 360, 360, 360, 365, + 360, 363, 360, 363, 360, 360, 360, 401, + 430, 360, 79, 194, 195, 360, 360, 360, + 365, 360, 363, 360, 363, 360, 429, 360, + 401, 401, 360, 79, 194, 195, 360, 360, + 360, 365, 360, 363, 360, 363, 81, 360, + 360, 98, 364, 360, 79, 194, 195, 360, + 360, 360, 365, 360, 363, 360, 116, 83, + 83, 84, 79, 431, 431, 431, 431, 156, + 116, 431, 190, 191, 362, 362, 84, 79, + 194, 195, 360, 360, 360, 197, 360, 360, + 200, 360, 116, 83, 83, 84, 79, 431, + 431, 431, 431, 431, 116, 431, 433, 434, + 435, 436, 123, 118, 437, 438, 432, 432, + 155, 439, 432, 432, 440, 432, 441, 434, + 436, 436, 123, 118, 437, 438, 432, 432, + 432, 439, 432, 432, 440, 432, 434, 436, + 436, 123, 118, 437, 438, 432, 432, 432, + 439, 432, 432, 440, 432, 442, 432, 432, + 432, 136, 443, 432, 118, 437, 438, 432, + 432, 432, 444, 432, 442, 432, 445, 446, + 447, 448, 123, 118, 437, 438, 432, 432, + 153, 449, 432, 432, 440, 432, 450, 446, + 451, 451, 123, 118, 437, 438, 432, 432, + 432, 449, 432, 432, 440, 432, 446, 451, + 451, 123, 118, 437, 438, 432, 432, 432, + 449, 432, 432, 440, 432, 452, 432, 432, + 432, 136, 453, 432, 118, 437, 438, 432, + 432, 432, 444, 432, 452, 432, 454, 455, + 456, 457, 123, 118, 437, 438, 432, 432, + 151, 458, 432, 432, 440, 432, 459, 455, + 460, 460, 123, 118, 437, 438, 432, 432, + 432, 458, 432, 432, 440, 432, 455, 460, + 460, 123, 118, 437, 438, 432, 432, 432, + 458, 432, 432, 440, 432, 461, 432, 432, + 432, 136, 462, 432, 118, 437, 438, 432, + 432, 432, 444, 432, 461, 432, 463, 464, + 465, 466, 123, 118, 437, 438, 432, 432, + 149, 467, 432, 432, 440, 432, 468, 464, + 469, 469, 123, 118, 437, 438, 432, 432, + 432, 467, 432, 432, 440, 432, 464, 469, + 469, 123, 118, 437, 438, 432, 432, 432, + 467, 432, 432, 440, 432, 470, 432, 432, + 432, 136, 471, 432, 118, 437, 438, 432, + 432, 432, 444, 432, 470, 432, 472, 473, + 474, 475, 123, 118, 437, 438, 432, 432, + 147, 476, 432, 432, 440, 432, 477, 473, + 478, 478, 123, 118, 437, 438, 432, 432, + 432, 476, 432, 432, 440, 432, 473, 478, + 478, 123, 118, 437, 438, 432, 432, 432, + 476, 432, 432, 440, 432, 136, 479, 432, + 118, 437, 438, 432, 432, 432, 444, 432, + 480, 480, 432, 118, 437, 438, 432, 432, + 432, 444, 432, 481, 432, 432, 482, 437, + 438, 432, 437, 438, 432, 483, 432, 437, + 484, 432, 437, 485, 432, 437, 432, 481, + 432, 432, 432, 437, 438, 432, 486, 432, + 487, 488, 432, 118, 437, 438, 432, 432, + 121, 432, 120, 432, 480, 480, 432, 118, + 437, 438, 432, 480, 480, 432, 118, 437, + 438, 432, 486, 432, 480, 480, 432, 118, + 437, 438, 432, 486, 432, 487, 480, 432, + 118, 437, 438, 432, 432, 121, 432, 136, + 432, 489, 489, 123, 118, 437, 438, 432, + 432, 432, 444, 432, 490, 145, 491, 492, + 126, 118, 437, 438, 432, 432, 432, 444, + 432, 145, 491, 492, 126, 118, 437, 438, + 432, 432, 432, 444, 432, 491, 491, 126, + 118, 437, 438, 432, 432, 432, 444, 432, + 493, 142, 494, 495, 129, 118, 437, 438, + 432, 432, 432, 444, 432, 142, 494, 495, + 129, 118, 437, 438, 432, 432, 432, 444, + 432, 494, 494, 129, 118, 437, 438, 432, + 432, 432, 444, 432, 496, 139, 497, 498, + 132, 118, 437, 438, 432, 432, 432, 444, + 432, 139, 497, 498, 132, 118, 437, 438, + 432, 432, 432, 444, 432, 497, 497, 132, + 118, 437, 438, 432, 432, 432, 444, 432, + 499, 136, 480, 500, 432, 118, 437, 438, + 432, 432, 432, 444, 432, 136, 480, 500, + 432, 118, 437, 438, 432, 432, 432, 444, + 432, 480, 501, 432, 118, 437, 438, 432, + 432, 432, 444, 432, 136, 432, 480, 480, + 432, 118, 437, 438, 432, 432, 432, 444, + 432, 119, 120, 432, 432, 136, 479, 432, + 118, 437, 438, 432, 432, 432, 444, 432, + 119, 432, 473, 478, 478, 123, 118, 437, + 438, 432, 432, 432, 476, 432, 472, 473, + 478, 478, 123, 118, 437, 438, 432, 432, + 432, 476, 432, 432, 440, 432, 472, 473, + 474, 478, 123, 118, 437, 438, 432, 432, + 147, 476, 432, 432, 440, 432, 470, 432, + 502, 432, 489, 489, 123, 118, 437, 438, + 432, 432, 432, 444, 432, 470, 432, 470, + 432, 432, 432, 480, 480, 432, 118, 437, + 438, 432, 432, 432, 444, 432, 470, 432, + 470, 432, 432, 432, 480, 503, 432, 118, + 437, 438, 432, 432, 432, 444, 432, 470, + 432, 470, 432, 502, 432, 480, 480, 432, + 118, 437, 438, 432, 432, 432, 444, 432, + 470, 432, 470, 120, 432, 432, 136, 471, + 432, 118, 437, 438, 432, 432, 432, 444, + 432, 470, 432, 463, 464, 469, 469, 123, + 118, 437, 438, 432, 432, 432, 467, 432, + 432, 440, 432, 463, 464, 465, 469, 123, + 118, 437, 438, 432, 432, 149, 467, 432, + 432, 440, 432, 461, 432, 504, 432, 489, + 489, 123, 118, 437, 438, 432, 432, 432, + 444, 432, 461, 432, 461, 432, 432, 432, + 480, 480, 432, 118, 437, 438, 432, 432, + 432, 444, 432, 461, 432, 461, 432, 432, + 432, 480, 505, 432, 118, 437, 438, 432, + 432, 432, 444, 432, 461, 432, 461, 432, + 504, 432, 480, 480, 432, 118, 437, 438, + 432, 432, 432, 444, 432, 461, 432, 461, + 120, 432, 432, 136, 462, 432, 118, 437, + 438, 432, 432, 432, 444, 432, 461, 432, + 454, 455, 460, 460, 123, 118, 437, 438, + 432, 432, 432, 458, 432, 432, 440, 432, + 454, 455, 456, 460, 123, 118, 437, 438, + 432, 432, 151, 458, 432, 432, 440, 432, + 452, 432, 506, 432, 489, 489, 123, 118, + 437, 438, 432, 432, 432, 444, 432, 452, + 432, 452, 432, 432, 432, 480, 480, 432, + 118, 437, 438, 432, 432, 432, 444, 432, + 452, 432, 452, 432, 432, 432, 480, 507, + 432, 118, 437, 438, 432, 432, 432, 444, + 432, 452, 432, 452, 432, 506, 432, 480, + 480, 432, 118, 437, 438, 432, 432, 432, + 444, 432, 452, 432, 452, 120, 432, 432, + 136, 453, 432, 118, 437, 438, 432, 432, + 432, 444, 432, 452, 432, 445, 446, 451, + 451, 123, 118, 437, 438, 432, 432, 432, + 449, 432, 432, 440, 432, 445, 446, 447, + 451, 123, 118, 437, 438, 432, 432, 153, + 449, 432, 432, 440, 432, 442, 432, 508, + 432, 489, 489, 123, 118, 437, 438, 432, + 432, 432, 444, 432, 442, 432, 442, 432, + 432, 432, 480, 480, 432, 118, 437, 438, + 432, 432, 432, 444, 432, 442, 432, 442, + 432, 432, 432, 480, 509, 432, 118, 437, + 438, 432, 432, 432, 444, 432, 442, 432, + 442, 432, 508, 432, 480, 480, 432, 118, + 437, 438, 432, 432, 432, 444, 432, 442, + 432, 442, 120, 432, 432, 136, 443, 432, + 118, 437, 438, 432, 432, 432, 444, 432, + 442, 432, 433, 434, 436, 436, 123, 118, + 437, 438, 432, 432, 432, 439, 432, 432, + 440, 432, 188, 189, 190, 191, 510, 362, + 84, 79, 194, 195, 196, 196, 156, 197, + 360, 188, 200, 360, 203, 511, 205, 206, + 6, 1, 207, 208, 202, 202, 38, 209, + 202, 202, 210, 202, 213, 189, 190, 191, + 512, 513, 84, 157, 514, 515, 202, 196, + 156, 516, 202, 213, 200, 202, 116, 517, + 517, 84, 157, 207, 208, 202, 202, 156, + 518, 202, 519, 202, 202, 520, 514, 515, + 202, 514, 515, 202, 254, 202, 514, 521, + 202, 514, 522, 202, 514, 202, 519, 202, + 202, 202, 514, 515, 202, 523, 3, 360, + 360, 401, 430, 360, 79, 194, 195, 360, + 360, 360, 365, 360, 523, 360, 524, 367, + 525, 526, 84, 157, 514, 515, 202, 202, + 158, 370, 202, 202, 200, 202, 527, 367, + 528, 528, 84, 157, 514, 515, 202, 202, + 202, 370, 202, 202, 200, 202, 367, 528, + 528, 84, 157, 514, 515, 202, 202, 202, + 370, 202, 202, 200, 202, 524, 367, 528, + 528, 84, 157, 514, 515, 202, 202, 202, + 370, 202, 202, 200, 202, 524, 367, 525, + 528, 84, 157, 514, 515, 202, 202, 158, + 370, 202, 202, 200, 202, 213, 202, 279, + 116, 529, 529, 160, 157, 207, 208, 202, + 202, 202, 518, 202, 213, 202, 530, 184, + 531, 532, 162, 157, 514, 515, 202, 202, + 202, 533, 202, 184, 531, 532, 162, 157, + 514, 515, 202, 202, 202, 533, 202, 531, + 531, 162, 157, 514, 515, 202, 202, 202, + 533, 202, 534, 181, 535, 536, 165, 157, + 514, 515, 202, 202, 202, 533, 202, 181, + 535, 536, 165, 157, 514, 515, 202, 202, + 202, 533, 202, 535, 535, 165, 157, 514, + 515, 202, 202, 202, 533, 202, 537, 178, + 538, 539, 168, 157, 514, 515, 202, 202, + 202, 533, 202, 178, 538, 539, 168, 157, + 514, 515, 202, 202, 202, 533, 202, 538, + 538, 168, 157, 514, 515, 202, 202, 202, + 533, 202, 540, 175, 541, 542, 202, 157, + 514, 515, 202, 202, 202, 533, 202, 175, + 541, 542, 202, 157, 514, 515, 202, 202, + 202, 533, 202, 541, 541, 202, 157, 514, + 515, 202, 202, 202, 533, 202, 543, 202, + 544, 545, 202, 157, 514, 515, 202, 202, + 172, 202, 171, 202, 541, 541, 202, 157, + 514, 515, 202, 541, 541, 202, 157, 514, + 515, 202, 543, 202, 541, 541, 202, 157, + 514, 515, 202, 543, 202, 544, 541, 202, + 157, 514, 515, 202, 202, 172, 202, 523, + 171, 360, 360, 98, 364, 360, 79, 194, + 195, 360, 360, 360, 365, 360, 523, 360, + 547, 546, 548, 548, 546, 186, 549, 550, + 546, 548, 548, 546, 186, 549, 550, 546, + 551, 546, 546, 552, 549, 550, 546, 549, + 550, 546, 553, 546, 549, 554, 546, 549, + 555, 546, 549, 546, 551, 546, 546, 546, + 549, 550, 546, 0 }; static const short _indic_syllable_machine_trans_targs[] = { 178, 200, 207, 209, 210, 4, 213, 5, 7, 216, 8, 10, 219, 11, 13, 222, 14, 16, 17, 199, 19, 20, 221, 22, - 23, 218, 25, 26, 215, 224, 229, 233, - 236, 240, 243, 247, 250, 254, 257, 178, - 280, 287, 289, 290, 41, 293, 42, 44, - 296, 45, 47, 299, 48, 50, 302, 51, - 53, 54, 279, 56, 57, 301, 59, 60, - 298, 62, 63, 295, 304, 309, 313, 316, - 320, 323, 327, 330, 334, 338, 178, 359, - 366, 368, 369, 78, 372, 178, 79, 81, - 375, 82, 84, 378, 85, 87, 381, 88, - 90, 91, 358, 93, 94, 380, 96, 97, - 377, 99, 100, 374, 383, 388, 392, 395, - 399, 402, 406, 409, 413, 178, 440, 447, - 449, 450, 114, 453, 115, 117, 456, 118, - 120, 459, 121, 123, 462, 124, 126, 127, - 439, 129, 130, 461, 132, 133, 458, 135, - 136, 455, 464, 469, 473, 476, 480, 483, - 487, 490, 494, 497, 417, 502, 513, 152, - 516, 154, 519, 155, 157, 522, 158, 160, - 525, 161, 528, 530, 531, 166, 167, 527, - 169, 170, 524, 172, 173, 521, 175, 176, - 518, 178, 536, 178, 179, 259, 339, 341, - 416, 418, 361, 362, 419, 415, 498, 499, - 386, 534, 387, 178, 180, 182, 36, 258, - 202, 203, 256, 227, 228, 181, 35, 183, - 252, 1, 184, 186, 34, 251, 249, 185, - 33, 187, 245, 188, 190, 32, 244, 242, - 189, 31, 191, 238, 192, 194, 30, 237, - 235, 193, 29, 195, 231, 196, 198, 28, - 230, 226, 197, 27, 212, 0, 201, 206, - 178, 204, 205, 208, 2, 211, 3, 214, - 6, 24, 217, 9, 21, 220, 12, 18, - 223, 15, 225, 232, 234, 239, 241, 246, - 248, 253, 255, 178, 260, 262, 73, 336, - 282, 283, 337, 307, 308, 261, 72, 263, - 332, 38, 264, 266, 71, 331, 329, 265, - 70, 267, 325, 268, 270, 69, 324, 322, - 269, 68, 271, 318, 272, 274, 67, 317, - 315, 273, 66, 275, 311, 276, 278, 65, - 310, 306, 277, 64, 292, 37, 281, 286, - 178, 284, 285, 288, 39, 291, 40, 294, - 43, 61, 297, 46, 58, 300, 49, 55, - 303, 52, 305, 312, 314, 319, 321, 326, - 328, 333, 335, 178, 340, 109, 342, 411, - 75, 343, 345, 108, 410, 408, 344, 107, - 346, 404, 347, 349, 106, 403, 401, 348, - 105, 350, 397, 351, 353, 104, 396, 394, - 352, 103, 354, 390, 355, 357, 102, 389, - 385, 356, 101, 371, 74, 360, 365, 178, - 363, 364, 367, 76, 370, 77, 373, 80, - 98, 376, 83, 95, 379, 86, 92, 382, - 89, 384, 391, 393, 398, 400, 405, 407, - 412, 414, 178, 178, 420, 422, 146, 145, - 442, 443, 496, 467, 468, 421, 423, 492, - 111, 424, 426, 144, 491, 489, 425, 143, - 427, 485, 428, 430, 142, 484, 482, 429, - 141, 431, 478, 432, 434, 140, 477, 475, - 433, 139, 435, 471, 436, 438, 138, 470, - 466, 437, 137, 452, 110, 441, 446, 178, - 444, 445, 448, 112, 451, 113, 454, 116, - 134, 457, 119, 131, 460, 122, 128, 463, - 125, 465, 472, 474, 479, 481, 486, 488, - 493, 495, 147, 500, 501, 515, 504, 505, - 533, 148, 509, 503, 508, 506, 507, 510, - 511, 150, 514, 512, 149, 151, 517, 153, - 174, 163, 520, 156, 171, 523, 159, 168, - 526, 162, 165, 529, 164, 532, 178, 535, - 177, 538, 539, 537, 542, 178, 540, 541 + 23, 218, 25, 26, 215, 224, 228, 232, + 235, 239, 242, 246, 249, 253, 256, 178, + 279, 286, 288, 289, 41, 292, 42, 44, + 295, 45, 47, 298, 48, 50, 301, 51, + 53, 54, 278, 56, 57, 300, 59, 60, + 297, 62, 63, 294, 303, 307, 311, 314, + 318, 321, 325, 328, 332, 336, 178, 357, + 364, 366, 367, 78, 370, 178, 79, 81, + 373, 82, 84, 376, 85, 87, 379, 88, + 90, 91, 356, 93, 94, 378, 96, 97, + 375, 99, 100, 372, 381, 385, 389, 392, + 396, 399, 403, 406, 410, 178, 437, 444, + 446, 447, 114, 450, 115, 117, 453, 118, + 120, 456, 121, 123, 459, 124, 126, 127, + 436, 129, 130, 458, 132, 133, 455, 135, + 136, 452, 461, 465, 469, 472, 476, 479, + 483, 486, 490, 493, 414, 498, 509, 152, + 512, 154, 515, 155, 157, 518, 158, 160, + 521, 161, 524, 526, 527, 166, 167, 523, + 169, 170, 520, 172, 173, 517, 175, 176, + 514, 178, 532, 178, 179, 258, 337, 339, + 413, 415, 359, 360, 416, 412, 494, 495, + 384, 530, 178, 180, 182, 36, 257, 202, + 203, 255, 227, 181, 35, 183, 251, 1, + 184, 186, 34, 250, 248, 185, 33, 187, + 244, 188, 190, 32, 243, 241, 189, 31, + 191, 237, 192, 194, 30, 236, 234, 193, + 29, 195, 230, 196, 198, 28, 229, 226, + 197, 27, 212, 0, 201, 206, 178, 204, + 205, 208, 2, 211, 3, 214, 6, 24, + 217, 9, 21, 220, 12, 18, 223, 15, + 225, 231, 233, 238, 240, 245, 247, 252, + 254, 178, 259, 261, 73, 334, 281, 282, + 335, 306, 260, 72, 262, 330, 38, 263, + 265, 71, 329, 327, 264, 70, 266, 323, + 267, 269, 69, 322, 320, 268, 68, 270, + 316, 271, 273, 67, 315, 313, 272, 66, + 274, 309, 275, 277, 65, 308, 305, 276, + 64, 291, 37, 280, 285, 178, 283, 284, + 287, 39, 290, 40, 293, 43, 61, 296, + 46, 58, 299, 49, 55, 302, 52, 304, + 310, 312, 317, 319, 324, 326, 331, 333, + 178, 338, 109, 340, 408, 75, 341, 343, + 108, 407, 405, 342, 107, 344, 401, 345, + 347, 106, 400, 398, 346, 105, 348, 394, + 349, 351, 104, 393, 391, 350, 103, 352, + 387, 353, 355, 102, 386, 383, 354, 101, + 369, 74, 358, 363, 178, 361, 362, 365, + 76, 368, 77, 371, 80, 98, 374, 83, + 95, 377, 86, 92, 380, 89, 382, 388, + 390, 395, 397, 402, 404, 409, 411, 178, + 178, 417, 419, 146, 145, 439, 440, 492, + 464, 418, 420, 488, 111, 421, 423, 144, + 487, 485, 422, 143, 424, 481, 425, 427, + 142, 480, 478, 426, 141, 428, 474, 429, + 431, 140, 473, 471, 430, 139, 432, 467, + 433, 435, 138, 466, 463, 434, 137, 449, + 110, 438, 443, 178, 441, 442, 445, 112, + 448, 113, 451, 116, 134, 454, 119, 131, + 457, 122, 128, 460, 125, 462, 468, 470, + 475, 477, 482, 484, 489, 491, 147, 496, + 497, 511, 500, 501, 529, 148, 505, 499, + 504, 502, 503, 506, 507, 150, 510, 508, + 149, 151, 513, 153, 174, 163, 516, 156, + 171, 519, 159, 168, 522, 162, 165, 525, + 164, 528, 178, 531, 177, 534, 535, 533, + 538, 178, 536, 537 }; static const char _indic_syllable_machine_trans_actions[] = { @@ -1285,51 +1087,51 @@ static const char _indic_syllable_machine_trans_actions[] = { 0, 0, 2, 0, 0, 2, 0, 0, 2, 9, 0, 12, 2, 2, 6, 2, 13, 13, 0, 0, 2, 2, 6, 2, - 6, 2, 6, 14, 2, 2, 0, 2, - 0, 0, 2, 2, 2, 2, 0, 2, - 2, 0, 2, 2, 0, 2, 2, 2, - 0, 2, 2, 2, 2, 0, 2, 2, - 2, 0, 2, 2, 2, 2, 0, 2, - 2, 2, 0, 2, 2, 2, 2, 0, - 2, 2, 2, 0, 2, 0, 0, 0, - 15, 0, 0, 2, 0, 2, 0, 2, - 0, 0, 2, 0, 0, 2, 0, 0, - 2, 0, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 16, 2, 2, 0, 2, - 0, 0, 2, 2, 2, 2, 0, 2, - 2, 0, 2, 2, 0, 2, 2, 2, - 0, 2, 2, 2, 2, 0, 2, 2, - 2, 0, 2, 2, 2, 2, 0, 2, - 2, 2, 0, 2, 2, 2, 2, 0, - 2, 2, 2, 0, 2, 0, 0, 0, - 17, 0, 0, 2, 0, 2, 0, 2, - 0, 0, 2, 0, 0, 2, 0, 0, - 2, 0, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 18, 6, 0, 6, 6, - 0, 6, 2, 0, 6, 2, 6, 0, - 6, 6, 6, 2, 0, 6, 2, 6, - 0, 6, 6, 6, 2, 0, 6, 2, - 6, 0, 6, 6, 6, 2, 0, 6, - 2, 6, 0, 6, 0, 0, 0, 19, - 0, 0, 2, 0, 2, 0, 2, 0, - 0, 2, 0, 0, 2, 0, 0, 2, - 0, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 20, 21, 2, 2, 0, 0, - 0, 0, 2, 2, 2, 2, 2, 2, - 0, 2, 2, 0, 2, 2, 2, 0, + 6, 2, 14, 2, 2, 0, 2, 0, + 0, 2, 2, 2, 0, 2, 2, 0, + 2, 2, 0, 2, 2, 2, 0, 2, + 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, - 2, 0, 2, 2, 2, 2, 0, 2, - 2, 2, 0, 2, 0, 0, 0, 22, - 0, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 0, 0, 15, 0, + 0, 2, 0, 2, 0, 2, 0, 0, + 2, 0, 0, 2, 0, 0, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 16, 2, 2, 0, 2, 0, 0, + 2, 2, 2, 0, 2, 2, 0, 2, + 2, 0, 2, 2, 2, 0, 2, 2, + 2, 2, 0, 2, 2, 2, 0, 2, + 2, 2, 2, 0, 2, 2, 2, 0, + 2, 2, 2, 2, 0, 2, 2, 2, + 0, 2, 0, 0, 0, 17, 0, 0, + 2, 0, 2, 0, 2, 0, 0, 2, + 0, 0, 2, 0, 0, 2, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 18, 6, 0, 6, 6, 0, 6, 2, + 0, 6, 2, 6, 0, 6, 6, 6, + 2, 0, 6, 2, 6, 0, 6, 6, + 6, 2, 0, 6, 2, 6, 0, 6, + 6, 6, 2, 0, 6, 2, 6, 0, + 6, 0, 0, 0, 19, 0, 0, 2, + 0, 2, 0, 2, 0, 0, 2, 0, + 0, 2, 0, 0, 2, 0, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 20, + 21, 2, 2, 0, 0, 0, 0, 2, + 2, 2, 2, 2, 0, 2, 2, 0, + 2, 2, 2, 0, 2, 2, 2, 2, + 0, 2, 2, 2, 0, 2, 2, 2, + 2, 0, 2, 2, 2, 0, 2, 2, + 2, 2, 0, 2, 2, 2, 0, 2, + 0, 0, 0, 22, 0, 0, 2, 0, + 2, 0, 2, 0, 0, 2, 0, 0, + 2, 0, 0, 2, 0, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 0, 0, + 8, 2, 0, 0, 2, 0, 2, 0, + 0, 0, 0, 8, 8, 0, 8, 8, + 0, 0, 2, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, - 0, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 0, 0, 8, 2, 0, 0, - 2, 0, 2, 0, 0, 0, 0, 8, - 8, 0, 8, 8, 0, 0, 2, 0, - 0, 0, 2, 0, 0, 2, 0, 0, - 2, 0, 0, 2, 0, 2, 23, 2, - 0, 0, 0, 0, 0, 24, 0, 0 + 0, 2, 23, 2, 0, 0, 0, 0, + 0, 24, 0, 0 }; static const char _indic_syllable_machine_to_state_actions[] = { @@ -1400,7 +1202,7 @@ static const char _indic_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0 }; static const char _indic_syllable_machine_from_state_actions[] = { @@ -1471,7 +1273,7 @@ static const char _indic_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0 }; static const short _indic_syllable_machine_eof_trans[] = { @@ -1497,52 +1299,52 @@ static const short _indic_syllable_machine_eof_trans[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 186, 0, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, - 435, 364, 435, 436, 436, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 436, - 436, 436, 364, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 364, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 364, 551, 551, - 551, 551, 551, 551, 551, 551, 551 + 1, 186, 0, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, + 282, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 361, 361, 361, 432, 361, 432, + 433, 433, 433, 433, 433, 433, 433, 433, + 433, 433, 433, 433, 433, 433, 433, 433, + 433, 433, 433, 433, 433, 433, 433, 433, + 433, 433, 433, 433, 433, 433, 433, 433, + 433, 433, 433, 433, 433, 433, 433, 433, + 433, 433, 433, 433, 433, 433, 433, 433, + 433, 433, 433, 433, 433, 433, 433, 433, + 433, 433, 433, 433, 433, 433, 433, 433, + 433, 433, 433, 433, 433, 433, 433, 433, + 433, 433, 433, 433, 433, 433, 361, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 361, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, + 203, 361, 547, 547, 547, 547, 547, 547, + 547, 547, 547 }; static const int indic_syllable_machine_start = 178; @@ -1556,7 +1358,7 @@ static const int indic_syllable_machine_en_main = 178; -#line 97 "hb-ot-shape-complex-indic-machine.rl" +#line 96 "hb-ot-shape-complex-indic-machine.rl" #define found_syllable(syllable_type) \ @@ -1576,7 +1378,7 @@ find_syllables (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 1580 "hb-ot-shape-complex-indic-machine.hh" +#line 1382 "hb-ot-shape-complex-indic-machine.hh" { cs = indic_syllable_machine_start; ts = 0; @@ -1584,7 +1386,7 @@ find_syllables (hb_buffer_t *buffer) act = 0; } -#line 118 "hb-ot-shape-complex-indic-machine.rl" +#line 117 "hb-ot-shape-complex-indic-machine.rl" p = 0; @@ -1593,7 +1395,7 @@ find_syllables (hb_buffer_t *buffer) unsigned int last = 0; unsigned int syllable_serial = 1; -#line 1597 "hb-ot-shape-complex-indic-machine.hh" +#line 1399 "hb-ot-shape-complex-indic-machine.hh" { int _slen; int _trans; @@ -1607,7 +1409,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 1611 "hb-ot-shape-complex-indic-machine.hh" +#line 1413 "hb-ot-shape-complex-indic-machine.hh" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -1630,71 +1432,71 @@ _eof_trans: {te = p+1;} break; case 15: -#line 88 "hb-ot-shape-complex-indic-machine.rl" +#line 87 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (consonant_syllable); }} break; case 17: -#line 89 "hb-ot-shape-complex-indic-machine.rl" +#line 88 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (vowel_syllable); }} break; case 22: -#line 90 "hb-ot-shape-complex-indic-machine.rl" +#line 89 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (standalone_cluster); }} break; case 24: -#line 91 "hb-ot-shape-complex-indic-machine.rl" +#line 90 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (symbol_cluster); }} break; case 19: -#line 92 "hb-ot-shape-complex-indic-machine.rl" +#line 91 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (broken_cluster); }} break; case 12: -#line 93 "hb-ot-shape-complex-indic-machine.rl" +#line 92 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (non_indic_cluster); }} break; case 14: -#line 88 "hb-ot-shape-complex-indic-machine.rl" +#line 87 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (consonant_syllable); }} break; case 16: -#line 89 "hb-ot-shape-complex-indic-machine.rl" +#line 88 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (vowel_syllable); }} break; case 21: -#line 90 "hb-ot-shape-complex-indic-machine.rl" +#line 89 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (standalone_cluster); }} break; case 23: -#line 91 "hb-ot-shape-complex-indic-machine.rl" +#line 90 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (symbol_cluster); }} break; case 18: -#line 92 "hb-ot-shape-complex-indic-machine.rl" +#line 91 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; case 20: -#line 93 "hb-ot-shape-complex-indic-machine.rl" +#line 92 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (non_indic_cluster); }} break; case 1: -#line 88 "hb-ot-shape-complex-indic-machine.rl" +#line 87 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (consonant_syllable); }} break; case 3: -#line 89 "hb-ot-shape-complex-indic-machine.rl" +#line 88 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (vowel_syllable); }} break; case 7: -#line 90 "hb-ot-shape-complex-indic-machine.rl" +#line 89 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (standalone_cluster); }} break; case 9: -#line 91 "hb-ot-shape-complex-indic-machine.rl" +#line 90 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (symbol_cluster); }} break; case 4: -#line 92 "hb-ot-shape-complex-indic-machine.rl" +#line 91 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (broken_cluster); }} break; case 5: @@ -1715,22 +1517,22 @@ _eof_trans: case 8: #line 1 "NONE" {te = p+1;} -#line 88 "hb-ot-shape-complex-indic-machine.rl" +#line 87 "hb-ot-shape-complex-indic-machine.rl" {act = 1;} break; case 6: #line 1 "NONE" {te = p+1;} -#line 92 "hb-ot-shape-complex-indic-machine.rl" +#line 91 "hb-ot-shape-complex-indic-machine.rl" {act = 5;} break; case 13: #line 1 "NONE" {te = p+1;} -#line 93 "hb-ot-shape-complex-indic-machine.rl" +#line 92 "hb-ot-shape-complex-indic-machine.rl" {act = 6;} break; -#line 1734 "hb-ot-shape-complex-indic-machine.hh" +#line 1536 "hb-ot-shape-complex-indic-machine.hh" } _again: @@ -1739,7 +1541,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 1743 "hb-ot-shape-complex-indic-machine.hh" +#line 1545 "hb-ot-shape-complex-indic-machine.hh" } if ( ++p != pe ) @@ -1755,7 +1557,7 @@ _again: } -#line 127 "hb-ot-shape-complex-indic-machine.rl" +#line 126 "hb-ot-shape-complex-indic-machine.rl" } diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl index 694b235d1..86a7ceb22 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl @@ -57,7 +57,6 @@ Repha = 15; Ra = 16; CM = 17; Symbol= 18; -CM2 = 31; c = (C | Ra); # is_consonant n = ((ZWNJ?.RS)? (N.N?)?); # is_consonant_modifier @@ -73,7 +72,7 @@ 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; -medial_group = CM?.CM2?; +medial_group = CM?; halant_or_matra_group = (final_halant_group | (h.ZWJ)? matra_group{0,4}) (Coeng (cn|V))?; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh index 559ebe498..c880311ee 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh @@ -60,11 +60,10 @@ enum indic_category_t { OT_Repha = 15, /* Atomically-encoded logical or visual repha. */ OT_Ra = 16, OT_CM = 17, /* Consonant-Medial. */ - OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */ - OT_CM2 = 31 /* Consonant-Medial, second slot. */ + OT_Symbol = 18 /* Avagraha, etc that take marks (SM,A,VD). */ }; -#define MEDIAL_FLAGS (FLAG (OT_CM) | FLAG (OT_CM2)) +#define MEDIAL_FLAGS (FLAG (OT_CM)) /* Note: * @@ -109,27 +108,31 @@ enum indic_syllabic_category_t { INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Symbol, INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM, - INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* TODO */ + INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* Don't care. */ INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK = OT_A, INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C, INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C, INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM, INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C, + INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER = OT_M, /* U+17CD only. */ INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM, INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_PLACEHOLDER, INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA = OT_Repha, + INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED = OT_X, /* Don't care. */ INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM, INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_N, + INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_C, INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, - INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_H, /* TODO */ + INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng, INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ, INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X, INDIC_SYLLABIC_CATEGORY_NON_JOINER = OT_ZWNJ, INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N, INDIC_SYLLABIC_CATEGORY_NUMBER = OT_PLACEHOLDER, - INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* TODO */ - INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_H, /* TODO */ + INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* Don't care. */ + INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_M, /* Is like a vowel matra. */ INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS, + INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER = OT_SM, INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X, INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N, INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H, @@ -162,17 +165,23 @@ enum indic_matra_category_t { }; #define INDIC_COMBINE_CATEGORIES(S,M) \ - (ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || \ - ( \ - S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \ - S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \ - S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \ - S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \ - S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \ - S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \ - false)) + \ - ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \ - ((M << 8) | S)) + ( \ + ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \ + ( S | \ + ( \ + ( \ + S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \ + S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \ + S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \ + S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \ + S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \ + S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \ + false \ + ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \ + ) << 8 \ + ) \ + ) \ + ) HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE hb_indic_get_categories (hb_codepoint_t u); diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc index 2e159a12b..3bf5285e6 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc @@ -2,67 +2,71 @@ /* * The following table is generated by running: * - * ./gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt + * ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt * * on files with these headers: * - * # IndicSyllabicCategory-7.0.0.txt - * # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP] - * # IndicMatraCategory-7.0.0.txt - * # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP] - * # Blocks-7.0.0.txt - * # Date: 2014-04-03, 23:23:00 GMT [RP, KW] + * # IndicSyllabicCategory-9.0.0.txt + * # Date: 2016-05-21, 02:46:00 GMT [RP] + * # IndicPositionalCategory-9.0.0.txt + * # Date: 2016-02-25, 00:48:00 GMT [RP] + * # Blocks-9.0.0.txt + * # Date: 2016-02-05, 23:48:00 GMT [KW] */ #include "hb-ot-shape-complex-indic-private.hh" -#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 13 chars; Avagraha */ -#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 59 chars; Bindu */ +#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 15 chars; Avagraha */ +#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 67 chars; Bindu */ #define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */ -#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 30 chars; Cantillation_Mark */ -#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 1744 chars; Consonant */ -#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 7 chars; Consonant_Dead */ -#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 61 chars; Consonant_Final */ +#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 53 chars; Cantillation_Mark */ +#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 1907 chars; Consonant */ +#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 10 chars; Consonant_Dead */ +#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 62 chars; Consonant_Final */ #define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */ -#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 19 chars; Consonant_Medial */ -#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 11 chars; Consonant_Placeholder */ +#define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */ +#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 22 chars; Consonant_Medial */ +#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 16 chars; Consonant_Placeholder */ #define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 1 chars; Consonant_Preceding_Repha */ -#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 61 chars; Consonant_Subjoined */ +#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 2 chars; Consonant_Prefixed */ +#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 90 chars; Consonant_Subjoined */ #define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 4 chars; Consonant_Succeeding_Repha */ +#define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 4 chars; Consonant_With_Stacker */ #define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 2 chars; Gemination_Mark */ #define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 7 chars; Invisible_Stacker */ #define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */ #define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */ #define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */ -#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 18 chars; Nukta */ -#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 408 chars; Number */ +#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 24 chars; Nukta */ +#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 459 chars; Number */ #define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */ #define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */ -#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 15 chars; Pure_Killer */ -#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 3 chars; Register_Shifter */ +#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 16 chars; Pure_Killer */ +#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */ +#define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 22 chars; Syllable_Modifier */ #define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */ -#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 62 chars; Tone_Mark */ -#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 22 chars; Virama */ -#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 29 chars; Visarga */ +#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 42 chars; Tone_Mark */ +#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 24 chars; Virama */ +#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 31 chars; Visarga */ #define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */ -#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 553 chars; Vowel_Dependent */ -#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 395 chars; Vowel_Independent */ +#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 602 chars; Vowel_Dependent */ +#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 431 chars; Vowel_Independent */ -#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 142 chars; Bottom */ +#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 300 chars; Bottom */ #define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 2 chars; Bottom_And_Right */ #define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 57 chars; Left */ #define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 21 chars; Left_And_Right */ #define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */ -#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 2 chars; Overstruck */ -#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 163 chars; Right */ -#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 169 chars; Top */ +#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */ +#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 258 chars; Right */ +#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 342 chars; Top */ #define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */ #define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */ #define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 6 chars; Top_And_Left */ #define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 4 chars; Top_And_Left_And_Right */ #define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 13 chars; Top_And_Right */ -#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 15 chars; Visual_Order_Left */ +#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 19 chars; Visual_Order_Left */ #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M) @@ -79,29 +83,33 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 0030 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* 0038 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), -#define indic_offset_0x00d0u 24 +#define indic_offset_0x00b0u 24 /* Latin-1 Supplement */ + /* 00B0 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 00B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 00C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 00C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), /* 00D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), -#define indic_offset_0x0900u 32 +#define indic_offset_0x0900u 64 /* Devanagari */ - /* 0900 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), + /* 0900 */ _(Bi,T), _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x), /* 0908 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), /* 0910 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), /* 0918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0920 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0928 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,x), _(A,x), _(M,R), _(M,L), + /* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,B), _(A,x), _(M,R), _(M,L), /* 0940 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), /* 0948 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(M,L), _(M,R), - /* 0950 */ _(x,x), _(TM,x), _(TM,x), _(x,x), _(x,x), _(M,T), _(M,B), _(M,B), + /* 0950 */ _(x,x), _(Ca,T), _(Ca,B), _(x,T), _(x,T), _(M,T), _(M,B), _(M,B), /* 0958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0960 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), /* 0968 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), @@ -110,14 +118,14 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* Bengali */ - /* 0980 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0980 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), /* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x), /* 0990 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), /* 0998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 09A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 09A8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 09B0 */ _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), - /* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,L), + /* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L), /* 09C0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L), /* 09C8 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,B), _(CD,x), _(x,x), /* 09D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), @@ -129,33 +137,33 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* Gurmukhi */ - /* 0A00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0A00 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), /* 0A08 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x), /* 0A10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), /* 0A18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0A28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0A30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), - /* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(x,x), _(M,R), _(M,L), + /* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(x,x), _(M,R), _(M,L), /* 0A40 */ _(M,R), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), /* 0A48 */ _(M,T), _(x,x), _(x,x), _(M,T), _(M,T), _(V,B), _(x,x), _(x,x), /* 0A50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), /* 0A58 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), /* 0A60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x), /* 0A68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 0A70 */ _(Bi,x), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,x), _(x,x), _(x,x), + /* 0A70 */ _(Bi,T), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,B), _(x,x), _(x,x), /* 0A78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), /* Gujarati */ - /* 0A80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0A80 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), /* 0A88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), /* 0A90 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), /* 0A98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0AA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0AA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0AB0 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), - /* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,L), + /* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L), /* 0AC0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(x,x), _(M,T), /* 0AC8 */ _(M,T), _(M,TR), _(x,x), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x), /* 0AD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), @@ -163,18 +171,18 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* 0AF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 0AF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0AF8 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), /* Oriya */ - /* 0B00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0B00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), /* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x), /* 0B10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), /* 0B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0B28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0B30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), - /* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,T), + /* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T), /* 0B40 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L), /* 0B48 */ _(M,TL), _(x,x), _(x,x), _(M,LR),_(M,TLR), _(V,B), _(x,x), _(x,x), /* 0B50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,TR), @@ -186,7 +194,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* Tamil */ - /* 0B80 */ _(x,x), _(x,x), _(Bi,x), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0B80 */ _(x,x), _(x,x), _(Bi,T), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), /* 0B88 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(VI,x), /* 0B90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(x,x), _(x,x), /* 0B98 */ _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(C,x), _(C,x), @@ -194,7 +202,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 0BA8 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), /* 0BB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0BB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), - /* 0BC0 */ _(M,T), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L), + /* 0BC0 */ _(M,T), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L), /* 0BC8 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T), _(x,x), _(x,x), /* 0BD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), /* 0BD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), @@ -205,7 +213,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* Telugu */ - /* 0C00 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0C00 */ _(Bi,T), _(Bi,R), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), /* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), /* 0C10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), /* 0C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), @@ -216,7 +224,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 0C40 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,T), /* 0C48 */ _(M,TB), _(x,x), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), _(x,x), /* 0C50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(x,x), - /* 0C58 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0C58 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), /* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), /* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), @@ -224,26 +232,26 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* Kannada */ - /* 0C80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0C80 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), /* 0C88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), /* 0C90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), /* 0C98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0CA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0CA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0CB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), - /* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,T), + /* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T), /* 0CC0 */ _(M,TR), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,TR), /* 0CC8 */ _(M,TR), _(x,x), _(M,TR), _(M,TR), _(M,T), _(V,T), _(x,x), _(x,x), /* 0CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), /* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(x,x), /* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 0CF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0CF0 */ _(x,x),_(CWS,x),_(CWS,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), /* 0CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), /* Malayalam */ - /* 0D00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0D00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), /* 0D10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), /* 0D18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), @@ -253,8 +261,8 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 0D38 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(A,x), _(M,R), _(M,R), /* 0D40 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(x,x), _(M,L), _(M,L), /* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T),_(CPR,x), _(x,x), - /* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), - /* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(M,R), + /* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x), /* 0D60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), /* 0D68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* 0D70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), @@ -262,7 +270,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* Sinhala */ - /* 0D80 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0D80 */ _(x,x), _(x,x), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), /* 0D88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), /* 0D90 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), /* 0D98 */ _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), @@ -278,7 +286,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 0DE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* 0DF0 */ _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(x,x), -#define indic_offset_0x1000u 1304 +#define indic_offset_0x1000u 1336 /* Myanmar */ @@ -289,52 +297,24 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 1018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 1020 */ _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), /* 1028 */ _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), - /* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,x), _(TM,x), - /* 1038 */ _(Vs,x), _(IS,x), _(PK,T), _(CM,x), _(CM,x), _(CM,x), _(CM,x), _(C,x), + /* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,T), _(TM,B), + /* 1038 */ _(Vs,R), _(IS,x), _(PK,T), _(CM,R), _(CM,x), _(CM,B), _(CM,B), _(C,x), /* 1040 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* 1048 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), _(x,x), /* 1050 */ _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), - /* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,x), _(CM,x), - /* 1060 */ _(CM,x), _(C,x), _(M,R), _(TM,x), _(TM,x), _(C,x), _(C,x), _(M,R), - /* 1068 */ _(M,R), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(C,x), + /* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,B), _(CM,B), + /* 1060 */ _(CM,B), _(C,x), _(M,R), _(TM,R), _(TM,R), _(C,x), _(C,x), _(M,R), + /* 1068 */ _(M,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(C,x), _(C,x), /* 1070 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(C,x), _(C,x), _(C,x), /* 1078 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1080 */ _(C,x), _(C,x), _(CM,x), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,x), - /* 1088 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(TM,x), + /* 1080 */ _(C,x), _(C,x), _(CM,B), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,R), + /* 1088 */ _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,B), _(C,x), _(TM,R), /* 1090 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 1098 */ _(Nd,x), _(Nd,x), _(TM,x), _(TM,x), _(M,R), _(M,T), _(x,x), _(x,x), + /* 1098 */ _(Nd,x), _(Nd,x), _(TM,R), _(TM,R), _(M,R), _(M,T), _(x,x), _(x,x), -#define indic_offset_0x1700u 1464 +#define indic_offset_0x1780u 1496 - /* Tagalog */ - - /* 1700 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1708 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), - /* 1710 */ _(C,x), _(C,x), _(M,T), _(M,B), _(PK,B), _(x,x), _(x,x), _(x,x), - /* 1718 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Hanunoo */ - - /* 1720 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1728 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1730 */ _(C,x), _(C,x), _(M,T), _(M,B), _(PK,B), _(x,x), _(x,x), _(x,x), - /* 1738 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Buhid */ - - /* 1740 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1748 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1750 */ _(C,x), _(C,x), _(M,T), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1758 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Tagbanwa */ - - /* 1760 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1768 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), - /* 1770 */ _(C,x), _(x,x), _(M,T), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1778 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* Khmer */ /* 1780 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), @@ -345,515 +325,72 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 17A8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), /* 17B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(M,R), _(M,T), /* 17B8 */ _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,TL),_(M,TLR), - /* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,x), _(Vs,x), - /* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(RS,T),_(CSR,T), _(M,T), _(M,T), _(M,T), - /* 17D0 */ _(M,T), _(PK,T), _(IS,x), _(M,T), _(x,x), _(x,x), _(x,x), _(x,x), - /* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(x,x), _(x,x), _(x,x), + /* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,T), _(Vs,R), + /* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(SM,T),_(CSR,T), _(CK,T), _(SM,T), _(SM,T), + /* 17D0 */ _(SM,T), _(PK,T), _(IS,x), _(SM,T), _(x,x), _(x,x), _(x,x), _(x,x), + /* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(SM,T), _(x,x), _(x,x), /* 17E0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* 17E8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), -#define indic_offset_0x1900u 1704 - - - /* Limbu */ - - /* 1900 */ _(CP,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1908 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), - /* 1920 */ _(M,T), _(M,T), _(M,B), _(M,R), _(M,R), _(M,TR), _(M,TR), _(M,T), - /* 1928 */ _(M,T), _(CS,x), _(CS,x), _(CS,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1930 */ _(CF,x), _(CF,x), _(Bi,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), - /* 1938 */ _(CF,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1940 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x), - /* 1948 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - - /* Tai Le */ - - /* 1950 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1960 */ _(C,x), _(C,x), _(C,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), - /* 1968 */ _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(x,x), _(x,x), - /* 1970 */ _(TL,x), _(TL,x), _(TL,x), _(TL,x), _(TL,x), _(x,x), _(x,x), _(x,x), - /* 1978 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* New Tai Lue */ - - /* 1980 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1988 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1990 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 19A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 19A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 19B0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,L), _(M,L), _(M,L), - /* 19B8 */ _(M,R), _(M,R), _(M,L), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), - /* 19C0 */ _(M,R), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), - /* 19C8 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 19D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 19D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 19E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 19E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 19F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 19F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Buginese */ - - /* 1A00 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1A08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1A10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T), - /* 1A18 */ _(M,B), _(M,L), _(M,R), _(M,T), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Tai Tham */ - - /* 1A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1A28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1A30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1A38 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1A40 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1A48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), - /* 1A50 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(CM,L), _(CM,x), _(CF,x), - /* 1A58 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x), - /* 1A60 */ _(IS,x), _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T), - /* 1A68 */ _(M,T), _(M,B), _(M,B), _(M,T), _(M,B), _(M,R), _(M,L), _(M,L), - /* 1A70 */ _(M,L), _(M,L), _(M,L), _(M,T), _(M,T), _(TM,x), _(TM,x), _(TM,x), - /* 1A78 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1A80 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 1A88 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1A90 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 1A98 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - -#define indic_offset_0x1b00u 2120 - - - /* Balinese */ - - /* 1B00 */ _(Bi,x), _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), - /* 1B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 1B10 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1B28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1B30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(N,x), _(M,R), _(M,T), _(M,T), - /* 1B38 */ _(M,B), _(M,B), _(M,B), _(M,BR), _(M,TB),_(M,TBR), _(M,L), _(M,L), - /* 1B40 */ _(M,LR), _(M,LR), _(M,T), _(M,TR), _(V,R), _(C,x), _(C,x), _(C,x), - /* 1B48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1B50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 1B58 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1B60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1B68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1B70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Sundanese */ - - /* 1B80 */ _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 1B88 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1B90 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1B98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1BA0 */ _(C,x), _(CS,x), _(CS,x), _(CS,x), _(M,T), _(M,B), _(M,L), _(M,R), - /* 1BA8 */ _(M,T), _(M,T), _(PK,R), _(IS,x), _(CS,x), _(CS,x), _(C,x), _(C,x), - /* 1BB0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 1BB8 */ _(Nd,x), _(Nd,x), _(A,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x), - - /* Batak */ - - /* 1BC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1BC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1BD0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1BD8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1BE0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(N,x), _(M,R), - /* 1BE8 */ _(M,T), _(M,T), _(M,R), _(M,R), _(M,R), _(M,T), _(M,R), _(M,T), - /* 1BF0 */ _(CF,x), _(CF,x), _(PK,R), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Lepcha */ - - /* 1C00 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1C08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1C10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 1C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CS,x), _(CS,x), _(M,R), _(M,L), - /* 1C28 */ _(M,L), _(M,TL), _(M,R), _(M,R), _(M,B), _(CF,x), _(CF,x), _(CF,x), - /* 1C30 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(Bi,L), _(Bi,L), _(x,x), _(N,x), - /* 1C38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1C40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 1C48 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), - -#define indic_offset_0x1cd0u 2456 +#define indic_offset_0x1cd0u 1608 /* Vedic Extensions */ - /* 1CD0 */ _(TM,x), _(TM,x), _(TM,x), _(x,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), - /* 1CD8 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), - /* 1CE0 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1CE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(TM,x), _(x,x), _(x,x), _(x,x), + /* 1CD0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(x,x), _(Ca,O), _(Ca,B), _(Ca,B), _(Ca,B), + /* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B), + /* 1CE0 */ _(Ca,T), _(Ca,R), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), + /* 1CE8 */ _(x,O), _(x,x), _(x,x), _(x,x), _(x,x), _(x,B), _(x,x), _(x,x), + /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(Ca,T), _(x,x), _(x,x), _(x,x), + /* 1CF8 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), -#define indic_offset_0x2008u 2496 +#define indic_offset_0x2008u 1656 /* General Punctuation */ /* 2008 */ _(x,x), _(x,x), _(x,x), _(x,x),_(ZWNJ,x),_(ZWJ,x), _(x,x), _(x,x), - /* 2010 */ _(x,x), _(x,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x), + /* 2010 */ _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x), -#define indic_offset_0xa800u 2512 +#define indic_offset_0x2070u 1672 - /* Syloti Nagri */ + /* Superscripts and Subscripts */ - /* A800 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(PK,T), _(C,x), - /* A808 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A810 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A818 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A820 */ _(C,x), _(C,x), _(C,x), _(M,R), _(M,R), _(M,B), _(M,T), _(M,R), - /* A828 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* A830 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* A838 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 2070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(SM,x), _(x,x), _(x,x), _(x,x), + /* 2078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 2080 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x), - /* Phags-pa */ +#define indic_offset_0xa8e0u 1696 - /* A840 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A848 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A850 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A858 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Vo,x), _(Vo,x), - /* A860 */ _(Vo,x), _(Vo,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Vo,x), _(CS,x), - /* A868 */ _(CS,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A870 */ _(C,x), _(CS,x), _(C,x), _(Bi,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* A878 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Saurashtra */ - - /* A880 */ _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* A888 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* A890 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A898 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A8A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A8A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A8B0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(M,R), _(M,R), _(M,R), - /* A8B8 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), - /* A8C0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x), _(x,x), - /* A8C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* A8D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* A8D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), /* Devanagari Extended */ - /* A8E0 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), - /* A8E8 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), - /* A8F0 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* A8F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), + /* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), + /* A8F0 */ _(Ca,T), _(Ca,T), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* Kayah Li */ +#define indic_offset_0xa9e0u 1720 - /* A900 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* A908 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A920 */ _(C,x), _(C,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), - /* A928 */ _(Vo,x), _(Vo,x), _(Vo,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(x,x), - - /* Rejang */ - - /* A930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A938 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A940 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,B), - /* A948 */ _(M,B), _(M,B), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B), _(CF,x), - /* A950 */ _(CF,x), _(CF,x), _(CF,x), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x), - /* A958 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* A960 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* A968 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* A970 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* A978 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Javanese */ - - /* A980 */ _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* A988 */ _(VI,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), - /* A990 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A9A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A9A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* A9B0 */ _(C,x), _(C,x), _(C,x), _(N,x), _(M,R), _(M,R), _(M,T), _(M,T), - /* A9B8 */ _(M,B), _(M,B), _(M,L), _(M,L), _(M,T), _(CS,x), _(CM,x), _(CM,x), - /* A9C0 */ _(V,BR), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* A9C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* A9D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* A9D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), /* Myanmar Extended-B */ - /* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(C,x), + /* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T), _(x,x), _(C,x), /* A9E8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* A9F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* A9F8 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), - /* Cham */ +#define indic_offset_0xaa60u 1752 - /* AA00 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), - /* AA08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AA10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AA18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AA20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AA28 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(M,B), _(M,T), _(M,L), - /* AA30 */ _(M,L), _(M,T), _(M,B), _(CM,x), _(CM,L), _(CM,x), _(CM,x), _(x,x), - /* AA38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* AA40 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), - /* AA48 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x), _(x,x), - /* AA50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* AA58 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), /* Myanmar Extended-A */ /* AA60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* AA68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(C,x), + /* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), + /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x), - /* Tai Viet */ - - /* AA80 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AA88 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AA90 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AA98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AAA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AAA8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AAB0 */ _(M,T), _(M,R), _(M,T), _(M,T), _(M,B),_(M,VOL),_(M,VOL), _(M,T), - /* AAB8 */ _(M,T),_(M,VOL), _(M,R),_(M,VOL),_(M,VOL), _(M,R), _(M,T), _(TM,x), - /* AAC0 */ _(TL,x), _(TM,x), _(TL,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* AAC8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* AAD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* AAD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Meetei Mayek Extensions */ - - /* AAE0 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* AAE8 */ _(C,x), _(C,x), _(C,x), _(M,L), _(M,B), _(M,T), _(M,L), _(M,R), - /* AAF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Vs,x), _(IS,x), _(x,x), - -#define indic_offset_0xabc0u 3272 - - - /* Meetei Mayek */ - - /* ABC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* ABC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), - /* ABD0 */ _(C,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* ABD8 */ _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), - /* ABE0 */ _(CF,x), _(CF,x), _(CF,x), _(M,R), _(M,R), _(M,T), _(M,R), _(M,R), - /* ABE8 */ _(M,B), _(M,R), _(M,R), _(x,x), _(TM,x), _(PK,B), _(x,x), _(x,x), - /* ABF0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* ABF8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - -#define indic_offset_0x10a00u 3336 - - - /* Kharoshthi */ - - /* 10A00 */ _(C,x), _(M,O), _(M,B), _(M,B), _(x,x), _(M,T), _(M,O), _(x,x), - /* 10A08 */ _(x,x), _(x,x), _(x,x), _(x,x), _(M,B), _(x,x), _(Bi,x), _(Vs,x), - /* 10A10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), - /* 10A18 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 10A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 10A28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 10A30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 10A38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(IS,x), - /* 10A40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - -#define indic_offset_0x11000u 3408 - - - /* Brahmi */ - - /* 11000 */ _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), - /* 11008 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 11010 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11020 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11028 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11030 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11038 */ _(M,T), _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B), - /* 11040 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), - /* 11048 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 11050 */ _(x,x), _(x,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x), - /* 11058 */_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x), - /* 11060 */_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x), _(Nd,x), _(Nd,x), - /* 11068 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 11070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 11078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(NJ,x), - - /* Kaithi */ - - /* 11080 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 11088 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), - /* 11090 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11098 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 110A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 110A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 110B0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,T), _(M,T), _(M,R), - /* 110B8 */ _(M,R), _(V,B), _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - -#define indic_offset_0x11100u 3600 - - - /* Chakma */ - - /* 11100 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), - /* 11108 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11110 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11118 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11120 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T), - /* 11128 */ _(M,T), _(M,T), _(M,B), _(M,B), _(M,L), _(M,T), _(M,TB), _(M,TB), - /* 11130 */ _(M,T), _(M,B), _(M,B), _(IS,x), _(PK,T), _(x,x), _(Nd,x), _(Nd,x), - /* 11138 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 11140 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 11148 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Mahajani */ - - /* 11150 */ _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(C,x), _(C,x), _(C,x), - /* 11158 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11160 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11168 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11170 */ _(C,x), _(C,x), _(C,x), _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 11178 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Sharada */ - - /* 11180 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 11188 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 11190 */ _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11198 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 111A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 111A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 111B0 */ _(C,x), _(C,x), _(C,x), _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), - /* 111B8 */ _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,TR), - /* 111C0 */ _(V,R), _(A,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 111C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 111D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 111D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Sinhala Archaic Numbers */ - - /* 111E0 */ _(x,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 111E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 111F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), - /* 111F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Khojki */ - - /* 11200 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 11208 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11210 */ _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11218 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11220 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11228 */ _(C,x), _(C,x), _(C,x), _(C,x), _(M,R), _(M,R), _(M,R), _(M,B), - /* 11230 */ _(M,T), _(M,T), _(M,TR), _(M,TR), _(Bi,x), _(V,R), _(N,x), _(GM,T), - -#define indic_offset_0x112b0u 3912 - - - /* Khudawadi */ - - /* 112B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 112B8 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 112C0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 112C8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 112D0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 112D8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Bi,x), - /* 112E0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), - /* 112E8 */ _(M,T), _(N,x), _(PK,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 112F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 112F8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Grantha */ - - /* 11300 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), - /* 11308 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x), - /* 11310 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), - /* 11318 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11320 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11328 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11330 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), - /* 11338 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,R), - /* 11340 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(x,x), _(M,L), - /* 11348 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,R), _(x,x), _(x,x), - /* 11350 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), - /* 11358 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 11360 */ _(VI,x), _(VI,x), _(M,R), _(M,R), _(x,x), _(x,x), _(Ca,x), _(Ca,x), - /* 11368 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), - /* 11370 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), - -#define indic_offset_0x11480u 4112 - - - /* Tirhuta */ - - /* 11480 */ _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 11488 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), - /* 11490 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11498 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 114A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 114A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 114B0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,B), - /* 114B8 */ _(M,B), _(M,L), _(M,T), _(M,TL), _(M,LR), _(M,R), _(M,LR), _(Bi,x), - /* 114C0 */ _(Bi,x), _(Vs,x), _(V,B), _(N,x), _(A,x), _(x,x), _(x,x), _(x,x), - /* 114C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 114D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 114D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - -#define indic_offset_0x11580u 4208 - - - /* Siddham */ - - /* 11580 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 11588 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), - /* 11590 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11598 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 115A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 115A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,R), - /* 115B0 */ _(M,L), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), - /* 115B8 */ _(M,L), _(M,TL), _(M,LR),_(M,TLR), _(Bi,x), _(Bi,x), _(Vs,x), _(V,B), - /* 115C0 */ _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - -#define indic_offset_0x11600u 4280 - - - /* Modi */ - - /* 11600 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 11608 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), - /* 11610 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11618 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11620 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11628 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11630 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,B), - /* 11638 */ _(M,B), _(M,T), _(M,T), _(M,R), _(M,R), _(Bi,x), _(Vs,x), _(V,B), - /* 11640 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 11648 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 11650 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 11658 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 11660 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 11668 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 11670 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 11678 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - - /* Takri */ - - /* 11680 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), - /* 11688 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11690 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 11698 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 116A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 116A8 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(Vs,x), _(M,T), _(M,L), _(M,R), - /* 116B0 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,T), _(N,x), - /* 116B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 116C0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), - /* 116C8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - -}; /* Table items: 4488; occupancy: 73% */ +}; /* Table items: 1784; occupancy: 69% */ INDIC_TABLE_ELEMENT_TYPE hb_indic_get_categories (hb_codepoint_t u) @@ -861,41 +398,35 @@ hb_indic_get_categories (hb_codepoint_t u) switch (u >> 12) { case 0x0u: - if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u]; - if (hb_in_range (u, 0x00D0u, 0x00D7u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u]; - if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u]; + if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u]; + if (hb_in_range (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u]; + if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u]; if (unlikely (u == 0x00A0u)) return _(CP,x); break; case 0x1u: - if (hb_in_range (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u]; - if (hb_in_range (u, 0x1700u, 0x17EFu)) return indic_table[u - 0x1700u + indic_offset_0x1700u]; - if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return indic_table[u - 0x1900u + indic_offset_0x1900u]; - if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u]; - if (hb_in_range (u, 0x1CD0u, 0x1CF7u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u]; + if (hb_in_range (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u]; + if (hb_in_range (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u]; + if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u]; break; case 0x2u: - if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u]; + if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u]; + if (hb_in_range (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u]; if (unlikely (u == 0x25CCu)) return _(CP,x); break; case 0xAu: - if (hb_in_range (u, 0xA800u, 0xAAF7u)) return indic_table[u - 0xA800u + indic_offset_0xa800u]; - if (hb_in_range (u, 0xABC0u, 0xABFFu)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u]; - break; - - case 0x10u: - if (hb_in_range (u, 0x10A00u, 0x10A47u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u]; + if (hb_in_range (u, 0xA8E0u, 0xA8F7u)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u]; + if (hb_in_range (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u]; + if (hb_in_range (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u]; break; case 0x11u: - if (hb_in_range (u, 0x11000u, 0x110BFu)) return indic_table[u - 0x11000u + indic_offset_0x11000u]; - if (hb_in_range (u, 0x11100u, 0x11237u)) return indic_table[u - 0x11100u + indic_offset_0x11100u]; - if (hb_in_range (u, 0x112B0u, 0x11377u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u]; - if (hb_in_range (u, 0x11480u, 0x114DFu)) return indic_table[u - 0x11480u + indic_offset_0x11480u]; - if (hb_in_range (u, 0x11580u, 0x115C7u)) return indic_table[u - 0x11580u + indic_offset_0x11580u]; - if (hb_in_range (u, 0x11600u, 0x116CFu)) return indic_table[u - 0x11600u + indic_offset_0x11600u]; + // According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil, + // so the Indic shaper needs to know their categories. + if (unlikely (u == 0x11303)) return _(Vs,R); + if (unlikely (u == 0x1133c)) return _(N,B); break; default: @@ -914,11 +445,14 @@ hb_indic_get_categories (hb_codepoint_t u) #undef ISC_CD #undef ISC_CF #undef ISC_CHL +#undef ISC_CK #undef ISC_CM #undef ISC_CP #undef ISC_CPR +#undef ISC_CPrf #undef ISC_CS #undef ISC_CSR +#undef ISC_CWS #undef ISC_GM #undef ISC_IS #undef ISC_ZWJ @@ -930,6 +464,7 @@ hb_indic_get_categories (hb_codepoint_t u) #undef ISC_x #undef ISC_PK #undef ISC_RS +#undef ISC_SM #undef ISC_TL #undef ISC_TM #undef ISC_V diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc index 84282bd8d..3cd8fd6c3 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc @@ -176,32 +176,16 @@ set_indic_properties (hb_glyph_info_t &info) * Re-assign category */ - - /* The spec says U+0952 is OT_A. However, testing shows that Uniscribe - * treats a whole bunch of characters similarly. - * TESTS: For example, for U+0951: - * U+092E,U+0947,U+0952 - * U+092E,U+0952,U+0947 - * U+092E,U+0947,U+0951 - * U+092E,U+0951,U+0947 - * U+092E,U+0951,U+0952 - * U+092E,U+0952,U+0951 - */ - if (unlikely (hb_in_ranges (u, 0x0951u, 0x0952u, - 0x1CD0u, 0x1CD2u, - 0x1CD4u, 0x1CE1u) || - u == 0x1CF4u)) - cat = OT_A; /* The following act more like the Bindus. */ - else if (unlikely (hb_in_range (u, 0x0953u, 0x0954u))) + if (unlikely (hb_in_range (u, 0x0953u, 0x0954u))) cat = OT_SM; /* The following act like consonants. */ - else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u, + else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u, 0x1CF5u, 0x1CF6u))) cat = OT_C; /* TODO: The following should only be allowed after a Visarga. * For now, just treat them like regular tone marks. */ - else if (unlikely (hb_in_range (u, 0x1CE2u, 0x1CE8u))) + else if (unlikely (hb_in_range (u, 0x1CE2u, 0x1CE8u))) cat = OT_A; /* TODO: The following should only be allowed after some of * the nasalization marks, maybe only for U+1CE9..U+1CF1. @@ -209,28 +193,26 @@ set_indic_properties (hb_glyph_info_t &info) else if (unlikely (u == 0x1CEDu)) cat = OT_A; /* The following take marks in standalone clusters, similar to Avagraha. */ - else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u, + else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u, 0x1CE9u, 0x1CECu, 0x1CEEu, 0x1CF1u))) { cat = OT_Symbol; ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol); } - else if (unlikely (hb_in_range (u, 0x17CDu, 0x17D1u) || + else if (unlikely (hb_in_range (u, 0x17CDu, 0x17D1u) || u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */ { - /* These are like Top Matras. */ + /* These can occur mid-syllable (eg. before matras), even though Unicode marks them as Syllable_Modifier. + * https://github.com/roozbehp/unicode-data/issues/5 */ cat = OT_M; pos = POS_ABOVE_C; } + else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */ - else if (unlikely (u == 0x17D2u)) cat = OT_Coeng; /* Khmer coeng */ - else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) + else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) cat = OT_PLACEHOLDER; else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE; - else if (unlikely (u == 0xA982u)) cat = OT_SM; /* Javanese repha. */ - else if (unlikely (u == 0xA9BEu)) cat = OT_CM2; /* Javanese medial ya. */ - else if (unlikely (u == 0xA9BDu)) { cat = OT_M; pos = POS_POST_C; } /* Javanese vocalic r. */ /* @@ -296,11 +278,6 @@ enum blwf_mode_t { BLWF_MODE_PRE_AND_POST, /* Below-forms feature applied to pre-base and post-base. */ BLWF_MODE_POST_ONLY /* Below-forms feature applied to post-base only. */ }; -enum pref_len_t { - PREF_LEN_1 = 1, - PREF_LEN_2 = 2, - PREF_LEN_DONT_CARE = PREF_LEN_2 -}; struct indic_config_t { hb_script_t script; @@ -310,26 +287,24 @@ struct indic_config_t reph_position_t reph_pos; reph_mode_t reph_mode; blwf_mode_t blwf_mode; - pref_len_t pref_len; }; static const indic_config_t indic_configs[] = { /* Default. Should be first. */ - {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, - {HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_BENGALI, true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_GURMUKHI, true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_GUJARATI, true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_ORIYA, true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_TAMIL, true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, - {HB_SCRIPT_TELUGU, true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2}, - {HB_SCRIPT_KANNADA, true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2}, - {HB_SCRIPT_MALAYALAM, true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, + {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_BENGALI, true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_GURMUKHI, true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_GUJARATI, true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_ORIYA, true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_TAMIL, true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_TELUGU, true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY}, + {HB_SCRIPT_KANNADA, true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY}, + {HB_SCRIPT_MALAYALAM, true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST}, {HB_SCRIPT_SINHALA, false,0x0DCAu,BASE_POS_LAST_SINHALA, - REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_KHMER, false,0x17D2u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, - {HB_SCRIPT_JAVANESE, false,0xA9C0u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, + REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_KHMER, false,0x17D2u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST}, }; @@ -445,12 +420,12 @@ collect_features_indic (hb_ot_shape_planner_t *plan) unsigned int i = 0; map->add_gsub_pause (initial_reordering); for (; i < INDIC_BASIC_FEATURES; i++) { - map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ); + map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); map->add_gsub_pause (NULL); } map->add_gsub_pause (final_reordering); for (; i < INDIC_NUM_FEATURES; i++) { - map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ); + map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); } map->add_global_bool_feature (HB_TAG('c','a','l','t')); @@ -512,12 +487,12 @@ struct indic_shape_plan_t hb_codepoint_t glyph = virama_glyph; if (unlikely (virama_glyph == (hb_codepoint_t) -1)) { - if (!config->virama || !font->get_glyph (config->virama, 0, &glyph)) + if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph)) glyph = 0; /* Technically speaking, the spec says we should apply 'locl' to virama too. * Maybe one day... */ - /* Our get_glyph() function needs a font, so we can't get the virama glyph + /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph * during shape planning... Instead, overwrite it here. It's safe. Don't worry! */ (const_cast (this))->virama_glyph = glyph; } @@ -557,8 +532,15 @@ data_create_indic (const hb_ot_shape_plan_t *plan) indic_plan->virama_glyph = (hb_codepoint_t) -1; /* Use zero-context would_substitute() matching for new-spec of the main - * Indic scripts, and scripts with one spec only, but not for old-specs. */ - bool zero_context = !indic_plan->is_old_spec; + * Indic scripts, and scripts with one spec only, but not for old-specs. + * The new-spec for all dual-spec scripts says zero-context matching happens. + * + * However, testing with Malayalam shows that old and new spec both allow + * context. Testing with Bengali new-spec however shows that it doesn't. + * So, the heuristic here is the way it is. It should *only* be changed, + * as we discover more cases of what Windows does. DON'T TOUCH OTHERWISE. + */ + bool zero_context = !indic_plan->is_old_spec && plan->props.script != HB_SCRIPT_MALAYALAM; indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context); indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context); indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context); @@ -600,12 +582,8 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan, if (indic_plan->pstf.would_substitute (glyphs , 2, face) || indic_plan->pstf.would_substitute (glyphs+1, 2, face)) return POS_POST_C; - unsigned int pref_len = indic_plan->config->pref_len; - if ((pref_len == PREF_LEN_2 && - (indic_plan->pref.would_substitute (glyphs , 2, face) || - indic_plan->pref.would_substitute (glyphs+1, 2, face))) - || (pref_len == PREF_LEN_1 && - indic_plan->pref.would_substitute (glyphs+1, 1, face))) + if (indic_plan->pref.would_substitute (glyphs , 2, face) || + indic_plan->pref.would_substitute (glyphs+1, 2, face)) return POS_POST_C; return POS_BASE_C; } @@ -646,6 +624,8 @@ setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer) { find_syllables (buffer); + foreach_syllable (buffer, start, end) + buffer->unsafe_to_break (start, end); } static int @@ -754,10 +734,6 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, switch (indic_plan->config->base_pos) { - default: - assert (false); - HB_FALLTHROUGH; - case BASE_POS_LAST: { /* -> starting from the end of the syllable, move backwards */ @@ -1115,10 +1091,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, } } - unsigned int pref_len = indic_plan->config->pref_len; + unsigned int pref_len = 2; if (indic_plan->mask_array[PREF] && base + pref_len < end) { - assert (1 <= pref_len && pref_len <= 2); /* Find a Halant,Ra sequence and mark it for pre-base reordering processing. */ for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) { hb_codepoint_t glyphs[2]; @@ -1231,7 +1206,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_codepoint_t dottedcircle_glyph; - if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph)) + if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph)) return; hb_glyph_info_t dottedcircle = {0}; @@ -1258,7 +1233,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, /* TODO Set glyph_props? */ /* Insert dottedcircle after possible Repha. */ - while (buffer->idx < buffer->len && + while (buffer->idx < buffer->len && !buffer->in_error && last_syllable == buffer->cur().syllable() && buffer->cur().indic_category() == OT_Repha) buffer->next_glyph (); @@ -1328,7 +1303,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, for (base = start; base < end; base++) if (info[base].indic_position() >= POS_BASE_C) { - if (try_pref && base + 1 < end && indic_plan->config->pref_len == 2) + if (try_pref && base + 1 < end) { for (unsigned int i = base + 1; i < end; i++) if ((info[i].mask & indic_plan->mask_array[PREF]) != 0) @@ -1348,6 +1323,25 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, break; } } + /* For Malayalam, skip over unformed below- (but NOT post-) forms. */ + if (buffer->props.script == HB_SCRIPT_MALAYALAM) + { + for (unsigned int i = base + 1; i < end; i++) + { + while (i < end && is_joiner (info[i])) + i++; + if (i == end || !is_halant_or_coeng (info[i])) + break; + i++; /* Skip halant. */ + while (i < end && is_joiner (info[i])) + i++; + if (i < end && is_consonant (info[i]) && info[i].indic_position() == POS_BELOW_C) + { + base = i; + info[base].indic_position() = POS_BASE_C; + } + } + } if (start < base && info[base].indic_position() > POS_BASE_C) base--; @@ -1514,7 +1508,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (reph_pos == REPH_POS_AFTER_SUB) { new_reph_pos = base; - while (new_reph_pos < end && + while (new_reph_pos + 1 < end && !( FLAG_SAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD)))) new_reph_pos++; if (new_reph_pos < end) @@ -1591,7 +1585,6 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */ { - unsigned int pref_len = indic_plan->config->pref_len; for (unsigned int i = base + 1; i < end; i++) if ((info[i].mask & indic_plan->mask_array[PREF]) != 0) { @@ -1602,10 +1595,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, /* Note: We just check that something got substituted. We don't check that * the feature actually did it... * - * If pref len is longer than one, then only reorder if it ligated. If - * pref len is one, only reorder if it didn't ligate with other things. */ - if (_hb_glyph_info_substituted (&info[i]) && - ((pref_len == 1) ^ _hb_glyph_info_ligated_and_didnt_multiply (&info[i]))) + * Reorder pref only if it ligated. */ + if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i])) { /* * 2. Try to find a target position the same way as for pre-base matra. @@ -1733,37 +1724,32 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, switch (ab) { /* Don't decompose these. */ - case 0x0931u : return false; - case 0x0B94u : return false; + case 0x0931u : return false; /* DEVANAGARI LETTER RRA */ + case 0x0B94u : return false; /* TAMIL LETTER AU */ /* * Decompose split matras that don't have Unicode decompositions. */ - case 0x0F77u : *a = 0x0FB2u; *b= 0x0F81u; return true; - case 0x0F79u : *a = 0x0FB3u; *b= 0x0F81u; return true; + /* Khmer */ case 0x17BEu : *a = 0x17C1u; *b= 0x17BEu; return true; case 0x17BFu : *a = 0x17C1u; *b= 0x17BFu; return true; case 0x17C0u : *a = 0x17C1u; *b= 0x17C0u; return true; case 0x17C4u : *a = 0x17C1u; *b= 0x17C4u; return true; case 0x17C5u : *a = 0x17C1u; *b= 0x17C5u; return true; - case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true; - case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true; - case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true; - case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; - case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; + #if 0 + /* Gujarati */ /* This one has no decomposition in Unicode, but needs no decomposition either. */ /* case 0x0AC9u : return false; */ + + /* Oriya */ case 0x0B57u : *a = no decomp, -> RIGHT; return true; - case 0x1C29u : *a = no decomp, -> LEFT; return true; - case 0xA9C0u : *a = no decomp, -> RIGHT; return true; - case 0x111BuF : *a = no decomp, -> ABOVE; return true; #endif } - if ((ab == 0x0DDAu || hb_in_range (ab, 0x0DDCu, 0x0DDEu))) + if ((ab == 0x0DDAu || hb_in_range (ab, 0x0DDCu, 0x0DDEu))) { /* * Sinhala split matras... Let the fun begin. @@ -1796,7 +1782,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t glyph; if (hb_options ().uniscribe_bug_compatible || - (c->font->get_glyph (ab, 0, &glyph) && + (c->font->get_nominal_glyph (ab, &glyph) && indic_plan->pstf.would_substitute (&glyph, 1, c->font->face))) { /* Ok, safe to use Uniscribe-style decomposition. */ @@ -1806,7 +1792,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, } } - return c->unicode->decompose (ab, a, b); + return (bool) c->unicode->decompose (ab, a, b); } static bool @@ -1822,7 +1808,7 @@ compose_indic (const hb_ot_shape_normalize_context_t *c, /* Composition-exclusion exceptions that we want to recompose. */ if (a == 0x09AFu && b == 0x09BCu) { *ab = 0x09DFu; return true; } - return c->unicode->compose (a, b, ab); + return (bool) c->unicode->compose (a, b, ab); } @@ -1839,6 +1825,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = decompose_indic, compose_indic, setup_masks_indic, + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc index 00368d8e4..ebd2b4096 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc @@ -175,7 +175,7 @@ set_myanmar_properties (hb_glyph_info_t &info) /* Myanmar * http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze */ - if (unlikely (hb_in_range (u, 0xFE00u, 0xFE0Fu))) + if (unlikely (hb_in_range (u, 0xFE00u, 0xFE0Fu))) cat = (indic_category_t) OT_VS; switch (u) @@ -199,6 +199,10 @@ set_myanmar_properties (hb_glyph_info_t &info) cat = (indic_category_t) OT_A; break; + case 0x1039u: + cat = (indic_category_t) OT_H; + break; + case 0x103Au: cat = (indic_category_t) OT_As; break; @@ -245,6 +249,11 @@ set_myanmar_properties (hb_glyph_info_t &info) case 0x104Au: case 0x104Bu: cat = (indic_category_t) OT_P; break; + + case 0xAA74u: case 0xAA75u: case 0xAA76u: + /* https://github.com/roozbehp/unicode-data/issues/3 */ + cat = (indic_category_t) OT_C; + break; } if (cat == OT_M) @@ -288,6 +297,8 @@ setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer) { find_syllables (buffer); + foreach_syllable (buffer, start, end) + buffer->unsafe_to_break (start, end); } static int @@ -435,7 +446,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_codepoint_t dottedcircle_glyph; - if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph)) + if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph)) return; hb_glyph_info_t dottedcircle = {0}; @@ -447,7 +458,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, buffer->idx = 0; unsigned int last_syllable = 0; - while (buffer->idx < buffer->len) + while (buffer->idx < buffer->len && !buffer->in_error) { unsigned int syllable = buffer->cur().syllable(); syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F); @@ -512,6 +523,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old = NULL, /* decompose */ NULL, /* compose */ NULL, /* setup_masks */ + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; @@ -529,6 +541,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = NULL, /* decompose */ NULL, /* compose */ setup_masks_myanmar, + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ }; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh index 80de4f316..952441b6a 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh @@ -41,12 +41,8 @@ enum hb_ot_shape_zero_width_marks_type_t { HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, -// HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY, - HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, - HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, - - HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE }; @@ -150,6 +146,14 @@ struct hb_ot_complex_shaper_t hb_buffer_t *buffer, hb_font_t *font); + /* disable_otl() + * Called during shape(). + * If set and returns true, GDEF/GSUB/GPOS of the font are ignored + * and fallback operations used. + * May be NULL. + */ + bool (*disable_otl) (const hb_ot_shape_plan_t *plan); + hb_ot_shape_zero_width_marks_type_t zero_width_marks; bool fallback_position; @@ -187,6 +191,9 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_MANICHAEAN: case HB_SCRIPT_PSALTER_PAHLAVI: + /* Unicode-9.0 additions */ + case HB_SCRIPT_ADLAM: + /* For Arabic script, use the Arabic shaper even if no OT script tag was found. * This is because we do fallback shaping for Arabic script (and not others). * But note that Arabic shaping is applicable only to horizontal layout; for @@ -245,9 +252,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) /* Unicode-3.0 additions */ case HB_SCRIPT_SINHALA: - /* Unicode-5.2 additions */ - case HB_SCRIPT_JAVANESE: - /* If the designer designed the font for the 'DFLT' script, * use the default shaper. Otherwise, use the specific shaper. * Note that for some simple scripts, there may not be *any* @@ -320,7 +324,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) /* Unicode-5.2 additions */ case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: - //case HB_SCRIPT_JAVANESE: + case HB_SCRIPT_JAVANESE: case HB_SCRIPT_KAITHI: case HB_SCRIPT_MEETEI_MAYEK: case HB_SCRIPT_TAI_THAM: @@ -349,6 +353,15 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_SIDDHAM: case HB_SCRIPT_TIRHUTA: + /* Unicode-8.0 additions */ + case HB_SCRIPT_AHOM: + //case HB_SCRIPT_MULTANI: + + /* Unicode-9.0 additions */ + case HB_SCRIPT_BHAIKSUKI: + case HB_SCRIPT_MARCHEN: + case HB_SCRIPT_NEWA: + /* If the designer designed the font for the 'DFLT' script, * use the default shaper. Otherwise, use the specific shaper. * Note that for some simple scripts, there may not be *any* diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc index 6556a3251..924247f17 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc @@ -52,7 +52,7 @@ get_consonant_type (hb_codepoint_t u) return RC; if (u == 0x0E0Eu || u == 0x0E0Fu) return DC; - if (hb_in_range (u, 0x0E01u, 0x0E2Eu)) + if (hb_in_range (u, 0x0E01u, 0x0E2Eu)) return NC; return NOT_CONSONANT; } @@ -70,12 +70,12 @@ enum thai_mark_type_t static thai_mark_type_t get_mark_type (hb_codepoint_t u) { - if (u == 0x0E31u || hb_in_range (u, 0x0E34u, 0x0E37u) || - u == 0x0E47u || hb_in_range (u, 0x0E4Du, 0x0E4Eu)) + if (u == 0x0E31u || hb_in_range (u, 0x0E34u, 0x0E37u) || + u == 0x0E47u || hb_in_range (u, 0x0E4Du, 0x0E4Eu)) return AV; - if (hb_in_range (u, 0x0E38u, 0x0E3Au)) + if (hb_in_range (u, 0x0E38u, 0x0E3Au)) return BV; - if (hb_in_range (u, 0x0E48u, 0x0E4Cu)) + if (hb_in_range (u, 0x0E48u, 0x0E4Cu)) return T; return NOT_MARK; } @@ -139,7 +139,6 @@ thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font) }; switch (action) { - default: assert (false); HB_FALLTHROUGH; case NOP: return u; case SD: pua_mappings = SD_mappings; break; case SDL: pua_mappings = SDL_mappings; break; @@ -245,6 +244,7 @@ do_thai_pua_shaping (const hb_ot_shape_plan_t *plan HB_UNUSED, /* At least one of the above/below actions is NOP. */ thai_action_t action = above_edge.action != NOP ? above_edge.action : below_edge.action; + buffer->unsafe_to_break (base, i); if (action == RD) info[base].codepoint = thai_pua_shape (info[base].codepoint, action, font); else @@ -311,7 +311,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan, #define IS_SARA_AM(x) (((x) & ~0x0080u) == 0x0E33u) #define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0x0E33u + 0x0E4Du) #define SARA_AA_FROM_SARA_AM(x) ((x) - 1) -#define IS_TONE_MARK(x) (hb_in_ranges ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u)) +#define IS_TONE_MARK(x) (hb_in_ranges ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u)) buffer->clear_output (); unsigned int count = buffer->len; @@ -377,6 +377,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai = NULL, /* decompose */ NULL, /* compose */ NULL, /* setup_masks */ - HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, + NULL, /* disable_otl */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, false,/* fallback_position */ }; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc index 9f09287f6..aadf59f5a 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc @@ -57,6 +57,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan = NULL, /* decompose */ NULL, /* compose */ NULL, /* setup_masks */ - HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, + NULL, /* disable_otl */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh index ced9d97f2..1847c48af 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh @@ -36,335 +36,270 @@ #line 38 "hb-ot-shape-complex-use-machine.hh" static const unsigned char _use_syllable_machine_trans_keys[] = { - 0u, 0u, 4u, 4u, 1u, 1u, 0u, 39u, 21u, 21u, 8u, 39u, 8u, 39u, 1u, 1u, - 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, + 1u, 1u, 0u, 39u, 21u, 21u, 8u, 39u, 8u, 39u, 1u, 1u, 8u, 39u, 8u, 39u, + 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, - 8u, 39u, 8u, 39u, 8u, 39u, 1u, 1u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, - 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, - 8u, 39u, 12u, 21u, 12u, 13u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, + 13u, 21u, 4u, 4u, 13u, 13u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, - 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u, - 42u, 42u, 0 + 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 1u, 1u, 1u, 39u, 8u, 39u, + 21u, 42u, 41u, 42u, 42u, 42u, 0 }; static const char _use_syllable_machine_key_spans[] = { - 0, 1, 1, 40, 1, 32, 32, 1, - 32, 32, 32, 19, 19, 19, 32, 32, + 1, 40, 1, 32, 32, 1, 32, 32, + 32, 19, 19, 19, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 1, 32, 32, 19, 19, - 19, 32, 32, 32, 32, 32, 32, 32, - 32, 10, 2, 32, 32, 32, 32, 19, + 9, 1, 1, 32, 32, 32, 32, 19, 19, 19, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 39, 32, 22, 2, - 1 + 32, 32, 32, 32, 32, 1, 39, 32, + 22, 2, 1 }; static const short _use_syllable_machine_index_offsets[] = { - 0, 0, 2, 4, 45, 47, 80, 113, - 115, 148, 181, 214, 234, 254, 274, 307, - 340, 373, 406, 439, 472, 505, 538, 571, - 604, 637, 670, 703, 705, 738, 771, 791, - 811, 831, 864, 897, 930, 963, 996, 1029, - 1062, 1095, 1106, 1109, 1142, 1175, 1208, 1241, - 1261, 1281, 1301, 1334, 1367, 1400, 1433, 1466, - 1499, 1532, 1565, 1598, 1631, 1671, 1704, 1727, - 1730 + 0, 2, 43, 45, 78, 111, 113, 146, + 179, 212, 232, 252, 272, 305, 338, 371, + 404, 437, 470, 503, 536, 569, 602, 635, + 668, 678, 680, 682, 715, 748, 781, 814, + 834, 854, 874, 907, 940, 973, 1006, 1039, + 1072, 1105, 1138, 1171, 1204, 1237, 1239, 1279, + 1312, 1335, 1338 }; static const char _use_syllable_machine_indicies[] = { - 1, 0, 3, 2, 4, 5, 6, - 4, 1, 5, 8, 8, 7, 8, 8, - 3, 9, 8, 8, 8, 4, 4, 10, - 11, 8, 8, 12, 13, 14, 15, 16, - 17, 18, 12, 19, 20, 21, 22, 23, - 24, 8, 25, 26, 27, 8, 29, 28, - 31, 30, 30, 32, 33, 30, 30, 30, - 30, 30, 30, 30, 30, 34, 35, 36, - 37, 38, 39, 40, 41, 35, 42, 34, - 43, 44, 45, 46, 30, 47, 48, 49, - 30, 31, 30, 30, 32, 33, 30, 30, - 30, 30, 30, 30, 30, 30, 50, 35, - 36, 37, 38, 39, 40, 41, 35, 42, - 43, 43, 44, 45, 46, 30, 47, 48, - 49, 30, 32, 51, 31, 30, 30, 32, - 33, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 35, 36, 37, 38, 39, 40, - 41, 35, 42, 43, 43, 44, 45, 46, - 30, 47, 48, 49, 30, 31, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 35, 36, 37, 38, 39, - 30, 30, 30, 30, 30, 30, 44, 45, - 46, 30, 47, 48, 49, 30, 31, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 36, 37, 38, - 39, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 47, 48, 49, 30, 31, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 37, - 38, 39, 30, 31, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 38, 39, 30, 31, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 39, 30, 31, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 37, 38, 39, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 47, 48, 49, 30, 31, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 37, 38, 39, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 48, 49, 30, 31, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 37, 38, 39, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 49, 30, 31, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 36, 37, 38, - 39, 30, 30, 30, 30, 30, 30, 44, - 45, 46, 30, 47, 48, 49, 30, 31, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 36, 37, - 38, 39, 30, 30, 30, 30, 30, 30, - 30, 45, 46, 30, 47, 48, 49, 30, - 31, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 36, - 37, 38, 39, 30, 30, 30, 30, 30, - 30, 30, 30, 46, 30, 47, 48, 49, - 30, 31, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 35, - 36, 37, 38, 39, 30, 41, 35, 30, - 30, 30, 44, 45, 46, 30, 47, 48, - 49, 30, 31, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 35, 36, 37, 38, 39, 30, 30, 35, - 30, 30, 30, 44, 45, 46, 30, 47, - 48, 49, 30, 31, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 35, 36, 37, 38, 39, 40, 41, - 35, 30, 30, 30, 44, 45, 46, 30, - 47, 48, 49, 30, 31, 30, 30, 32, - 33, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 35, 36, 37, 38, 39, 40, - 41, 35, 42, 30, 43, 44, 45, 46, - 30, 47, 48, 49, 30, 31, 30, 30, - 32, 33, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 35, 36, 37, 38, 39, - 40, 41, 35, 42, 34, 43, 44, 45, - 46, 30, 47, 48, 49, 30, 53, 52, - 52, 54, 55, 52, 52, 52, 52, 52, - 52, 52, 52, 56, 52, 57, 58, 59, - 60, 61, 62, 57, 63, 56, 64, 52, - 52, 52, 52, 65, 66, 67, 52, 53, - 52, 52, 54, 55, 52, 52, 52, 52, - 52, 52, 52, 52, 68, 52, 57, 58, - 59, 60, 61, 62, 57, 63, 64, 64, - 52, 52, 52, 52, 65, 66, 67, 52, - 54, 51, 53, 52, 52, 54, 55, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 52, 57, 58, 59, 60, 61, 62, 57, - 63, 64, 64, 52, 52, 52, 52, 65, - 66, 67, 52, 53, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 57, 58, 59, 60, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 65, 66, 67, 52, 53, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 58, 59, 60, 52, - 53, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 52, 59, 60, 52, 53, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 60, 52, - 53, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 58, 59, 60, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 65, 66, 67, - 52, 53, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 52, 58, 59, 60, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 66, - 67, 52, 53, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 58, 59, 60, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 52, 67, 52, 53, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 57, 58, 59, 60, 52, 62, - 57, 52, 52, 52, 52, 52, 52, 52, - 65, 66, 67, 52, 53, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 57, 58, 59, 60, 52, - 52, 57, 52, 52, 52, 52, 52, 52, - 52, 65, 66, 67, 52, 53, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 57, 58, 59, 60, - 61, 62, 57, 52, 52, 52, 52, 52, - 52, 52, 65, 66, 67, 52, 53, 52, - 52, 54, 55, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 57, 58, 59, - 60, 61, 62, 57, 63, 52, 64, 52, - 52, 52, 52, 65, 66, 67, 52, 53, - 52, 52, 54, 55, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 57, 58, - 59, 60, 61, 62, 57, 63, 56, 64, - 52, 52, 52, 52, 65, 66, 67, 52, - 70, 71, 69, 69, 69, 69, 69, 69, - 69, 72, 69, 70, 71, 69, 7, 73, - 73, 3, 9, 73, 73, 73, 73, 73, - 73, 73, 73, 74, 12, 13, 14, 15, - 16, 17, 18, 12, 19, 21, 21, 22, - 23, 24, 73, 25, 26, 27, 73, 7, - 73, 73, 3, 9, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 12, 13, 14, - 15, 16, 17, 18, 12, 19, 21, 21, - 22, 23, 24, 73, 25, 26, 27, 73, - 7, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 12, 13, - 14, 15, 16, 73, 73, 73, 73, 73, - 73, 22, 23, 24, 73, 25, 26, 27, - 73, 7, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 13, 14, 15, 16, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 25, 26, - 27, 73, 7, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 14, 15, 16, 73, 7, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 15, - 16, 73, 7, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 16, 73, 7, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 14, 15, - 16, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 25, 26, 27, 73, 7, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 14, - 15, 16, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 26, 27, 73, - 7, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 14, 15, 16, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 27, - 73, 7, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 13, 14, 15, 16, 73, 73, 73, 73, - 73, 73, 22, 23, 24, 73, 25, 26, - 27, 73, 7, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 13, 14, 15, 16, 73, 73, 73, - 73, 73, 73, 73, 23, 24, 73, 25, - 26, 27, 73, 7, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 13, 14, 15, 16, 73, 73, - 73, 73, 73, 73, 73, 73, 24, 73, - 25, 26, 27, 73, 7, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 12, 13, 14, 15, 16, 73, - 18, 12, 73, 73, 73, 22, 23, 24, - 73, 25, 26, 27, 73, 7, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 12, 13, 14, 15, 16, - 73, 73, 12, 73, 73, 73, 22, 23, - 24, 73, 25, 26, 27, 73, 7, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 12, 13, 14, 15, - 16, 17, 18, 12, 73, 73, 73, 22, - 23, 24, 73, 25, 26, 27, 73, 7, - 73, 73, 3, 9, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 12, 13, 14, - 15, 16, 17, 18, 12, 19, 73, 21, - 22, 23, 24, 73, 25, 26, 27, 73, - 5, 6, 73, 73, 5, 73, 73, 7, - 73, 73, 3, 9, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 12, 13, 14, - 15, 16, 17, 18, 12, 19, 20, 21, - 22, 23, 24, 73, 25, 26, 27, 73, - 7, 73, 73, 3, 9, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 12, 13, - 14, 15, 16, 17, 18, 12, 19, 20, - 21, 22, 23, 24, 73, 25, 26, 27, - 73, 76, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 76, 77, 75, - 76, 77, 75, 77, 75, 0 + 1, 0, 2, 3, 4, 2, 5, 3, + 4, 4, 6, 4, 4, 1, 7, 4, + 4, 4, 2, 2, 8, 9, 4, 4, + 10, 11, 12, 13, 14, 15, 16, 10, + 17, 18, 19, 20, 21, 22, 4, 23, + 24, 25, 4, 27, 26, 29, 28, 28, + 30, 31, 28, 28, 28, 28, 28, 28, + 28, 28, 32, 33, 34, 35, 36, 37, + 38, 39, 33, 40, 32, 41, 42, 43, + 44, 28, 45, 46, 47, 28, 29, 28, + 28, 30, 31, 28, 28, 28, 28, 28, + 28, 28, 28, 48, 33, 34, 35, 36, + 37, 38, 39, 33, 40, 41, 41, 42, + 43, 44, 28, 45, 46, 47, 28, 30, + 49, 29, 28, 28, 30, 31, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 33, + 34, 35, 36, 37, 38, 39, 33, 40, + 41, 41, 42, 43, 44, 28, 45, 46, + 47, 28, 29, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 33, 34, 35, 36, 37, 28, 28, 28, + 28, 28, 28, 42, 43, 44, 28, 45, + 46, 47, 28, 29, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 34, 35, 36, 37, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 45, 46, 47, 28, 29, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 35, 36, 37, 28, + 29, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 36, 37, 28, 29, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 37, 28, + 29, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 35, 36, 37, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 45, 46, 47, + 28, 29, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 35, 36, 37, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 46, + 47, 28, 29, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 35, 36, 37, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 47, 28, 29, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 34, 35, 36, 37, 28, 28, + 28, 28, 28, 28, 42, 43, 44, 28, + 45, 46, 47, 28, 29, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 34, 35, 36, 37, 28, + 28, 28, 28, 28, 28, 28, 43, 44, + 28, 45, 46, 47, 28, 29, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 34, 35, 36, 37, + 28, 28, 28, 28, 28, 28, 28, 28, + 44, 28, 45, 46, 47, 28, 29, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 33, 34, 35, 36, + 37, 28, 39, 33, 28, 28, 28, 42, + 43, 44, 28, 45, 46, 47, 28, 29, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 33, 34, 35, + 36, 37, 28, 50, 33, 28, 28, 28, + 42, 43, 44, 28, 45, 46, 47, 28, + 29, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 33, 34, + 35, 36, 37, 28, 28, 33, 28, 28, + 28, 42, 43, 44, 28, 45, 46, 47, + 28, 29, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 33, + 34, 35, 36, 37, 38, 39, 33, 28, + 28, 28, 42, 43, 44, 28, 45, 46, + 47, 28, 29, 28, 28, 30, 31, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 33, 34, 35, 36, 37, 38, 39, 33, + 40, 28, 41, 42, 43, 44, 28, 45, + 46, 47, 28, 29, 28, 28, 30, 31, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 33, 34, 35, 36, 37, 38, 39, + 33, 40, 32, 41, 42, 43, 44, 28, + 45, 46, 47, 28, 52, 51, 51, 51, + 51, 51, 51, 51, 53, 51, 5, 54, + 52, 51, 6, 55, 55, 1, 56, 55, + 55, 55, 55, 55, 55, 55, 55, 57, + 10, 11, 12, 13, 14, 15, 16, 10, + 17, 19, 19, 20, 21, 22, 55, 23, + 24, 25, 55, 6, 55, 55, 1, 56, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 10, 11, 12, 13, 14, 15, 16, + 10, 17, 19, 19, 20, 21, 22, 55, + 23, 24, 25, 55, 6, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 10, 11, 12, 13, 14, 55, + 55, 55, 55, 55, 55, 20, 21, 22, + 55, 23, 24, 25, 55, 6, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 11, 12, 13, 14, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 23, 24, 25, 55, 6, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 12, 13, + 14, 55, 6, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 13, 14, 55, 6, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 14, 55, 6, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 12, 13, 14, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 23, + 24, 25, 55, 6, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 12, 13, 14, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 24, 25, 55, 6, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 12, 13, 14, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 25, 55, 6, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 11, 12, 13, 14, + 55, 55, 55, 55, 55, 55, 20, 21, + 22, 55, 23, 24, 25, 55, 6, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 11, 12, 13, + 14, 55, 55, 55, 55, 55, 55, 55, + 21, 22, 55, 23, 24, 25, 55, 6, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 11, 12, + 13, 14, 55, 55, 55, 55, 55, 55, + 55, 55, 22, 55, 23, 24, 25, 55, + 6, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 10, 11, + 12, 13, 14, 55, 16, 10, 55, 55, + 55, 20, 21, 22, 55, 23, 24, 25, + 55, 6, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 10, + 11, 12, 13, 14, 55, 58, 10, 55, + 55, 55, 20, 21, 22, 55, 23, 24, + 25, 55, 6, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 10, 11, 12, 13, 14, 55, 55, 10, + 55, 55, 55, 20, 21, 22, 55, 23, + 24, 25, 55, 6, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 10, 11, 12, 13, 14, 15, 16, + 10, 55, 55, 55, 20, 21, 22, 55, + 23, 24, 25, 55, 6, 55, 55, 1, + 56, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 10, 11, 12, 13, 14, 15, + 16, 10, 17, 55, 19, 20, 21, 22, + 55, 23, 24, 25, 55, 1, 59, 3, + 55, 55, 55, 3, 55, 55, 6, 55, + 55, 1, 56, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 10, 11, 12, 13, + 14, 15, 16, 10, 17, 18, 19, 20, + 21, 22, 55, 23, 24, 25, 55, 6, + 55, 55, 1, 56, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 10, 11, 12, + 13, 14, 15, 16, 10, 17, 18, 19, + 20, 21, 22, 55, 23, 24, 25, 55, + 61, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 61, 62, 60, 61, + 62, 60, 62, 60, 0 }; static const char _use_syllable_machine_trans_targs[] = { - 3, 41, 3, 43, 4, 5, 25, 3, - 0, 2, 60, 62, 45, 46, 47, 48, - 49, 56, 57, 58, 61, 59, 53, 54, - 55, 50, 51, 52, 3, 3, 3, 3, - 6, 7, 24, 9, 10, 11, 12, 13, - 20, 21, 22, 23, 17, 18, 19, 14, - 15, 16, 8, 3, 3, 3, 26, 27, - 40, 29, 30, 31, 32, 36, 37, 38, - 39, 33, 34, 35, 28, 3, 3, 1, - 42, 3, 44, 3, 63, 64 + 1, 27, 2, 3, 1, 24, 1, 45, + 46, 48, 29, 30, 31, 32, 33, 40, + 41, 43, 47, 44, 37, 38, 39, 34, + 35, 36, 1, 1, 1, 1, 4, 5, + 23, 7, 8, 9, 10, 11, 18, 19, + 21, 22, 15, 16, 17, 12, 13, 14, + 6, 1, 20, 1, 25, 26, 1, 1, + 0, 28, 42, 1, 1, 49, 50 }; static const char _use_syllable_machine_trans_actions[] = { - 1, 2, 3, 4, 0, 0, 0, 7, - 0, 0, 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 4, 0, 0, - 0, 0, 0, 0, 8, 9, 10, 11, + 1, 2, 0, 0, 5, 0, 6, 0, + 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 0, 0, 0, + 0, 0, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 12, 13, 14, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 15, 16, 0, - 2, 17, 4, 18, 0, 0 + 0, 11, 0, 12, 0, 0, 13, 14, + 0, 2, 0, 15, 16, 0, 0 }; static const char _use_syllable_machine_to_state_actions[] = { - 0, 0, 0, 5, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0, 0 }; static const char _use_syllable_machine_from_state_actions[] = { - 0, 0, 0, 6, 0, 0, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0, 0 }; static const short _use_syllable_machine_eof_trans[] = { - 0, 1, 3, 0, 29, 31, 31, 52, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 53, 53, 52, 53, 53, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 53, 70, 70, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 76, 76, - 76 + 1, 0, 27, 29, 29, 50, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 52, 55, 52, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 60, 56, 56, + 61, 61, 61 }; -static const int use_syllable_machine_start = 3; -static const int use_syllable_machine_first_final = 3; -static const int use_syllable_machine_error = 0; +static const int use_syllable_machine_start = 1; +static const int use_syllable_machine_first_final = 1; +static const int use_syllable_machine_error = -1; -static const int use_syllable_machine_en_main = 3; +static const int use_syllable_machine_en_main = 1; #line 38 "hb-ot-shape-complex-use-machine.rl" -#line 145 "hb-ot-shape-complex-use-machine.rl" +#line 139 "hb-ot-shape-complex-use-machine.rl" #define found_syllable(syllable_type) \ @@ -384,7 +319,7 @@ find_syllables (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 388 "hb-ot-shape-complex-use-machine.hh" +#line 323 "hb-ot-shape-complex-use-machine.hh" { cs = use_syllable_machine_start; ts = 0; @@ -392,7 +327,7 @@ find_syllables (hb_buffer_t *buffer) act = 0; } -#line 166 "hb-ot-shape-complex-use-machine.rl" +#line 160 "hb-ot-shape-complex-use-machine.rl" p = 0; @@ -401,7 +336,7 @@ find_syllables (hb_buffer_t *buffer) unsigned int last = 0; unsigned int syllable_serial = 1; -#line 405 "hb-ot-shape-complex-use-machine.hh" +#line 340 "hb-ot-shape-complex-use-machine.hh" { int _slen; int _trans; @@ -409,15 +344,13 @@ find_syllables (hb_buffer_t *buffer) const char *_inds; if ( p == pe ) goto _test_eof; - if ( cs == 0 ) - goto _out; _resume: switch ( _use_syllable_machine_from_state_actions[cs] ) { - case 6: + case 4: #line 1 "NONE" {ts = p;} break; -#line 421 "hb-ot-shape-complex-use-machine.hh" +#line 354 "hb-ot-shape-complex-use-machine.hh" } _keys = _use_syllable_machine_trans_keys + (cs<<1); @@ -439,92 +372,70 @@ _eof_trans: #line 1 "NONE" {te = p+1;} break; - case 9: -#line 134 "hb-ot-shape-complex-use-machine.rl" + case 8: +#line 128 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (independent_cluster); }} break; - case 11: -#line 136 "hb-ot-shape-complex-use-machine.rl" - {te = p+1;{ found_syllable (consonant_cluster); }} + case 10: +#line 130 "hb-ot-shape-complex-use-machine.rl" + {te = p+1;{ found_syllable (standard_cluster); }} break; - case 14: -#line 137 "hb-ot-shape-complex-use-machine.rl" - {te = p+1;{ found_syllable (vowel_cluster); }} - break; - case 16: -#line 138 "hb-ot-shape-complex-use-machine.rl" - {te = p+1;{ found_syllable (number_joiner_terminated_cluster); }} - break; - case 7: -#line 141 "hb-ot-shape-complex-use-machine.rl" + case 6: +#line 134 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (broken_cluster); }} break; - case 8: -#line 134 "hb-ot-shape-complex-use-machine.rl" + case 5: +#line 135 "hb-ot-shape-complex-use-machine.rl" + {te = p+1;{ found_syllable (non_cluster); }} + break; + case 7: +#line 128 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (independent_cluster); }} break; - case 12: -#line 135 "hb-ot-shape-complex-use-machine.rl" + case 11: +#line 129 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (virama_terminated_cluster); }} break; - case 10: -#line 136 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (consonant_cluster); }} + case 9: +#line 130 "hb-ot-shape-complex-use-machine.rl" + {te = p;p--;{ found_syllable (standard_cluster); }} break; case 13: -#line 137 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (vowel_cluster); }} +#line 131 "hb-ot-shape-complex-use-machine.rl" + {te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }} break; - case 15: -#line 139 "hb-ot-shape-complex-use-machine.rl" + case 12: +#line 132 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (numeral_cluster); }} break; - case 18: -#line 140 "hb-ot-shape-complex-use-machine.rl" + case 16: +#line 133 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (symbol_cluster); }} break; - case 17: -#line 141 "hb-ot-shape-complex-use-machine.rl" + case 14: +#line 134 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; + case 15: +#line 135 "hb-ot-shape-complex-use-machine.rl" + {te = p;p--;{ found_syllable (non_cluster); }} + break; case 1: -#line 139 "hb-ot-shape-complex-use-machine.rl" - {{p = ((te))-1;}{ found_syllable (numeral_cluster); }} +#line 134 "hb-ot-shape-complex-use-machine.rl" + {{p = ((te))-1;}{ found_syllable (broken_cluster); }} break; - case 3: -#line 1 "NONE" - { switch( act ) { - case 0: - {{cs = 0; goto _again;}} - break; - case 8: - {{p = ((te))-1;} found_syllable (broken_cluster); } - break; - } - } - break; - case 4: -#line 1 "NONE" - {te = p+1;} -#line 141 "hb-ot-shape-complex-use-machine.rl" - {act = 8;} - break; -#line 513 "hb-ot-shape-complex-use-machine.hh" +#line 428 "hb-ot-shape-complex-use-machine.hh" } _again: switch ( _use_syllable_machine_to_state_actions[cs] ) { - case 5: + case 3: #line 1 "NONE" {ts = 0;} -#line 1 "NONE" - {act = 0;} break; -#line 524 "hb-ot-shape-complex-use-machine.hh" +#line 437 "hb-ot-shape-complex-use-machine.hh" } - if ( cs == 0 ) - goto _out; if ( ++p != pe ) goto _resume; _test_eof: {} @@ -536,10 +447,9 @@ _again: } } - _out: {} } -#line 175 "hb-ot-shape-complex-use-machine.rl" +#line 169 "hb-ot-shape-complex-use-machine.rl" } diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl b/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl index b8242bab1..2a7f75115 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl @@ -44,7 +44,6 @@ O = 0; # OTHER B = 1; # BASE -IV = 2; # BASE_VOWEL IND = 3; # BASE_IND N = 4; # BASE_NUM GB = 5; # BASE_OTHER @@ -90,17 +89,18 @@ SMBlw = 42; # SYM_MOD_BELOW consonant_modifiers = CMAbv* CMBlw* ((H B | SUB) VS? CMAbv? CMBlw*)*; -medial_consonants = MPre? MAbv? MBlw? MPst?; +# Override: Allow two MBlw. https://github.com/behdad/harfbuzz/issues/376 +medial_consonants = MPre? MAbv? MBlw?.MBlw? MPst?; dependent_vowels = VPre* VAbv* VBlw* VPst*; vowel_modifiers = VMPre* VMAbv* VMBlw* VMPst*; final_consonants = FAbv* FBlw* FPst* FM?; virama_terminated_cluster = - R? (B | GB | IV) VS? + R? (B | GB) VS? consonant_modifiers H ; -consonant_cluster = +standard_cluster = R? (B | GB) VS? consonant_modifiers medial_consonants @@ -108,13 +108,6 @@ consonant_cluster = vowel_modifiers final_consonants ; -vowel_cluster = - R? (IV) VS? - consonant_modifiers - medial_consonants - vowel_modifiers - final_consonants -; broken_cluster = R? @@ -125,20 +118,21 @@ broken_cluster = final_consonants ; -number_joiner_terminated_cluster = N VS? (HN N VS?)* H; +number_joiner_terminated_cluster = N VS? (HN N VS?)* HN; numeral_cluster = N VS? (HN N VS?)*; symbol_cluster = S VS? SMAbv* SMBlw*; independent_cluster = (IND | O | Rsv | WJ) VS?; +other = any; main := |* independent_cluster => { found_syllable (independent_cluster); }; virama_terminated_cluster => { found_syllable (virama_terminated_cluster); }; - consonant_cluster => { found_syllable (consonant_cluster); }; - vowel_cluster => { found_syllable (vowel_cluster); }; + standard_cluster => { found_syllable (standard_cluster); }; number_joiner_terminated_cluster => { found_syllable (number_joiner_terminated_cluster); }; numeral_cluster => { found_syllable (numeral_cluster); }; symbol_cluster => { found_syllable (symbol_cluster); }; broken_cluster => { found_syllable (broken_cluster); }; + other => { found_syllable (non_cluster); }; *|; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use-private.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-use-private.hh index a14373621..ae428cb5e 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-private.hh @@ -46,7 +46,6 @@ enum use_category_t { USE_O = 0, /* OTHER */ USE_B = 1, /* BASE */ - USE_IV = 2, /* BASE_VOWEL */ USE_IND = 3, /* BASE_IND */ USE_N = 4, /* BASE_NUM */ USE_GB = 5, /* BASE_OTHER */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc index 6cd1c5db7..941a003aa 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc @@ -6,12 +6,12 @@ * * on files with these headers: * - * # IndicSyllabicCategory-8.0.0.txt - * # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI] - * # IndicPositionalCategory-8.0.0.txt - * # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI] - * # Blocks-8.0.0.txt - * # Date: 2014-11-10, 23:04:00 GMT [KW] + * # IndicSyllabicCategory-9.0.0.txt + * # Date: 2016-05-21, 02:46:00 GMT [RP] + * # IndicPositionalCategory-9.0.0.txt + * # Date: 2016-06-09, 19:33:00 GMT [RP] + * # Blocks-9.0.0.txt + * # Date: 2016-02-05, 23:48:00 GMT [KW] * UnicodeData.txt does not have a header. */ @@ -24,7 +24,6 @@ #define H USE_H /* HALANT */ #define HN USE_HN /* HALANT_NUM */ #define IND USE_IND /* BASE_IND */ -#define IV USE_IV /* BASE_VOWEL */ #define N USE_N /* BASE_NUM */ #define O USE_O /* OTHER */ #define R USE_R /* REPHA */ @@ -80,30 +79,30 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Devanagari */ - /* 0900 */ VMAbv, VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, - /* 0910 */ IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, + /* 0900 */ VMAbv, VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, + /* 0910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0930 */ B, B, B, B, B, B, B, B, B, B, VAbv, VPst, CMBlw, B, VPst, VPre, /* 0940 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VPst, VPst, VPst, VPst, H, VPre, VPst, /* 0950 */ O, VMAbv, VMBlw, O, O, VAbv, VBlw, VBlw, B, B, B, B, B, B, B, B, - /* 0960 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0970 */ O, O, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, + /* 0960 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, + /* 0970 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* Bengali */ - /* 0980 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV, - /* 0990 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B, + /* 0980 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B, + /* 0990 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 09A0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 09B0 */ B, O, B, O, O, O, B, B, B, B, O, O, CMBlw, B, VPst, VPre, /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, IND, O, /* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B, - /* 09E0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, + /* 09E0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Gurmukhi */ - /* 0A00 */ O, VMAbv, VMAbv, VMPst, O, IV, IV, IV, IV, IV, IV, O, O, O, O, IV, - /* 0A10 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B, + /* 0A00 */ O, VMAbv, VMAbv, VMPst, O, B, B, B, B, B, B, O, O, O, O, B, + /* 0A10 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0A20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 0A30 */ B, O, B, B, O, B, B, O, B, B, O, O, CMBlw, O, VPst, VPre, /* 0A40 */ VPst, VBlw, VBlw, O, O, O, O, VAbv, VAbv, O, O, VAbv, VAbv, H, O, O, @@ -113,30 +112,30 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Gujarati */ - /* 0A80 */ O, VMAbv, VMAbv, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, - /* 0A90 */ IV, IV, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B, + /* 0A80 */ O, VMAbv, VMAbv, VMPst, O, B, B, B, B, B, B, B, B, B, O, B, + /* 0A90 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0AA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 0AB0 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPre, /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, O, VAbv, VAbv, VAbv, O, VPst, VPst, H, O, O, /* 0AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 0AE0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, + /* 0AE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, /* 0AF0 */ O, O, O, O, O, O, O, O, O, B, O, O, O, O, O, O, /* Oriya */ - /* 0B00 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV, - /* 0B10 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B, + /* 0B00 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B, + /* 0B10 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0B20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 0B30 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv, /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O, /* 0B50 */ O, O, O, O, O, O, VAbv, VAbv, O, O, O, O, B, B, O, B, - /* 0B60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, + /* 0B60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, /* 0B70 */ O, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Tamil */ - /* 0B80 */ O, O, VMAbv, IND, O, IV, IV, IV, IV, IV, IV, O, O, O, IV, IV, - /* 0B90 */ IV, O, IV, IV, IV, B, O, O, O, B, B, O, B, O, B, B, + /* 0B80 */ O, O, VMAbv, IND, O, B, B, B, B, B, B, O, O, O, B, B, + /* 0B90 */ B, O, B, B, B, B, O, O, O, B, B, O, B, O, B, B, /* 0BA0 */ O, O, O, B, B, O, O, O, B, B, B, O, O, O, B, B, /* 0BB0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, VPst, VPst, /* 0BC0 */ VAbv, VPst, VPst, O, O, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, O, O, @@ -146,41 +145,41 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Telugu */ - /* 0C00 */ VMAbv, VMPst, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV, - /* 0C10 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, + /* 0C00 */ VMAbv, VMPst, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B, + /* 0C10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0C20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 0C30 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, VAbv, VAbv, /* 0C40 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O, /* 0C50 */ O, O, O, O, O, VAbv, VBlw, O, B, B, B, O, O, O, O, O, - /* 0C60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, + /* 0C60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, /* 0C70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Kannada */ - /* 0C80 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV, - /* 0C90 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, + /* 0C80 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B, + /* 0C90 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0CA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 0CB0 */ B, B, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv, /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O, /* 0CD0 */ O, O, O, O, O, VPst, VPst, O, O, O, O, O, O, O, B, O, - /* 0CE0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, + /* 0CE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, /* 0CF0 */ O, R, R, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Malayalam */ - /* 0D00 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV, - /* 0D10 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, + /* 0D00 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B, + /* 0D10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, O, O, B, VPst, VPst, /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, R, O, - /* 0D50 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, IV, - /* 0D60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, + /* 0D50 */ O, O, O, O, IND, IND, IND, VPst, O, O, O, O, O, O, O, B, + /* 0D60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, /* 0D70 */ O, O, O, O, O, O, O, O, O, O, IND, IND, IND, IND, IND, IND, /* Sinhala */ - /* 0D80 */ O, O, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, - /* 0D90 */ IV, IV, IV, IV, IV, IV, IV, O, O, O, B, B, B, B, B, B, + /* 0D80 */ O, O, VMPst, VMPst, O, B, B, B, B, B, B, B, B, B, B, B, + /* 0D90 */ B, B, B, B, B, B, B, O, O, O, B, B, B, B, B, B, /* 0DA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0DB0 */ B, B, O, B, B, B, B, B, B, B, B, B, O, B, O, O, /* 0DC0 */ B, B, B, B, B, B, B, O, O, O, H, O, O, O, O, VPst, @@ -195,10 +194,10 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1020 */ B, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, VPst, VPst, VAbv, VAbv, VBlw, + /* 1020 */ B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VAbv, VAbv, VBlw, /* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, H, VAbv, MPst, MPre, MBlw, MBlw, B, /* 1040 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, GB, O, - /* 1050 */ B, B, IV, IV, IV, IV, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw, + /* 1050 */ B, B, B, B, B, B, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw, /* 1060 */ MBlw, B, VPst, VMPst, VMPst, B, B, VPst, VPst, VMPst, VMPst, VMPst, VMPst, VMPst, B, B, /* 1070 */ B, VAbv, VAbv, VAbv, VAbv, B, B, B, B, B, B, B, B, B, B, B, /* 1080 */ B, B, MBlw, VPst, VPre, VAbv, VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw, B, VMPst, @@ -209,30 +208,30 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Tagalog */ - /* 1700 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, O, B, B, + /* 1700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, B, B, /* 1710 */ B, B, VAbv, VBlw, VBlw, O, O, O, O, O, O, O, O, O, O, O, /* Hanunoo */ - /* 1720 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 1720 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1730 */ B, B, VAbv, VBlw, VBlw, O, O, O, O, O, O, O, O, O, O, O, /* Buhid */ - /* 1740 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 1740 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1750 */ B, B, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O, /* Tagbanwa */ - /* 1760 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, O, B, B, + /* 1760 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, B, B, /* 1770 */ B, O, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O, /* Khmer */ /* 1780 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 17A0 */ B, B, B, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, - /* 17B0 */ IV, IV, IV, IV, O, O, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre, + /* 17A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 17B0 */ B, B, B, B, O, O, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre, /* 17C0 */ VPre, VPre, VPre, VPre, VPre, VPre, VMAbv, VMPst, VPst, VMAbv, VMAbv, FM, FAbv, CMAbv, FM, FM, /* 17D0 */ FM, VAbv, H, FM, O, O, O, O, O, O, O, O, B, VAbv, O, O, /* 17E0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, @@ -274,8 +273,8 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, IV, IV, IV, - /* 1A50 */ IV, IV, IV, B, B, MPre, MBlw, FPst, FAbv, FAbv, FAbv, FBlw, FBlw, FBlw, FBlw, O, + /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 1A50 */ B, B, B, B, B, MPre, MBlw, FPst, FAbv, FAbv, FAbv, FBlw, FBlw, FBlw, FBlw, O, /* 1A60 */ H, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre, /* 1A70 */ VPre, VPre, VPre, VAbv, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, FM, FM, FM, O, O, FM, /* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, @@ -286,8 +285,8 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Balinese */ - /* 1B00 */ VMAbv, VMAbv, VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, - /* 1B10 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 1B00 */ VMAbv, VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, + /* 1B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre, /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, O, O, O, O, @@ -297,7 +296,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Sundanese */ - /* 1B80 */ VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, + /* 1B80 */ VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, H, SUB, SUB, B, B, /* 1BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, @@ -306,7 +305,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BE0 */ B, B, B, B, IV, IV, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv, + /* 1BE0 */ B, B, B, B, B, B, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv, /* 1BF0 */ FAbv, FAbv, VPst, VPst, O, O, O, O, O, O, O, O, O, O, O, O, /* Lepcha */ @@ -326,14 +325,20 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O, /* 1CF0 */ O, O, VMPst, VMPst, VMAbv, O, O, O, VMAbv, VMAbv, O, O, O, O, O, O, -#define use_offset_0x2008u 2552 +#define use_offset_0x1df8u 2552 + + + /* Combining Diacritical Marks Supplement */ + O, O, O, FM, O, O, O, O, + +#define use_offset_0x2008u 2560 /* General Punctuation */ O, O, O, O, ZWNJ, ZWJ, O, O, /* 2010 */ GB, GB, GB, GB, GB, O, O, O, -#define use_offset_0x2060u 2568 +#define use_offset_0x2060u 2576 /* 2060 */ WJ, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, @@ -342,12 +347,12 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 2070 */ O, O, O, O, FM, O, O, O, O, O, O, O, O, O, O, O, /* 2080 */ O, O, FM, FM, FM, O, O, O, -#define use_offset_0xa800u 2608 +#define use_offset_0xa800u 2616 /* Syloti Nagri */ - /* A800 */ IV, IV, O, IV, IV, IV, VAbv, B, B, B, B, VMAbv, B, B, B, B, + /* A800 */ B, B, O, B, B, B, VAbv, B, B, B, B, VMAbv, B, B, B, B, /* A810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, O, O, O, O, /* A830 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, @@ -361,11 +366,11 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Saurashtra */ - /* A880 */ VMPst, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, - /* A890 */ IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* A880 */ VMPst, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* A890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A8A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A8B0 */ B, B, B, B, FPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, - /* A8C0 */ VPst, VPst, VPst, VPst, H, O, O, O, O, O, O, O, O, O, O, O, + /* A8C0 */ VPst, VPst, VPst, VPst, H, VMAbv, O, O, O, O, O, O, O, O, O, O, /* A8D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, /* Devanagari Extended */ @@ -389,7 +394,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Javanese */ - /* A980 */ VMAbv, VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, B, B, B, IV, IV, IV, B, + /* A980 */ VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, /* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, SUB, MPst, MPst, @@ -403,9 +408,9 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Cham */ - /* AA00 */ IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, + /* AA00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* AA20 */ B, B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre, + /* AA20 */ B, B, B, B, B, B, B, B, B, VMAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre, /* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MBlw, MBlw, O, O, O, O, O, O, O, O, O, /* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, O, O, /* AA50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, @@ -413,7 +418,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Myanmar Extended-A */ /* AA60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* AA70 */ O, B, B, B, O, O, O, O, O, O, B, VMPst, VMAbv, VMPst, B, B, + /* AA70 */ O, B, B, B, GB, GB, GB, O, O, O, B, VMPst, VMAbv, VMPst, B, B, /* Tai Viet */ @@ -426,27 +431,27 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Meetei Mayek Extensions */ - /* AAE0 */ IV, IV, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst, + /* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst, /* AAF0 */ O, O, O, O, O, VMPst, H, O, -#define use_offset_0xabc0u 3368 +#define use_offset_0xabc0u 3376 /* Meetei Mayek */ - /* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, IV, IV, - /* ABD0 */ B, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* ABD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, O, O, /* ABF0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0xfe00u 3432 +#define use_offset_0xfe00u 3440 /* Variation Selectors */ /* FE00 */ VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, -#define use_offset_0x10a00u 3448 +#define use_offset_0x10a00u 3456 /* Kharoshthi */ @@ -457,13 +462,13 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 10A30 */ B, B, B, B, O, O, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H, /* 10A40 */ B, B, B, B, B, B, B, B, -#define use_offset_0x11000u 3520 +#define use_offset_0x11000u 3528 /* Brahmi */ - /* 11000 */ VMPst, VMAbv, VMPst, R, R, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, - /* 11010 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11000 */ VMPst, VMAbv, VMPst, R, R, B, B, B, B, B, B, B, B, B, B, B, + /* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, O, O, @@ -473,17 +478,17 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Kaithi */ - /* 11080 */ VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, + /* 11080 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O, -#define use_offset_0x11100u 3712 +#define use_offset_0x11100u 3720 /* Chakma */ - /* 11100 */ VMAbv, VMAbv, VMAbv, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B, + /* 11100 */ VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11120 */ B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VAbv, VAbv, /* 11130 */ VAbv, VBlw, VBlw, H, VAbv, O, B, B, B, B, B, B, B, B, B, B, @@ -497,8 +502,8 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Sharada */ - /* 11180 */ VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, - /* 11190 */ IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11180 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, /* 111C0 */ H, B, R, R, O, O, O, O, O, O, CMBlw, VAbv, VBlw, O, O, O, @@ -511,23 +516,23 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Khojki */ - /* 11200 */ IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, + /* 11200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11210 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw, - /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, + /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, O, -#define use_offset_0x11280u 4024 +#define use_offset_0x11280u 4040 /* Multani */ - /* 11280 */ IV, IV, IV, IV, B, B, B, O, B, O, B, B, B, B, O, B, + /* 11280 */ B, B, B, B, B, B, B, O, B, O, B, B, B, B, O, B, /* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, B, /* 112A0 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, /* Khudawadi */ - /* 112B0 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, + /* 112B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 112C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 112D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, /* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, O, O, O, O, O, @@ -535,44 +540,55 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Grantha */ - /* 11300 */ VMAbv, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV, - /* 11310 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B, + /* 11300 */ VMAbv, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B, + /* 11310 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 11330 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPst, /* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O, /* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O, - /* 11360 */ IV, IV, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, + /* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, -#define use_offset_0x11480u 4272 +#define use_offset_0x11400u 4288 + /* Newa */ + + /* 11400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11430 */ B, B, B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, + /* 11440 */ VPst, VPst, H, VMAbv, VMAbv, VMPst, CMBlw, B, O, O, O, O, O, O, O, O, + /* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 11460 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 11470 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* Tirhuta */ - /* 11480 */ O, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, + /* 11480 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11490 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 114A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPre, VPre, VPst, VPre, VMAbv, /* 114C0 */ VMAbv, VMPst, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O, /* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x11580u 4368 +#define use_offset_0x11580u 4512 /* Siddham */ - /* 11580 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, + /* 11580 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11590 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 115A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst, /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H, /* 115C0 */ CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 115D0 */ O, O, O, O, O, O, O, O, IV, IV, IV, IV, VBlw, VBlw, O, O, + /* 115D0 */ O, O, O, O, O, O, O, O, B, B, B, B, VBlw, VBlw, O, O, /* 115E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* 115F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Modi */ - /* 11600 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, + /* 11600 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11610 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11620 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11630 */ VPst, VPst, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPst, VPst, VMAbv, VMPst, H, @@ -583,7 +599,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Takri */ - /* 11680 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, + /* 11680 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11690 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 116A0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMPst, VAbv, VPre, VPst, /* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, O, O, O, O, O, O, O, O, @@ -599,7 +615,28 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O, /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, -}; /* Table items: 4816; occupancy: 72% */ +#define use_offset_0x11c00u 4960 + + + /* Bhaiksuki */ + + /* 11C00 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, + /* 11C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst, + /* 11C30 */ VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VBlw, O, VAbv, VAbv, VAbv, VAbv, VMAbv, VMAbv, VMPst, H, + /* 11C40 */ B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 11C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, + + /* Marchen */ + + /* 11C70 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11C90 */ O, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, + /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, + /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, O, + +}; /* Table items: 5144; occupancy: 72% */ USE_TABLE_ELEMENT_TYPE hb_use_get_categories (hb_codepoint_t u) @@ -607,45 +644,47 @@ hb_use_get_categories (hb_codepoint_t u) switch (u >> 12) { case 0x0u: - if (hb_in_range (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u]; - if (hb_in_range (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u]; - if (hb_in_range (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u]; + if (hb_in_range (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u]; + if (hb_in_range (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u]; + if (hb_in_range (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u]; if (unlikely (u == 0x034Fu)) return CGJ; break; case 0x1u: - if (hb_in_range (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u]; - if (hb_in_range (u, 0x1700u, 0x17EFu)) return use_table[u - 0x1700u + use_offset_0x1700u]; - if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u]; - if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u]; - if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u]; + if (hb_in_range (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u]; + if (hb_in_range (u, 0x1700u, 0x17EFu)) return use_table[u - 0x1700u + use_offset_0x1700u]; + if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u]; + if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u]; + if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u]; + if (hb_in_range (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u]; break; case 0x2u: - if (hb_in_range (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u]; - if (hb_in_range (u, 0x2060u, 0x2087u)) return use_table[u - 0x2060u + use_offset_0x2060u]; + if (hb_in_range (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u]; + if (hb_in_range (u, 0x2060u, 0x2087u)) return use_table[u - 0x2060u + use_offset_0x2060u]; if (unlikely (u == 0x25CCu)) return GB; break; case 0xAu: - if (hb_in_range (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u]; - if (hb_in_range (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u]; + if (hb_in_range (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u]; + if (hb_in_range (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u]; break; case 0xFu: - if (hb_in_range (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u]; + if (hb_in_range (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u]; break; case 0x10u: - if (hb_in_range (u, 0x10A00u, 0x10A47u)) return use_table[u - 0x10A00u + use_offset_0x10a00u]; + if (hb_in_range (u, 0x10A00u, 0x10A47u)) return use_table[u - 0x10A00u + use_offset_0x10a00u]; break; case 0x11u: - if (hb_in_range (u, 0x11000u, 0x110BFu)) return use_table[u - 0x11000u + use_offset_0x11000u]; - if (hb_in_range (u, 0x11100u, 0x11237u)) return use_table[u - 0x11100u + use_offset_0x11100u]; - if (hb_in_range (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u]; - if (hb_in_range (u, 0x11480u, 0x114DFu)) return use_table[u - 0x11480u + use_offset_0x11480u]; - if (hb_in_range (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u]; + if (hb_in_range (u, 0x11000u, 0x110BFu)) return use_table[u - 0x11000u + use_offset_0x11000u]; + if (hb_in_range (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u]; + if (hb_in_range (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u]; + if (hb_in_range (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u]; + if (hb_in_range (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u]; + if (hb_in_range (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u]; if (unlikely (u == 0x1107Fu)) return HN; break; @@ -662,7 +701,6 @@ hb_use_get_categories (hb_codepoint_t u) #undef H #undef HN #undef IND -#undef IV #undef N #undef O #undef R diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc index dc2d7af52..a5ab0ab2a 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc @@ -184,6 +184,9 @@ has_arabic_joining (hb_script_t script) case HB_SCRIPT_MANICHAEAN: case HB_SCRIPT_PSALTER_PAHLAVI: + /* Unicode-9.0 additions */ + case HB_SCRIPT_ADLAM: + return true; default: @@ -227,12 +230,12 @@ data_destroy_use (void *data) enum syllable_type_t { independent_cluster, virama_terminated_cluster, - consonant_cluster, - vowel_cluster, + standard_cluster, number_joiner_terminated_cluster, numeral_cluster, symbol_cluster, broken_cluster, + non_cluster, }; #include "hb-ot-shape-complex-use-machine.hh" @@ -285,6 +288,9 @@ static void setup_topographical_masks (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer) { + const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data; + if (use_plan->arabic_plan) + return; ASSERT_STATIC (INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4); hb_mask_t masks[4], all_masks = 0; @@ -309,13 +315,13 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, { case independent_cluster: case symbol_cluster: + case non_cluster: /* These don't join. Nothing to do. */ last_form = _NONE; break; case virama_terminated_cluster: - case consonant_cluster: - case vowel_cluster: + case standard_cluster: case number_joiner_terminated_cluster: case numeral_cluster: case broken_cluster: @@ -348,6 +354,8 @@ setup_syllables (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer) { find_syllables (buffer); + foreach_syllable (buffer, start, end) + buffer->unsafe_to_break (start, end); setup_rphf_mask (plan, buffer); setup_topographical_masks (plan, buffer); } @@ -360,7 +368,7 @@ clear_substitution_flags (const hb_ot_shape_plan_t *plan, hb_glyph_info_t *info = buffer->info; unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) - _hb_glyph_info_clear_substituted_and_ligated_and_multiplied (&info[i]); + _hb_glyph_info_clear_substituted (&info[i]); } static void @@ -405,6 +413,12 @@ record_pref (const hb_ot_shape_plan_t *plan, } } +static inline bool +is_halant (const hb_glyph_info_t &info) +{ + return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info); +} + static void reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end) { @@ -412,28 +426,26 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end) /* Only a few syllable types need reordering. */ if (unlikely (!(FLAG_SAFE (syllable_type) & (FLAG (virama_terminated_cluster) | - FLAG (consonant_cluster) | - FLAG (vowel_cluster) | + FLAG (standard_cluster) | FLAG (broken_cluster) | 0)))) return; hb_glyph_info_t *info = buffer->info; -#define HALANT_FLAGS FLAG(USE_H) -#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB) | FLAG (USE_IV)) +#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB)) /* Move things forward. */ if (info[start].use_category() == USE_R && end - start > 1) { /* Got a repha. Reorder it to after first base, before first halant. */ for (unsigned int i = start + 1; i < end; i++) - if (FLAG_UNSAFE (info[i].use_category()) & (HALANT_FLAGS | BASE_FLAGS)) + if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i])) { /* If we hit a halant, move before it; otherwise it's a base: move to it's * place, and shift things in between backward. */ - if (info[i].use_category() == USE_H) + if (is_halant (info[i])) i--; buffer->merge_clusters (start, i + 1); @@ -450,11 +462,11 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end) for (unsigned int i = start; i < end; i++) { uint32_t flag = FLAG_UNSAFE (info[i].use_category()); - if (flag & (HALANT_FLAGS | BASE_FLAGS)) + if ((flag & (BASE_FLAGS)) || is_halant (info[i])) { - /* If we hit a halant, move before it; otherwise it's a base: move to it's + /* If we hit a halant, move after it; otherwise it's a base: move to it's * place, and shift things in between backward. */ - if (info[i].use_category() == USE_H) + if (is_halant (info[i])) j = i + 1; else j = i; @@ -491,7 +503,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, return; hb_glyph_info_t dottedcircle = {0}; - if (!font->get_glyph (0x25CCu, 0, &dottedcircle.codepoint)) + if (!font->get_nominal_glyph (0x25CCu, &dottedcircle.codepoint)) return; dottedcircle.use_category() = hb_use_get_categories (0x25CC); @@ -514,7 +526,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, /* TODO Set glyph_props? */ /* Insert dottedcircle after possible Repha. */ - while (buffer->idx < buffer->len && + while (buffer->idx < buffer->len && !buffer->in_error && last_syllable == buffer->cur().syllable() && buffer->cur().use_category() == USE_R) buffer->next_glyph (); @@ -548,6 +560,25 @@ reorder (const hb_ot_shape_plan_t *plan, HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); } +static bool +decompose_use (const hb_ot_shape_normalize_context_t *c, + hb_codepoint_t ab, + hb_codepoint_t *a, + hb_codepoint_t *b) +{ + switch (ab) + { + /* Chakma: + * Special case where the Unicode decomp gives matras in the wrong order + * for cluster validation. + */ + case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; + case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; + } + + return (bool) c->unicode->decompose (ab, a, b); +} + static bool compose_use (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t a, @@ -558,7 +589,7 @@ compose_use (const hb_ot_shape_normalize_context_t *c, if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a))) return false; - return c->unicode->compose (a, b, ab); + return (bool)c->unicode->compose (a, b, ab); } @@ -572,9 +603,10 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use = NULL, /* preprocess_text */ NULL, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, - NULL, /* decompose */ + decompose_use, compose_use, setup_masks_use, - HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, + NULL, /* disable_otl */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ }; diff --git a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc index c9cf737f4..4da53f4cc 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc @@ -307,6 +307,9 @@ position_around_base (const hb_ot_shape_plan_t *plan, unsigned int end) { hb_direction_t horiz_dir = HB_DIRECTION_INVALID; + + buffer->unsafe_to_break (base, end); + hb_glyph_extents_t base_extents; if (!font->get_glyph_extents (buffer->info[base].codepoint, &base_extents)) @@ -526,7 +529,7 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan, case t::SPACE_FIGURE: for (char u = '0'; u <= '9'; u++) - if (font->get_glyph (u, 0, &glyph)) + if (font->get_nominal_glyph (u, &glyph)) { pos[i].x_advance = font->get_glyph_h_advance (glyph); break; @@ -534,9 +537,9 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan, break; case t::SPACE_PUNCTUATION: - if (font->get_glyph ('.', 0, &glyph)) + if (font->get_nominal_glyph ('.', &glyph)) pos[i].x_advance = font->get_glyph_h_advance (glyph); - else if (font->get_glyph (',', 0, &glyph)) + else if (font->get_nominal_glyph (',', &glyph)) pos[i].x_advance = font->get_glyph_h_advance (glyph); break; diff --git a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc index c553f7288..94a3d7d27 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc @@ -76,7 +76,7 @@ decompose_unicode (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t *a, hb_codepoint_t *b) { - return c->unicode->decompose (ab, a, b); + return (bool) c->unicode->decompose (ab, a, b); } static bool @@ -85,13 +85,13 @@ compose_unicode (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t b, hb_codepoint_t *ab) { - return c->unicode->compose (a, b, ab); + return (bool) c->unicode->compose (a, b, ab); } static inline void set_glyph (hb_glyph_info_t &info, hb_font_t *font) { - font->get_glyph (info.codepoint, 0, &info.glyph_index()); + (void) font->get_nominal_glyph (info.codepoint, &info.glyph_index()); } static inline void @@ -124,10 +124,10 @@ decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint hb_font_t * const font = c->font; if (!c->decompose (c, ab, &a, &b) || - (b && !font->get_glyph (b, 0, &b_glyph))) + (b && !font->get_nominal_glyph (b, &b_glyph))) return 0; - bool has_a = font->get_glyph (a, 0, &a_glyph); + bool has_a = (bool) font->get_nominal_glyph (a, &a_glyph); if (shortest && has_a) { /* Output a and b */ output_char (buffer, a, a_glyph); @@ -166,7 +166,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor hb_codepoint_t u = buffer->cur().codepoint; hb_codepoint_t glyph; - if (shortest && c->font->get_glyph (u, 0, &glyph)) + if (shortest && c->font->get_nominal_glyph (u, &glyph)) { next_char (buffer, glyph); return; @@ -178,7 +178,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor return; } - if (!shortest && c->font->get_glyph (u, 0, &glyph)) + if (!shortest && c->font->get_nominal_glyph (u, &glyph)) { next_char (buffer, glyph); return; @@ -188,7 +188,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor { hb_codepoint_t space_glyph; hb_unicode_funcs_t::space_t space_type = buffer->unicode->space_fallback_type (u); - if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_glyph (0x0020u, 0, &space_glyph)) + if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_nominal_glyph (0x0020u, &space_glyph)) { _hb_glyph_info_set_unicode_space_fallback_type (&buffer->cur(), space_type); next_char (buffer, space_glyph); @@ -202,7 +202,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor /* U+2011 is the only sensible character that is a no-break version of another character * and not a space. The space ones are handled already. Handle this lone one. */ hb_codepoint_t other_glyph; - if (c->font->get_glyph (0x2010u, 0, &other_glyph)) + if (c->font->get_nominal_glyph (0x2010u, &other_glyph)) { next_char (buffer, other_glyph); return; @@ -221,7 +221,7 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, uns for (; buffer->idx < end - 1 && !buffer->in_error;) { if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) { /* The next two lines are some ugly lines... But work. */ - if (font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) + if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) { buffer->replace_glyphs (2, 1, &buffer->cur().codepoint); } @@ -388,7 +388,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, buffer->cur().codepoint, &composed) && /* And the font has glyph for the composite. */ - font->get_glyph (composed, 0, &glyph)) + font->get_nominal_glyph (composed, &glyph)) { /* Composes. */ buffer->next_glyph (); /* Copy to out-buffer. */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-private.hh b/gfx/harfbuzz/src/hb-ot-shape-private.hh index 54ac2c3cf..594e54c02 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-private.hh @@ -77,11 +77,13 @@ struct hb_ot_shape_planner_t map (face, &props) {} ~hb_ot_shape_planner_t (void) { map.finish (); } - inline void compile (hb_ot_shape_plan_t &plan) + inline void compile (hb_ot_shape_plan_t &plan, + const int *coords, + unsigned int num_coords) { plan.props = props; plan.shaper = shaper; - map.compile (plan.map); + map.compile (plan.map, coords, num_coords); plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); diff --git a/gfx/harfbuzz/src/hb-ot-shape.cc b/gfx/harfbuzz/src/hb-ot-shape.cc index 464811d1f..8cd8fcc17 100644 --- a/gfx/harfbuzz/src/hb-ot-shape.cc +++ b/gfx/harfbuzz/src/hb-ot-shape.cc @@ -69,6 +69,9 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, { hb_ot_map_builder_t *map = &planner->map; + map->add_global_bool_feature (HB_TAG('r','v','r','n')); + map->add_gsub_pause (NULL); + switch (props->direction) { case HB_DIRECTION_LTR: map->add_global_bool_feature (HB_TAG ('l','t','r','a')); @@ -125,6 +128,8 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, * shaper face data */ +HB_SHAPER_DATA_ENSURE_DEFINE(ot, face) + hb_ot_shaper_face_data_t * _hb_ot_shaper_face_data_create (hb_face_t *face) { @@ -142,10 +147,12 @@ _hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data) * shaper font data */ +HB_SHAPER_DATA_ENSURE_DEFINE(ot, font) + struct hb_ot_shaper_font_data_t {}; hb_ot_shaper_font_data_t * -_hb_ot_shaper_font_data_create (hb_font_t *font) +_hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED) { return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; } @@ -163,7 +170,9 @@ _hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data) hb_ot_shaper_shape_plan_data_t * _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, const hb_feature_t *user_features, - unsigned int num_user_features) + unsigned int num_user_features, + const int *coords, + unsigned int num_coords) { hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t)); if (unlikely (!plan)) @@ -173,9 +182,10 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, planner.shaper = hb_ot_shape_complex_categorize (&planner); - hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features); + hb_ot_shape_collect_features (&planner, &shape_plan->props, + user_features, num_user_features); - planner.compile (*plan); + planner.compile (*plan, coords, num_coords); if (plan->shaper->data_create) { plan->data = plan->shaper->data_create (plan); @@ -212,6 +222,8 @@ struct hb_ot_shape_context_t unsigned int num_user_features; /* Transient stuff */ + bool fallback_positioning; + bool fallback_glyph_classes; hb_direction_t target_direction; }; @@ -263,23 +275,29 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) static void hb_form_clusters (hb_buffer_t *buffer) { - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) || - buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII)) return; - /* Loop duplicated in hb_ensure_native_direction(). */ + /* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */ unsigned int base = 0; unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 1; i < count; i++) { - if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) + if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) && + !_hb_glyph_info_is_joiner (&info[i]))) { - buffer->merge_clusters (base, i); + if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + buffer->merge_clusters (base, i); + else + buffer->unsafe_to_break (base, i); base = i; } } - buffer->merge_clusters (base, count); + if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + buffer->merge_clusters (base, count); + else + buffer->unsafe_to_break (base, count); } static void @@ -353,7 +371,18 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) hb_buffer_t *buffer = c->buffer; - /* TODO look in pre/post context text also. */ + hb_mask_t pre_mask, post_mask; + if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) + { + pre_mask = c->plan->numr_mask | c->plan->frac_mask; + post_mask = c->plan->frac_mask | c->plan->dnom_mask; + } + else + { + pre_mask = c->plan->frac_mask | c->plan->dnom_mask; + post_mask = c->plan->numr_mask | c->plan->frac_mask; + } + unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) @@ -370,11 +399,13 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) end++; + buffer->unsafe_to_break (start, end); + for (unsigned int j = start; j < i; j++) - info[j].mask |= c->plan->numr_mask | c->plan->frac_mask; + info[j].mask |= pre_mask; info[i].mask |= c->plan->frac_mask; for (unsigned int j = i + 1; j < end; j++) - info[j].mask |= c->plan->frac_mask | c->plan->dnom_mask; + info[j].mask |= post_mask; i = end - 1; } @@ -455,7 +486,7 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) return; hb_codepoint_t space; - if (c->font->get_glyph (' ', 0, &space)) + if (c->font->get_nominal_glyph (' ', &space)) { /* Replace default-ignorables with a zero-advance space glyph. */ for (/*continue*/; i < count; i++) @@ -485,9 +516,10 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) /* Merge cluster backward. */ if (cluster < info[j - 1].cluster) { + unsigned int mask = info[i].mask; unsigned int old_cluster = info[j - 1].cluster; for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) - info[k - 1].cluster = cluster; + buffer->set_cluster (info[k - 1], cluster, mask); } continue; } @@ -553,8 +585,6 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c) { hb_buffer_t *buffer = c->buffer; - hb_ot_shape_initialize_masks (c); - hb_ot_mirror_chars (c); HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index); @@ -564,7 +594,7 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c) hb_ot_shape_setup_masks (c); /* This is unfortunate to go here, but necessary... */ - if (!hb_ot_layout_has_positioning (c->face)) + if (c->fallback_positioning) _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer); hb_ot_map_glyphs_fast (buffer); @@ -584,8 +614,6 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c) c->plan->substitute (c->font, buffer); - hb_ot_layout_substitute_finish (c->font, buffer); - return; } @@ -615,30 +643,9 @@ zero_mark_width (hb_glyph_position_t *pos) pos->y_advance = 0; } -static inline void -zero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets) -{ - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII)) - return; - - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - for (unsigned int i = 0; i < count; i++) - if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) - { - if (adjust_offsets) - adjust_mark_offsets (&buffer->pos[i]); - zero_mark_width (&buffer->pos[i]); - } -} - static inline void zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets) { - /* This one is a hack; Technically GDEF can mark ASCII glyphs as marks, but we don't listen. */ - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII)) - return; - unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) @@ -662,6 +669,7 @@ hb_ot_position_default (hb_ot_shape_context_t *c) { for (unsigned int i = 0; i < count; i++) pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint); + /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ if (c->font->has_glyph_h_origin_func ()) for (unsigned int i = 0; i < count; i++) c->font->subtract_glyph_h_origin (info[i].codepoint, @@ -671,23 +679,24 @@ hb_ot_position_default (hb_ot_shape_context_t *c) else { for (unsigned int i = 0; i < count; i++) + { pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint); - if (c->font->has_glyph_v_origin_func ()) - for (unsigned int i = 0; i < count; i++) - c->font->subtract_glyph_v_origin (info[i].codepoint, - &pos[i].x_offset, - &pos[i].y_offset); + c->font->subtract_glyph_v_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); + } } if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK) _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer); } -static inline bool +static inline void hb_ot_position_complex (hb_ot_shape_context_t *c) { - bool ret = false; + hb_ot_layout_position_start (c->font, c->buffer); + unsigned int count = c->buffer->len; - bool has_positioning = hb_ot_layout_has_positioning (c->face); + /* If the font has no GPOS, AND, no fallback positioning will * happen, AND, direction is forward, then when zeroing mark * widths, we shift the mark with it, such that the mark @@ -697,8 +706,9 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) * If fallback positinoing happens or GPOS is present, we don't * care. */ - bool adjust_offsets_when_zeroing = !(has_positioning || c->plan->shaper->fallback_position || - HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)); + bool adjust_offsets_when_zeroing = c->fallback_positioning && + !c->plan->shaper->fallback_position && + HB_DIRECTION_IS_FORWARD (c->buffer->props.direction); switch (c->plan->shaper->zero_width_marks) { @@ -706,26 +716,20 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); break; - /* Not currently used for any shaper: - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: - zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing); - break; - */ - default: case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: break; } - if (has_positioning) + if (likely (!c->fallback_positioning)) { hb_glyph_info_t *info = c->buffer->info; hb_glyph_position_t *pos = c->buffer->pos; /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */ + /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ if (c->font->has_glyph_h_origin_func ()) for (unsigned int i = 0; i < count; i++) c->font->add_glyph_h_origin (info[i].codepoint, @@ -734,49 +738,43 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) c->plan->position (c->font, c->buffer); + /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ if (c->font->has_glyph_h_origin_func ()) for (unsigned int i = 0; i < count; i++) c->font->subtract_glyph_h_origin (info[i].codepoint, &pos[i].x_offset, &pos[i].y_offset); - ret = true; } switch (c->plan->shaper->zero_width_marks) { - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: - zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing); - break; - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); break; default: case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: - //case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: break; } - return ret; + /* Finishing off GPOS has to follow a certain order. */ + hb_ot_layout_position_finish_advances (c->font, c->buffer); + hb_ot_zero_width_default_ignorables (c); + hb_ot_layout_position_finish_offsets (c->font, c->buffer); } static inline void hb_ot_position (hb_ot_shape_context_t *c) { - hb_ot_layout_position_start (c->font, c->buffer); + c->buffer->clear_positions (); hb_ot_position_default (c); - hb_bool_t fallback = !hb_ot_position_complex (c); + hb_ot_position_complex (c); - hb_ot_zero_width_default_ignorables (c); - - hb_ot_layout_position_finish (c->font, c->buffer); - - if (fallback && c->plan->shaper->fallback_position) + if (c->fallback_positioning && c->plan->shaper->fallback_position) _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer); if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)) @@ -784,12 +782,37 @@ hb_ot_position (hb_ot_shape_context_t *c) /* Visual fallback goes here. */ - if (fallback) + if (c->fallback_positioning) _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); _hb_buffer_deallocate_gsubgpos_vars (c->buffer); } +static inline void +hb_propagate_flags (hb_buffer_t *buffer) +{ + /* Propagate cluster-level glyph flags to be the same on all cluster glyphs. + * Simplifies using them. */ + + if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK)) + return; + + hb_glyph_info_t *info = buffer->info; + + foreach_cluster (buffer, start, end) + { + unsigned int mask = 0; + for (unsigned int i = start; i < end; i++) + if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) + { + mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + break; + } + if (mask) + for (unsigned int i = start; i < end; i++) + info[i].mask |= mask; + } +} /* Pull it all together! */ @@ -804,6 +827,11 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) (unsigned) HB_BUFFER_MAX_LEN_MIN); } + bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan); + //c->fallback_substitute = disable_otl || !hb_ot_layout_has_substitution (c->face); + c->fallback_positioning = disable_otl || !hb_ot_layout_has_positioning (c->face); + c->fallback_glyph_classes = disable_otl || !hb_ot_layout_has_glyph_classes (c->face); + /* Save the original direction, we use it later. */ c->target_direction = c->buffer->props.direction; @@ -811,8 +839,10 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) c->buffer->clear_output (); + hb_ot_shape_initialize_masks (c); hb_set_unicode_props (c->buffer); hb_insert_dotted_circle (c->buffer, c->font); + hb_form_clusters (c->buffer); hb_ensure_native_direction (c->buffer); @@ -828,6 +858,8 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) if (c->plan->shaper->postprocess_glyphs) c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font); + hb_propagate_flags (c->buffer); + _hb_buffer_deallocate_unicode_vars (c->buffer); c->buffer->props.direction = c->target_direction; @@ -852,6 +884,8 @@ _hb_ot_shape (hb_shape_plan_t *shape_plan, /** + * hb_ot_shape_plan_collect_lookups: + * * Since: 0.9.7 **/ void @@ -873,18 +907,20 @@ add_char (hb_font_t *font, hb_set_t *glyphs) { hb_codepoint_t glyph; - if (font->get_glyph (u, 0, &glyph)) + if (font->get_nominal_glyph (u, &glyph)) glyphs->add (glyph); if (mirror) { hb_codepoint_t m = unicode->mirroring (u); - if (m != u && font->get_glyph (m, 0, &glyph)) + if (m != u && font->get_nominal_glyph (m, &glyph)) glyphs->add (glyph); } } /** + * hb_ot_shape_glyphs_closure: + * * Since: 0.9.2 **/ void diff --git a/gfx/harfbuzz/src/hb-ot-shape.h b/gfx/harfbuzz/src/hb-ot-shape.h index 1402f54ac..7b1bcc063 100644 --- a/gfx/harfbuzz/src/hb-ot-shape.h +++ b/gfx/harfbuzz/src/hb-ot-shape.h @@ -36,14 +36,14 @@ HB_BEGIN_DECLS /* TODO port to shape-plan / set. */ -void +HB_EXTERN void hb_ot_shape_glyphs_closure (hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, unsigned int num_features, hb_set_t *glyphs); -void +HB_EXTERN void hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, hb_tag_t table_tag, hb_set_t *lookup_indexes /* OUT */); diff --git a/gfx/harfbuzz/src/hb-ot-tag.cc b/gfx/harfbuzz/src/hb-ot-tag.cc index a2e5728fc..9b0db507b 100644 --- a/gfx/harfbuzz/src/hb-ot-tag.cc +++ b/gfx/harfbuzz/src/hb-ot-tag.cc @@ -28,9 +28,6 @@ #include "hb-private.hh" -#include - - /* hb_script_t */ @@ -186,17 +183,22 @@ static const LangTag ot_languages[] = { {"aa", HB_TAG('A','F','R',' ')}, /* Afar */ {"ab", HB_TAG('A','B','K',' ')}, /* Abkhazian */ {"abq", HB_TAG('A','B','A',' ')}, /* Abaza */ + {"acf", HB_TAG('F','A','N',' ')}, /* French Antillean */ {"ach", HB_TAG('A','C','H',' ')}, /* Acoli */ + {"acr", HB_TAG('A','C','R',' ')}, /* Achi */ {"ada", HB_TAG('D','N','G',' ')}, /* Dangme */ {"ady", HB_TAG('A','D','Y',' ')}, /* Adyghe */ {"af", HB_TAG('A','F','K',' ')}, /* Afrikaans */ + {"ahg", HB_TAG('A','G','W',' ')}, /* Agaw */ {"aii", HB_TAG('S','W','A',' ')}, /* Swadaya Aramaic */ {"aio", HB_TAG('A','I','O',' ')}, /* Aiton */ {"aiw", HB_TAG('A','R','I',' ')}, /* Aari */ {"ak", HB_TAG('T','W','I',' ')}, /* Akan [macrolanguage] */ + {"aka", HB_TAG('A','K','A',' ')}, /* Akan */ {"alt", HB_TAG('A','L','T',' ')}, /* [Southern] Altai */ {"am", HB_TAG('A','M','H',' ')}, /* Amharic */ {"amf", HB_TAG('H','B','N',' ')}, /* Hammer-Banna */ + {"amw", HB_TAG('S','Y','R',' ')}, /* Western Neo-Aramaic */ {"an", HB_TAG('A','R','G',' ')}, /* Aragonese */ {"ang", HB_TAG('A','N','G',' ')}, /* Old English (ca. 450-1100) */ {"ar", HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */ @@ -206,6 +208,7 @@ static const LangTag ot_languages[] = { {"as", HB_TAG('A','S','M',' ')}, /* Assamese */ {"ast", HB_TAG('A','S','T',' ')}, /* Asturian/Asturleonese/Bable/Leonese */ {"ath", HB_TAG('A','T','H',' ')}, /* Athapaskan [family] */ + {"atj", HB_TAG('R','C','R',' ')}, /* R-Cree */ {"atv", HB_TAG('A','L','T',' ')}, /* [Northern] Altai */ {"av", HB_TAG('A','V','R',' ')}, /* Avaric */ {"awa", HB_TAG('A','W','A',' ')}, /* Awadhi */ @@ -214,6 +217,7 @@ static const LangTag ot_languages[] = { {"azb", HB_TAG('A','Z','B',' ')}, /* South Azerbaijani */ {"azj", HB_TAG('A','Z','E',' ')}, /* North Azerbaijani */ {"ba", HB_TAG('B','S','H',' ')}, /* Bashkir */ + {"bad", HB_TAG('B','A','D','0')}, /* Banda */ {"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [family] */ {"bal", HB_TAG('B','L','I',' ')}, /* Baluchi [macrolangauge] */ {"ban", HB_TAG('B','A','N',' ')}, /* Balinese */ @@ -222,15 +226,18 @@ static const LangTag ot_languages[] = { {"bci", HB_TAG('B','A','U',' ')}, /* Baoulé */ {"bcl", HB_TAG('B','I','K',' ')}, /* Central Bikol */ {"bcq", HB_TAG('B','C','H',' ')}, /* Bench */ + {"bdy", HB_TAG('B','D','Y',' ')}, /* Bandjalang */ {"be", HB_TAG('B','E','L',' ')}, /* Belarusian */ {"bem", HB_TAG('B','E','M',' ')}, /* Bemba (Zambia) */ {"ber", HB_TAG('B','E','R',' ')}, /* Berber [family] */ {"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */ {"bft", HB_TAG('B','L','T',' ')}, /* Balti */ + {"bfu", HB_TAG('L','A','H',' ')}, /* Lahuli */ {"bfy", HB_TAG('B','A','G',' ')}, /* Baghelkhandi */ {"bg", HB_TAG('B','G','R',' ')}, /* Bulgarian */ {"bgc", HB_TAG('B','G','C',' ')}, /* Haryanvi */ {"bgq", HB_TAG('B','G','Q',' ')}, /* Bagri */ + {"bgr", HB_TAG('Q','I','N',' ')}, /* Bawm Chin */ {"bhb", HB_TAG('B','H','I',' ')}, /* Bhili */ {"bhk", HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) */ {"bho", HB_TAG('B','H','O',' ')}, /* Bhojpuri */ @@ -260,44 +267,71 @@ static const LangTag ot_languages[] = { {"bxr", HB_TAG('R','B','U',' ')}, /* Russian Buriat */ {"byn", HB_TAG('B','I','L',' ')}, /* Bilen */ {"ca", HB_TAG('C','A','T',' ')}, /* Catalan */ + {"cak", HB_TAG('C','A','K',' ')}, /* Kaqchikel */ {"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano */ + {"cbl", HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin */ {"ce", HB_TAG('C','H','E',' ')}, /* Chechen */ {"ceb", HB_TAG('C','E','B',' ')}, /* Cebuano */ + {"cfm", HB_TAG('H','A','L',' ')}, /* Halam/Falam Chin */ {"cgg", HB_TAG('C','G','G',' ')}, /* Chiga */ {"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */ + {"chk", HB_TAG('C','H','K','0')}, /* Chuukese */ {"cho", HB_TAG('C','H','O',' ')}, /* Choctaw */ {"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */ {"chr", HB_TAG('C','H','R',' ')}, /* Cherokee */ {"chy", HB_TAG('C','H','Y',' ')}, /* Cheyenne */ + {"cja", HB_TAG('C','J','A',' ')}, /* Western Cham */ + {"cjm", HB_TAG('C','J','M',' ')}, /* Eastern Cham */ + {"cka", HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin */ {"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish (Sorani) */ {"ckt", HB_TAG('C','H','K',' ')}, /* Chukchi */ + {"cld", HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic */ + {"cmr", HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin */ + {"cnb", HB_TAG('Q','I','N',' ')}, /* Chinbon Chin */ + {"cnh", HB_TAG('Q','I','N',' ')}, /* Hakha Chin */ + {"cnk", HB_TAG('Q','I','N',' ')}, /* Khumi Chin */ + {"cnw", HB_TAG('Q','I','N',' ')}, /* Ngawn Chin */ {"cop", HB_TAG('C','O','P',' ')}, /* Coptic */ + {"cpp", HB_TAG('C','P','P',' ')}, /* Creoles */ {"cr", HB_TAG('C','R','E',' ')}, /* Cree */ + {"cre", HB_TAG('Y','C','R',' ')}, /* Y-Cree */ {"crh", HB_TAG('C','R','T',' ')}, /* Crimean Tatar */ {"crj", HB_TAG('E','C','R',' ')}, /* [Southern] East Cree */ + {"crk", HB_TAG('W','C','R',' ')}, /* West-Cree */ {"crl", HB_TAG('E','C','R',' ')}, /* [Northern] East Cree */ {"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */ {"crx", HB_TAG('C','R','R',' ')}, /* Carrier */ {"cs", HB_TAG('C','S','Y',' ')}, /* Czech */ {"csb", HB_TAG('C','S','B',' ')}, /* Kashubian */ + {"csh", HB_TAG('Q','I','N',' ')}, /* Asho Chin */ + {"csy", HB_TAG('Q','I','N',' ')}, /* Siyin Chin */ + {"ctd", HB_TAG('Q','I','N',' ')}, /* Tedim Chin */ {"ctg", HB_TAG('C','T','G',' ')}, /* Chittagonian */ {"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol */ {"cu", HB_TAG('C','S','L',' ')}, /* Church Slavic */ + {"cuk", HB_TAG('C','U','K',' ')}, /* San Blas Kuna */ {"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */ {"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */ {"cy", HB_TAG('W','E','L',' ')}, /* Welsh */ + {"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin */ {"da", HB_TAG('D','A','N',' ')}, /* Danish */ + {"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin */ {"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) */ {"dar", HB_TAG('D','A','R',' ')}, /* Dargwa */ + {"dax", HB_TAG('D','A','X',' ')}, /* Dayi */ {"de", HB_TAG('D','E','U',' ')}, /* German */ {"dgo", HB_TAG('D','G','O',' ')}, /* Dogri */ {"dhd", HB_TAG('M','A','W',' ')}, /* Dhundari */ + {"dhg", HB_TAG('D','H','G',' ')}, /* Dhangu */ {"din", HB_TAG('D','N','K',' ')}, /* Dinka [macrolanguage] */ {"diq", HB_TAG('D','I','Q',' ')}, /* Dimli */ {"dje", HB_TAG('D','J','R',' ')}, /* Zarma */ + {"djr", HB_TAG('D','J','R','0')}, /* Djambarrpuyngu */ {"dng", HB_TAG('D','U','N',' ')}, /* Dungan */ + {"dnj", HB_TAG('D','N','J',' ')}, /* Dan */ {"doi", HB_TAG('D','G','R',' ')}, /* Dogri [macrolanguage] */ {"dsb", HB_TAG('L','S','B',' ')}, /* Lower Sorbian */ + {"duj", HB_TAG('D','U','J',' ')}, /* Dhuwal */ {"dv", HB_TAG('D','I','V',' ')}, /* Dhivehi/Divehi/Maldivian */ {"dyu", HB_TAG('J','U','L',' ')}, /* Jula */ {"dz", HB_TAG('D','Z','N',' ')}, /* Dzongkha */ @@ -307,23 +341,30 @@ static const LangTag ot_languages[] = { {"el", HB_TAG('E','L','L',' ')}, /* Modern Greek (1453-) */ {"emk", HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan */ {"en", HB_TAG('E','N','G',' ')}, /* English */ + {"enf", HB_TAG('F','N','E',' ')}, /* Forest Nenets */ + {"enh", HB_TAG('T','N','E',' ')}, /* Tundra Nenets */ {"eo", HB_TAG('N','T','O',' ')}, /* Esperanto */ {"eot", HB_TAG('B','T','I',' ')}, /* Beti (Côte d'Ivoire) */ {"es", HB_TAG('E','S','P',' ')}, /* Spanish */ + {"esu", HB_TAG('E','S','U',' ')}, /* Central Yupik */ {"et", HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */ {"eu", HB_TAG('E','U','Q',' ')}, /* Basque */ {"eve", HB_TAG('E','V','N',' ')}, /* Even */ {"evn", HB_TAG('E','V','K',' ')}, /* Evenki */ {"fa", HB_TAG('F','A','R',' ')}, /* Persian [macrolanguage] */ + {"fan", HB_TAG('F','A','N','0')}, /* Fang */ + {"fat", HB_TAG('F','A','T',' ')}, /* Fanti */ {"ff", HB_TAG('F','U','L',' ')}, /* Fulah [macrolanguage] */ {"fi", HB_TAG('F','I','N',' ')}, /* Finnish */ {"fil", HB_TAG('P','I','L',' ')}, /* Filipino */ {"fj", HB_TAG('F','J','I',' ')}, /* Fijian */ + {"flm", HB_TAG('H','A','L',' ')}, /* Halam/Falam Chin [retired ISO639 code] */ {"fo", HB_TAG('F','O','S',' ')}, /* Faroese */ {"fon", HB_TAG('F','O','N',' ')}, /* Fon */ {"fr", HB_TAG('F','R','A',' ')}, /* French */ {"frc", HB_TAG('F','R','C',' ')}, /* Cajun French */ {"frp", HB_TAG('F','R','P',' ')}, /* Arpitan/Francoprovençal */ + {"fuf", HB_TAG('F','T','A',' ')}, /* Futa */ {"fur", HB_TAG('F','R','L',' ')}, /* Friulian */ {"fuv", HB_TAG('F','U','V',' ')}, /* Nigerian Fulfulde */ {"fy", HB_TAG('F','R','I',' ')}, /* Western Frisian */ @@ -334,17 +375,24 @@ static const LangTag ot_languages[] = { {"gd", HB_TAG('G','A','E',' ')}, /* Scottish Gaelic */ {"gez", HB_TAG('G','E','Z',' ')}, /* Ge'ez */ {"ggo", HB_TAG('G','O','N',' ')}, /* Southern Gondi */ + {"gih", HB_TAG('G','I','H',' ')}, /* Githabul */ + {"gil", HB_TAG('G','I','L','0')}, /* Kiribati (Gilbertese) */ + {"gkp", HB_TAG('G','K','P',' ')}, /* Kpelle (Guinea) */ {"gl", HB_TAG('G','A','L',' ')}, /* Galician */ {"gld", HB_TAG('N','A','N',' ')}, /* Nanai */ + {"gle", HB_TAG('I','R','T',' ')}, /* Irish Traditional */ {"glk", HB_TAG('G','L','K',' ')}, /* Gilaki */ {"gn", HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */ + {"gnn", HB_TAG('G','N','N',' ')}, /* Gumatj */ {"gno", HB_TAG('G','O','N',' ')}, /* Northern Gondi */ {"gog", HB_TAG('G','O','G',' ')}, /* Gogo */ {"gon", HB_TAG('G','O','N',' ')}, /* Gondi [macrolanguage] */ {"grt", HB_TAG('G','R','O',' ')}, /* Garo */ {"gru", HB_TAG('S','O','G',' ')}, /* Sodo Gurage */ + {"gsw", HB_TAG('A','L','S',' ')}, /* Alsatian */ {"gu", HB_TAG('G','U','J',' ')}, /* Gujarati */ {"guc", HB_TAG('G','U','C',' ')}, /* Wayuu */ + {"guf", HB_TAG('G','U','F',' ')}, /* Gupapuyngu */ {"guk", HB_TAG('G','M','Z',' ')}, /* Gumuz */ /*{"guk", HB_TAG('G','U','K',' ')},*/ /* Gumuz (in SIL fonts) */ {"guz", HB_TAG('G','U','Z',' ')}, /* Ekegusii/Gusii */ @@ -355,9 +403,10 @@ static const LangTag ot_languages[] = { {"hay", HB_TAG('H','A','Y',' ')}, /* Haya */ {"haz", HB_TAG('H','A','Z',' ')}, /* Hazaragi */ {"he", HB_TAG('I','W','R',' ')}, /* Hebrew */ - {"hz", HB_TAG('H','E','R',' ')}, /* Herero */ {"hi", HB_TAG('H','I','N',' ')}, /* Hindi */ {"hil", HB_TAG('H','I','L',' ')}, /* Hiligaynon */ + {"hlt", HB_TAG('Q','I','N',' ')}, /* Matu Chin */ + {"hmn", HB_TAG('H','M','N',' ')}, /* Hmong */ {"hnd", HB_TAG('H','N','D',' ')}, /* [Southern] Hindko */ {"hne", HB_TAG('C','H','H',' ')}, /* Chattisgarhi */ {"hno", HB_TAG('H','N','D',' ')}, /* [Northern] Hindko */ @@ -371,11 +420,13 @@ static const LangTag ot_languages[] = { {"hy", HB_TAG('H','Y','E',' ')}, /* Armenian */ {"hz", HB_TAG('H','E','R',' ')}, /* Herero */ {"ia", HB_TAG('I','N','A',' ')}, /* Interlingua (International Auxiliary Language Association) */ + {"iba", HB_TAG('I','B','A',' ')}, /* Iban */ {"ibb", HB_TAG('I','B','B',' ')}, /* Ibibio */ {"id", HB_TAG('I','N','D',' ')}, /* Indonesian */ {"ie", HB_TAG('I','L','E',' ')}, /* Interlingue/Occidental */ {"ig", HB_TAG('I','B','O',' ')}, /* Igbo */ {"igb", HB_TAG('E','B','I',' ')}, /* Ebira */ + {"ii", HB_TAG('Y','I','M',' ')}, /* Yi Modern */ {"ijc", HB_TAG('I','J','O',' ')}, /* Izon */ {"ijo", HB_TAG('I','J','O',' ')}, /* Ijo [family] */ {"ik", HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] */ @@ -391,15 +442,20 @@ static const LangTag ot_languages[] = { {"jv", HB_TAG('J','A','V',' ')}, /* Javanese */ {"ka", HB_TAG('K','A','T',' ')}, /* Georgian */ {"kaa", HB_TAG('K','R','K',' ')}, /* Karakalpak */ - {"kab", HB_TAG('K','A','B',' ')}, /* Kabyle */ + {"kab", HB_TAG('K','A','B','0')}, /* Kabyle */ {"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */ {"kar", HB_TAG('K','R','N',' ')}, /* Karen [family] */ + {"kat", HB_TAG('K','G','E',' ')}, /* Khutsuri Georgian */ {"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */ {"kde", HB_TAG('K','D','E',' ')}, /* Makonde */ {"kdr", HB_TAG('K','R','M',' ')}, /* Karaim */ {"kdt", HB_TAG('K','U','Y',' ')}, /* Kuy */ + {"kea", HB_TAG('K','E','A',' ')}, /* Kabuverdianu (Crioulo) */ + {"kek", HB_TAG('K','E','K',' ')}, /* Kekchi */ {"kex", HB_TAG('K','K','N',' ')}, /* Kokni */ + {"kfa", HB_TAG('K','O','D',' ')}, /* Kodagu */ {"kfr", HB_TAG('K','A','C',' ')}, /* Kachchi */ + {"kfx", HB_TAG('K','U','L',' ')}, /* Kulvi */ {"kfy", HB_TAG('K','M','N',' ')}, /* Kumaoni */ {"kg", HB_TAG('K','O','N',' ')}, /* Kongo [macrolanguage] */ {"kha", HB_TAG('K','S','I',' ')}, /* Khasi */ @@ -408,7 +464,9 @@ static const LangTag ot_languages[] = { /*{"kht", HB_TAG('K','H','T',' ')},*/ /* Khamti (OpenType spec and SIL fonts) */ {"khw", HB_TAG('K','H','W',' ')}, /* Khowar */ {"ki", HB_TAG('K','I','K',' ')}, /* Gikuyu/Kikuyu */ + {"kiu", HB_TAG('K','I','U',' ')}, /* Kirmanjki */ {"kj", HB_TAG('K','U','A',' ')}, /* Kuanyama/Kwanyama */ + {"kjd", HB_TAG('K','J','D',' ')}, /* Southern Kiwai */ {"kjh", HB_TAG('K','H','A',' ')}, /* Khakass */ {"kjp", HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen */ {"kk", HB_TAG('K','A','Z',' ')}, /* Kazakh */ @@ -422,6 +480,8 @@ static const LangTag ot_languages[] = { {"ko", HB_TAG('K','O','R',' ')}, /* Korean */ {"koi", HB_TAG('K','O','P',' ')}, /* Komi-Permyak */ {"kok", HB_TAG('K','O','K',' ')}, /* Konkani [macrolanguage] */ + {"kon", HB_TAG('K','O','N','0')}, /* Kongo */ + {"kos", HB_TAG('K','O','S',' ')}, /* Kosraean */ {"kpe", HB_TAG('K','P','L',' ')}, /* Kpelle [macrolanguage] */ {"kpv", HB_TAG('K','O','Z',' ')}, /* Komi-Zyrian */ {"kpy", HB_TAG('K','Y','K',' ')}, /* Koryak */ @@ -431,9 +491,11 @@ static const LangTag ot_languages[] = { {"krl", HB_TAG('K','R','L',' ')}, /* Karelian */ {"kru", HB_TAG('K','U','U',' ')}, /* Kurukh */ {"ks", HB_TAG('K','S','H',' ')}, /* Kashmiri */ - {"ksh", HB_TAG('K','S','H',' ')}, /* Kölsch */ + {"ksh", HB_TAG('K','S','H','0')}, /* Ripuarian, Kölsch */ /*{"ksw", HB_TAG('K','R','N',' ')},*/ /* S'gaw Karen (Microsoft fonts?) */ {"ksw", HB_TAG('K','S','W',' ')}, /* S'gaw Karen (OpenType spec and SIL fonts) */ + {"ktb", HB_TAG('K','E','B',' ')}, /* Kebena */ + {"ktu", HB_TAG('K','O','N',' ')}, /* Kikongo */ {"ku", HB_TAG('K','U','R',' ')}, /* Kurdish [macrolanguage] */ {"kum", HB_TAG('K','U','M',' ')}, /* Kumyk */ {"kv", HB_TAG('K','O','M',' ')}, /* Komi [macrolanguage] */ @@ -461,6 +523,7 @@ static const LangTag ot_languages[] = { {"lmo", HB_TAG('L','M','O',' ')}, /* Lombard */ {"ln", HB_TAG('L','I','N',' ')}, /* Lingala */ {"lo", HB_TAG('L','A','O',' ')}, /* Lao */ + {"lom", HB_TAG('L','O','M',' ')}, /* Loma */ {"lrc", HB_TAG('L','R','C',' ')}, /* Northern Luri */ {"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */ {"lu", HB_TAG('L','U','B',' ')}, /* Luba-Katanga */ @@ -475,6 +538,8 @@ static const LangTag ot_languages[] = { {"mag", HB_TAG('M','A','G',' ')}, /* Magahi */ {"mai", HB_TAG('M','T','H',' ')}, /* Maithili */ {"mak", HB_TAG('M','K','R',' ')}, /* Makasar */ + {"mal", HB_TAG('M','A','L',' ')}, /* Malayalam */ + {"mam", HB_TAG('M','A','M',' ')}, /* Mam */ {"man", HB_TAG('M','N','K',' ')}, /* Manding/Mandingo [macrolanguage] */ {"mdc", HB_TAG('M','L','E',' ')}, /* Male (Papua New Guinea) */ {"mdf", HB_TAG('M','O','K',' ')}, /* Moksha */ @@ -504,6 +569,7 @@ static const LangTag ot_languages[] = { {"mos", HB_TAG('M','O','S',' ')}, /* Mossi */ {"mpe", HB_TAG('M','A','J',' ')}, /* Majang */ {"mr", HB_TAG('M','A','R',' ')}, /* Marathi */ + {"mrh", HB_TAG('Q','I','N',' ')}, /* Mara Chin */ {"mrj", HB_TAG('H','M','A',' ')}, /* High Mari */ {"ms", HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */ {"msc", HB_TAG('M','N','K',' ')}, /* Sankaran Maninka */ @@ -517,6 +583,7 @@ static const LangTag ot_languages[] = { {"mww", HB_TAG('M','W','W',' ')}, /* Hmong Daw */ {"my", HB_TAG('B','R','M',' ')}, /* Burmese */ {"mym", HB_TAG('M','E','N',' ')}, /* Me'en */ + {"myn", HB_TAG('M','Y','N',' ')}, /* Mayan */ {"myq", HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) */ {"myv", HB_TAG('E','R','Z',' ')}, /* Erzya */ {"mzn", HB_TAG('M','Z','N',' ')}, /* Mazanderani */ @@ -534,6 +601,7 @@ static const LangTag ot_languages[] = { {"ng", HB_TAG('N','D','G',' ')}, /* Ndonga */ {"nga", HB_TAG('N','G','A',' ')}, /* Ngabaka */ {"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */ + {"ngo", HB_TAG('S','X','T',' ')}, /* Sutu */ {"niu", HB_TAG('N','I','U',' ')}, /* Niuean */ {"niv", HB_TAG('G','I','L',' ')}, /* Gilyak */ {"nl", HB_TAG('N','L','D',' ')}, /* Dutch */ @@ -554,16 +622,19 @@ static const LangTag ot_languages[] = { {"oc", HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */ {"oj", HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] */ {"ojs", HB_TAG('O','C','R',' ')}, /* Oji-Cree */ + {"okm", HB_TAG('K','O','H',' ')}, /* Korean Old Hangul */ {"om", HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */ {"or", HB_TAG('O','R','I',' ')}, /* Oriya */ {"os", HB_TAG('O','S','S',' ')}, /* Ossetian */ {"pa", HB_TAG('P','A','N',' ')}, /* Panjabi */ {"pag", HB_TAG('P','A','G',' ')}, /* Pangasinan */ {"pam", HB_TAG('P','A','M',' ')}, /* Kapampangan/Pampanga */ - {"pap", HB_TAG('P','A','P',' ')}, /* Papiamento */ + {"pap", HB_TAG('P','A','P','0')}, /* Papiamento */ + {"pau", HB_TAG('P','A','U',' ')}, /* Palauan */ {"pcc", HB_TAG('P','C','C',' ')}, /* Bouyei */ {"pcd", HB_TAG('P','C','D',' ')}, /* Picard */ {"pce", HB_TAG('P','L','G',' ')}, /* [Ruching] Palaung */ + {"pck", HB_TAG('Q','I','N',' ')}, /* Paite Chin */ {"pdc", HB_TAG('P','D','C',' ')}, /* Pennsylvania German */ {"pes", HB_TAG('F','A','R',' ')}, /* Iranian Persian */ {"phk", HB_TAG('P','H','K',' ')}, /* Phake */ @@ -574,24 +645,34 @@ static const LangTag ot_languages[] = { {"plp", HB_TAG('P','A','P',' ')}, /* Palpa */ {"pms", HB_TAG('P','M','S',' ')}, /* Piemontese */ {"pnb", HB_TAG('P','N','B',' ')}, /* Western Panjabi */ + {"poh", HB_TAG('P','O','H',' ')}, /* Pocomchi */ + {"pon", HB_TAG('P','O','N',' ')}, /* Pohnpeian */ {"prs", HB_TAG('D','R','I',' ')}, /* Afghan Persian/Dari */ {"ps", HB_TAG('P','A','S',' ')}, /* Pashto/Pushto [macrolanguage] */ {"pt", HB_TAG('P','T','G',' ')}, /* Portuguese */ {"pwo", HB_TAG('P','W','O',' ')}, /* Pwo Western Karen */ {"qu", HB_TAG('Q','U','Z',' ')}, /* Quechua [macrolanguage] */ {"quc", HB_TAG('Q','U','C',' ')}, /* K'iche'/Quiché */ + {"quh", HB_TAG('Q','U','H',' ')}, /* Quechua (Bolivia) */ {"quz", HB_TAG('Q','U','Z',' ')}, /* Cusco Quechua */ + {"qvi", HB_TAG('Q','V','I',' ')}, /* Quechua (Ecuador) */ + {"qwh", HB_TAG('Q','W','H',' ')}, /* Quechua (Peru) */ {"raj", HB_TAG('R','A','J',' ')}, /* Rajasthani [macrolanguage] */ + {"rar", HB_TAG('R','A','R',' ')}, /* Rarotongan */ {"rbb", HB_TAG('P','L','G',' ')}, /* Rumai Palaung */ {"rej", HB_TAG('R','E','J',' ')}, /* Rejang */ {"ria", HB_TAG('R','I','A',' ')}, /* Riang (India) */ + {"rif", HB_TAG('R','I','F',' ')}, /* Tarifit */ {"ril", HB_TAG('R','I','A',' ')}, /* Riang (Myanmar) */ + {"rit", HB_TAG('R','I','T',' ')}, /* Ritarungo */ {"rki", HB_TAG('A','R','K',' ')}, /* Rakhine */ + {"rkw", HB_TAG('R','K','W',' ')}, /* Arakwal */ {"rm", HB_TAG('R','M','S',' ')}, /* Romansh */ {"rmy", HB_TAG('R','M','Y',' ')}, /* Vlax Romani */ {"rn", HB_TAG('R','U','N',' ')}, /* Rundi */ {"ro", HB_TAG('R','O','M',' ')}, /* Romanian */ {"rom", HB_TAG('R','O','Y',' ')}, /* Romany [macrolanguage] */ + {"rtm", HB_TAG('R','T','M',' ')}, /* Rotuman */ {"ru", HB_TAG('R','U','S',' ')}, /* Russian */ {"rue", HB_TAG('R','S','Y',' ')}, /* Rusyn */ {"rup", HB_TAG('R','U','P',' ')}, /* Aromanian/Arumanian/Macedo-Romanian */ @@ -599,10 +680,11 @@ static const LangTag ot_languages[] = { {"rwr", HB_TAG('M','A','W',' ')}, /* Marwari (India) */ {"sa", HB_TAG('S','A','N',' ')}, /* Sanskrit */ {"sah", HB_TAG('Y','A','K',' ')}, /* Yakut */ + {"sam", HB_TAG('P','A','A',' ')}, /* Palestinian Aramaic */ {"sas", HB_TAG('S','A','S',' ')}, /* Sasak */ {"sat", HB_TAG('S','A','T',' ')}, /* Santali */ - {"sck", HB_TAG('S','A','D',' ')}, /* Sadri */ {"sc", HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */ + {"sck", HB_TAG('S','A','D',' ')}, /* Sadri */ {"scn", HB_TAG('S','C','N',' ')}, /* Sicilian */ {"sco", HB_TAG('S','C','O',' ')}, /* Scots */ {"scs", HB_TAG('S','L','A',' ')}, /* [North] Slavey */ @@ -610,11 +692,13 @@ static const LangTag ot_languages[] = { {"se", HB_TAG('N','S','M',' ')}, /* Northern Sami */ {"seh", HB_TAG('S','N','A',' ')}, /* Sena */ {"sel", HB_TAG('S','E','L',' ')}, /* Selkup */ + {"sez", HB_TAG('Q','I','N',' ')}, /* Senthang Chin */ {"sg", HB_TAG('S','G','O',' ')}, /* Sango */ {"sga", HB_TAG('S','G','A',' ')}, /* Old Irish (to 900) */ {"sgs", HB_TAG('S','G','S',' ')}, /* Samogitian */ {"sgw", HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage */ /*{"sgw", HB_TAG('S','G','W',' ')},*/ /* Sebat Bet Gurage (in SIL fonts) */ + {"shi", HB_TAG('S','H','I',' ')}, /* Tachelhit */ {"shn", HB_TAG('S','H','N',' ')}, /* Shan */ {"si", HB_TAG('S','N','H',' ')}, /* Sinhala */ {"sid", HB_TAG('S','I','D',' ')}, /* Sidamo */ @@ -627,7 +711,7 @@ static const LangTag ot_languages[] = { {"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */ {"smn", HB_TAG('I','S','M',' ')}, /* Inari Sami */ {"sms", HB_TAG('S','K','S',' ')}, /* Skolt Sami */ - {"sn", HB_TAG('S','N','A',' ')}, /* Shona */ + {"sn", HB_TAG('S','N','A','0')}, /* Shona */ {"snk", HB_TAG('S','N','K',' ')}, /* Soninke */ {"so", HB_TAG('S','M','L',' ')}, /* Somali */ {"sop", HB_TAG('S','O','P',' ')}, /* Songe */ @@ -648,12 +732,15 @@ static const LangTag ot_languages[] = { {"swh", HB_TAG('S','W','K',' ')}, /* Kiswahili/Swahili */ {"swv", HB_TAG('M','A','W',' ')}, /* Shekhawati */ {"sxu", HB_TAG('S','X','U',' ')}, /* Upper Saxon */ + {"syc", HB_TAG('S','Y','R',' ')}, /* Classical Syriac */ {"syl", HB_TAG('S','Y','L',' ')}, /* Sylheti */ {"syr", HB_TAG('S','Y','R',' ')}, /* Syriac [macrolanguage] */ {"szl", HB_TAG('S','Z','L',' ')}, /* Silesian */ {"ta", HB_TAG('T','A','M',' ')}, /* Tamil */ {"tab", HB_TAG('T','A','B',' ')}, /* Tabasaran */ + {"tcp", HB_TAG('Q','I','N',' ')}, /* Tawr Chin */ {"tcy", HB_TAG('T','U','L',' ')}, /* Tulu */ + {"tcz", HB_TAG('Q','I','N',' ')}, /* Thado Chin */ {"tdd", HB_TAG('T','D','D',' ')}, /* Tai Nüa */ {"te", HB_TAG('T','E','L',' ')}, /* Telugu */ {"tem", HB_TAG('T','M','N',' ')}, /* Temne */ @@ -665,20 +752,24 @@ static const LangTag ot_languages[] = { {"tiv", HB_TAG('T','I','V',' ')}, /* Tiv */ {"tk", HB_TAG('T','K','M',' ')}, /* Turkmen */ {"tl", HB_TAG('T','G','L',' ')}, /* Tagalog */ - {"tmh", HB_TAG('t','m','h',' ')}, /* Tamashek [macrolanguage] */ + {"tmh", HB_TAG('T','M','H',' ')}, /* Tamashek */ {"tn", HB_TAG('T','N','A',' ')}, /* Tswana */ {"to", HB_TAG('T','G','N',' ')}, /* Tonga (Tonga Islands) */ + {"tod", HB_TAG('T','O','D','0')}, /* Toma */ + {"toi", HB_TAG('T','N','G',' ')}, /* Tonga */ {"tpi", HB_TAG('T','P','I',' ')}, /* Tok Pisin */ {"tr", HB_TAG('T','R','K',' ')}, /* Turkish */ {"tru", HB_TAG('T','U','A',' ')}, /* Turoyo Aramaic */ {"ts", HB_TAG('T','S','G',' ')}, /* Tsonga */ {"tt", HB_TAG('T','A','T',' ')}, /* Tatar */ {"tum", HB_TAG('T','U','M',' ')}, /* Tumbuka */ + {"tvl", HB_TAG('T','V','L',' ')}, /* Tuvalu */ {"tw", HB_TAG('T','W','I',' ')}, /* Twi */ {"ty", HB_TAG('T','H','T',' ')}, /* Tahitian */ {"tyv", HB_TAG('T','U','V',' ')}, /* Tuvin */ {"tyz", HB_TAG('T','Y','Z',' ')}, /* Tày */ {"tzm", HB_TAG('T','Z','M',' ')}, /* Central Atlas Tamazight */ + {"tzo", HB_TAG('T','Z','O',' ')}, /* Tzotzil */ {"udm", HB_TAG('U','D','M',' ')}, /* Udmurt */ {"ug", HB_TAG('U','Y','G',' ')}, /* Uighur */ {"uk", HB_TAG('U','K','R',' ')}, /* Ukrainian */ @@ -690,8 +781,8 @@ static const LangTag ot_languages[] = { {"uzs", HB_TAG('U','Z','B',' ')}, /* Southern Uzbek */ {"ve", HB_TAG('V','E','N',' ')}, /* Venda */ {"vec", HB_TAG('V','E','C',' ')}, /* Venetian */ - {"vls", HB_TAG('F','L','E',' ')}, /* Vlaams */ {"vi", HB_TAG('V','I','T',' ')}, /* Vietnamese */ + {"vls", HB_TAG('F','L','E',' ')}, /* Vlaams */ {"vmw", HB_TAG('M','A','K',' ')}, /* Makhuwa */ {"vo", HB_TAG('V','O','L',' ')}, /* Volapük */ {"vro", HB_TAG('V','R','O',' ')}, /* Võro */ @@ -700,85 +791,78 @@ static const LangTag ot_languages[] = { {"wbm", HB_TAG('W','A',' ',' ')}, /* Wa */ {"wbr", HB_TAG('W','A','G',' ')}, /* Wagdi */ {"wle", HB_TAG('S','I','G',' ')}, /* Wolane */ + {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */ {"wry", HB_TAG('M','A','W',' ')}, /* Merwari */ {"wtm", HB_TAG('W','T','M',' ')}, /* Mewati */ - {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */ {"xal", HB_TAG('K','L','M',' ')}, /* Kalmyk */ + {"xan", HB_TAG('S','E','K',' ')}, /* Sekota */ {"xh", HB_TAG('X','H','S',' ')}, /* Xhosa */ + {"xjb", HB_TAG('X','J','B',' ')}, /* Minjangbal */ {"xog", HB_TAG('X','O','G',' ')}, /* Soga */ {"xom", HB_TAG('K','M','O',' ')}, /* Komo (Sudan) */ + {"xpe", HB_TAG('X','P','E',' ')}, /* Kpelle (Liberia) */ {"xsl", HB_TAG('S','S','L',' ')}, /* South Slavey */ {"xst", HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) */ {"xwo", HB_TAG('T','O','D',' ')}, /* Written Oirat (Todo) */ {"yao", HB_TAG('Y','A','O',' ')}, /* Yao */ + {"yap", HB_TAG('Y','A','P',' ')}, /* Yapese */ {"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */ {"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */ + {"yos", HB_TAG('Q','I','N',' ')}, /* Yos, deprecated by IANA in favor of Zou [zom] */ {"yso", HB_TAG('N','I','S',' ')}, /* Nisi (China) */ {"za", HB_TAG('Z','H','A',' ')}, /* Chuang/Zhuang [macrolanguage] */ {"zea", HB_TAG('Z','E','A',' ')}, /* Zeeuws */ + {"zgh", HB_TAG('Z','G','H',' ')}, /* Standard Morrocan Tamazigh */ {"zne", HB_TAG('Z','N','D',' ')}, /* Zande */ + {"zom", HB_TAG('Q','I','N',' ')}, /* Zou */ {"zu", HB_TAG('Z','U','L',' ')}, /* Zulu */ - {"zum", HB_TAG('L','R','C',' ')} /* Kumzari */ + {"zum", HB_TAG('L','R','C',' ')}, /* Kumzari */ + {"zza", HB_TAG('Z','Z','A',' ')}, /* Zazaki */ /* The corresponding languages IDs for the following IDs are unclear, * overlap, or are architecturally weird. Needs more research. */ -/*{"ahg/awn/xan?", HB_TAG('A','G','W',' ')},*/ /* Agaw */ -/*{"gsw?/gsw-FR?", HB_TAG('A','L','S',' ')},*/ /* Alsatian */ +/*{"chp", HB_TAG('S','A','Y',' ')},*/ /* Sayisi */ +/*{"cwd", HB_TAG('T','C','R',' ')},*/ /* TH-Cree */ +/*{"emk", HB_TAG('E','M','K',' ')},*/ /* Eastern Maninkakan */ /*{"krc", HB_TAG('B','A','L',' ')},*/ /* Balkar */ /*{"??", HB_TAG('B','C','R',' ')},*/ /* Bible Cree */ /*{"zh?", HB_TAG('C','H','N',' ')},*/ /* Chinese (seen in Microsoft fonts) */ -/*{"acf/gcf?", HB_TAG('F','A','N',' ')},*/ /* French Antillean */ -/*{"enf?/yrk?", HB_TAG('F','N','E',' ')},*/ /* Forest Nenets */ -/*{"fuf?", HB_TAG('F','T','A',' ')},*/ /* Futa */ /*{"ar-Syrc?", HB_TAG('G','A','R',' ')},*/ /* Garshuni */ -/*{"cfm/rnl?", HB_TAG('H','A','L',' ')},*/ /* Halam */ -/*{"ga-Latg?/Latg?", HB_TAG('I','R','T',' ')},*/ /* Irish Traditional */ +/*{"hy?", HB_TAG('H','Y','E','0')},*/ /* Armenian East (ISO 639-3 hye according to Microsoft, but that’s equivalent to ISO 639-1 hy) */ +/*{"ga-Latg?/" HB_TAG('I','R','T',' ')},*/ /* Irish Traditional */ /*{"krc", HB_TAG('K','A','R',' ')},*/ /* Karachay */ -/*{"alw?/ktb?", HB_TAG('K','E','B',' ')},*/ /* Kebena */ -/*{"Geok", HB_TAG('K','G','E',' ')},*/ /* Khutsuri Georgian */ +/*{"ka-Geok?", HB_TAG('K','G','E',' ')},*/ /* Khutsuri Georgian */ /*{"kca", HB_TAG('K','H','K',' ')},*/ /* Khanty-Kazim */ /*{"kca", HB_TAG('K','H','S',' ')},*/ /* Khanty-Shurishkar */ /*{"kca", HB_TAG('K','H','V',' ')},*/ /* Khanty-Vakhi */ -/*{"guz?/kqs?/kss?", HB_TAG('K','I','S',' ')},*/ /* Kisii */ -/*{"kfa/kfi?/kpb?/xua?/xuj?", HB_TAG('K','O','D',' ')},*/ /* Kodagu */ -/*{"okm?/oko?", HB_TAG('K','O','H',' ')},*/ /* Korean Old Hangul */ -/*{"kon?/ktu?/...", HB_TAG('K','O','N',' ')},*/ /* Kikongo */ -/*{"kfx?", HB_TAG('K','U','L',' ')},*/ /* Kulvi */ -/*{"??", HB_TAG('L','A','H',' ')},*/ /* Lahuli */ -/*{"??", HB_TAG('L','C','R',' ')},*/ /* L-Cree */ +/*{"kqs, kss", HB_TAG('K','I','S',' ')},*/ /* Kisii */ +/*{"lua", HB_TAG('L','U','A',' ')},*/ /* Luba-Lulua */ +/*{"mlq", HB_TAG('M','L','N',' ')},*/ /* Malinke */ +/*{"nso", HB_TAG('N','S','O',' ')},*/ /* Sotho, Northern */ /*{"??", HB_TAG('M','A','L',' ')},*/ /* Malayalam Traditional */ -/*{"mnk?/mlq?/...", HB_TAG('M','L','N',' ')},*/ /* Malinke */ -/*{"??", HB_TAG('N','C','R',' ')},*/ /* N-Cree */ -/*{"??", HB_TAG('N','H','C',' ')},*/ /* Norway House Cree */ -/*{"jpa?/sam?", HB_TAG('P','A','A',' ')},*/ /* Palestinian Aramaic */ -/*{"polyton", HB_TAG('P','G','R',' ')},*/ /* Polytonic Greek */ -/*{"??", HB_TAG('Q','I','N',' ')},*/ /* Asho Chin */ -/*{"??", HB_TAG('R','C','R',' ')},*/ /* R-Cree */ -/*{"chp?", HB_TAG('S','A','Y',' ')},*/ /* Sayisi */ -/*{"xan?", HB_TAG('S','E','K',' ')},*/ /* Sekota */ -/*{"ngo?", HB_TAG('S','X','T',' ')},*/ /* Sutu */ -/*{"??", HB_TAG('T','C','R',' ')},*/ /* TH-Cree */ -/*{"tnz?/tog?/toi?", HB_TAG('T','N','G',' ')},*/ /* Tonga */ -/*{"enh?/yrk?", HB_TAG('T','N','E',' ')},*/ /* Tundra Nenets */ -/*{"??", HB_TAG('W','C','R',' ')},*/ /* West-Cree */ -/*{"cre?", HB_TAG('Y','C','R',' ')},*/ /* Y-Cree */ +/*{"csw", HB_TAG('N','C','R',' ')},*/ /* N-Cree */ +/*{"csw", HB_TAG('N','H','C',' ')},*/ /* Norway House Cree */ +/*{"el-polyton", HB_TAG('P','G','R',' ')},*/ /* Polytonic Greek */ +/*{"bgr, cnh, cnw, czt, sez, tcp, csy, ctd, flm, pck, tcz, zom, cmr, dao, hlt, cka, cnk, mrh, mwg, cbl, cnb, csh", HB_TAG('Q','I','N',' ')},*/ /* Chin */ /*{"??", HB_TAG('Y','I','C',' ')},*/ /* Yi Classic */ -/*{"ii?/Yiii?", HB_TAG('Y','I','M',' ')},*/ /* Yi Modern */ -/*{"??", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */ +/*{"zh-Latn-pinyin", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */ }; typedef struct { - char language[8]; + char language[11]; hb_tag_t tag; } LangTagLong; static const LangTagLong ot_languages_zh[] = { + /* Store longest-first, if one is a prefix of another. */ {"zh-cn", HB_TAG('Z','H','S',' ')}, /* Chinese (China) */ {"zh-hk", HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */ - {"zh-mo", HB_TAG('Z','H','T',' ')}, /* Chinese (Macao) */ + {"zh-mo", HB_TAG('Z','H','H',' ')}, /* Chinese (Macao) */ {"zh-sg", HB_TAG('Z','H','S',' ')}, /* Chinese (Singapore) */ {"zh-tw", HB_TAG('Z','H','T',' ')}, /* Chinese (Taiwan) */ {"zh-hans", HB_TAG('Z','H','S',' ')}, /* Chinese (Simplified) */ + {"zh-hant-hk",HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */ + {"zh-hant-mo",HB_TAG('Z','H','H',' ')}, /* Chinese (Macao) */ {"zh-hant", HB_TAG('Z','H','T',' ')}, /* Chinese (Traditional) */ }; @@ -832,13 +916,45 @@ hb_ot_tag_from_language (hb_language_t language) } /* - * The International Phonetic Alphabet is a variant tag in BCP-47, - * which can be applied to any language. + * "fonipa" is a variant tag in BCP-47, meaning the International Phonetic Alphabet. + * It can be applied to any language. */ if (strstr (lang_str, "-fonipa")) { return HB_TAG('I','P','P','H'); /* Phonetic transcription—IPA conventions */ } + /* + * "fonnapa" is a variant tag in BCP-47, meaning the North American Phonetic Alphabet + * also known as Americanist Phonetic Notation. It can be applied to any language. + */ + if (strstr (lang_str, "-fonnapa")) { + return HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */ + } + + /* + * "Syre" is a BCP-47 script tag, meaning the Estrangela variant of the Syriac script. + * It can be applied to any language. + */ + if (strstr (lang_str, "-syre")) { + return HB_TAG('S','Y','R','E'); /* Estrangela Syriac */ + } + + /* + * "Syrj" is a BCP-47 script tag, meaning the Western variant of the Syriac script. + * It can be applied to any language. + */ + if (strstr (lang_str, "-syrj")) { + return HB_TAG('S','Y','R','J'); /* Western Syriac */ + } + + /* + * "Syrn" is a BCP-47 script tag, meaning the Eastern variant of the Syriac script. + * It can be applied to any language. + */ + if (strstr (lang_str, "-syrn")) { + return HB_TAG('S','Y','R','N'); /* Eastern Syriac */ + } + /* Find a language matching in the first component */ { const LangTag *lang_tag; @@ -894,6 +1010,22 @@ hb_ot_tag_to_language (hb_tag_t tag) if (tag == HB_OT_TAG_DEFAULT_LANGUAGE) return NULL; + /* struct LangTag has only room for 3-letter language tags. */ + switch (tag) { + case HB_TAG('A','P','P','H'): /* Phonetic transcription—Americanist conventions */ + return hb_language_from_string ("und-fonnapa", -1); + case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */ + return hb_language_from_string ("und-fonipa", -1); + case HB_TAG('S','Y','R',' '): /* Syriac [macrolanguage] */ + return hb_language_from_string ("syr", -1); + case HB_TAG('S','Y','R','E'): /* Estrangela Syriac */ + return hb_language_from_string ("und-Syre", -1); + case HB_TAG('S','Y','R','J'): /* Western Syriac */ + return hb_language_from_string ("und-Syrj", -1); + case HB_TAG('S','Y','R','N'): /* Eastern Syriac */ + return hb_language_from_string ("und-Syrn", -1); + } + for (i = 0; i < ARRAY_LENGTH (ot_languages); i++) if (ot_languages[i].tag == tag) return hb_language_from_string (ot_languages[i].language, -1); @@ -908,12 +1040,6 @@ hb_ot_tag_to_language (hb_tag_t tag) } } - /* struct LangTag has only room for 3-letter language tags. */ - switch (tag) { - case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */ - return hb_language_from_string ("und-fonipa", -1); - } - /* Else return a custom language in the form of "x-hbotABCD" */ { unsigned char buf[11] = "x-hbot"; @@ -928,4 +1054,27 @@ hb_ot_tag_to_language (hb_tag_t tag) } } +#ifdef MAIN +static inline void +test_langs_sorted (void) +{ + for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++) + { + int c = lang_compare_first_component (ot_languages[i-1].language, ot_languages[i].language); + if (c >= 0) + { + fprintf (stderr, "ot_languages not sorted at index %d: %s %d %s\n", + i, ot_languages[i-1].language, c, ot_languages[i].language); + abort(); + } + } +} +int +main (void) +{ + test_langs_sorted (); + return 0; +} + +#endif diff --git a/gfx/harfbuzz/src/hb-ot-tag.h b/gfx/harfbuzz/src/hb-ot-tag.h index 1bf12ab3c..54fb747f5 100644 --- a/gfx/harfbuzz/src/hb-ot-tag.h +++ b/gfx/harfbuzz/src/hb-ot-tag.h @@ -39,18 +39,18 @@ HB_BEGIN_DECLS #define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T') #define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't') -void +HB_EXTERN void hb_ot_tags_from_script (hb_script_t script, hb_tag_t *script_tag_1, hb_tag_t *script_tag_2); -hb_script_t +HB_EXTERN hb_script_t hb_ot_tag_to_script (hb_tag_t tag); -hb_tag_t +HB_EXTERN hb_tag_t hb_ot_tag_from_language (hb_language_t language); -hb_language_t +HB_EXTERN hb_language_t hb_ot_tag_to_language (hb_tag_t tag); diff --git a/gfx/harfbuzz/src/hb-ot-var-avar-table.hh b/gfx/harfbuzz/src/hb-ot-var-avar-table.hh new file mode 100644 index 000000000..464cf35bb --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-var-avar-table.hh @@ -0,0 +1,149 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_VAR_AVAR_TABLE_HH +#define HB_OT_VAR_AVAR_TABLE_HH + +#include "hb-open-type-private.hh" + +namespace OT { + + +struct AxisValueMap +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + F2DOT14 fromCoord; /* A normalized coordinate value obtained using + * default normalization. */ + F2DOT14 toCoord; /* The modified, normalized coordinate value. */ + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct SegmentMaps : ArrayOf +{ + inline int map (int value) const + { + /* The following special-cases are not part of OpenType, which requires + * that at least -1, 0, and +1 must be mapped. But we include these as + * part of a better error recovery scheme. */ + + if (len < 2) + { + if (!len) + return value; + else /* len == 1*/ + return value - array[0].fromCoord + array[0].toCoord; + } + + if (value <= array[0].fromCoord) + return value - array[0].fromCoord + array[0].toCoord; + + unsigned int i; + unsigned int count = len; + for (i = 1; i < count && value > array[i].fromCoord; i++) + ; + + if (value >= array[i].fromCoord) + return value - array[i].fromCoord + array[i].toCoord; + + if (unlikely (array[i-1].fromCoord == array[i].fromCoord)) + return array[i-1].toCoord; + + int denom = array[i].fromCoord - array[i-1].fromCoord; + return array[i-1].toCoord + + ((array[i].toCoord - array[i-1].toCoord) * + (value - array[i-1].fromCoord) + denom/2) / denom; + } + + DEFINE_SIZE_ARRAY (2, array); +}; + +/* + * avar — Axis Variations Table + */ + +#define HB_OT_TAG_avar HB_TAG('a','v','a','r') + +struct avar +{ + static const hb_tag_t tableTag = HB_OT_TAG_avar; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!(version.sanitize (c) && + version.major == 1 && + c->check_struct (this)))) + return_trace (false); + + const SegmentMaps *map = &axisSegmentMapsZ; + unsigned int count = axisCount; + for (unsigned int i = 0; i < count; i++) + { + if (unlikely (!map->sanitize (c))) + return_trace (false); + map = &StructAfter (*map); + } + + return_trace (true); + } + + inline void map_coords (int *coords, unsigned int coords_length) const + { + unsigned int count = MIN (coords_length, axisCount); + + const SegmentMaps *map = &axisSegmentMapsZ; + for (unsigned int i = 0; i < count; i++) + { + coords[i] = map->map (coords[i]); + map = &StructAfter (*map); + } + } + + protected: + FixedVersion<>version; /* Version of the avar table + * initially set to 0x00010000u */ + USHORT reserved; /* This field is permanently reserved. Set to 0. */ + USHORT axisCount; /* The number of variation axes in the font. This + * must be the same number as axisCount in the + * 'fvar' table. */ + SegmentMaps axisSegmentMapsZ; + + public: + DEFINE_SIZE_MIN (8); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_AVAR_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-var-fvar-table.hh b/gfx/harfbuzz/src/hb-ot-var-fvar-table.hh new file mode 100644 index 000000000..9f6fb3250 --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-var-fvar-table.hh @@ -0,0 +1,209 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_VAR_FVAR_TABLE_HH +#define HB_OT_VAR_FVAR_TABLE_HH + +#include "hb-open-type-private.hh" + +namespace OT { + + +struct InstanceRecord +{ + inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (coordinates, coordinates[0].static_size, axis_count)); + } + + protected: + USHORT subfamilyNameID;/* The name ID for entries in the 'name' table + * that provide subfamily names for this instance. */ + USHORT reserved; /* Reserved for future use — set to 0. */ + Fixed coordinates[VAR];/* The coordinates array for this instance. */ + //USHORT postScriptNameIDX;/*Optional. The name ID for entries in the 'name' + // * table that provide PostScript names for this + // * instance. */ + + public: + DEFINE_SIZE_ARRAY (4, coordinates); +}; + +struct AxisRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + Tag axisTag; /* Tag identifying the design variation for the axis. */ + Fixed minValue; /* The minimum coordinate value for the axis. */ + Fixed defaultValue; /* The default coordinate value for the axis. */ + Fixed maxValue; /* The maximum coordinate value for the axis. */ + USHORT reserved; /* Reserved for future use — set to 0. */ + USHORT axisNameID; /* The name ID for entries in the 'name' table that + * provide a display name for this axis. */ + + public: + DEFINE_SIZE_STATIC (20); +}; + + +/* + * fvar — Font Variations Table + */ + +#define HB_OT_TAG_fvar HB_TAG('f','v','a','r') + +struct fvar +{ + static const hb_tag_t tableTag = HB_OT_TAG_fvar; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + c->check_struct (this) && + instanceSize >= axisCount * 4 + 4 && + axisSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */ + instanceSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */ + c->check_range (this, things) && + c->check_range (&StructAtOffset (this, things), + axisCount * axisSize + instanceCount * instanceSize)); + } + + inline unsigned int get_axis_count (void) const + { return axisCount; } + + inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const + { + if (unlikely (index >= axisCount)) + return false; + + if (info) + { + const AxisRecord &axis = get_axes ()[index]; + info->tag = axis.axisTag; + info->name_id = axis.axisNameID; + info->default_value = axis.defaultValue / 65536.; + /* Ensure order, to simplify client math. */ + info->min_value = MIN (info->default_value, axis.minValue / 65536.); + info->max_value = MAX (info->default_value, axis.maxValue / 65536.); + } + + return true; + } + + inline unsigned int get_axis_infos (unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_t *axes_array /* OUT */) const + { + if (axes_count) + { + unsigned int count = axisCount; + start_offset = MIN (start_offset, count); + + count -= start_offset; + axes_array += start_offset; + + count = MIN (count, *axes_count); + *axes_count = count; + + for (unsigned int i = 0; i < count; i++) + get_axis (start_offset + i, axes_array + i); + } + return axisCount; + } + + inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const + { + const AxisRecord *axes = get_axes (); + unsigned int count = get_axis_count (); + for (unsigned int i = 0; i < count; i++) + if (axes[i].axisTag == tag) + { + if (index) + *index = i; + return get_axis (i, info); + } + if (index) + *index = HB_OT_VAR_NO_AXIS_INDEX; + return false; + } + + inline int normalize_axis_value (unsigned int axis_index, float v) const + { + hb_ot_var_axis_t axis; + if (!get_axis (axis_index, &axis)) + return 0; + + v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */ + + if (v == axis.default_value) + return 0; + else if (v < axis.default_value) + v = (v - axis.default_value) / (axis.default_value - axis.min_value); + else + v = (v - axis.default_value) / (axis.max_value - axis.default_value); + return (int) (v * 16384. + (v >= 0. ? .5 : -.5)); + } + + protected: + inline const AxisRecord * get_axes (void) const + { return &StructAtOffset (this, things); } + + inline const InstanceRecord * get_instances (void) const + { return &StructAtOffset (get_axes () + axisCount, 0); } + + protected: + FixedVersion<>version; /* Version of the fvar table + * initially set to 0x00010000u */ + Offset<> things; /* Offset in bytes from the beginning of the table + * to the start of the AxisRecord array. */ + USHORT reserved; /* This field is permanently reserved. Set to 2. */ + USHORT axisCount; /* The number of variation axes in the font (the + * number of records in the axes array). */ + USHORT axisSize; /* The size in bytes of each VariationAxisRecord — + * set to 20 (0x0014) for this version. */ + USHORT instanceCount; /* The number of named instances defined in the font + * (the number of records in the instances array). */ + USHORT instanceSize; /* The size in bytes of each InstanceRecord — set + * to either axisCount * sizeof(Fixed) + 4, or to + * axisCount * sizeof(Fixed) + 6. */ + + public: + DEFINE_SIZE_STATIC (16); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_FVAR_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-var-hvar-table.hh b/gfx/harfbuzz/src/hb-ot-var-hvar-table.hh new file mode 100644 index 000000000..f9d801e3b --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-var-hvar-table.hh @@ -0,0 +1,165 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_VAR_HVAR_TABLE_HH +#define HB_OT_VAR_HVAR_TABLE_HH + +#include "hb-ot-layout-common-private.hh" + + +namespace OT { + + +struct DeltaSetIndexMap +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (mapData, get_width (), mapCount)); + } + + unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */ + { + /* If count is zero, pass value unchanged. This takes + * care of direct mapping for advance map. */ + if (!mapCount) + return v; + + if (v >= mapCount) + v = mapCount - 1; + + unsigned int u = 0; + { /* Fetch it. */ + unsigned int w = get_width (); + const BYTE *p = mapData + w * v; + for (; w; w--) + u = (u << 8) + *p++; + } + + { /* Repack it. */ + unsigned int n = get_inner_bitcount (); + unsigned int outer = u >> n; + unsigned int inner = u & ((1 << n) - 1); + u = (outer<<16) | inner; + } + + return u; + } + + protected: + inline unsigned int get_width (void) const + { return ((format >> 4) & 3) + 1; } + + inline unsigned int get_inner_bitcount (void) const + { return (format & 0xF) + 1; } + + protected: + USHORT format; /* A packed field that describes the compressed + * representation of delta-set indices. */ + USHORT mapCount; /* The number of mapping entries. */ + BYTE mapData[VAR]; /* The delta-set index mapping data. */ + + public: + DEFINE_SIZE_ARRAY (4, mapData); +}; + + +/* + * HVAR -- The Horizontal Metrics Variations Table + * VVAR -- The Vertical Metrics Variations Table + */ + +#define HB_OT_TAG_HVAR HB_TAG('H','V','A','R') +#define HB_OT_TAG_VVAR HB_TAG('V','V','A','R') + +struct HVARVVAR +{ + static const hb_tag_t HVARTag = HB_OT_TAG_HVAR; + static const hb_tag_t VVARTag = HB_OT_TAG_VVAR; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + varStore.sanitize (c, this) && + advMap.sanitize (c, this) && + lsbMap.sanitize (c, this) && + rsbMap.sanitize (c, this)); + } + + inline float get_advance_var (hb_codepoint_t glyph, + int *coords, unsigned int coord_count) const + { + unsigned int varidx = (this+advMap).map (glyph); + return (this+varStore).get_delta (varidx, coords, coord_count); + } + + inline bool has_sidebearing_deltas (void) const + { return lsbMap && rsbMap; } + + protected: + FixedVersion<>version; /* Version of the metrics variation table + * initially set to 0x00010000u */ + LOffsetTo + varStore; /* Offset to item variation store table. */ + LOffsetTo + advMap; /* Offset to advance var-idx mapping. */ + LOffsetTo + lsbMap; /* Offset to lsb/tsb var-idx mapping. */ + LOffsetTo + rsbMap; /* Offset to rsb/bsb var-idx mapping. */ + + public: + DEFINE_SIZE_STATIC (20); +}; + +struct HVAR : HVARVVAR { + static const hb_tag_t tableTag = HB_OT_TAG_HVAR; +}; +struct VVAR : HVARVVAR { + static const hb_tag_t tableTag = HB_OT_TAG_VVAR; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (static_cast (this)->sanitize (c) && + vorgMap.sanitize (c, this)); + } + + protected: + LOffsetTo + vorgMap; /* Offset to vertical-origin var-idx mapping. */ + + public: + DEFINE_SIZE_STATIC (24); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_HVAR_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh b/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh new file mode 100644 index 000000000..3cb749847 --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh @@ -0,0 +1,110 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_VAR_MVAR_TABLE_HH +#define HB_OT_VAR_MVAR_TABLE_HH + +#include "hb-ot-layout-common-private.hh" + + +namespace OT { + + +struct VariationValueRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + Tag valueTag; /* Four-byte tag identifying a font-wide measure. */ + ULONG varIdx; /* Outer/inner index into VariationStore item. */ + + public: + DEFINE_SIZE_STATIC (8); +}; + + +/* + * MVAR -- Metrics Variations Table + */ + +#define HB_OT_TAG_MVAR HB_TAG('M','V','A','R') + +struct MVAR +{ + static const hb_tag_t tableTag = HB_OT_TAG_MVAR; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + c->check_struct (this) && + valueRecordSize >= VariationValueRecord::static_size && + varStore.sanitize (c, this) && + c->check_array (values, valueRecordSize, valueRecordCount)); + } + + inline float get_var (hb_tag_t tag, + int *coords, unsigned int coord_count) const + { + const VariationValueRecord *record; + record = (VariationValueRecord *) bsearch (&tag, values, + valueRecordCount, valueRecordSize, + (hb_compare_func_t) tag_compare); + if (!record) + return 0.; + + return (this+varStore).get_delta (record->varIdx, coords, coord_count); + } + +protected: + static inline int tag_compare (const hb_tag_t *a, const Tag *b) + { return b->cmp (*a); } + + protected: + FixedVersion<>version; /* Version of the metrics variation table + * initially set to 0x00010000u */ + USHORT reserved; /* Not used; set to 0. */ + USHORT valueRecordSize;/* The size in bytes of each value record — + * must be greater than zero. */ + USHORT valueRecordCount;/* The number of value records — may be zero. */ + OffsetTo + varStore; /* Offset to item variation store table. */ + BYTE values[VAR]; /* Array of value records. The records must be + * in binary order of their valueTag field. */ + + public: + DEFINE_SIZE_ARRAY (12, values); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_MVAR_TABLE_HH */ diff --git a/gfx/harfbuzz/src/hb-ot-var.cc b/gfx/harfbuzz/src/hb-ot-var.cc new file mode 100644 index 000000000..691196d9b --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-var.cc @@ -0,0 +1,159 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-open-type-private.hh" + +#include "hb-ot-layout-private.hh" +#include "hb-ot-var-avar-table.hh" +#include "hb-ot-var-fvar-table.hh" +#include "hb-ot-var-mvar-table.hh" +#include "hb-ot-var.h" + +/* + * fvar/avar + */ + +static inline const OT::fvar& +_get_fvar (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::fvar); + hb_ot_layout_t * layout = hb_ot_layout_from_face (face); + return *(layout->fvar.get ()); +} +static inline const OT::avar& +_get_avar (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::avar); + hb_ot_layout_t * layout = hb_ot_layout_from_face (face); + return *(layout->avar.get ()); +} + +/** + * hb_ot_var_has_data: + * @face: #hb_face_t to test + * + * This function allows to verify the presence of OpenType variation data on the face. + * Alternatively, use hb_ot_var_get_axis_count(). + * + * Return value: true if face has a `fvar' table and false otherwise + * + * Since: 1.4.2 + **/ +hb_bool_t +hb_ot_var_has_data (hb_face_t *face) +{ + return &_get_fvar (face) != &OT::Null(OT::fvar); +} + +/** + * hb_ot_var_get_axis_count: + * + * Since: 1.4.2 + **/ +unsigned int +hb_ot_var_get_axis_count (hb_face_t *face) +{ + const OT::fvar &fvar = _get_fvar (face); + return fvar.get_axis_count (); +} + +/** + * hb_ot_var_get_axes: + * + * Since: 1.4.2 + **/ +unsigned int +hb_ot_var_get_axes (hb_face_t *face, + unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_t *axes_array /* OUT */) +{ + const OT::fvar &fvar = _get_fvar (face); + return fvar.get_axis_infos (start_offset, axes_count, axes_array); +} + +/** + * hb_ot_var_find_axis: + * + * Since: 1.4.2 + **/ +hb_bool_t +hb_ot_var_find_axis (hb_face_t *face, + hb_tag_t axis_tag, + unsigned int *axis_index, + hb_ot_var_axis_t *axis_info) +{ + const OT::fvar &fvar = _get_fvar (face); + return fvar.find_axis (axis_tag, axis_index, axis_info); +} + + +/** + * hb_ot_var_normalize_variations: + * + * Since: 1.4.2 + **/ +void +hb_ot_var_normalize_variations (hb_face_t *face, + const hb_variation_t *variations, /* IN */ + unsigned int variations_length, + int *coords, /* OUT */ + unsigned int coords_length) +{ + for (unsigned int i = 0; i < coords_length; i++) + coords[i] = 0; + + const OT::fvar &fvar = _get_fvar (face); + for (unsigned int i = 0; i < variations_length; i++) + { + unsigned int axis_index; + if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, NULL) && + axis_index < coords_length) + coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value); + } + + const OT::avar &avar = _get_avar (face); + avar.map_coords (coords, coords_length); +} + +/** + * hb_ot_var_normalize_coords: + * + * Since: 1.4.2 + **/ +void +hb_ot_var_normalize_coords (hb_face_t *face, + unsigned int coords_length, + const float *design_coords, /* IN */ + int *normalized_coords /* OUT */) +{ + const OT::fvar &fvar = _get_fvar (face); + for (unsigned int i = 0; i < coords_length; i++) + normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]); + + const OT::avar &avar = _get_avar (face); + avar.map_coords (normalized_coords, coords_length); +} diff --git a/gfx/harfbuzz/src/hb-ot-var.h b/gfx/harfbuzz/src/hb-ot-var.h new file mode 100644 index 000000000..a2c0c5f2b --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-var.h @@ -0,0 +1,105 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_H_IN +#error "Include instead." +#endif + +#ifndef HB_OT_VAR_H +#define HB_OT_VAR_H + +#include "hb.h" + +HB_BEGIN_DECLS + + +#define HB_OT_TAG_VAR_AXIS_ITALIC HB_TAG('i','t','a','l') +#define HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE HB_TAG('o','p','s','z') +#define HB_OT_TAG_VAR_AXIS_SLANT HB_TAG('s','l','n','t') +#define HB_OT_TAG_VAR_AXIS_WIDTH HB_TAG('w','d','t','h') +#define HB_OT_TAG_VAR_AXIS_WEIGHT HB_TAG('w','g','h','t') + + +/* + * fvar / avar + */ + +/** + * hb_ot_var_axis_t: + * + * Since: 1.4.2 + */ +typedef struct hb_ot_var_axis_t { + hb_tag_t tag; + unsigned int name_id; + float min_value; + float default_value; + float max_value; +} hb_ot_var_axis_t; + +HB_EXTERN hb_bool_t +hb_ot_var_has_data (hb_face_t *face); + +/** + * HB_OT_VAR_NO_AXIS_INDEX: + * + * Since: 1.4.2 + */ +#define HB_OT_VAR_NO_AXIS_INDEX 0xFFFFFFFFu + +HB_EXTERN unsigned int +hb_ot_var_get_axis_count (hb_face_t *face); + +HB_EXTERN unsigned int +hb_ot_var_get_axes (hb_face_t *face, + unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_t *axes_array /* OUT */); + +HB_EXTERN hb_bool_t +hb_ot_var_find_axis (hb_face_t *face, + hb_tag_t axis_tag, + unsigned int *axis_index, + hb_ot_var_axis_t *axis_info); + + +HB_EXTERN void +hb_ot_var_normalize_variations (hb_face_t *face, + const hb_variation_t *variations, /* IN */ + unsigned int variations_length, + int *coords, /* OUT */ + unsigned int coords_length); + +HB_EXTERN void +hb_ot_var_normalize_coords (hb_face_t *face, + unsigned int coords_length, + const float *design_coords, /* IN */ + int *normalized_coords /* OUT */); + + +HB_END_DECLS + +#endif /* HB_OT_VAR_H */ diff --git a/gfx/harfbuzz/src/hb-ot.h b/gfx/harfbuzz/src/hb-ot.h index 47c92a58e..2120a3efa 100644 --- a/gfx/harfbuzz/src/hb-ot.h +++ b/gfx/harfbuzz/src/hb-ot.h @@ -32,8 +32,10 @@ #include "hb-ot-font.h" #include "hb-ot-layout.h" +#include "hb-ot-math.h" #include "hb-ot-tag.h" #include "hb-ot-shape.h" +#include "hb-ot-var.h" HB_BEGIN_DECLS diff --git a/gfx/harfbuzz/src/hb-private.hh b/gfx/harfbuzz/src/hb-private.hh index 36fce0bd4..b5dccc556 100644 --- a/gfx/harfbuzz/src/hb-private.hh +++ b/gfx/harfbuzz/src/hb-private.hh @@ -53,9 +53,6 @@ #include #include -#ifdef _MSC_VER -#include /* ensure DEFINE_ENUM_FLAG_OPERATORS is defined */ -#endif /* Compile-time custom allocator support. */ @@ -77,16 +74,15 @@ extern "C" void hb_free_impl(void *ptr); /* Compiler attributes */ -#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) -#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0) -#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1)) -#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0)) +#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__) +#define likely(expr) (__builtin_expect (!!(expr), 1)) +#define unlikely(expr) (__builtin_expect (!!(expr), 0)) #else #define likely(expr) (expr) #define unlikely(expr) (expr) #endif -#ifndef __GNUC__ +#if !defined(__GNUC__) && !defined(__clang__) #undef __attribute__ #define __attribute__(x) #endif @@ -171,7 +167,7 @@ extern "C" void hb_free_impl(void *ptr); # if defined(_WIN32_WCE) /* Some things not defined on Windows CE. */ -# define strdup _strdup +# define vsnprintf _vsnprintf # define getenv(Name) NULL # if _WIN32_WCE < 0x800 # define setlocale(Category, Locale) "C" @@ -611,6 +607,15 @@ static inline unsigned char TOLOWER (unsigned char c) /* Debug */ +/* HB_NDEBUG disables some sanity checks that are very safe to disable and + * should be disabled in production systems. If NDEBUG is defined, enable + * HB_NDEBUG; but if it's desirable that normal assert()s (which are very + * light-weight) to be enabled, then HB_DEBUG can be defined to disable + * the costlier checks. */ +#ifdef NDEBUG +#define HB_NDEBUG +#endif + #ifndef HB_DEBUG #define HB_DEBUG 0 #endif @@ -679,17 +684,20 @@ _hb_debug_msg_va (const char *what, fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), ""); if (indented) { -/* One may want to add ASCII version of these. See: - * https://bugs.freedesktop.org/show_bug.cgi?id=50970 */ #define VBAR "\342\224\202" /* U+2502 BOX DRAWINGS LIGHT VERTICAL */ #define VRBAR "\342\224\234" /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ #define DLBAR "\342\225\256" /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */ #define ULBAR "\342\225\257" /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */ #define LBAR "\342\225\264" /* U+2574 BOX DRAWINGS LIGHT LEFT */ - static const char bars[] = VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR; + static const char bars[] = + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR; fprintf (stderr, "%2u %s" VRBAR "%s", level, - bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), (unsigned int) (sizeof (VBAR) - 1) * level), + bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level), level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR); } else fprintf (stderr, " " VRBAR LBAR); @@ -899,27 +907,22 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) * one enum to another... So this doesn't provide the type-checking that I * originally had in mind... :(. * - * On MSVC use DEFINE_ENUM_FLAG_OPERATORS. See: - * https://github.com/behdad/harfbuzz/pull/163 + * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163 */ #ifdef _MSC_VER # pragma warning(disable:4200) # pragma warning(disable:4800) -# define HB_MARK_AS_FLAG_T(flags_t) DEFINE_ENUM_FLAG_OPERATORS (##flags_t##); -#else -# define HB_MARK_AS_FLAG_T(flags_t) template <> class hb_mark_as_flags_t {}; -template class hb_mark_as_flags_t; -template static inline T operator | (T l, T r) -{ hb_mark_as_flags_t unused HB_UNUSED; return T ((unsigned int) l | (unsigned int) r); } -template static inline T operator & (T l, T r) -{ hb_mark_as_flags_t unused HB_UNUSED; return T ((unsigned int) l & (unsigned int) r); } -template static inline T operator ~ (T r) -{ hb_mark_as_flags_t unused HB_UNUSED; return T (~(unsigned int) r); } -template static inline T& operator |= (T &l, T r) -{ hb_mark_as_flags_t unused HB_UNUSED; l = l | r; return l; } -template static inline T& operator &= (T& l, T r) -{ hb_mark_as_flags_t unused HB_UNUSED; l = l & r; return l; } #endif +#define HB_MARK_AS_FLAG_T(T) \ + extern "C++" { \ + static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \ + static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \ + static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \ + static inline T operator ~ (T r) { return T (~(unsigned int) r); } \ + static inline T& operator |= (T &l, T r) { l = l | r; return l; } \ + static inline T& operator &= (T& l, T r) { l = l & r; return l; } \ + static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \ + } /* Useful for set-operations on small enums. diff --git a/gfx/harfbuzz/src/hb-set-private.hh b/gfx/harfbuzz/src/hb-set-private.hh index 3c302b1da..e2010d762 100644 --- a/gfx/harfbuzz/src/hb-set-private.hh +++ b/gfx/harfbuzz/src/hb-set-private.hh @@ -313,7 +313,7 @@ struct hb_set_t for (unsigned int i = 0; i < ELTS; i++) if (elts[i]) for (unsigned int j = 0; j < BITS; j++) - if (elts[i] & (1 << j)) + if (elts[i] & (1u << j)) return i * BITS + j; return INVALID; } @@ -322,7 +322,7 @@ struct hb_set_t for (unsigned int i = ELTS; i; i--) if (elts[i - 1]) for (unsigned int j = BITS; j; j--) - if (elts[i - 1] & (1 << (j - 1))) + if (elts[i - 1] & (1u << (j - 1))) return (i - 1) * BITS + (j - 1); return INVALID; } diff --git a/gfx/harfbuzz/src/hb-set.cc b/gfx/harfbuzz/src/hb-set.cc index cb7fcdbf6..f3fe1ba43 100644 --- a/gfx/harfbuzz/src/hb-set.cc +++ b/gfx/harfbuzz/src/hb-set.cc @@ -105,7 +105,7 @@ hb_set_destroy (hb_set_t *set) * @set: a set. * @key: * @data: - * @destroy (closure data): + * @destroy: * @replace: * * Return value: diff --git a/gfx/harfbuzz/src/hb-set.h b/gfx/harfbuzz/src/hb-set.h index 29bf6556a..2164c1a65 100644 --- a/gfx/harfbuzz/src/hb-set.h +++ b/gfx/harfbuzz/src/hb-set.h @@ -44,109 +44,109 @@ HB_BEGIN_DECLS typedef struct hb_set_t hb_set_t; -hb_set_t * +HB_EXTERN hb_set_t * hb_set_create (void); -hb_set_t * +HB_EXTERN hb_set_t * hb_set_get_empty (void); -hb_set_t * +HB_EXTERN hb_set_t * hb_set_reference (hb_set_t *set); -void +HB_EXTERN void hb_set_destroy (hb_set_t *set); -hb_bool_t +HB_EXTERN hb_bool_t hb_set_set_user_data (hb_set_t *set, hb_user_data_key_t *key, void * data, hb_destroy_func_t destroy, hb_bool_t replace); -void * +HB_EXTERN void * hb_set_get_user_data (hb_set_t *set, hb_user_data_key_t *key); /* Returns false if allocation has failed before */ -hb_bool_t +HB_EXTERN hb_bool_t hb_set_allocation_successful (const hb_set_t *set); -void +HB_EXTERN void hb_set_clear (hb_set_t *set); -hb_bool_t +HB_EXTERN hb_bool_t hb_set_is_empty (const hb_set_t *set); -hb_bool_t +HB_EXTERN hb_bool_t hb_set_has (const hb_set_t *set, hb_codepoint_t codepoint); /* Right now limited to 16-bit integers. Eventually will do full codepoint range, sans -1 * which we will use as a sentinel. */ -void +HB_EXTERN void hb_set_add (hb_set_t *set, hb_codepoint_t codepoint); -void +HB_EXTERN void hb_set_add_range (hb_set_t *set, hb_codepoint_t first, hb_codepoint_t last); -void +HB_EXTERN void hb_set_del (hb_set_t *set, hb_codepoint_t codepoint); -void +HB_EXTERN void hb_set_del_range (hb_set_t *set, hb_codepoint_t first, hb_codepoint_t last); -hb_bool_t +HB_EXTERN hb_bool_t hb_set_is_equal (const hb_set_t *set, const hb_set_t *other); -void +HB_EXTERN void hb_set_set (hb_set_t *set, const hb_set_t *other); -void +HB_EXTERN void hb_set_union (hb_set_t *set, const hb_set_t *other); -void +HB_EXTERN void hb_set_intersect (hb_set_t *set, const hb_set_t *other); -void +HB_EXTERN void hb_set_subtract (hb_set_t *set, const hb_set_t *other); -void +HB_EXTERN void hb_set_symmetric_difference (hb_set_t *set, const hb_set_t *other); -void +HB_EXTERN void hb_set_invert (hb_set_t *set); -unsigned int +HB_EXTERN unsigned int hb_set_get_population (const hb_set_t *set); /* Returns -1 if set empty. */ -hb_codepoint_t +HB_EXTERN hb_codepoint_t hb_set_get_min (const hb_set_t *set); /* Returns -1 if set empty. */ -hb_codepoint_t +HB_EXTERN hb_codepoint_t hb_set_get_max (const hb_set_t *set); /* Pass -1 in to get started. */ -hb_bool_t +HB_EXTERN hb_bool_t hb_set_next (const hb_set_t *set, hb_codepoint_t *codepoint); /* Pass -1 for first and last to get started. */ -hb_bool_t +HB_EXTERN hb_bool_t hb_set_next_range (const hb_set_t *set, hb_codepoint_t *first, hb_codepoint_t *last); diff --git a/gfx/harfbuzz/src/hb-shape-plan-private.hh b/gfx/harfbuzz/src/hb-shape-plan-private.hh index 607da5e77..aa0413a27 100644 --- a/gfx/harfbuzz/src/hb-shape-plan-private.hh +++ b/gfx/harfbuzz/src/hb-shape-plan-private.hh @@ -47,12 +47,17 @@ struct hb_shape_plan_t hb_feature_t *user_features; unsigned int num_user_features; + int *coords; + unsigned int num_coords; + struct hb_shaper_data_t shaper_data; }; #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \ - , const hb_feature_t *user_features \ - , unsigned int num_user_features + , const hb_feature_t *user_features \ + , unsigned int num_user_features \ + , const int *coords \ + , unsigned int num_coords #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, shape_plan); #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT diff --git a/gfx/harfbuzz/src/hb-shape-plan.cc b/gfx/harfbuzz/src/hb-shape-plan.cc index 56e2ea5c1..3abf555c5 100644 --- a/gfx/harfbuzz/src/hb-shape-plan.cc +++ b/gfx/harfbuzz/src/hb-shape-plan.cc @@ -35,22 +35,18 @@ #endif -#define HB_SHAPER_IMPLEMENT(shaper) \ - HB_SHAPER_DATA_ENSURE_DECLARE(shaper, face) \ - HB_SHAPER_DATA_ENSURE_DECLARE(shaper, font) -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - - static void hb_shape_plan_plan (hb_shape_plan_t *shape_plan, const hb_feature_t *user_features, unsigned int num_user_features, + const int *coords, + unsigned int num_coords, const char * const *shaper_list) { DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, - "num_features=%d shaper_list=%p", + "num_features=%d num_coords=%d shaper_list=%p", num_user_features, + num_coords, shaper_list); const hb_shaper_pair_t *shapers = _hb_shapers_get (); @@ -59,7 +55,9 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan, HB_STMT_START { \ if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \ HB_SHAPER_DATA (shaper, shape_plan) = \ - HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, user_features, num_user_features); \ + HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \ + user_features, num_user_features, \ + coords, num_coords); \ shape_plan->shaper_func = _hb_##shaper##_shape; \ shape_plan->shaper_name = #shaper; \ return; \ @@ -114,15 +112,32 @@ hb_shape_plan_create (hb_face_t *face, const hb_feature_t *user_features, unsigned int num_user_features, const char * const *shaper_list) +{ + return hb_shape_plan_create2 (face, props, + user_features, num_user_features, + NULL, 0, + shaper_list); +} + +hb_shape_plan_t * +hb_shape_plan_create2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *orig_coords, + unsigned int num_coords, + const char * const *shaper_list) { DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, - "face=%p num_features=%d shaper_list=%p", + "face=%p num_features=%d num_coords=%d shaper_list=%p", face, num_user_features, + num_coords, shaper_list); hb_shape_plan_t *shape_plan; hb_feature_t *features = NULL; + int *coords = NULL; if (unlikely (!face)) face = hb_face_get_empty (); @@ -130,7 +145,14 @@ hb_shape_plan_create (hb_face_t *face, return hb_shape_plan_get_empty (); if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t)))) return hb_shape_plan_get_empty (); - if (!(shape_plan = hb_object_create ())) { + if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int)))) + { + free (features); + return hb_shape_plan_get_empty (); + } + if (!(shape_plan = hb_object_create ())) + { + free (coords); free (features); return hb_shape_plan_get_empty (); } @@ -138,15 +160,22 @@ hb_shape_plan_create (hb_face_t *face, assert (props->direction != HB_DIRECTION_INVALID); hb_face_make_immutable (face); - shape_plan->default_shaper_list = shaper_list == NULL; + shape_plan->default_shaper_list = !shaper_list; shape_plan->face_unsafe = face; shape_plan->props = *props; shape_plan->num_user_features = num_user_features; shape_plan->user_features = features; if (num_user_features) memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); + shape_plan->num_coords = num_coords; + shape_plan->coords = coords; + if (num_coords) + memcpy (coords, orig_coords, num_coords * sizeof (int)); - hb_shape_plan_plan (shape_plan, user_features, num_user_features, shaper_list); + hb_shape_plan_plan (shape_plan, + user_features, num_user_features, + coords, num_coords, + shaper_list); return shape_plan; } @@ -176,6 +205,9 @@ hb_shape_plan_get_empty (void) NULL, /* user_features */ 0, /* num_user_featurs */ + NULL, /* coords */ + 0, /* num_coords */ + { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -220,6 +252,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) #undef HB_SHAPER_IMPLEMENT free (shape_plan->user_features); + free (shape_plan->coords); free (shape_plan); } @@ -289,9 +322,10 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, unsigned int num_features) { DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, - "num_features=%d shaper_func=%p", + "num_features=%d shaper_func=%p, shaper_name=%s", num_features, - shape_plan->shaper_func); + shape_plan->shaper_func, + shape_plan->shaper_name); if (unlikely (!buffer->len)) return true; @@ -350,6 +384,8 @@ struct hb_shape_plan_proposal_t const char * const *shaper_list; const hb_feature_t *user_features; unsigned int num_user_features; + const int *coords; + unsigned int num_coords; hb_shape_func_t *shaper_func; }; @@ -357,12 +393,26 @@ static inline hb_bool_t hb_shape_plan_user_features_match (const hb_shape_plan_t *shape_plan, const hb_shape_plan_proposal_t *proposal) { - if (proposal->num_user_features != shape_plan->num_user_features) return false; + if (proposal->num_user_features != shape_plan->num_user_features) + return false; for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++) if (proposal->user_features[i].tag != shape_plan->user_features[i].tag || proposal->user_features[i].value != shape_plan->user_features[i].value || proposal->user_features[i].start != shape_plan->user_features[i].start || - proposal->user_features[i].end != shape_plan->user_features[i].end) return false; + proposal->user_features[i].end != shape_plan->user_features[i].end) + return false; + return true; +} + +static inline hb_bool_t +hb_shape_plan_coords_match (const hb_shape_plan_t *shape_plan, + const hb_shape_plan_proposal_t *proposal) +{ + if (proposal->num_coords != shape_plan->num_coords) + return false; + for (unsigned int i = 0, n = proposal->num_coords; i < n; i++) + if (proposal->coords[i] != shape_plan->coords[i]) + return false; return true; } @@ -372,7 +422,8 @@ hb_shape_plan_matches (const hb_shape_plan_t *shape_plan, { return hb_segment_properties_equal (&shape_plan->props, &proposal->props) && hb_shape_plan_user_features_match (shape_plan, proposal) && - ((shape_plan->default_shaper_list && proposal->shaper_list == NULL) || + hb_shape_plan_coords_match (shape_plan, proposal) && + ((shape_plan->default_shaper_list && !proposal->shaper_list) || (shape_plan->shaper_func == proposal->shaper_func)); } @@ -380,14 +431,22 @@ static inline hb_bool_t hb_non_global_user_features_present (const hb_feature_t *user_features, unsigned int num_user_features) { - while (num_user_features) + while (num_user_features) { if (user_features->start != 0 || user_features->end != (unsigned int) -1) return true; - else - num_user_features--, user_features++; + num_user_features--; + user_features++; + } return false; } +static inline hb_bool_t +hb_coords_present (const int *coords, + unsigned int num_coords) +{ + return num_coords != 0; +} + /** * hb_shape_plan_create_cached: * @face: @@ -408,6 +467,21 @@ hb_shape_plan_create_cached (hb_face_t *face, const hb_feature_t *user_features, unsigned int num_user_features, const char * const *shaper_list) +{ + return hb_shape_plan_create_cached2 (face, props, + user_features, num_user_features, + NULL, 0, + shaper_list); +} + +hb_shape_plan_t * +hb_shape_plan_create_cached2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list) { DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, "face=%p num_features=%d shaper_list=%p", @@ -455,16 +529,21 @@ retry: /* Not found. */ - hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list); + hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props, + user_features, num_user_features, + coords, num_coords, + shaper_list); /* Don't add to the cache if face is inert. */ if (unlikely (hb_object_is_inert (face))) return shape_plan; /* Don't add the plan to the cache if there were user features with non-global ranges */ - if (hb_non_global_user_features_present (user_features, num_user_features)) return shape_plan; + /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */ + if (hb_coords_present (coords, num_coords)) + return shape_plan; hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t)); if (unlikely (!node)) diff --git a/gfx/harfbuzz/src/hb-shape-plan.h b/gfx/harfbuzz/src/hb-shape-plan.h index 8f54552f9..b62ae7ca3 100644 --- a/gfx/harfbuzz/src/hb-shape-plan.h +++ b/gfx/harfbuzz/src/hb-shape-plan.h @@ -38,49 +38,68 @@ HB_BEGIN_DECLS typedef struct hb_shape_plan_t hb_shape_plan_t; -hb_shape_plan_t * +HB_EXTERN hb_shape_plan_t * hb_shape_plan_create (hb_face_t *face, const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features, const char * const *shaper_list); -hb_shape_plan_t * +HB_EXTERN hb_shape_plan_t * hb_shape_plan_create_cached (hb_face_t *face, const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features, const char * const *shaper_list); -hb_shape_plan_t * +HB_EXTERN hb_shape_plan_t * +hb_shape_plan_create2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list); + +HB_EXTERN hb_shape_plan_t * +hb_shape_plan_create_cached2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list); + + +HB_EXTERN hb_shape_plan_t * hb_shape_plan_get_empty (void); -hb_shape_plan_t * +HB_EXTERN hb_shape_plan_t * hb_shape_plan_reference (hb_shape_plan_t *shape_plan); -void +HB_EXTERN void hb_shape_plan_destroy (hb_shape_plan_t *shape_plan); -hb_bool_t +HB_EXTERN hb_bool_t hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan, hb_user_data_key_t *key, void * data, hb_destroy_func_t destroy, hb_bool_t replace); -void * +HB_EXTERN void * hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, hb_user_data_key_t *key); -hb_bool_t +HB_EXTERN hb_bool_t hb_shape_plan_execute (hb_shape_plan_t *shape_plan, hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, unsigned int num_features); -const char * +HB_EXTERN const char * hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan); diff --git a/gfx/harfbuzz/src/hb-shape.cc b/gfx/harfbuzz/src/hb-shape.cc index 8a9858398..f080a15e3 100644 --- a/gfx/harfbuzz/src/hb-shape.cc +++ b/gfx/harfbuzz/src/hb-shape.cc @@ -45,252 +45,6 @@ * contains the output glyphs and their positions. **/ -static bool -parse_space (const char **pp, const char *end) -{ - while (*pp < end && ISSPACE (**pp)) - (*pp)++; - return true; -} - -static bool -parse_char (const char **pp, const char *end, char c) -{ - parse_space (pp, end); - - if (*pp == end || **pp != c) - return false; - - (*pp)++; - return true; -} - -static bool -parse_uint (const char **pp, const char *end, unsigned int *pv) -{ - char buf[32]; - unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); - strncpy (buf, *pp, len); - buf[len] = '\0'; - - char *p = buf; - char *pend = p; - unsigned int v; - - /* Intentionally use strtol instead of strtoul, such that - * -1 turns into "big number"... */ - errno = 0; - v = strtol (p, &pend, 0); - if (errno || p == pend) - return false; - - *pv = v; - *pp += pend - p; - return true; -} - -static bool -parse_bool (const char **pp, const char *end, unsigned int *pv) -{ - parse_space (pp, end); - - const char *p = *pp; - while (*pp < end && ISALPHA(**pp)) - (*pp)++; - - /* CSS allows on/off as aliases 1/0. */ - if (*pp - p == 2 || 0 == strncmp (p, "on", 2)) - *pv = 1; - else if (*pp - p == 3 || 0 == strncmp (p, "off", 2)) - *pv = 0; - else - return false; - - return true; -} - -static bool -parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) -{ - if (parse_char (pp, end, '-')) - feature->value = 0; - else { - parse_char (pp, end, '+'); - feature->value = 1; - } - - return true; -} - -static bool -parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature) -{ - parse_space (pp, end); - - char quote = 0; - - if (*pp < end && (**pp == '\'' || **pp == '"')) - { - quote = **pp; - (*pp)++; - } - - const char *p = *pp; - while (*pp < end && ISALNUM(**pp)) - (*pp)++; - - if (p == *pp || *pp - p > 4) - return false; - - feature->tag = hb_tag_from_string (p, *pp - p); - - if (quote) - { - /* CSS expects exactly four bytes. And we only allow quotations for - * CSS compatibility. So, enforce the length. */ - if (*pp - p != 4) - return false; - if (*pp == end || **pp != quote) - return false; - (*pp)++; - } - - return true; -} - -static bool -parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) -{ - parse_space (pp, end); - - bool has_start; - - feature->start = 0; - feature->end = (unsigned int) -1; - - if (!parse_char (pp, end, '[')) - return true; - - has_start = parse_uint (pp, end, &feature->start); - - if (parse_char (pp, end, ':')) { - parse_uint (pp, end, &feature->end); - } else { - if (has_start) - feature->end = feature->start + 1; - } - - return parse_char (pp, end, ']'); -} - -static bool -parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature) -{ - bool had_equal = parse_char (pp, end, '='); - bool had_value = parse_uint (pp, end, &feature->value) || - parse_bool (pp, end, &feature->value); - /* CSS doesn't use equal-sign between tag and value. - * If there was an equal-sign, then there *must* be a value. - * A value without an eqaul-sign is ok, but not required. */ - return !had_equal || had_value; -} - - -static bool -parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) -{ - return parse_feature_value_prefix (pp, end, feature) && - parse_feature_tag (pp, end, feature) && - parse_feature_indices (pp, end, feature) && - parse_feature_value_postfix (pp, end, feature) && - parse_space (pp, end) && - *pp == end; -} - -/** - * hb_feature_from_string: - * @str: (array length=len) (element-type uint8_t): a string to parse - * @len: length of @str, or -1 if string is nul-terminated - * @feature: (out): the #hb_feature_t to initialize with the parsed values - * - * Parses a string into a #hb_feature_t. If @len is -1 then @str is - * %NULL-terminated. - * - * Return value: %TRUE if @str is successfully parsed, %FALSE otherwise - * - * Since: 0.9.5 - **/ -hb_bool_t -hb_feature_from_string (const char *str, int len, - hb_feature_t *feature) -{ - hb_feature_t feat; - - if (len < 0) - len = strlen (str); - - if (likely (parse_one_feature (&str, str + len, &feat))) - { - if (feature) - *feature = feat; - return true; - } - - if (feature) - memset (feature, 0, sizeof (*feature)); - return false; -} - -/** - * hb_feature_to_string: - * @feature: an #hb_feature_t to convert - * @buf: (array length=size) (out): output string - * @size: the allocated size of @buf - * - * Converts a #hb_feature_t into a %NULL-terminated string in the format - * understood by hb_feature_from_string(). The client in responsible for - * allocating big enough size for @buf, 128 bytes is more than enough. - * - * Since: 0.9.5 - **/ -void -hb_feature_to_string (hb_feature_t *feature, - char *buf, unsigned int size) -{ - if (unlikely (!size)) return; - - char s[128]; - unsigned int len = 0; - if (feature->value == 0) - s[len++] = '-'; - hb_tag_to_string (feature->tag, s + len); - len += 4; - while (len && s[len - 1] == ' ') - len--; - if (feature->start != 0 || feature->end != (unsigned int) -1) - { - s[len++] = '['; - if (feature->start) - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start)); - if (feature->end != feature->start + 1) { - s[len++] = ':'; - if (feature->end != (unsigned int) -1) - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end)); - } - s[len++] = ']'; - } - if (feature->value > 1) - { - s[len++] = '='; - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); - } - assert (len < ARRAY_LENGTH (s)); - len = MIN (len, size - 1); - memcpy (buf, s, len); - buf[len] = '\0'; -} - - static const char **static_shaper_list; #ifdef HB_USE_ATEXIT @@ -360,7 +114,7 @@ retry: * shapers will be used in the given order, otherwise the default shapers list * will be used. * - * Return value: %FALSE if all shapers failed, %TRUE otherwise + * Return value: false if all shapers failed, true otherwise * * Since: 0.9.2 **/ @@ -371,7 +125,10 @@ hb_shape_full (hb_font_t *font, unsigned int num_features, const char * const *shaper_list) { - hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list); + hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props, + features, num_features, + font->coords, font->num_coords, + shaper_list); hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features); hb_shape_plan_destroy (shape_plan); @@ -392,8 +149,6 @@ hb_shape_full (hb_font_t *font, * positioned glyphs. If @features is not %NULL, it will be used to control the * features applied during shaping. * - * Return value: %FALSE if all shapers failed, %TRUE otherwise - * * Since: 0.9.2 **/ void diff --git a/gfx/harfbuzz/src/hb-shape.h b/gfx/harfbuzz/src/hb-shape.h index b665509a0..39507ff74 100644 --- a/gfx/harfbuzz/src/hb-shape.h +++ b/gfx/harfbuzz/src/hb-shape.h @@ -40,36 +40,20 @@ HB_BEGIN_DECLS -typedef struct hb_feature_t { - hb_tag_t tag; - uint32_t value; - unsigned int start; - unsigned int end; -} hb_feature_t; - -hb_bool_t -hb_feature_from_string (const char *str, int len, - hb_feature_t *feature); - -void -hb_feature_to_string (hb_feature_t *feature, - char *buf, unsigned int size); - - -void +HB_EXTERN void hb_shape (hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, unsigned int num_features); -hb_bool_t +HB_EXTERN hb_bool_t hb_shape_full (hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, unsigned int num_features, const char * const *shaper_list); -const char ** +HB_EXTERN const char ** hb_shape_list_shapers (void); diff --git a/gfx/harfbuzz/src/hb-shaper-list.hh b/gfx/harfbuzz/src/hb-shaper-list.hh index 6c537d492..b0835d31a 100644 --- a/gfx/harfbuzz/src/hb-shaper-list.hh +++ b/gfx/harfbuzz/src/hb-shaper-list.hh @@ -46,6 +46,9 @@ HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */ #ifdef HAVE_UNISCRIBE HB_SHAPER_IMPLEMENT (uniscribe) #endif +#ifdef HAVE_DIRECTWRITE +HB_SHAPER_IMPLEMENT (directwrite) +#endif #ifdef HAVE_CORETEXT HB_SHAPER_IMPLEMENT (coretext) #endif diff --git a/gfx/harfbuzz/src/hb-shaper-private.hh b/gfx/harfbuzz/src/hb-shaper-private.hh index d1d1146da..381398a61 100644 --- a/gfx/harfbuzz/src/hb-shaper-private.hh +++ b/gfx/harfbuzz/src/hb-shaper-private.hh @@ -65,27 +65,31 @@ struct hb_shaper_data_t { #define HB_SHAPER_DATA_INVALID ((void *) -1) #define HB_SHAPER_DATA_IS_INVALID(data) ((void *) (data) == HB_SHAPER_DATA_INVALID) -#define HB_SHAPER_DATA_TYPE(shaper, object) struct hb_##shaper##_shaper_##object##_data_t +#define HB_SHAPER_DATA_TYPE_NAME(shaper, object) hb_##shaper##_shaper_##object##_data_t +#define HB_SHAPER_DATA_TYPE(shaper, object) struct HB_SHAPER_DATA_TYPE_NAME(shaper, object) #define HB_SHAPER_DATA_INSTANCE(shaper, object, instance) (* (HB_SHAPER_DATA_TYPE(shaper, object) **) &(instance)->shaper_data.shaper) -#define HB_SHAPER_DATA(shaper, object) HB_SHAPER_DATA_INSTANCE (shaper, object, object) +#define HB_SHAPER_DATA(shaper, object) HB_SHAPER_DATA_INSTANCE(shaper, object, object) #define HB_SHAPER_DATA_CREATE_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_create #define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_destroy +#define HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) hb_##shaper##_shaper_##object##_data_ensure #define HB_SHAPER_DATA_PROTOTYPE(shaper, object) \ HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \ extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \ HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS); \ extern "C" HB_INTERNAL void \ - HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data) + HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data); \ + extern "C" HB_INTERNAL bool \ + HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object) #define HB_SHAPER_DATA_DESTROY(shaper, object) \ if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \ if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \ HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); -#define HB_SHAPER_DATA_ENSURE_DECLARE(shaper, object) \ -static inline bool \ -hb_##shaper##_shaper_##object##_data_ensure (hb_##object##_t *object) \ +#define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \ +bool \ +HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \ {\ retry: \ HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \ diff --git a/gfx/harfbuzz/src/hb-ucdn.cc b/gfx/harfbuzz/src/hb-ucdn.cc index b4a583324..a884e3ffd 100644 --- a/gfx/harfbuzz/src/hb-ucdn.cc +++ b/gfx/harfbuzz/src/hb-ucdn.cc @@ -154,6 +154,12 @@ static const hb_script_t ucdn_script_translate[] = HB_SCRIPT_MULTANI, HB_SCRIPT_OLD_HUNGARIAN, HB_SCRIPT_SIGNWRITING, + HB_SCRIPT_ADLAM, + HB_SCRIPT_BHAIKSUKI, + HB_SCRIPT_MARCHEN, + HB_SCRIPT_NEWA, + HB_SCRIPT_OSAGE, + HB_SCRIPT_TANGUT, }; static hb_unicode_combining_class_t diff --git a/gfx/harfbuzz/src/hb-unicode-private.hh b/gfx/harfbuzz/src/hb-unicode-private.hh index ecbec513c..34513e132 100644 --- a/gfx/harfbuzz/src/hb-unicode-private.hh +++ b/gfx/harfbuzz/src/hb-unicode-private.hh @@ -105,6 +105,10 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE inline unsigned int modified_combining_class (hb_codepoint_t unicode) { + /* XXX This hack belongs to the Arabic shaper: + * Put HAMZA ABOVE in the same class as SHADDA. */ + if (unlikely (unicode == 0x0654u)) unicode = 0x0651u; + /* XXX This hack belongs to the Myanmar shaper. */ if (unlikely (unicode == 0x1037u)) unicode = 0x103Au; @@ -115,6 +119,8 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE /* XXX This hack belongs to the Tibetan shaper: * Reorder PADMA to ensure it comes after any vowel marks. */ if (unlikely (unicode == 0x0FC6u)) return 254; + /* Reorder TSA -PHRU to reorder before U+0F74 */ + if (unlikely (unicode == 0x0F39u)) return 127; return _hb_modified_combining_class[combining_class (unicode)]; } @@ -124,7 +130,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE { /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the * Arabic shaper. No need to match them here. */ - return unlikely (hb_in_ranges (unicode, + return unlikely (hb_in_ranges (unicode, 0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */ 0xE0100u, 0xE01EFu)); /* VARIATION SELECTOR-17..256 */ } @@ -177,13 +183,13 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE case 0x00: return unlikely (ch == 0x00ADu); case 0x03: return unlikely (ch == 0x034Fu); case 0x06: return unlikely (ch == 0x061Cu); - case 0x17: return hb_in_range (ch, 0x17B4u, 0x17B5u); - case 0x18: return hb_in_range (ch, 0x180Bu, 0x180Eu); - case 0x20: return hb_in_ranges (ch, 0x200Bu, 0x200Fu, - 0x202Au, 0x202Eu, - 0x2060u, 0x206Fu); - case 0xFE: return hb_in_range (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu; - case 0xFF: return hb_in_range (ch, 0xFFF0u, 0xFFF8u); + case 0x17: return hb_in_range (ch, 0x17B4u, 0x17B5u); + case 0x18: return hb_in_range (ch, 0x180Bu, 0x180Eu); + case 0x20: return hb_in_ranges (ch, 0x200Bu, 0x200Fu, + 0x202Au, 0x202Eu, + 0x2060u, 0x206Fu); + case 0xFE: return hb_in_range (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu; + case 0xFF: return hb_in_range (ch, 0xFFF0u, 0xFFF8u); default: return false; } } @@ -191,9 +197,9 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE { /* Other planes */ switch (plane) { - case 0x01: return hb_in_ranges (ch, 0x1BCA0u, 0x1BCA3u, + case 0x01: return hb_in_ranges (ch, 0x1BCA0u, 0x1BCA3u, 0x1D173u, 0x1D17Au); - case 0x0E: return hb_in_range (ch, 0xE0000u, 0xE0FFFu); + case 0x0E: return hb_in_range (ch, 0xE0000u, 0xE0FFFu); default: return false; } } @@ -224,7 +230,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE switch (u) { /* All GC=Zs chars that can use a fallback. */ - default: return NOT_SPACE; /* Shouldn't happen. */ + default: return NOT_SPACE; /* U+1680 OGHAM SPACE MARK */ case 0x0020u: return SPACE; /* U+0020 SPACE */ case 0x00A0u: return SPACE; /* U+00A0 NO-BREAK SPACE */ case 0x2000u: return SPACE_EM_2; /* U+2000 EN QUAD */ @@ -343,11 +349,14 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil; #define HB_MODIFIED_COMBINING_CLASS_CCC118 118 /* sign u / sign uu */ #define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */ -/* Tibetan */ +/* Tibetan + * + * In case of multiple vowel-signs, use u first (but after achung) + * this allows Dzongkha multi-vowel shortcuts to render correctly + */ #define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */ -#define HB_MODIFIED_COMBINING_CLASS_CCC130 130 /* sign i */ -#define HB_MODIFIED_COMBINING_CLASS_CCC132 132 /* sign u */ - +#define HB_MODIFIED_COMBINING_CLASS_CCC130 132 /* sign i */ +#define HB_MODIFIED_COMBINING_CLASS_CCC132 131 /* sign u */ /* Misc */ @@ -357,9 +366,10 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil; FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \ FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))) -#define HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK(gen_cat) \ +#define HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL(gen_cat) \ (FLAG_SAFE (gen_cat) & \ (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \ - FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))) + FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \ + FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL))) #endif /* HB_UNICODE_PRIVATE_HH */ diff --git a/gfx/harfbuzz/src/hb-unicode.cc b/gfx/harfbuzz/src/hb-unicode.cc index 487d10b93..d553a7172 100644 --- a/gfx/harfbuzz/src/hb-unicode.cc +++ b/gfx/harfbuzz/src/hb-unicode.cc @@ -131,12 +131,12 @@ hb_unicode_funcs_get_default (void) #define HB_UNICODE_FUNCS_IMPLEMENT(set) \ return hb_##set##_get_unicode_funcs (); -#ifdef HAVE_GLIB +#if defined(HAVE_UCDN) + HB_UNICODE_FUNCS_IMPLEMENT(ucdn) +#elif defined(HAVE_GLIB) HB_UNICODE_FUNCS_IMPLEMENT(glib) #elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN) HB_UNICODE_FUNCS_IMPLEMENT(icu) -#elif defined(HAVE_UCDN) - HB_UNICODE_FUNCS_IMPLEMENT(ucdn) #else #define HB_UNICODE_FUNCS_NIL 1 HB_UNICODE_FUNCS_IMPLEMENT(nil) diff --git a/gfx/harfbuzz/src/hb-unicode.h b/gfx/harfbuzz/src/hb-unicode.h index 3a12e2f9a..2657f4813 100644 --- a/gfx/harfbuzz/src/hb-unicode.h +++ b/gfx/harfbuzz/src/hb-unicode.h @@ -174,23 +174,23 @@ typedef struct hb_unicode_funcs_t hb_unicode_funcs_t; /* * just give me the best implementation you've got there. */ -hb_unicode_funcs_t * +HB_EXTERN hb_unicode_funcs_t * hb_unicode_funcs_get_default (void); -hb_unicode_funcs_t * +HB_EXTERN hb_unicode_funcs_t * hb_unicode_funcs_create (hb_unicode_funcs_t *parent); -hb_unicode_funcs_t * +HB_EXTERN hb_unicode_funcs_t * hb_unicode_funcs_get_empty (void); -hb_unicode_funcs_t * +HB_EXTERN hb_unicode_funcs_t * hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs); -void +HB_EXTERN void hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs); -hb_bool_t +HB_EXTERN hb_bool_t hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, hb_user_data_key_t *key, void * data, @@ -198,18 +198,18 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, hb_bool_t replace); -void * +HB_EXTERN void * hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, hb_user_data_key_t *key); -void +HB_EXTERN void hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs); -hb_bool_t +HB_EXTERN hb_bool_t hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs); -hb_unicode_funcs_t * +HB_EXTERN hb_unicode_funcs_t * hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs); @@ -285,7 +285,7 @@ typedef unsigned int (*hb_unicode_decompose_compatibility_func_t) (hb_unicode_ * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs, hb_unicode_combining_class_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -301,7 +301,7 @@ hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs, hb_unicode_eastasian_width_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -317,7 +317,7 @@ hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs, hb_unicode_general_category_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -333,7 +333,7 @@ hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs, hb_unicode_mirroring_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -349,7 +349,7 @@ hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs, hb_unicode_script_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -365,7 +365,7 @@ hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs, hb_unicode_compose_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -381,7 +381,7 @@ hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs, hb_unicode_decompose_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -397,7 +397,7 @@ hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs, * * Since: 0.9.2 **/ -void +HB_EXTERN void hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs, hb_unicode_decompose_compatibility_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -405,62 +405,63 @@ hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs, /* accessors */ /** + * hb_unicode_combining_class: + * * Since: 0.9.2 **/ -hb_unicode_combining_class_t +HB_EXTERN hb_unicode_combining_class_t hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode); /** + * hb_unicode_eastasian_width: + * * Since: 0.9.2 **/ -unsigned int +HB_EXTERN unsigned int hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode); /** + * hb_unicode_general_category: + * * Since: 0.9.2 **/ -hb_unicode_general_category_t +HB_EXTERN hb_unicode_general_category_t hb_unicode_general_category (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode); /** + * hb_unicode_mirroring: + * * Since: 0.9.2 **/ -hb_codepoint_t +HB_EXTERN hb_codepoint_t hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode); /** + * hb_unicode_script: + * * Since: 0.9.2 **/ -hb_script_t +HB_EXTERN hb_script_t hb_unicode_script (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode); -/** - * Since: 0.9.2 - **/ -hb_bool_t +HB_EXTERN hb_bool_t hb_unicode_compose (hb_unicode_funcs_t *ufuncs, hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab); -/** - * Since: 0.9.2 - **/ -hb_bool_t +HB_EXTERN hb_bool_t hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b); -/** - * Since: 0.9.2 - **/ -unsigned int +HB_EXTERN unsigned int hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, hb_codepoint_t u, hb_codepoint_t *decomposed); diff --git a/gfx/harfbuzz/src/hb-uniscribe.cc b/gfx/harfbuzz/src/hb-uniscribe.cc index 01be0cc84..d25accd56 100644 --- a/gfx/harfbuzz/src/hb-uniscribe.cc +++ b/gfx/harfbuzz/src/hb-uniscribe.cc @@ -293,8 +293,8 @@ struct range_record_t { unsigned int index_last; /* == end - 1 */ }; -HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face) -HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font) +HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, face) +HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, font) /* @@ -587,7 +587,9 @@ struct hb_uniscribe_shaper_shape_plan_data_t {}; hb_uniscribe_shaper_shape_plan_data_t * _hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } @@ -771,7 +773,7 @@ retry: pchars[chars_len++] = 0xFFFDu; else { pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10); - pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1)); + pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1)); } } @@ -827,7 +829,7 @@ retry: /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */ //bidi_control.fMergeNeutralItems = true; - *(uint32_t*)&bidi_control |= 1<<24; + *(uint32_t*)&bidi_control |= 1u<<24; bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1; bidi_state.fOverrideDirection = 1; @@ -919,7 +921,7 @@ retry: if (unlikely (items[i].a.fNoGlyphIndex)) FAIL ("ScriptShapeOpenType() set fNoGlyphIndex"); - if (unlikely (hr == E_OUTOFMEMORY)) + if (unlikely (hr == E_OUTOFMEMORY || hr == E_NOT_SUFFICIENT_BUFFER)) { if (unlikely (!buffer->ensure (buffer->allocated * 2))) FAIL ("Buffer resize failed"); @@ -1019,9 +1021,11 @@ retry: hb_glyph_position_t *pos = &buffer->pos[i]; /* TODO vertical */ - pos->x_advance = x_mult * info->mask; + pos->x_advance = x_mult * (int32_t) info->mask; pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32); pos->y_offset = y_mult * info->var2.i32; + + info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; } if (backward) diff --git a/gfx/harfbuzz/src/hb-uniscribe.h b/gfx/harfbuzz/src/hb-uniscribe.h index 001ab38ea..4e4ef9986 100644 --- a/gfx/harfbuzz/src/hb-uniscribe.h +++ b/gfx/harfbuzz/src/hb-uniscribe.h @@ -34,10 +34,10 @@ HB_BEGIN_DECLS -LOGFONTW * +HB_EXTERN LOGFONTW * hb_uniscribe_font_get_logfontw (hb_font_t *font); -HFONT +HB_EXTERN HFONT hb_uniscribe_font_get_hfont (hb_font_t *font); diff --git a/gfx/harfbuzz/src/hb-utf-private.hh b/gfx/harfbuzz/src/hb-utf-private.hh index 74cf5d66a..211eb4dc0 100644 --- a/gfx/harfbuzz/src/hb-utf-private.hh +++ b/gfx/harfbuzz/src/hb-utf-private.hh @@ -48,7 +48,7 @@ struct hb_utf8_t if (c > 0x7Fu) { - if (hb_in_range (c, 0xC2u, 0xDFu)) /* Two-byte */ + if (hb_in_range (c, 0xC2u, 0xDFu)) /* Two-byte */ { unsigned int t1; if (likely (text < end && @@ -60,7 +60,7 @@ struct hb_utf8_t else goto error; } - else if (hb_in_range (c, 0xE0u, 0xEFu)) /* Three-byte */ + else if (hb_in_range (c, 0xE0u, 0xEFu)) /* Three-byte */ { unsigned int t1, t2; if (likely (1 < end - text && @@ -68,14 +68,14 @@ struct hb_utf8_t (t2 = text[1] - 0x80u) <= 0x3Fu)) { c = ((c&0xFu)<<12) | (t1<<6) | t2; - if (unlikely (c < 0x0800u || hb_in_range (c, 0xD800u, 0xDFFFu))) + if (unlikely (c < 0x0800u || hb_in_range (c, 0xD800u, 0xDFFFu))) goto error; text += 2; } else goto error; } - else if (hb_in_range (c, 0xF0u, 0xF4u)) /* Four-byte */ + else if (hb_in_range (c, 0xF0u, 0xF4u)) /* Four-byte */ { unsigned int t1, t2, t3; if (likely (2 < end - text && @@ -84,7 +84,7 @@ struct hb_utf8_t (t3 = text[2] - 0x80u) <= 0x3Fu)) { c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3; - if (unlikely (!hb_in_range (c, 0x10000u, 0x10FFFFu))) + if (unlikely (!hb_in_range (c, 0x10000u, 0x10FFFFu))) goto error; text += 3; } @@ -140,7 +140,7 @@ struct hb_utf16_t { hb_codepoint_t c = *text++; - if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu))) + if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu))) { *unicode = c; return text; @@ -150,7 +150,7 @@ struct hb_utf16_t { /* High-surrogate in c */ hb_codepoint_t l = *text; - if (likely (hb_in_range (l, 0xDC00u, 0xDFFFu))) + if (likely (hb_in_range (l, 0xDC00u, 0xDFFFu))) { /* Low-surrogate in l */ *unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u); @@ -172,7 +172,7 @@ struct hb_utf16_t { hb_codepoint_t c = *--text; - if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu))) + if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu))) { *unicode = c; return text; @@ -182,7 +182,7 @@ struct hb_utf16_t { /* Low-surrogate in c */ hb_codepoint_t h = text[-1]; - if (likely (hb_in_range (h, 0xD800u, 0xDBFFu))) + if (likely (hb_in_range (h, 0xD800u, 0xDBFFu))) { /* High-surrogate in h */ *unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u); diff --git a/gfx/harfbuzz/src/hb-version.h b/gfx/harfbuzz/src/hb-version.h index 41ca378b0..457f5b7be 100644 --- a/gfx/harfbuzz/src/hb-version.h +++ b/gfx/harfbuzz/src/hb-version.h @@ -37,25 +37,25 @@ HB_BEGIN_DECLS #define HB_VERSION_MAJOR 1 -#define HB_VERSION_MINOR 1 -#define HB_VERSION_MICRO 0 +#define HB_VERSION_MINOR 5 +#define HB_VERSION_MICRO 1 -#define HB_VERSION_STRING "1.1.0" +#define HB_VERSION_STRING "1.5.1" #define HB_VERSION_ATLEAST(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) <= \ HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO) -void +HB_EXTERN void hb_version (unsigned int *major, unsigned int *minor, unsigned int *micro); -const char * +HB_EXTERN const char * hb_version_string (void); -hb_bool_t +HB_EXTERN hb_bool_t hb_version_atleast (unsigned int major, unsigned int minor, unsigned int micro); diff --git a/gfx/harfbuzz/src/hb-version.h.in b/gfx/harfbuzz/src/hb-version.h.in index 2517160d1..0ffd889b2 100644 --- a/gfx/harfbuzz/src/hb-version.h.in +++ b/gfx/harfbuzz/src/hb-version.h.in @@ -47,15 +47,15 @@ HB_BEGIN_DECLS HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO) -void +HB_EXTERN void hb_version (unsigned int *major, unsigned int *minor, unsigned int *micro); -const char * +HB_EXTERN const char * hb_version_string (void); -hb_bool_t +HB_EXTERN hb_bool_t hb_version_atleast (unsigned int major, unsigned int minor, unsigned int micro); diff --git a/gfx/harfbuzz/src/hb.h b/gfx/harfbuzz/src/hb.h index c5a938a38..7402034f4 100644 --- a/gfx/harfbuzz/src/hb.h +++ b/gfx/harfbuzz/src/hb.h @@ -28,6 +28,10 @@ #define HB_H #define HB_H_IN +#ifndef HB_EXTERN +#define HB_EXTERN extern +#endif + #include "hb-blob.h" #include "hb-buffer.h" #include "hb-common.h" diff --git a/gfx/harfbuzz/src/moz.build b/gfx/harfbuzz/src/moz.build index 51dfc705c..e56fe1aaa 100644 --- a/gfx/harfbuzz/src/moz.build +++ b/gfx/harfbuzz/src/moz.build @@ -1,4 +1,4 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -13,8 +13,10 @@ EXPORTS.harfbuzz += [ 'hb-font.h', 'hb-ot-font.h', 'hb-ot-layout.h', + 'hb-ot-math.h', 'hb-ot-shape.h', 'hb-ot-tag.h', + 'hb-ot-var.h', 'hb-ot.h', 'hb-set.h', 'hb-shape-plan.h', @@ -27,6 +29,7 @@ EXPORTS.harfbuzz += [ SOURCES += [ 'hb-blob.cc', # error: use of undeclared identifier 'snprintf' (FreeBSD) 'hb-common.cc', # error: use of undeclared identifier 'strdup' + 'hb-ot-math.cc', # conflict with hb-ot-layout.cc 'hb-ot-shape-complex-hangul.cc', # error: redefinition of enumerator 'NONE' 'hb-ot-shape-complex-indic.cc', # error: redefinition of enumerator 'INIT' 'hb-ot-shape-complex-use.cc', # error: redefinition of 'basic_features' @@ -37,7 +40,6 @@ SOURCES += [ UNIFIED_SOURCES += [ 'hb-buffer.cc', 'hb-face.cc', - 'hb-fallback-shape.cc', 'hb-font.cc', 'hb-ot-layout.cc', 'hb-ot-map.cc', @@ -52,6 +54,7 @@ UNIFIED_SOURCES += [ 'hb-ot-shape-fallback.cc', 'hb-ot-shape-normalize.cc', 'hb-ot-tag.cc', + 'hb-ot-var.cc', 'hb-set.cc', 'hb-shape.cc', 'hb-shaper.cc', @@ -59,6 +62,15 @@ UNIFIED_SOURCES += [ 'hb-warning.cc', ] +if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: + EXPORTS.harfbuzz += [ + 'hb-glib.h', + ] + UNIFIED_SOURCES += [ + 'hb-glib.cc', + ] + CXXFLAGS += CONFIG['GLIB_CFLAGS'] + # We allow warnings for third-party code that can be updated from upstream. ALLOW_COMPILER_WARNINGS = True @@ -69,3 +81,6 @@ DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"' DEFINES['HAVE_OT'] = 1 DEFINES['HB_NO_MT'] = True DEFINES['HB_NO_UNICODE_FUNCS'] = True +# Cancel the effect of the -DDEBUG macro if present, +# because harfbuzz uses that name for its own purposes +DEFINES['DEBUG'] = False diff --git a/gfx/harfbuzz/src/sample.py b/gfx/harfbuzz/src/sample.py index f8d221699..c2cb94d53 100755 --- a/gfx/harfbuzz/src/sample.py +++ b/gfx/harfbuzz/src/sample.py @@ -3,6 +3,7 @@ from __future__ import print_function import sys +import array from gi.repository import HarfBuzz as hb from gi.repository import GLib @@ -33,7 +34,32 @@ hb.font_set_scale (font, upem, upem) hb.ot_font_set_funcs (font) buf = hb.buffer_create () -hb.buffer_add_utf8 (buf, text.encode('utf-8'), 0, -1) +class Debugger(object): + def message (self, buf, font, msg, data, _x_what_is_this): + print(msg) + return True +debugger = Debugger() +hb.buffer_set_message_func (buf, debugger.message, 1, 0) + +## +## Add text to buffer +## +# +# See https://github.com/behdad/harfbuzz/pull/271 +# +if False: + # If you do not care about cluster values reflecting Python + # string indices, then this is quickest way to add text to + # buffer: + hb.buffer_add_utf8 (buf, text.encode('utf-8'), 0, -1) + # Otherwise, then following handles both narrow and wide + # Python builds: +elif sys.maxunicode == 0x10FFFF: + hb.buffer_add_utf32 (buf, array.array('I', text.encode('utf-32')), 0, -1) +else: + hb.buffer_add_utf16 (buf, array.array('H', text.encode('utf-16')), 0, -1) + + hb.buffer_guess_segment_properties (buf) hb.shape (font, buf, []) diff --git a/gfx/harfbuzz/src/test.cc b/gfx/harfbuzz/src/test.cc index a8fe046f3..0c90f8ff4 100644 --- a/gfx/harfbuzz/src/test.cc +++ b/gfx/harfbuzz/src/test.cc @@ -120,7 +120,7 @@ main (int argc, char **argv) info->cluster, info->codepoint, pos->x_offset, - pos->x_offset, + pos->y_offset, pos->x_advance, pos->y_advance);