diff options
author | jshin@chromium.org <jshin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-01 21:30:34 +0000 |
---|---|---|
committer | jshin@chromium.org <jshin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-01 21:30:34 +0000 |
commit | 7f49dcbe337599792a76255059d867dfb6c0546e (patch) | |
tree | 26fc30ef257f9de6fc78149e0d52f12202ec2214 /third_party | |
parent | 22f3763954e1d3e559fe92bf8add0a36104c14cd (diff) | |
download | chromium_src-7f49dcbe337599792a76255059d867dfb6c0546e.zip chromium_src-7f49dcbe337599792a76255059d867dfb6c0546e.tar.gz chromium_src-7f49dcbe337599792a76255059d867dfb6c0546e.tar.bz2 |
Update harfbuzz-ng to 0.9.14 from 0.9.10
Old revision: 34e6c3e3e452bdf6f93df565a70453a6e74d4c6e
New revision: f872a17462a75a3493623747bf3a3fbe54556c7b
What's new:
- A lot of Indic shaping bugs as well as a work-around for bugs in
FreeSans (Devanagari)
- New Win8-style Myanmar shaper
- New shaper for Tai Tham, Chan, New Tai Lue
See NEWS file for more details.
While I'm at this, I also 'fixed' README.chromium to make the copyright
information show up in about:credits page.
Two tests requiring rebaselines (khmer-selection and danda-space) are added to
the list of expected failure until they're rebaselined.
See also http://webkit.org/b/113450
BUG=chromium:96143
TEST=See comment #5 in the bug.
TBR=cpu
Review URL: https://chromiumcodereview.appspot.com/12438036
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191666 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
53 files changed, 5333 insertions, 1562 deletions
diff --git a/third_party/harfbuzz-ng/NEWS b/third_party/harfbuzz-ng/NEWS new file mode 100644 index 0000000..858a916 --- /dev/null +++ b/third_party/harfbuzz-ng/NEWS @@ -0,0 +1,681 @@ +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/third_party/harfbuzz-ng/README.chromium b/third_party/harfbuzz-ng/README.chromium index ec10ad8..8d8d69e 100644 --- a/third_party/harfbuzz-ng/README.chromium +++ b/third_party/harfbuzz-ng/README.chromium @@ -1,15 +1,26 @@ Name: harfbuzz-ng Short Name: harfbuzz-ng URL: http://freedesktop.org/wiki/Software/HarfBuzz -Version: unknown -Date: 20120103 -Revision: 34e6c3e3e452bdf6f93df565a70453a6e74d4c6e (0.9.10) +Version: 0.9.14 +Date: 20130321 +Revision: f872a17462a75a3493623747bf3a3fbe54556c7b Security Critical: yes License: MIT -License File: NOT_SHIPPED +License File: COPYING Description: This is harfbuzz-ng, a new implementation of harfbuzz with a different API from the old one. -I also deleted all unneeded files from the root directory and src/ directory (hb-icu-le, hb-ucdn, hb-old, scripts to generate data tables, automake/conf files). +The following header files are generated by running 'sh autogen.sh; make' +in a separate tree. + + hb-buffer-deserialize-json.hh + hb-buffer-deserialize-text.hh + hb-ot-shape-complex-indic-machine.hh + hb-ot-shape-complex-myanmar-machine.hh + hb-ot-shape-complex-sea-machine.hh + +In addition, all unneeded files from the root directory and src/ directory +(hb-icu-le, hb-ucdn, hb-old, scripts to generate data tables, automake/conf +files) are deleted. diff --git a/third_party/harfbuzz-ng/harfbuzz.gyp b/third_party/harfbuzz-ng/harfbuzz.gyp index af5d0fc..59ca045 100644 --- a/third_party/harfbuzz-ng/harfbuzz.gyp +++ b/third_party/harfbuzz-ng/harfbuzz.gyp @@ -24,7 +24,10 @@ 'src/hb-atomic-private.hh', 'src/hb-blob.cc', 'src/hb-blob.h', + 'src/hb-buffer-deserialize-json.hh', + 'src/hb-buffer-deserialize-text.hh', 'src/hb-buffer-private.hh', + 'src/hb-buffer-serialize.cc', 'src/hb-buffer.cc', 'src/hb-buffer.h', 'src/hb-cache-private.hh', @@ -61,9 +64,14 @@ 'src/hb-ot-shape-complex-default.cc', 'src/hb-ot-shape-complex-indic-machine.hh', 'src/hb-ot-shape-complex-indic-private.hh', + 'src/hb-ot-shape-complex-indic-table.cc', 'src/hb-ot-shape-complex-indic-table.hh', 'src/hb-ot-shape-complex-indic.cc', + 'src/hb-ot-shape-complex-myanmar-machine.hh', + 'src/hb-ot-shape-complex-myanmar.cc', 'src/hb-ot-shape-complex-private.hh', + 'src/hb-ot-shape-complex-sea-machine.hh', + 'src/hb-ot-shape-complex-sea.cc', 'src/hb-ot-shape-complex-thai.cc', 'src/hb-ot-shape-fallback-private.hh', 'src/hb-ot-shape-fallback.cc', diff --git a/third_party/harfbuzz-ng/src/hb-atomic-private.hh b/third_party/harfbuzz-ng/src/hb-atomic-private.hh index 67579cd..7047e21 100644 --- a/third_party/harfbuzz-ng/src/hb-atomic-private.hh +++ b/third_party/harfbuzz-ng/src/hb-atomic-private.hh @@ -42,27 +42,15 @@ #if 0 -#elif !defined(HB_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__) +#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) #define WIN32_LEAN_AND_MEAN #include <windows.h> -/* mingw32 does not have MemoryBarrier. - * MemoryBarrier may be defined as a macro or a function. - * Just make a failsafe version for ourselves. */ -#ifdef MemoryBarrier -#define HBMemoryBarrier MemoryBarrier -#else -static inline void HBMemoryBarrier (void) { - long dummy = 0; - InterlockedExchange (&dummy, 1); -} -#endif - typedef LONG hb_atomic_int_t; #define hb_atomic_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V)) -#define hb_atomic_ptr_get(P) (HBMemoryBarrier (), (void *) *(P)) +#define hb_atomic_ptr_get(P) (MemoryBarrier (), (void *) *(P)) #define hb_atomic_ptr_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O)) @@ -99,6 +87,18 @@ typedef int hb_atomic_int_t; #define hb_atomic_ptr_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N)) +#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS) + +#include <atomic.h> +#include <mbarrier.h> + +typedef unsigned int hb_atomic_int_t; +#define hb_atomic_int_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V)) + +#define hb_atomic_ptr_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P)) +#define hb_atomic_ptr_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) #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ diff --git a/third_party/harfbuzz-ng/src/hb-blob.cc b/third_party/harfbuzz-ng/src/hb-blob.cc index b6e696b..dfd134b 100644 --- a/third_party/harfbuzz-ng/src/hb-blob.cc +++ b/third_party/harfbuzz-ng/src/hb-blob.cc @@ -24,6 +24,9 @@ * Red Hat Author(s): Behdad Esfahbod */ +/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */ +#define _POSIX_C_SOURCE 199309L + #include "hb-private.hh" #include "hb-blob.h" @@ -120,7 +123,7 @@ hb_blob_create_sub_blob (hb_blob_t *parent, blob = hb_blob_create (parent->data + offset, MIN (length, parent->length - offset), - parent->mode, + HB_MEMORY_MODE_READONLY, hb_blob_reference (parent), (hb_destroy_func_t) hb_blob_destroy); diff --git a/third_party/harfbuzz-ng/src/hb-blob.h b/third_party/harfbuzz-ng/src/hb-blob.h index 1a93baa..d3d0f41 100644 --- a/third_party/harfbuzz-ng/src/hb-blob.h +++ b/third_party/harfbuzz-ng/src/hb-blob.h @@ -36,6 +36,26 @@ HB_BEGIN_DECLS +/* + * Note re various memory-modes: + * + * - In no case shall the HarfBuzz client modify memory + * that is passed to HarfBuzz in a blob. If there is + * any such possibility, MODE_DUPLICATE should be used + * such that HarfBuzz makes a copy immediately, + * + * - Use MODE_READONLY otherse, unless you really really + * really know what you are doing, + * + * - MODE_WRITABLE is appropriate if you relaly made a + * copy of data solely for the purpose of passing to + * HarfBuzz and doing that just once (no reuse!), + * + * - If the font is mmap()ed, it's ok to use + * READONLY_MAY_MAKE_WRITABLE, however, there were + * design problems with that mode, so HarfBuzz do not + * really use it anymore. If not sure, use MODE_READONLY. + */ typedef enum { HB_MEMORY_MODE_DUPLICATE, HB_MEMORY_MODE_READONLY, @@ -52,6 +72,12 @@ hb_blob_create (const char *data, void *user_data, hb_destroy_func_t destroy); +/* Always creates with MEMORY_MODE_READONLY. + * Even if the parent blob is writable, we don't + * want the user of the sub-blob to be able to + * modify the parent data as that data may be + * shared among multiple sub-blobs. + */ hb_blob_t * hb_blob_create_sub_blob (hb_blob_t *parent, unsigned int offset, diff --git a/third_party/harfbuzz-ng/src/hb-buffer-deserialize-json.hh b/third_party/harfbuzz-ng/src/hb-buffer-deserialize-json.hh new file mode 100644 index 0000000..b120eaf --- /dev/null +++ b/third_party/harfbuzz-ng/src/hb-buffer-deserialize-json.hh @@ -0,0 +1,643 @@ + +#line 1 "hb-buffer-deserialize-json.rl" +/* + * Copyright © 2013 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_BUFFER_DESERIALIZE_JSON_HH +#define HB_BUFFER_DESERIALIZE_JSON_HH + +#include "hb-private.hh" + + +#line 36 "hb-buffer-deserialize-json.hh.tmp" +static const unsigned char _deserialize_json_trans_keys[] = { + 0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, + 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, + 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, + 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, + 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, + 65u, 122u, 34u, 122u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0 +}; + +static const char _deserialize_json_key_spans[] = { + 0, 115, 26, 7, 2, 1, 50, 49, + 10, 117, 117, 117, 1, 50, 49, 10, + 117, 117, 1, 1, 50, 49, 117, 117, + 2, 1, 50, 49, 10, 117, 117, 1, + 50, 49, 10, 117, 117, 1, 50, 49, + 58, 89, 117, 117, 85, 115, 0 +}; + +static const short _deserialize_json_index_offsets[] = { + 0, 0, 116, 143, 151, 154, 156, 207, + 257, 268, 386, 504, 622, 624, 675, 725, + 736, 854, 972, 974, 976, 1027, 1077, 1195, + 1313, 1316, 1318, 1369, 1419, 1430, 1548, 1666, + 1668, 1719, 1769, 1780, 1898, 2016, 2018, 2069, + 2119, 2178, 2268, 2386, 2504, 2590, 2706 +}; + +static const char _deserialize_json_indicies[] = { + 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 1, 3, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 4, 1, + 5, 1, 6, 7, 1, 1, 8, 1, + 9, 10, 1, 11, 1, 11, 11, 11, + 11, 11, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 11, 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, 12, 1, + 12, 12, 12, 12, 12, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 12, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 13, 1, 1, 14, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 1, 16, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 1, 18, 18, 18, + 18, 18, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 18, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 19, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 20, 1, 21, 21, 21, 21, 21, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 21, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 22, + 1, 18, 18, 18, 18, 18, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 18, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 19, 1, 1, 1, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 20, 1, 23, + 1, 23, 23, 23, 23, 23, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 23, 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, 24, 1, 24, 24, 24, 24, + 24, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 24, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 25, 1, 1, 26, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 1, 28, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 1, 30, 30, 30, 30, 30, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 30, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 31, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 32, 1, 30, + 30, 30, 30, 30, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 30, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 31, 1, 1, 1, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 32, 1, 33, 1, 34, + 1, 34, 34, 34, 34, 34, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 34, 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, 35, 1, 35, 35, 35, 35, + 35, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 35, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 36, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 1, 38, 38, + 38, 38, 38, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 38, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 39, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 40, 1, 38, 38, 38, 38, + 38, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 38, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 39, + 1, 1, 1, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 40, 1, 42, 43, 1, 44, 1, 44, + 44, 44, 44, 44, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 44, 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, + 45, 1, 45, 45, 45, 45, 45, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 45, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 46, 1, + 1, 47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 1, 49, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 1, 51, + 51, 51, 51, 51, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 51, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 52, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 53, 1, 51, 51, 51, + 51, 51, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 51, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 52, 1, 1, 1, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 53, 1, 54, 1, 54, 54, 54, + 54, 54, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 54, 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, 55, 1, + 55, 55, 55, 55, 55, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 55, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 56, 1, 1, 57, + 58, 58, 58, 58, 58, 58, 58, 58, + 58, 1, 59, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 1, 61, 61, 61, + 61, 61, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 61, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 62, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 63, 1, 61, 61, 61, 61, 61, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 61, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 62, 1, + 1, 1, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 63, + 1, 64, 1, 64, 64, 64, 64, 64, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 64, 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, 65, 1, 65, 65, + 65, 65, 65, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 65, 1, 66, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 67, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 1, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 1, 1, 1, 1, 1, 1, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 1, 70, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 71, 71, + 1, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 1, 1, 1, 1, 1, + 1, 1, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 1, 1, 1, 1, + 71, 1, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 1, 72, 72, 72, + 72, 72, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 72, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 73, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 74, 1, 72, 72, 72, 72, 72, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 72, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 73, 1, + 1, 1, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 74, + 1, 76, 76, 76, 76, 76, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 76, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 77, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 78, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 0 +}; + +static const char _deserialize_json_trans_targs[] = { + 1, 0, 2, 2, 3, 4, 18, 24, + 37, 5, 12, 6, 7, 8, 9, 11, + 9, 11, 10, 2, 44, 10, 44, 13, + 14, 15, 16, 17, 16, 17, 10, 2, + 44, 19, 20, 21, 22, 23, 10, 2, + 44, 23, 25, 31, 26, 27, 28, 29, + 30, 29, 30, 10, 2, 44, 32, 33, + 34, 35, 36, 35, 36, 10, 2, 44, + 38, 39, 40, 42, 43, 41, 10, 41, + 10, 2, 44, 43, 44, 45, 46 +}; + +static const char _deserialize_json_trans_actions[] = { + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 2, + 0, 0, 3, 3, 4, 0, 5, 0, + 0, 2, 2, 2, 0, 0, 6, 6, + 7, 0, 0, 0, 2, 2, 8, 8, + 9, 0, 0, 0, 0, 0, 2, 2, + 2, 0, 0, 10, 10, 11, 0, 0, + 2, 2, 2, 0, 0, 12, 12, 13, + 0, 0, 0, 2, 2, 2, 14, 0, + 15, 15, 16, 0, 0, 0, 0 +}; + +static const int deserialize_json_start = 1; +static const int deserialize_json_first_final = 44; +static const int deserialize_json_error = 0; + +static const int deserialize_json_en_main = 1; + + +#line 97 "hb-buffer-deserialize-json.rl" + + +static hb_bool_t +_hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer, + const char *buf, + unsigned int buf_len, + const char **end_ptr, + hb_font_t *font) +{ + const char *p = buf, *pe = buf + buf_len; + + /* Ensure we have positions. */ + (void) hb_buffer_get_glyph_positions (buffer, NULL); + + while (p < pe && ISSPACE (*p)) + p++; + if (p < pe && *p == (buffer->len ? ',' : '[')) + { + *end_ptr = ++p; + } + + const char *tok = NULL; + int cs; + hb_glyph_info_t info; + hb_glyph_position_t pos; + +#line 466 "hb-buffer-deserialize-json.hh.tmp" + { + cs = deserialize_json_start; + } + +#line 471 "hb-buffer-deserialize-json.hh.tmp" + { + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _deserialize_json_trans_keys + (cs<<1); + _inds = _deserialize_json_indicies + _deserialize_json_index_offsets[cs]; + + _slen = _deserialize_json_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=(*p) && + (*p) <= _keys[1] ? + (*p) - _keys[0] : _slen ]; + + cs = _deserialize_json_trans_targs[_trans]; + + if ( _deserialize_json_trans_actions[_trans] == 0 ) + goto _again; + + switch ( _deserialize_json_trans_actions[_trans] ) { + case 1: +#line 38 "hb-buffer-deserialize-json.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} + break; + case 5: +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 2: +#line 51 "hb-buffer-deserialize-json.rl" + { + tok = p; +} + break; + case 14: +#line 55 "hb-buffer-deserialize-json.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 15: +#line 62 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.codepoint)) return false; } + break; + case 8: +#line 63 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 10: +#line 64 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 12: +#line 65 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 3: +#line 66 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 6: +#line 67 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } + break; + case 16: +#line 62 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.codepoint)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 9: +#line 63 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 64 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 13: +#line 65 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 4: +#line 66 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 7: +#line 67 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 624 "hb-buffer-deserialize-json.hh.tmp" + } + +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + _out: {} + } + +#line 125 "hb-buffer-deserialize-json.rl" + + + *end_ptr = p; + + return p == pe && *(p-1) != ']'; +} + +#endif /* HB_BUFFER_DESERIALIZE_JSON_HH */ diff --git a/third_party/harfbuzz-ng/src/hb-buffer-deserialize-text.hh b/third_party/harfbuzz-ng/src/hb-buffer-deserialize-text.hh new file mode 100644 index 0000000..f95704b --- /dev/null +++ b/third_party/harfbuzz-ng/src/hb-buffer-deserialize-text.hh @@ -0,0 +1,571 @@ + +#line 1 "hb-buffer-deserialize-text.rl" +/* + * Copyright © 2013 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_BUFFER_DESERIALIZE_TEXT_HH +#define HB_BUFFER_DESERIALIZE_TEXT_HH + +#include "hb-private.hh" + + +#line 36 "hb-buffer-deserialize-text.hh.tmp" +static const unsigned char _deserialize_text_trans_keys[] = { + 0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, + 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, + 9u, 122u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, + 9u, 124u, 9u, 124u, 9u, 124u, 0 +}; + +static const char _deserialize_text_key_spans[] = { + 0, 114, 13, 10, 13, 10, 10, 13, + 10, 1, 13, 10, 14, 116, 116, 0, + 114, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116 +}; + +static const short _deserialize_text_index_offsets[] = { + 0, 0, 115, 129, 140, 154, 165, 176, + 190, 201, 203, 217, 228, 243, 360, 477, + 478, 593, 710, 827, 944, 1061, 1178, 1295, + 1412, 1529, 1646 +}; + +static const char _deserialize_text_indicies[] = { + 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 1, + 1, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 1, 1, 1, 1, 1, + 1, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 1, 5, 1, 1, 6, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 1, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 1, 10, 1, 1, + 11, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 1, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 1, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 1, 17, 1, 1, 18, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 1, 20, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 1, 22, 1, 23, 1, 1, 24, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 1, 26, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 1, 22, 1, 1, + 1, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 1, 28, 28, 28, 28, + 28, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 28, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 29, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 30, 1, 1, 31, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 32, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 33, + 1, 34, 34, 34, 34, 34, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 34, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 35, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 36, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 1, 1, 1, 1, 1, 1, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 1, 28, 28, 28, 28, 28, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 28, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 29, 1, 1, 1, + 1, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 1, 1, 1, 30, 1, + 1, 31, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 32, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 33, 1, 38, + 38, 38, 38, 38, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 38, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 39, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 40, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 41, 1, 42, 42, 42, 42, + 42, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 42, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 43, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 44, + 1, 42, 42, 42, 42, 42, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 42, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 43, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 44, 1, 38, 38, + 38, 38, 38, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 38, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 39, 1, 1, 1, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 40, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 41, 1, 45, 45, 45, 45, 45, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 45, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 46, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 47, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 48, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 49, 1, + 50, 50, 50, 50, 50, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 50, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 51, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 52, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 53, 1, 50, 50, 50, + 50, 50, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 50, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 51, + 1, 1, 1, 1, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 52, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 53, 1, 45, 45, 45, 45, 45, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 45, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 46, 1, 1, 1, + 1, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 1, 1, 1, 1, 1, + 1, 47, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 48, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 49, 1, 28, + 28, 28, 28, 28, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 28, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 29, 1, 55, 55, 1, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 1, 1, 1, 30, 1, 1, 31, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 1, 1, 32, 1, 55, 1, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 1, 33, 1, 0 +}; + +static const char _deserialize_text_trans_targs[] = { + 1, 0, 13, 17, 26, 3, 18, 21, + 18, 21, 5, 19, 20, 19, 20, 22, + 25, 8, 9, 12, 9, 12, 10, 11, + 23, 24, 23, 24, 14, 2, 6, 7, + 15, 16, 14, 15, 16, 17, 14, 4, + 15, 16, 14, 15, 16, 14, 2, 7, + 15, 16, 14, 2, 15, 16, 25, 26 +}; + +static const char _deserialize_text_trans_actions[] = { + 0, 0, 1, 1, 1, 2, 2, 2, + 0, 0, 2, 2, 2, 0, 0, 2, + 2, 2, 2, 2, 0, 0, 3, 2, + 2, 2, 0, 0, 4, 5, 5, 5, + 4, 4, 0, 0, 0, 0, 6, 7, + 6, 6, 8, 8, 8, 9, 10, 10, + 9, 9, 11, 12, 11, 11, 0, 0 +}; + +static const char _deserialize_text_eof_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, + 0, 4, 6, 8, 8, 6, 9, 11, + 11, 9, 4 +}; + +static const int deserialize_text_start = 1; +static const int deserialize_text_first_final = 13; +static const int deserialize_text_error = 0; + +static const int deserialize_text_en_main = 1; + + +#line 91 "hb-buffer-deserialize-text.rl" + + +static hb_bool_t +_hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer, + const char *buf, + unsigned int buf_len, + const char **end_ptr, + hb_font_t *font) +{ + const char *p = buf, *pe = buf + buf_len; + + /* Ensure we have positions. */ + (void) hb_buffer_get_glyph_positions (buffer, NULL); + + while (p < pe && ISSPACE (*p)) + p++; + if (p < pe && *p == (buffer->len ? '|' : '[')) + { + *end_ptr = ++p; + } + + const char *eof = pe, *tok = NULL; + int cs; + hb_glyph_info_t info; + hb_glyph_position_t pos; + +#line 343 "hb-buffer-deserialize-text.hh.tmp" + { + cs = deserialize_text_start; + } + +#line 348 "hb-buffer-deserialize-text.hh.tmp" + { + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _deserialize_text_trans_keys + (cs<<1); + _inds = _deserialize_text_indicies + _deserialize_text_index_offsets[cs]; + + _slen = _deserialize_text_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=(*p) && + (*p) <= _keys[1] ? + (*p) - _keys[0] : _slen ]; + + cs = _deserialize_text_trans_targs[_trans]; + + if ( _deserialize_text_trans_actions[_trans] == 0 ) + goto _again; + + switch ( _deserialize_text_trans_actions[_trans] ) { + case 2: +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} + break; + case 5: +#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 10: +#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 3: +#line 63 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 12: +#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 7: +#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 1: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} + break; + case 4: +#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 9: +#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 6: +#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 8: +#line 66 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 480 "hb-buffer-deserialize-text.hh.tmp" + } + +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + if ( p == eof ) + { + switch ( _deserialize_text_eof_actions[cs] ) { + case 4: +#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 9: +#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 6: +#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 8: +#line 66 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 557 "hb-buffer-deserialize-text.hh.tmp" + } + } + + _out: {} + } + +#line 119 "hb-buffer-deserialize-text.rl" + + + *end_ptr = p; + + return p == pe && *(p-1) != ']'; +} + +#endif /* HB_BUFFER_DESERIALIZE_TEXT_HH */ diff --git a/third_party/harfbuzz-ng/src/hb-buffer-private.hh b/third_party/harfbuzz-ng/src/hb-buffer-private.hh index 13cf4bb..387ebd9 100644 --- a/third_party/harfbuzz-ng/src/hb-buffer-private.hh +++ b/third_party/harfbuzz-ng/src/hb-buffer-private.hh @@ -110,6 +110,7 @@ struct hb_buffer_t { HB_INTERNAL void add (hb_codepoint_t codepoint, unsigned int cluster); + HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info); HB_INTERNAL void reverse_range (unsigned int start, unsigned int end); HB_INTERNAL void reverse (void); @@ -128,7 +129,7 @@ struct hb_buffer_t { HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index); /* Makes a copy of the glyph at idx to output and replace glyph_index */ HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index); - HB_INTERNAL void output_info (hb_glyph_info_t &glyph_info); + HB_INTERNAL void output_info (const hb_glyph_info_t &glyph_info); /* Copies glyph at idx to output but doesn't advance idx */ HB_INTERNAL void copy_glyph (void); /* Copies glyph at idx to output and advance idx. diff --git a/third_party/harfbuzz-ng/src/hb-buffer-serialize.cc b/third_party/harfbuzz-ng/src/hb-buffer-serialize.cc new file mode 100644 index 0000000..dc47ba7 --- /dev/null +++ b/third_party/harfbuzz-ng/src/hb-buffer-serialize.cc @@ -0,0 +1,336 @@ +/* + * Copyright © 2012,2013 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-buffer-private.hh" + + +static const char *serialize_formats[] = { + "text", + "json", + NULL +}; + +const char ** +hb_buffer_serialize_list_formats (void) +{ + return serialize_formats; +} + +hb_buffer_serialize_format_t +hb_buffer_serialize_format_from_string (const char *str, int len) +{ + /* Upper-case it. */ + return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020); +} + +const char * +hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) +{ + switch (format) + { + case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0]; + case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1]; + default: + case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return NULL; + } +} + +static unsigned int +_hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, + unsigned int *buf_consumed, + hb_font_t *font, + hb_buffer_serialize_flags_t flags) +{ + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); + + *buf_consumed = 0; + for (unsigned int i = start; i < end; i++) + { + char b[1024]; + char *p = b; + + /* In the following code, we know b is large enough that no overflow can happen. */ + +#define APPEND(s) HB_STMT_START { strcpy (p, s); p += strlen (s); } HB_STMT_END + + if (i) + *p++ = ','; + + *p++ = '{'; + + APPEND ("\"g\":"); + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES)) + { + char g[128]; + hb_font_glyph_to_string (font, info[i].codepoint, g, sizeof (g)); + *p++ = '"'; + for (char *q = g; *q; q++) { + if (*q == '"') + *p++ = '\\'; + *p++ = *q; + } + *p++ = '"'; + } + else + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint); + + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster); + } + + 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++ = '}'; + + if (buf_size > (p - b)) + { + unsigned int l = p - b; + memcpy (buf, b, l); + buf += l; + buf_size -= l; + *buf_consumed += l; + *buf = '\0'; + } else + return i - start; + } + + return end - start; +} + +static unsigned int +_hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, + unsigned int *buf_consumed, + hb_font_t *font, + hb_buffer_serialize_flags_t flags) +{ + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); + + *buf_consumed = 0; + for (unsigned int i = start; i < end; i++) + { + char b[1024]; + char *p = b; + + /* In the following code, we know b is large enough that no overflow can happen. */ + + if (i) + *p++ = '|'; + + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES)) + { + hb_font_glyph_to_string (font, info[i].codepoint, p, 128); + p += strlen (p); + } + else + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint); + + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster); + } + + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) + { + if (pos[i].x_offset || pos[i].y_offset) + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", pos[i].x_offset, pos[i].y_offset); + + *p++ = '+'; + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance); + if (pos->y_advance) + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance); + } + + if (buf_size > (p - b)) + { + unsigned int l = p - b; + memcpy (buf, b, l); + buf += l; + buf_size -= l; + *buf_consumed += l; + *buf = '\0'; + } else + return i - start; + } + + return end - start; +} + +/* Returns number of items, starting at start, that were serialized. */ +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 */ + hb_buffer_serialize_format_t format, + hb_buffer_serialize_flags_t flags) +{ + assert (start <= end && end <= buffer->len); + + unsigned int sconsumed; + if (!buf_consumed) + buf_consumed = &sconsumed; + *buf_consumed = 0; + + assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || + buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); + + if (unlikely (start == end)) + return 0; + + if (!font) + font = hb_font_get_empty (); + + switch (format) + { + case HB_BUFFER_SERIALIZE_FORMAT_TEXT: + return _hb_buffer_serialize_glyphs_text (buffer, start, end, + buf, buf_size, buf_consumed, + font, flags); + + case HB_BUFFER_SERIALIZE_FORMAT_JSON: + return _hb_buffer_serialize_glyphs_json (buffer, start, end, + buf, buf_size, buf_consumed, + font, flags); + + default: + case HB_BUFFER_SERIALIZE_FORMAT_INVALID: + return 0; + + } +} + + +static hb_bool_t +parse_uint (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; + uint32_t v; + + errno = 0; + v = strtol (p, &pend, 10); + if (errno || p == pend || pend - p != end - pp) + return false; + + *pv = v; + return true; +} + +static hb_bool_t +parse_int (const char *pp, const char *end, int32_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; + int32_t v; + + errno = 0; + v = strtol (p, &pend, 10); + if (errno || p == pend || pend - p != end - pp) + return false; + + *pv = v; + return true; +} + +#include "hb-buffer-deserialize-json.hh" +#include "hb-buffer-deserialize-text.hh" + +hb_bool_t +hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, + const char *buf, + int buf_len, /* -1 means nul-terminated */ + const char **end_ptr, /* May be NULL */ + hb_font_t *font, /* May be NULL */ + hb_buffer_serialize_format_t format) +{ + const char *end; + if (!end_ptr) + end_ptr = &end; + *end_ptr = buf; + + assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || + buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); + + if (buf_len == -1) + buf_len = strlen (buf); + + if (!buf_len) + { + *end_ptr = buf; + return false; + } + + hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); + + if (!font) + font = hb_font_get_empty (); + + switch (format) + { + case HB_BUFFER_SERIALIZE_FORMAT_TEXT: + return _hb_buffer_deserialize_glyphs_text (buffer, + buf, buf_len, end_ptr, + font); + + case HB_BUFFER_SERIALIZE_FORMAT_JSON: + return _hb_buffer_deserialize_glyphs_json (buffer, + buf, buf_len, end_ptr, + font); + + default: + case HB_BUFFER_SERIALIZE_FORMAT_INVALID: + return false; + + } +} diff --git a/third_party/harfbuzz-ng/src/hb-buffer.cc b/third_party/harfbuzz-ng/src/hb-buffer.cc index 4b644e4..4e26250 100644 --- a/third_party/harfbuzz-ng/src/hb-buffer.cc +++ b/third_party/harfbuzz-ng/src/hb-buffer.cc @@ -215,6 +215,17 @@ hb_buffer_t::add (hb_codepoint_t codepoint, } void +hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info) +{ + if (unlikely (!ensure (len + 1))) return; + + info[len] = glyph_info; + + len++; +} + + +void hb_buffer_t::remove_output (void) { if (unlikely (hb_object_is_inert (this))) @@ -315,7 +326,7 @@ hb_buffer_t::output_glyph (hb_codepoint_t glyph_index) } void -hb_buffer_t::output_info (hb_glyph_info_t &glyph_info) +hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info) { if (unlikely (!make_room_for (0, 1))) return; @@ -790,7 +801,7 @@ hb_buffer_reset (hb_buffer_t *buffer) } void -hb_buffer_clear (hb_buffer_t *buffer) +hb_buffer_clear_contents (hb_buffer_t *buffer) { buffer->clear (); } @@ -1064,231 +1075,3 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer) } normalize_glyphs_cluster (buffer, start, end, backward); } - - -/* - * Serialize - */ - -static const char *serialize_formats[] = { - "text", - "json", - NULL -}; - -const char ** -hb_buffer_serialize_list_formats (void) -{ - return serialize_formats; -} - -hb_buffer_serialize_format_t -hb_buffer_serialize_format_from_string (const char *str, int len) -{ - /* Upper-case it. */ - return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020); -} - -const char * -hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) -{ - switch (format) - { - case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0]; - case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1]; - default: - case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return NULL; - } -} - -static unsigned int -_hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, - unsigned int start, - unsigned int end, - char *buf, - unsigned int buf_size, - unsigned int *buf_consumed, - hb_font_t *font, - hb_buffer_serialize_flags_t flags) -{ - hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); - hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); - - *buf_consumed = 0; - for (unsigned int i = start; i < end; i++) - { - char b[1024]; - char *p = b; - - /* In the following code, we know b is large enough that no overflow can happen. */ - -#define APPEND(s) HB_STMT_START { strcpy (p, s); p += strlen (s); } HB_STMT_END - - if (i) - *p++ = ','; - - *p++ = '{'; - - APPEND ("\"g\":"); - if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES)) - { - char g[128]; - hb_font_glyph_to_string (font, info[i].codepoint, g, sizeof (g)); - *p++ = '"'; - for (char *q = g; *q; q++) { - if (*q == '"') - *p++ = '\\'; - *p++ = *q; - } - *p++ = '"'; - } - else - p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint); - - if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { - p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster); - } - - 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++ = '}'; - - if (buf_size > (p - b)) - { - unsigned int l = p - b; - memcpy (buf, b, l); - buf += l; - buf_size -= l; - *buf_consumed += l; - *buf = '\0'; - } else - return i - start; - } - - return end - start; -} - -static unsigned int -_hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, - unsigned int start, - unsigned int end, - char *buf, - unsigned int buf_size, - unsigned int *buf_consumed, - hb_font_t *font, - hb_buffer_serialize_flags_t flags) -{ - hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); - hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); - hb_direction_t direction = hb_buffer_get_direction (buffer); - - *buf_consumed = 0; - for (unsigned int i = start; i < end; i++) - { - char b[1024]; - char *p = b; - - /* In the following code, we know b is large enough that no overflow can happen. */ - - if (i) - *p++ = '|'; - - if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES)) - { - hb_font_glyph_to_string (font, info[i].codepoint, p, 128); - p += strlen (p); - } - else - p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint); - - if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { - p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster); - } - - if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) - { - if (pos[i].x_offset || pos[i].y_offset) - p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", pos[i].x_offset, pos[i].y_offset); - - *p++ = '+'; - if (HB_DIRECTION_IS_HORIZONTAL (direction) || pos[i].x_advance) - p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance); - if (HB_DIRECTION_IS_VERTICAL (direction) || pos->y_advance) - p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance); - } - - if (buf_size > (p - b)) - { - unsigned int l = p - b; - memcpy (buf, b, l); - buf += l; - buf_size -= l; - *buf_consumed += l; - *buf = '\0'; - } else - return i - start; - } - - return end - start; -} - -/* Returns number of items, starting at start, that were serialized. */ -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, - hb_font_t *font, /* May be NULL */ - hb_buffer_serialize_format_t format, - hb_buffer_serialize_flags_t flags) -{ - assert (start <= end && end <= buffer->len); - - *buf_consumed = 0; - - assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || - buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); - - if (unlikely (start == end)) - return 0; - - if (!font) - font = hb_font_get_empty (); - - switch (format) - { - case HB_BUFFER_SERIALIZE_FORMAT_TEXT: - return _hb_buffer_serialize_glyphs_text (buffer, start, end, - buf, buf_size, buf_consumed, - font, flags); - - case HB_BUFFER_SERIALIZE_FORMAT_JSON: - return _hb_buffer_serialize_glyphs_json (buffer, start, end, - buf, buf_size, buf_consumed, - font, flags); - - default: - case HB_BUFFER_SERIALIZE_FORMAT_INVALID: - return 0; - - } -} - -hb_bool_t -hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, - const char *buf, - unsigned int buf_len, - unsigned int *buf_consumed, - hb_font_t *font, /* May be NULL */ - hb_buffer_serialize_format_t format) -{ - return false; -} diff --git a/third_party/harfbuzz-ng/src/hb-buffer.h b/third_party/harfbuzz-ng/src/hb-buffer.h index 48ec4a5..55a4045 100644 --- a/third_party/harfbuzz-ng/src/hb-buffer.h +++ b/third_party/harfbuzz-ng/src/hb-buffer.h @@ -193,7 +193,7 @@ hb_buffer_reset (hb_buffer_t *buffer); /* Like reset, but does NOT clear unicode_funcs. */ void -hb_buffer_clear (hb_buffer_t *buffer); +hb_buffer_clear_contents (hb_buffer_t *buffer); /* Returns false if allocation failed */ hb_bool_t @@ -304,7 +304,7 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, unsigned int end, char *buf, unsigned int buf_size, - unsigned int *buf_consumed, + unsigned int *buf_consumed, /* May be NULL */ hb_font_t *font, /* May be NULL */ hb_buffer_serialize_format_t format, hb_buffer_serialize_flags_t flags); @@ -312,8 +312,8 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, hb_bool_t hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, const char *buf, - unsigned int buf_len, - unsigned int *buf_consumed, + int buf_len, /* -1 means nul-terminated */ + const char **end_ptr, /* May be NULL */ hb_font_t *font, /* May be NULL */ hb_buffer_serialize_format_t format); diff --git a/third_party/harfbuzz-ng/src/hb-common.cc b/third_party/harfbuzz-ng/src/hb-common.cc index 9422555..540d252 100644 --- a/third_party/harfbuzz-ng/src/hb-common.cc +++ b/third_party/harfbuzz-ng/src/hb-common.cc @@ -36,6 +36,24 @@ #include <locale.h> +/* hb_options_t */ + +hb_options_union_t _hb_options; + +void +_hb_options_init (void) +{ + hb_options_union_t u; + u.i = 0; + u.opts.initialized = 1; + + char *c = getenv ("HB_OPTIONS"); + u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible"); + + /* This is idempotent and threadsafe. */ + _hb_options = u; +} + /* hb_tag_t */ @@ -177,7 +195,7 @@ struct hb_language_item_t { static hb_language_item_t *langs; -static +static inline void free_langs (void) { while (langs) { @@ -414,5 +432,3 @@ hb_version_check (unsigned int major, { return HB_VERSION_CHECK (major, minor, micro); } - - diff --git a/third_party/harfbuzz-ng/src/hb-fallback-shape.cc b/third_party/harfbuzz-ng/src/hb-fallback-shape.cc index bdc8a80..1a1fcfb 100644 --- a/third_party/harfbuzz-ng/src/hb-fallback-shape.cc +++ b/third_party/harfbuzz-ng/src/hb-fallback-shape.cc @@ -98,7 +98,6 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, hb_codepoint_t space; font->get_glyph (' ', 0, &space); - buffer->guess_segment_properties (); buffer->clear_positions (); unsigned int count = buffer->len; diff --git a/third_party/harfbuzz-ng/src/hb-ft.cc b/third_party/harfbuzz-ng/src/hb-ft.cc index 6198185..978230c 100644 --- a/third_party/harfbuzz-ng/src/hb-ft.cc +++ b/third_party/harfbuzz-ng/src/hb-ft.cc @@ -53,14 +53,7 @@ * * - We don't handle / allow for emboldening / obliqueing. * - * - Rounding, etc? - * - * - In the future, we should add constructors to create fonts in font space. - * - * - I believe transforms are not correctly implemented. FreeType does not - * provide any API to get to the transform/delta set on the face. :( - * - * - Always use FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH? + * - In the future, we should add constructors to create fonts in font space? * * - FT_Load_Glyph() is exteremely costly. Do something about it? */ @@ -242,8 +235,8 @@ hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED, FT_Face ft_face = (FT_Face) font_data; hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size); - if (!ret || (size && !*name)) - snprintf (name, size, "gid%u", glyph); + if (ret && (size && !*name)) + ret = false; return ret; } @@ -403,7 +396,7 @@ hb_ft_font_create (FT_Face ft_face, static FT_Library ft_library; -static +static inline void free_ft_library (void) { FT_Done_FreeType (ft_library); diff --git a/third_party/harfbuzz-ng/src/hb-gobject-enums.cc b/third_party/harfbuzz-ng/src/hb-gobject-enums.cc deleted file mode 100644 index 5045923..0000000 --- a/third_party/harfbuzz-ng/src/hb-gobject-enums.cc +++ /dev/null @@ -1,366 +0,0 @@ - -/* Generated data (by glib-mkenums) */ - -/* - * Copyright © 2011 Google, Inc. - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Google Author(s): Behdad Esfahbod - */ - -#include "hb-private.hh" - -/* g++ didn't like older gtype.h gcc-only code path. */ -#include <glib.h> -#if !GLIB_CHECK_VERSION(2,29,16) -#undef __GNUC__ -#undef __GNUC_MINOR__ -#define __GNUC__ 2 -#define __GNUC_MINOR__ 6 -#endif - -#include "hb-gobject.h" - -/* enumerations from "hb-blob.h" */ -inline static /* TODO(behdad) disable these for now until we fix them... */ -GType -hb_memory_mode_t_hb_memory_mode_t_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { HB_MEMORY_MODE_DUPLICATE, "HB_MEMORY_MODE_DUPLICATE", "duplicate" }, - { HB_MEMORY_MODE_READONLY, "HB_MEMORY_MODE_READONLY", "readonly" }, - { HB_MEMORY_MODE_WRITABLE, "HB_MEMORY_MODE_WRITABLE", "writable" }, - { HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, "HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE", "readonly-may-make-writable" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("hb_memory_mode_t"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} - -/* enumerations from "hb-buffer.h" */ -inline static /* TODO(behdad) disable these for now until we fix them... */ -GType -hb_buffer_content_type_t_hb_buffer_content_type_t_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { HB_BUFFER_CONTENT_TYPE_INVALID, "HB_BUFFER_CONTENT_TYPE_INVALID", "invalid" }, - { HB_BUFFER_CONTENT_TYPE_UNICODE, "HB_BUFFER_CONTENT_TYPE_UNICODE", "unicode" }, - { HB_BUFFER_CONTENT_TYPE_GLYPHS, "HB_BUFFER_CONTENT_TYPE_GLYPHS", "glyphs" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("hb_buffer_content_type_t"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} - -/* enumerations from "hb-common.h" */ -inline static /* TODO(behdad) disable these for now until we fix them... */ -GType -hb_direction_t_hb_direction_t_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { HB_DIRECTION_INVALID, "HB_DIRECTION_INVALID", "invalid" }, - { HB_DIRECTION_LTR, "HB_DIRECTION_LTR", "ltr" }, - { HB_DIRECTION_RTL, "HB_DIRECTION_RTL", "rtl" }, - { HB_DIRECTION_TTB, "HB_DIRECTION_TTB", "ttb" }, - { HB_DIRECTION_BTT, "HB_DIRECTION_BTT", "btt" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("hb_direction_t"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} - -inline static /* TODO(behdad) disable these for now until we fix them... */ -GType -hb_script_t_hb_script_t_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { HB_SCRIPT_COMMON, "HB_SCRIPT_COMMON", "common" }, - { HB_SCRIPT_ARABIC, "HB_SCRIPT_ARABIC", "arabic" }, - { HB_SCRIPT_ARMENIAN, "HB_SCRIPT_ARMENIAN", "armenian" }, - { HB_SCRIPT_BENGALI, "HB_SCRIPT_BENGALI", "bengali" }, - { HB_SCRIPT_BOPOMOFO, "HB_SCRIPT_BOPOMOFO", "bopomofo" }, - { HB_SCRIPT_CANADIAN_ABORIGINAL, "HB_SCRIPT_CANADIAN_ABORIGINAL", "canadian-aboriginal" }, - { HB_SCRIPT_CHEROKEE, "HB_SCRIPT_CHEROKEE", "cherokee" }, - { HB_SCRIPT_COPTIC, "HB_SCRIPT_COPTIC", "coptic" }, - { HB_SCRIPT_CYRILLIC, "HB_SCRIPT_CYRILLIC", "cyrillic" }, - { HB_SCRIPT_DEVANAGARI, "HB_SCRIPT_DEVANAGARI", "devanagari" }, - { HB_SCRIPT_GEORGIAN, "HB_SCRIPT_GEORGIAN", "georgian" }, - { HB_SCRIPT_GREEK, "HB_SCRIPT_GREEK", "greek" }, - { HB_SCRIPT_GUJARATI, "HB_SCRIPT_GUJARATI", "gujarati" }, - { HB_SCRIPT_GURMUKHI, "HB_SCRIPT_GURMUKHI", "gurmukhi" }, - { HB_SCRIPT_HANGUL, "HB_SCRIPT_HANGUL", "hangul" }, - { HB_SCRIPT_HAN, "HB_SCRIPT_HAN", "han" }, - { HB_SCRIPT_HEBREW, "HB_SCRIPT_HEBREW", "hebrew" }, - { HB_SCRIPT_HIRAGANA, "HB_SCRIPT_HIRAGANA", "hiragana" }, - { HB_SCRIPT_INHERITED, "HB_SCRIPT_INHERITED", "inherited" }, - { HB_SCRIPT_KANNADA, "HB_SCRIPT_KANNADA", "kannada" }, - { HB_SCRIPT_KATAKANA, "HB_SCRIPT_KATAKANA", "katakana" }, - { HB_SCRIPT_LAO, "HB_SCRIPT_LAO", "lao" }, - { HB_SCRIPT_LATIN, "HB_SCRIPT_LATIN", "latin" }, - { HB_SCRIPT_MALAYALAM, "HB_SCRIPT_MALAYALAM", "malayalam" }, - { HB_SCRIPT_MONGOLIAN, "HB_SCRIPT_MONGOLIAN", "mongolian" }, - { HB_SCRIPT_OGHAM, "HB_SCRIPT_OGHAM", "ogham" }, - { HB_SCRIPT_ORIYA, "HB_SCRIPT_ORIYA", "oriya" }, - { HB_SCRIPT_RUNIC, "HB_SCRIPT_RUNIC", "runic" }, - { HB_SCRIPT_SYRIAC, "HB_SCRIPT_SYRIAC", "syriac" }, - { HB_SCRIPT_TAMIL, "HB_SCRIPT_TAMIL", "tamil" }, - { HB_SCRIPT_TELUGU, "HB_SCRIPT_TELUGU", "telugu" }, - { HB_SCRIPT_THAI, "HB_SCRIPT_THAI", "thai" }, - { HB_SCRIPT_YI, "HB_SCRIPT_YI", "yi" }, - { HB_SCRIPT_TIBETAN, "HB_SCRIPT_TIBETAN", "tibetan" }, - { HB_SCRIPT_ETHIOPIC, "HB_SCRIPT_ETHIOPIC", "ethiopic" }, - { HB_SCRIPT_KHMER, "HB_SCRIPT_KHMER", "khmer" }, - { HB_SCRIPT_MYANMAR, "HB_SCRIPT_MYANMAR", "myanmar" }, - { HB_SCRIPT_SINHALA, "HB_SCRIPT_SINHALA", "sinhala" }, - { HB_SCRIPT_THAANA, "HB_SCRIPT_THAANA", "thaana" }, - { HB_SCRIPT_DESERET, "HB_SCRIPT_DESERET", "deseret" }, - { HB_SCRIPT_GOTHIC, "HB_SCRIPT_GOTHIC", "gothic" }, - { HB_SCRIPT_OLD_ITALIC, "HB_SCRIPT_OLD_ITALIC", "old-italic" }, - { HB_SCRIPT_BUHID, "HB_SCRIPT_BUHID", "buhid" }, - { HB_SCRIPT_HANUNOO, "HB_SCRIPT_HANUNOO", "hanunoo" }, - { HB_SCRIPT_TAGALOG, "HB_SCRIPT_TAGALOG", "tagalog" }, - { HB_SCRIPT_TAGBANWA, "HB_SCRIPT_TAGBANWA", "tagbanwa" }, - { HB_SCRIPT_BRAILLE, "HB_SCRIPT_BRAILLE", "braille" }, - { HB_SCRIPT_CYPRIOT, "HB_SCRIPT_CYPRIOT", "cypriot" }, - { HB_SCRIPT_LIMBU, "HB_SCRIPT_LIMBU", "limbu" }, - { HB_SCRIPT_LINEAR_B, "HB_SCRIPT_LINEAR_B", "linear-b" }, - { HB_SCRIPT_OSMANYA, "HB_SCRIPT_OSMANYA", "osmanya" }, - { HB_SCRIPT_SHAVIAN, "HB_SCRIPT_SHAVIAN", "shavian" }, - { HB_SCRIPT_TAI_LE, "HB_SCRIPT_TAI_LE", "tai-le" }, - { HB_SCRIPT_UGARITIC, "HB_SCRIPT_UGARITIC", "ugaritic" }, - { HB_SCRIPT_BUGINESE, "HB_SCRIPT_BUGINESE", "buginese" }, - { HB_SCRIPT_GLAGOLITIC, "HB_SCRIPT_GLAGOLITIC", "glagolitic" }, - { HB_SCRIPT_KHAROSHTHI, "HB_SCRIPT_KHAROSHTHI", "kharoshthi" }, - { HB_SCRIPT_NEW_TAI_LUE, "HB_SCRIPT_NEW_TAI_LUE", "new-tai-lue" }, - { HB_SCRIPT_OLD_PERSIAN, "HB_SCRIPT_OLD_PERSIAN", "old-persian" }, - { HB_SCRIPT_SYLOTI_NAGRI, "HB_SCRIPT_SYLOTI_NAGRI", "syloti-nagri" }, - { HB_SCRIPT_TIFINAGH, "HB_SCRIPT_TIFINAGH", "tifinagh" }, - { HB_SCRIPT_BALINESE, "HB_SCRIPT_BALINESE", "balinese" }, - { HB_SCRIPT_CUNEIFORM, "HB_SCRIPT_CUNEIFORM", "cuneiform" }, - { HB_SCRIPT_NKO, "HB_SCRIPT_NKO", "nko" }, - { HB_SCRIPT_PHAGS_PA, "HB_SCRIPT_PHAGS_PA", "phags-pa" }, - { HB_SCRIPT_PHOENICIAN, "HB_SCRIPT_PHOENICIAN", "phoenician" }, - { HB_SCRIPT_UNKNOWN, "HB_SCRIPT_UNKNOWN", "unknown" }, - { HB_SCRIPT_CARIAN, "HB_SCRIPT_CARIAN", "carian" }, - { HB_SCRIPT_CHAM, "HB_SCRIPT_CHAM", "cham" }, - { HB_SCRIPT_KAYAH_LI, "HB_SCRIPT_KAYAH_LI", "kayah-li" }, - { HB_SCRIPT_LEPCHA, "HB_SCRIPT_LEPCHA", "lepcha" }, - { HB_SCRIPT_LYCIAN, "HB_SCRIPT_LYCIAN", "lycian" }, - { HB_SCRIPT_LYDIAN, "HB_SCRIPT_LYDIAN", "lydian" }, - { HB_SCRIPT_OL_CHIKI, "HB_SCRIPT_OL_CHIKI", "ol-chiki" }, - { HB_SCRIPT_REJANG, "HB_SCRIPT_REJANG", "rejang" }, - { HB_SCRIPT_SAURASHTRA, "HB_SCRIPT_SAURASHTRA", "saurashtra" }, - { HB_SCRIPT_SUNDANESE, "HB_SCRIPT_SUNDANESE", "sundanese" }, - { HB_SCRIPT_VAI, "HB_SCRIPT_VAI", "vai" }, - { HB_SCRIPT_AVESTAN, "HB_SCRIPT_AVESTAN", "avestan" }, - { HB_SCRIPT_BAMUM, "HB_SCRIPT_BAMUM", "bamum" }, - { HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, "HB_SCRIPT_EGYPTIAN_HIEROGLYPHS", "egyptian-hieroglyphs" }, - { HB_SCRIPT_IMPERIAL_ARAMAIC, "HB_SCRIPT_IMPERIAL_ARAMAIC", "imperial-aramaic" }, - { HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, "HB_SCRIPT_INSCRIPTIONAL_PAHLAVI", "inscriptional-pahlavi" }, - { HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, "HB_SCRIPT_INSCRIPTIONAL_PARTHIAN", "inscriptional-parthian" }, - { HB_SCRIPT_JAVANESE, "HB_SCRIPT_JAVANESE", "javanese" }, - { HB_SCRIPT_KAITHI, "HB_SCRIPT_KAITHI", "kaithi" }, - { HB_SCRIPT_LISU, "HB_SCRIPT_LISU", "lisu" }, - { HB_SCRIPT_MEETEI_MAYEK, "HB_SCRIPT_MEETEI_MAYEK", "meetei-mayek" }, - { HB_SCRIPT_OLD_SOUTH_ARABIAN, "HB_SCRIPT_OLD_SOUTH_ARABIAN", "old-south-arabian" }, - { HB_SCRIPT_OLD_TURKIC, "HB_SCRIPT_OLD_TURKIC", "old-turkic" }, - { HB_SCRIPT_SAMARITAN, "HB_SCRIPT_SAMARITAN", "samaritan" }, - { HB_SCRIPT_TAI_THAM, "HB_SCRIPT_TAI_THAM", "tai-tham" }, - { HB_SCRIPT_TAI_VIET, "HB_SCRIPT_TAI_VIET", "tai-viet" }, - { HB_SCRIPT_BATAK, "HB_SCRIPT_BATAK", "batak" }, - { HB_SCRIPT_BRAHMI, "HB_SCRIPT_BRAHMI", "brahmi" }, - { HB_SCRIPT_MANDAIC, "HB_SCRIPT_MANDAIC", "mandaic" }, - { HB_SCRIPT_CHAKMA, "HB_SCRIPT_CHAKMA", "chakma" }, - { HB_SCRIPT_MEROITIC_CURSIVE, "HB_SCRIPT_MEROITIC_CURSIVE", "meroitic-cursive" }, - { HB_SCRIPT_MEROITIC_HIEROGLYPHS, "HB_SCRIPT_MEROITIC_HIEROGLYPHS", "meroitic-hieroglyphs" }, - { HB_SCRIPT_MIAO, "HB_SCRIPT_MIAO", "miao" }, - { HB_SCRIPT_SHARADA, "HB_SCRIPT_SHARADA", "sharada" }, - { HB_SCRIPT_SORA_SOMPENG, "HB_SCRIPT_SORA_SOMPENG", "sora-sompeng" }, - { HB_SCRIPT_TAKRI, "HB_SCRIPT_TAKRI", "takri" }, - { HB_SCRIPT_INVALID, "HB_SCRIPT_INVALID", "invalid" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("hb_script_t"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} - -/* enumerations from "hb-unicode.h" */ -inline static /* TODO(behdad) disable these for now until we fix them... */ -GType -hb_unicode_general_category_t_hb_unicode_general_category_t_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { HB_UNICODE_GENERAL_CATEGORY_CONTROL, "HB_UNICODE_GENERAL_CATEGORY_CONTROL", "control" }, - { HB_UNICODE_GENERAL_CATEGORY_FORMAT, "HB_UNICODE_GENERAL_CATEGORY_FORMAT", "format" }, - { HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED, "HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED", "unassigned" }, - { HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE, "HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE", "private-use" }, - { HB_UNICODE_GENERAL_CATEGORY_SURROGATE, "HB_UNICODE_GENERAL_CATEGORY_SURROGATE", "surrogate" }, - { HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER, "HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER", "lowercase-letter" }, - { HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER, "HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER", "modifier-letter" }, - { HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER, "HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER", "other-letter" }, - { HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER, "HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER", "titlecase-letter" }, - { HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER, "HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER", "uppercase-letter" }, - { HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK, "HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK", "spacing-mark" }, - { HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK, "HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK", "enclosing-mark" }, - { HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK, "HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK", "non-spacing-mark" }, - { HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER, "HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER", "decimal-number" }, - { HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER, "HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER", "letter-number" }, - { HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER, "HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER", "other-number" }, - { HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION", "connect-punctuation" }, - { HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION", "dash-punctuation" }, - { HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION", "close-punctuation" }, - { HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION", "final-punctuation" }, - { HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION", "initial-punctuation" }, - { HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION", "other-punctuation" }, - { HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION", "open-punctuation" }, - { HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL", "currency-symbol" }, - { HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL", "modifier-symbol" }, - { HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL", "math-symbol" }, - { HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL", "other-symbol" }, - { HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR, "HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR", "line-separator" }, - { HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR, "HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR", "paragraph-separator" }, - { HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR, "HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR", "space-separator" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("hb_unicode_general_category_t"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} - -inline static /* TODO(behdad) disable these for now until we fix them... */ -GType -hb_unicode_combining_class_t_hb_unicode_combining_class_t_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { HB_UNICODE_COMBINING_CLASS_NOT_REORDERED, "HB_UNICODE_COMBINING_CLASS_NOT_REORDERED", "not-reordered" }, - { HB_UNICODE_COMBINING_CLASS_OVERLAY, "HB_UNICODE_COMBINING_CLASS_OVERLAY", "overlay" }, - { HB_UNICODE_COMBINING_CLASS_NUKTA, "HB_UNICODE_COMBINING_CLASS_NUKTA", "nukta" }, - { HB_UNICODE_COMBINING_CLASS_KANA_VOICING, "HB_UNICODE_COMBINING_CLASS_KANA_VOICING", "kana-voicing" }, - { HB_UNICODE_COMBINING_CLASS_VIRAMA, "HB_UNICODE_COMBINING_CLASS_VIRAMA", "virama" }, - { HB_UNICODE_COMBINING_CLASS_CCC10, "HB_UNICODE_COMBINING_CLASS_CCC10", "ccc10" }, - { HB_UNICODE_COMBINING_CLASS_CCC11, "HB_UNICODE_COMBINING_CLASS_CCC11", "ccc11" }, - { HB_UNICODE_COMBINING_CLASS_CCC12, "HB_UNICODE_COMBINING_CLASS_CCC12", "ccc12" }, - { HB_UNICODE_COMBINING_CLASS_CCC13, "HB_UNICODE_COMBINING_CLASS_CCC13", "ccc13" }, - { HB_UNICODE_COMBINING_CLASS_CCC14, "HB_UNICODE_COMBINING_CLASS_CCC14", "ccc14" }, - { HB_UNICODE_COMBINING_CLASS_CCC15, "HB_UNICODE_COMBINING_CLASS_CCC15", "ccc15" }, - { HB_UNICODE_COMBINING_CLASS_CCC16, "HB_UNICODE_COMBINING_CLASS_CCC16", "ccc16" }, - { HB_UNICODE_COMBINING_CLASS_CCC17, "HB_UNICODE_COMBINING_CLASS_CCC17", "ccc17" }, - { HB_UNICODE_COMBINING_CLASS_CCC18, "HB_UNICODE_COMBINING_CLASS_CCC18", "ccc18" }, - { HB_UNICODE_COMBINING_CLASS_CCC19, "HB_UNICODE_COMBINING_CLASS_CCC19", "ccc19" }, - { HB_UNICODE_COMBINING_CLASS_CCC20, "HB_UNICODE_COMBINING_CLASS_CCC20", "ccc20" }, - { HB_UNICODE_COMBINING_CLASS_CCC21, "HB_UNICODE_COMBINING_CLASS_CCC21", "ccc21" }, - { HB_UNICODE_COMBINING_CLASS_CCC22, "HB_UNICODE_COMBINING_CLASS_CCC22", "ccc22" }, - { HB_UNICODE_COMBINING_CLASS_CCC23, "HB_UNICODE_COMBINING_CLASS_CCC23", "ccc23" }, - { HB_UNICODE_COMBINING_CLASS_CCC24, "HB_UNICODE_COMBINING_CLASS_CCC24", "ccc24" }, - { HB_UNICODE_COMBINING_CLASS_CCC25, "HB_UNICODE_COMBINING_CLASS_CCC25", "ccc25" }, - { HB_UNICODE_COMBINING_CLASS_CCC26, "HB_UNICODE_COMBINING_CLASS_CCC26", "ccc26" }, - { HB_UNICODE_COMBINING_CLASS_CCC27, "HB_UNICODE_COMBINING_CLASS_CCC27", "ccc27" }, - { HB_UNICODE_COMBINING_CLASS_CCC28, "HB_UNICODE_COMBINING_CLASS_CCC28", "ccc28" }, - { HB_UNICODE_COMBINING_CLASS_CCC29, "HB_UNICODE_COMBINING_CLASS_CCC29", "ccc29" }, - { HB_UNICODE_COMBINING_CLASS_CCC30, "HB_UNICODE_COMBINING_CLASS_CCC30", "ccc30" }, - { HB_UNICODE_COMBINING_CLASS_CCC31, "HB_UNICODE_COMBINING_CLASS_CCC31", "ccc31" }, - { HB_UNICODE_COMBINING_CLASS_CCC32, "HB_UNICODE_COMBINING_CLASS_CCC32", "ccc32" }, - { HB_UNICODE_COMBINING_CLASS_CCC33, "HB_UNICODE_COMBINING_CLASS_CCC33", "ccc33" }, - { HB_UNICODE_COMBINING_CLASS_CCC34, "HB_UNICODE_COMBINING_CLASS_CCC34", "ccc34" }, - { HB_UNICODE_COMBINING_CLASS_CCC35, "HB_UNICODE_COMBINING_CLASS_CCC35", "ccc35" }, - { HB_UNICODE_COMBINING_CLASS_CCC36, "HB_UNICODE_COMBINING_CLASS_CCC36", "ccc36" }, - { HB_UNICODE_COMBINING_CLASS_CCC84, "HB_UNICODE_COMBINING_CLASS_CCC84", "ccc84" }, - { HB_UNICODE_COMBINING_CLASS_CCC91, "HB_UNICODE_COMBINING_CLASS_CCC91", "ccc91" }, - { HB_UNICODE_COMBINING_CLASS_CCC103, "HB_UNICODE_COMBINING_CLASS_CCC103", "ccc103" }, - { HB_UNICODE_COMBINING_CLASS_CCC107, "HB_UNICODE_COMBINING_CLASS_CCC107", "ccc107" }, - { HB_UNICODE_COMBINING_CLASS_CCC118, "HB_UNICODE_COMBINING_CLASS_CCC118", "ccc118" }, - { HB_UNICODE_COMBINING_CLASS_CCC122, "HB_UNICODE_COMBINING_CLASS_CCC122", "ccc122" }, - { HB_UNICODE_COMBINING_CLASS_CCC129, "HB_UNICODE_COMBINING_CLASS_CCC129", "ccc129" }, - { HB_UNICODE_COMBINING_CLASS_CCC130, "HB_UNICODE_COMBINING_CLASS_CCC130", "ccc130" }, - { HB_UNICODE_COMBINING_CLASS_CCC133, "HB_UNICODE_COMBINING_CLASS_CCC133", "ccc133" }, - { HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT, "HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT", "attached-below-left" }, - { HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW, "HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW", "attached-below" }, - { HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE, "HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE", "attached-above" }, - { HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT, "HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT", "attached-above-right" }, - { HB_UNICODE_COMBINING_CLASS_BELOW_LEFT, "HB_UNICODE_COMBINING_CLASS_BELOW_LEFT", "below-left" }, - { HB_UNICODE_COMBINING_CLASS_BELOW, "HB_UNICODE_COMBINING_CLASS_BELOW", "below" }, - { HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT, "HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT", "below-right" }, - { HB_UNICODE_COMBINING_CLASS_LEFT, "HB_UNICODE_COMBINING_CLASS_LEFT", "left" }, - { HB_UNICODE_COMBINING_CLASS_RIGHT, "HB_UNICODE_COMBINING_CLASS_RIGHT", "right" }, - { HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT, "HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT", "above-left" }, - { HB_UNICODE_COMBINING_CLASS_ABOVE, "HB_UNICODE_COMBINING_CLASS_ABOVE", "above" }, - { HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT, "HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT", "above-right" }, - { HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW, "HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW", "double-below" }, - { HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE, "HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE", "double-above" }, - { HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT, "HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT", "iota-subscript" }, - { HB_UNICODE_COMBINING_CLASS_INVALID, "HB_UNICODE_COMBINING_CLASS_INVALID", "invalid" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("hb_unicode_combining_class_t"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} - - -/* Generated data ends here */ - diff --git a/third_party/harfbuzz-ng/src/hb-mutex-private.hh b/third_party/harfbuzz-ng/src/hb-mutex-private.hh index 5b3a17e..0fb21c2 100644 --- a/third_party/harfbuzz-ng/src/hb-mutex-private.hh +++ b/third_party/harfbuzz-ng/src/hb-mutex-private.hh @@ -42,7 +42,7 @@ #if 0 -#elif !defined(HB_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__) +#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) #define WIN32_LEAN_AND_MEAN #include <windows.h> diff --git a/third_party/harfbuzz-ng/src/hb-open-type-private.hh b/third_party/harfbuzz-ng/src/hb-open-type-private.hh index 5bfeb16..cd1163e 100644 --- a/third_party/harfbuzz-ng/src/hb-open-type-private.hh +++ b/third_party/harfbuzz-ng/src/hb-open-type-private.hh @@ -171,6 +171,10 @@ ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) (&c->debug_depth, c->get_name (), this, HB_FUNC, \ ""); +/* This limits sanitizing time on really broken fonts. */ +#ifndef HB_SANITIZE_MAX_EDITS +#define HB_SANITIZE_MAX_EDITS 100 +#endif struct hb_sanitize_context_t { @@ -178,7 +182,7 @@ struct hb_sanitize_context_t static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; typedef bool return_t; template <typename T> - inline return_t process (const T &obj) { return obj.sanitize (this); } + inline return_t dispatch (const T &obj) { return obj.sanitize (this); } static return_t default_return_value (void) { return true; } bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; } @@ -247,6 +251,9 @@ struct hb_sanitize_context_t inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED) { + if (this->edit_count >= HB_SANITIZE_MAX_EDITS) + return false; + const char *p = (const char *) base; this->edit_count++; @@ -404,7 +411,7 @@ struct hb_serialize_context_t template <typename Type> inline Type *allocate_size (unsigned int size) { - if (unlikely (this->ran_out_of_room || this->end - this->head < size)) { + if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) { this->ran_out_of_room = true; return NULL; } @@ -616,10 +623,20 @@ struct Index : USHORT { DEFINE_NULL_DATA (Index, "\xff\xff"); /* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */ -typedef USHORT Offset; +struct Offset : USHORT +{ + inline bool is_null (void) const { return 0 == *this; } + public: + DEFINE_SIZE_STATIC (2); +}; /* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */ -typedef ULONG LongOffset; +struct LongOffset : ULONG +{ + inline bool is_null (void) const { return 0 == *this; } + public: + DEFINE_SIZE_STATIC (4); +}; /* CheckSum */ @@ -674,11 +691,6 @@ struct GenericOffsetTo : OffsetType if (unlikely (!offset)) return Null(Type); return StructAtOffset<Type> (base, offset); } - inline Type& operator () (void *base) - { - unsigned int offset = *this; - return StructAtOffset<Type> (base, offset); - } inline Type& serialize (hb_serialize_context_t *c, void *base) { diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh index d27ce4f..4413927 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh @@ -336,8 +336,10 @@ struct Anchor struct AnchorMatrix { - inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols) const { + inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const { + *found = false; if (unlikely (row >= rows || col >= cols)) return Null(Anchor); + *found = !matrix[row * cols + col].is_null (); return this+matrix[row * cols + col]; } @@ -392,7 +394,11 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde unsigned int mark_class = record.klass; const Anchor& mark_anchor = this + record.markAnchor; - const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count); + bool found; + const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found); + /* If this subtable doesn't have an anchor for this base and this class, + * return false such that the subsequent subtables have a chance at it. */ + if (unlikely (!found)) return TRACE_RETURN (false); hb_position_t mark_x, mark_y, base_x, base_y; @@ -513,12 +519,12 @@ struct SinglePosFormat2 struct SinglePos { template <typename context_t> - inline typename context_t::return_t process (context_t *c) const + inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_PROCESS (this); + TRACE_DISPATCH (this); switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); - case 2: return TRACE_RETURN (c->process (u.format2)); + case 1: return TRACE_RETURN (c->dispatch (u.format1)); + case 2: return TRACE_RETURN (c->dispatch (u.format2)); default:return TRACE_RETURN (c->default_return_value ()); } } @@ -590,6 +596,7 @@ struct PairSet unsigned int count = len; for (unsigned int i = 0; i < count; i++) { + /* TODO bsearch */ if (c->buffer->info[pos].codepoint == record->secondGlyph) { valueFormats[0].apply_value (c->font, c->direction, this, @@ -652,7 +659,7 @@ struct PairPosFormat1 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); @@ -724,7 +731,7 @@ struct PairPosFormat2 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); @@ -803,12 +810,12 @@ struct PairPosFormat2 struct PairPos { template <typename context_t> - inline typename context_t::return_t process (context_t *c) const + inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_PROCESS (this); + TRACE_DISPATCH (this); switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); - case 2: return TRACE_RETURN (c->process (u.format2)); + case 1: return TRACE_RETURN (c->dispatch (u.format1)); + case 2: return TRACE_RETURN (c->dispatch (u.format2)); default:return TRACE_RETURN (c->default_return_value ()); } } @@ -872,9 +879,9 @@ struct CursivePosFormat1 TRACE_APPLY (this); /* We don't handle mark glyphs here. */ - if (c->property & HB_OT_LAYOUT_GLYPH_PROPS_MARK) return TRACE_RETURN (false); + if (c->buffer->cur().glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK) return TRACE_RETURN (false); - hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (c->buffer->cur().codepoint)]; @@ -969,11 +976,11 @@ struct CursivePosFormat1 struct CursivePos { template <typename context_t> - inline typename context_t::return_t process (context_t *c) const + inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_PROCESS (this); + TRACE_DISPATCH (this); switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); + case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); } } @@ -1022,17 +1029,17 @@ struct MarkBasePosFormat1 if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); /* now we search backwards for a non-mark glyph */ - unsigned int property; - hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); + hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); + skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); do { - if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_RETURN (false); + if (!skippy_iter.prev ()) return TRACE_RETURN (false); /* We only want to attach to the first of a MultipleSubst sequence. Reject others. */ if (0 == get_lig_comp (c->buffer->info[skippy_iter.idx])) break; skippy_iter.reject (); } while (1); /* The following assertion is too strong, so we've disabled it. */ - if (!(property & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH)) {/*return TRACE_RETURN (false);*/} + if (!(c->buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH)) {/*return TRACE_RETURN (false);*/} unsigned int base_index = (this+baseCoverage).get_coverage (c->buffer->info[skippy_iter.idx].codepoint); if (base_index == NOT_COVERED) return TRACE_RETURN (false); @@ -1068,11 +1075,11 @@ struct MarkBasePosFormat1 struct MarkBasePos { template <typename context_t> - inline typename context_t::return_t process (context_t *c) const + inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_PROCESS (this); + TRACE_DISPATCH (this); switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); + case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); } } @@ -1126,12 +1133,12 @@ struct MarkLigPosFormat1 if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); /* now we search backwards for a non-mark glyph */ - unsigned int property; - hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); - if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_RETURN (false); + hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); + skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); + if (!skippy_iter.prev ()) return TRACE_RETURN (false); /* The following assertion is too strong, so we've disabled it. */ - if (!(property & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE)) {/*return TRACE_RETURN (false);*/} + if (!(c->buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE)) {/*return TRACE_RETURN (false);*/} unsigned int j = skippy_iter.idx; unsigned int lig_index = (this+ligatureCoverage).get_coverage (c->buffer->info[j].codepoint); @@ -1189,11 +1196,11 @@ struct MarkLigPosFormat1 struct MarkLigPos { template <typename context_t> - inline typename context_t::return_t process (context_t *c) const + inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_PROCESS (this); + TRACE_DISPATCH (this); switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); + case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); } } @@ -1242,11 +1249,11 @@ struct MarkMarkPosFormat1 if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false); /* now we search backwards for a suitable mark glyph until a non-mark glyph */ - unsigned int property; - hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); - if (!skippy_iter.prev (&property)) return TRACE_RETURN (false); + hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); + skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags); + if (!skippy_iter.prev ()) return TRACE_RETURN (false); - if (!(property & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) return TRACE_RETURN (false); + if (!(c->buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) { return TRACE_RETURN (false); } unsigned int j = skippy_iter.idx; @@ -1308,11 +1315,11 @@ struct MarkMarkPosFormat1 struct MarkMarkPos { template <typename context_t> - inline typename context_t::return_t process (context_t *c) const + inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_PROCESS (this); + TRACE_DISPATCH (this); switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); + case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); } } @@ -1367,19 +1374,19 @@ struct PosLookupSubTable }; template <typename context_t> - inline typename context_t::return_t process (context_t *c, unsigned int lookup_type) const + inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const { - TRACE_PROCESS (this); + TRACE_DISPATCH (this); switch (lookup_type) { - case Single: return TRACE_RETURN (u.single.process (c)); - case Pair: return TRACE_RETURN (u.pair.process (c)); - case Cursive: return TRACE_RETURN (u.cursive.process (c)); - case MarkBase: return TRACE_RETURN (u.markBase.process (c)); - case MarkLig: return TRACE_RETURN (u.markLig.process (c)); - case MarkMark: return TRACE_RETURN (u.markMark.process (c)); - case Context: return TRACE_RETURN (u.context.process (c)); - case ChainContext: return TRACE_RETURN (u.chainContext.process (c)); - case Extension: return TRACE_RETURN (u.extension.process (c)); + case Single: return TRACE_RETURN (u.single.dispatch (c)); + case Pair: return TRACE_RETURN (u.pair.dispatch (c)); + case Cursive: return TRACE_RETURN (u.cursive.dispatch (c)); + case MarkBase: return TRACE_RETURN (u.markBase.dispatch (c)); + case MarkLig: return TRACE_RETURN (u.markLig.dispatch (c)); + case MarkMark: return TRACE_RETURN (u.markMark.dispatch (c)); + case Context: return TRACE_RETURN (u.context.dispatch (c)); + case ChainContext: return TRACE_RETURN (u.chainContext.dispatch (c)); + case Extension: return TRACE_RETURN (u.extension.dispatch (c)); default: return TRACE_RETURN (c->default_return_value ()); } } @@ -1427,27 +1434,11 @@ struct PosLookup : Lookup inline const PosLookupSubTable& get_subtable (unsigned int i) const { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; } - template <typename context_t> - inline typename context_t::return_t process (context_t *c) const - { - TRACE_PROCESS (this); - unsigned int lookup_type = get_type (); - unsigned int count = get_subtable_count (); - for (unsigned int i = 0; i < count; i++) { - typename context_t::return_t r = get_subtable (i).process (c, lookup_type); - if (c->stop_sublookup_iteration (r)) - return TRACE_RETURN (r); - } - return TRACE_RETURN (c->default_return_value ()); - } - template <typename context_t> - static inline typename context_t::return_t process_recurse_func (context_t *c, unsigned int lookup_index); - inline hb_collect_glyphs_context_t::return_t collect_glyphs_lookup (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); c->set_recurse_func (NULL); - return TRACE_RETURN (process (c)); + return TRACE_RETURN (dispatch (c)); } template <typename set_t> @@ -1457,7 +1448,7 @@ struct PosLookup : Lookup const Coverage *last = NULL; unsigned int count = get_subtable_count (); for (unsigned int i = 0; i < count; i++) { - const Coverage *coverage = &get_subtable (i).process (&c, get_type ()); + const Coverage *coverage = &get_subtable (i).dispatch (&c, get_type ()); if (coverage != last) { coverage->add_coverage (glyphs); last = coverage; @@ -1468,9 +1459,9 @@ struct PosLookup : Lookup inline bool apply_once (hb_apply_context_t *c) const { TRACE_APPLY (this); - if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props, &c->property)) + if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props)) return TRACE_RETURN (false); - return TRACE_RETURN (process (c)); + return TRACE_RETURN (dispatch (c)); } static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index); @@ -1500,6 +1491,23 @@ struct PosLookup : Lookup return ret; } + template <typename context_t> + static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); + + template <typename context_t> + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this); + unsigned int lookup_type = get_type (); + unsigned int count = get_subtable_count (); + for (unsigned int i = 0; i < count; i++) { + typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type); + if (c->stop_sublookup_iteration (r)) + return TRACE_RETURN (r); + } + return TRACE_RETURN (c->default_return_value ()); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); @@ -1522,7 +1530,7 @@ struct GPOS : GSUBGPOS { return CastR<PosLookup> (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, hb_bool_t zero_width_attahced_marks); + static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer); inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); @@ -1555,17 +1563,13 @@ fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction } static void -fix_mark_attachment (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, hb_bool_t zero_width_attached_marks) +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(); - if (zero_width_attached_marks) { - pos[i].x_advance = 0; - pos[i].y_advance = 0; - } pos[i].x_offset += pos[j].x_offset; pos[i].y_offset += pos[j].y_offset; @@ -1592,7 +1596,7 @@ GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) } void -GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer, hb_bool_t zero_width_attached_marks) +GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { unsigned int len; hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len); @@ -1604,7 +1608,7 @@ GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer, hb_bool_t /* Handle attachments */ for (unsigned int i = 0; i < len; i++) - fix_mark_attachment (pos, i, direction, zero_width_attached_marks); + fix_mark_attachment (pos, i, direction); HB_BUFFER_DEALLOCATE_VAR (buffer, syllable); HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props); @@ -1615,11 +1619,11 @@ GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer, hb_bool_t /* Out-of-class implementation for methods recursing */ template <typename context_t> -inline typename context_t::return_t PosLookup::process_recurse_func (context_t *c, unsigned int lookup_index) +inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) { const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos); const PosLookup &l = gpos.get_lookup (lookup_index); - return l.process (c); + return l.dispatch (c); } inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index) @@ -1627,11 +1631,9 @@ inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int l const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos); const PosLookup &l = gpos.get_lookup (lookup_index); unsigned int saved_lookup_props = c->lookup_props; - unsigned int saved_property = c->property; c->set_lookup (l); bool ret = l.apply_once (c); c->lookup_props = saved_lookup_props; - c->property = saved_property; return ret; } diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh index 2642acb..35d0729 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh @@ -192,17 +192,6 @@ struct SingleSubstFormat2 struct SingleSubst { - template <typename context_t> - inline typename context_t::return_t process (context_t *c) const - { - TRACE_PROCESS (this); - switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); - case 2: return TRACE_RETURN (c->process (u.format2)); - default:return TRACE_RETURN (c->default_return_value ()); - } - } - inline bool serialize (hb_serialize_context_t *c, Supplier<GlyphID> &glyphs, Supplier<GlyphID> &substitutes, @@ -230,6 +219,17 @@ struct SingleSubst } } + template <typename context_t> + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this); + switch (u.format) { + case 1: return TRACE_RETURN (c->dispatch (u.format1)); + case 2: return TRACE_RETURN (c->dispatch (u.format2)); + default:return TRACE_RETURN (c->default_return_value ()); + } + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return TRACE_RETURN (false); @@ -272,7 +272,8 @@ struct Sequence TRACE_APPLY (this); if (unlikely (!substitute.len)) return TRACE_RETURN (false); - unsigned int klass = c->property & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE ? HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; + unsigned int klass = c->buffer->cur().glyph_props() & + HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE ? HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; unsigned int count = substitute.len; for (unsigned int i = 0; i < count; i++) { set_lig_props_for_component (c->buffer->cur(), i); @@ -384,16 +385,6 @@ struct MultipleSubstFormat1 struct MultipleSubst { - template <typename context_t> - inline typename context_t::return_t process (context_t *c) const - { - TRACE_PROCESS (this); - switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); - default:return TRACE_RETURN (c->default_return_value ()); - } - } - inline bool serialize (hb_serialize_context_t *c, Supplier<GlyphID> &glyphs, Supplier<unsigned int> &substitute_len_list, @@ -410,6 +401,16 @@ struct MultipleSubst } } + template <typename context_t> + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this); + switch (u.format) { + case 1: return TRACE_RETURN (c->dispatch (u.format1)); + default:return TRACE_RETURN (c->default_return_value ()); + } + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return TRACE_RETURN (false); @@ -535,16 +536,6 @@ struct AlternateSubstFormat1 struct AlternateSubst { - template <typename context_t> - inline typename context_t::return_t process (context_t *c) const - { - TRACE_PROCESS (this); - switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); - default:return TRACE_RETURN (c->default_return_value ()); - } - } - inline bool serialize (hb_serialize_context_t *c, Supplier<GlyphID> &glyphs, Supplier<unsigned int> &alternate_len_list, @@ -561,6 +552,16 @@ struct AlternateSubst } } + template <typename context_t> + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this); + switch (u.format) { + case 1: return TRACE_RETURN (c->dispatch (u.format1)); + default:return TRACE_RETURN (c->default_return_value ()); + } + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return TRACE_RETURN (false); @@ -637,9 +638,9 @@ struct Ligature ligate_input (c, count, &component[1], - ligGlyph, match_glyph, NULL, + ligGlyph, is_mark_ligature, total_component_count); @@ -840,16 +841,6 @@ struct LigatureSubstFormat1 struct LigatureSubst { - template <typename context_t> - inline typename context_t::return_t process (context_t *c) const - { - TRACE_PROCESS (this); - switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); - default:return TRACE_RETURN (c->default_return_value ()); - } - } - inline bool serialize (hb_serialize_context_t *c, Supplier<GlyphID> &first_glyphs, Supplier<unsigned int> &ligature_per_first_glyph_count_list, @@ -869,6 +860,16 @@ struct LigatureSubst } } + template <typename context_t> + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this); + switch (u.format) { + case 1: return TRACE_RETURN (c->dispatch (u.format1)); + default:return TRACE_RETURN (c->default_return_value ()); + } + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return TRACE_RETURN (false); @@ -1022,11 +1023,11 @@ struct ReverseChainSingleSubstFormat1 struct ReverseChainSingleSubst { template <typename context_t> - inline typename context_t::return_t process (context_t *c) const + inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_PROCESS (this); + TRACE_DISPATCH (this); switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); + case 1: return TRACE_RETURN (c->dispatch (u.format1)); default:return TRACE_RETURN (c->default_return_value ()); } } @@ -1069,18 +1070,18 @@ struct SubstLookupSubTable }; template <typename context_t> - inline typename context_t::return_t process (context_t *c, unsigned int lookup_type) const + inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const { - TRACE_PROCESS (this); + TRACE_DISPATCH (this); switch (lookup_type) { - case Single: return TRACE_RETURN (u.single.process (c)); - case Multiple: return TRACE_RETURN (u.multiple.process (c)); - case Alternate: return TRACE_RETURN (u.alternate.process (c)); - case Ligature: return TRACE_RETURN (u.ligature.process (c)); - case Context: return TRACE_RETURN (u.context.process (c)); - case ChainContext: return TRACE_RETURN (u.chainContext.process (c)); - case Extension: return TRACE_RETURN (u.extension.process (c)); - case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.process (c)); + case Single: return TRACE_RETURN (u.single.dispatch (c)); + case Multiple: return TRACE_RETURN (u.multiple.dispatch (c)); + case Alternate: return TRACE_RETURN (u.alternate.dispatch (c)); + case Ligature: return TRACE_RETURN (u.ligature.dispatch (c)); + case Context: return TRACE_RETURN (u.context.dispatch (c)); + case ChainContext: return TRACE_RETURN (u.chainContext.dispatch (c)); + case Extension: return TRACE_RETURN (u.extension.dispatch (c)); + case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.dispatch (c)); default: return TRACE_RETURN (c->default_return_value ()); } } @@ -1137,34 +1138,18 @@ struct SubstLookup : Lookup return lookup_type_is_reverse (type); } - template <typename context_t> - inline typename context_t::return_t process (context_t *c) const - { - TRACE_PROCESS (this); - unsigned int lookup_type = get_type (); - unsigned int count = get_subtable_count (); - for (unsigned int i = 0; i < count; i++) { - typename context_t::return_t r = get_subtable (i).process (c, lookup_type); - if (c->stop_sublookup_iteration (r)) - return TRACE_RETURN (r); - } - return TRACE_RETURN (c->default_return_value ()); - } - template <typename context_t> - static inline typename context_t::return_t process_recurse_func (context_t *c, unsigned int lookup_index); - inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); - c->set_recurse_func (process_recurse_func<hb_closure_context_t>); - return TRACE_RETURN (process (c)); + c->set_recurse_func (dispatch_recurse_func<hb_closure_context_t>); + return TRACE_RETURN (dispatch (c)); } inline hb_collect_glyphs_context_t::return_t collect_glyphs_lookup (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - c->set_recurse_func (process_recurse_func<hb_collect_glyphs_context_t>); - return TRACE_RETURN (process (c)); + c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>); + return TRACE_RETURN (dispatch (c)); } template <typename set_t> @@ -1174,7 +1159,7 @@ struct SubstLookup : Lookup const Coverage *last = NULL; unsigned int count = get_subtable_count (); for (unsigned int i = 0; i < count; i++) { - const Coverage *coverage = &get_subtable (i).process (&c, get_type ()); + const Coverage *coverage = &get_subtable (i).dispatch (&c, get_type ()); if (coverage != last) { coverage->add_coverage (glyphs); last = coverage; @@ -1187,15 +1172,15 @@ struct SubstLookup : Lookup TRACE_WOULD_APPLY (this); if (unlikely (!c->len)) return TRACE_RETURN (false); if (!digest->may_have (c->glyphs[0])) return TRACE_RETURN (false); - return TRACE_RETURN (process (c)); + return TRACE_RETURN (dispatch (c)); } inline bool apply_once (hb_apply_context_t *c) const { TRACE_APPLY (this); - if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props, &c->property)) + if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props)) return TRACE_RETURN (false); - return TRACE_RETURN (process (c)); + return TRACE_RETURN (dispatch (c)); } static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index); @@ -1304,6 +1289,23 @@ struct SubstLookup : Lookup ligatures_list, component_count_list, component_list)); } + template <typename context_t> + static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); + + template <typename context_t> + inline typename context_t::return_t dispatch (context_t *c) const + { + TRACE_DISPATCH (this); + unsigned int lookup_type = get_type (); + unsigned int count = get_subtable_count (); + for (unsigned int i = 0; i < count; i++) { + typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type); + if (c->stop_sublookup_iteration (r)) + return TRACE_RETURN (r); + } + return TRACE_RETURN (c->default_return_value ()); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); @@ -1315,9 +1317,7 @@ struct SubstLookup : Lookup { /* The spec says all subtables of an Extension lookup should * have the same type. This is specially important if one has - * a reverse type! - * - * We just check that they are all either forward, or reverse. */ + * a reverse type! */ unsigned int type = get_subtable (0).u.extension.get_type (); unsigned int count = get_subtable_count (); for (unsigned int i = 1; i < count; i++) @@ -1387,11 +1387,11 @@ inline bool ExtensionSubst::is_reverse (void) const } template <typename context_t> -inline typename context_t::return_t SubstLookup::process_recurse_func (context_t *c, unsigned int lookup_index) +inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) { const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); const SubstLookup &l = gsub.get_lookup (lookup_index); - return l.process (c); + return l.dispatch (c); } inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index) @@ -1399,11 +1399,9 @@ inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); const SubstLookup &l = gsub.get_lookup (lookup_index); unsigned int saved_lookup_props = c->lookup_props; - unsigned int saved_property = c->property; c->set_lookup (l); bool ret = l.apply_once (c); c->lookup_props = saved_lookup_props; - c->property = saved_property; return ret; } diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh index 40be861..f46b378 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh @@ -38,7 +38,7 @@ namespace OT { -#define TRACE_PROCESS(this) \ +#define TRACE_DISPATCH(this) \ hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \ (&c->debug_depth, c->get_name (), this, HB_FUNC, \ ""); @@ -60,9 +60,9 @@ struct hb_closure_context_t typedef hb_void_t return_t; typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index); template <typename T> - inline return_t process (const T &obj) { obj.closure (this); return HB_VOID; } + inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; } static return_t default_return_value (void) { return HB_VOID; } - bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; } + bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; } return_t recurse (unsigned int lookup_index) { if (unlikely (nesting_level_left == 0 || !recurse_func)) @@ -109,9 +109,9 @@ struct hb_would_apply_context_t static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY; typedef bool return_t; template <typename T> - inline return_t process (const T &obj) { return obj.would_apply (this); } + inline return_t dispatch (const T &obj) { return obj.would_apply (this); } static return_t default_return_value (void) { return false; } - bool stop_sublookup_iteration (const return_t r) const { return r; } + bool stop_sublookup_iteration (return_t r) const { return r; } hb_face_t *face; const hb_codepoint_t *glyphs; @@ -148,9 +148,9 @@ struct hb_collect_glyphs_context_t typedef hb_void_t return_t; typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index); template <typename T> - inline return_t process (const T &obj) { obj.collect_glyphs (this); return HB_VOID; } + inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; } static return_t default_return_value (void) { return HB_VOID; } - bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; } + bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; } return_t recurse (unsigned int lookup_index) { if (unlikely (nesting_level_left == 0 || !recurse_func)) @@ -214,7 +214,7 @@ struct hb_get_coverage_context_t static const unsigned int max_debug_depth = 0; typedef const Coverage &return_t; template <typename T> - inline return_t process (const T &obj) { return obj.get_coverage (); } + inline return_t dispatch (const T &obj) { return obj.get_coverage (); } static return_t default_return_value (void) { return Null(Coverage); } hb_get_coverage_context_t (void) : @@ -241,9 +241,9 @@ struct hb_apply_context_t typedef bool return_t; typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index); template <typename T> - inline return_t process (const T &obj) { return obj.apply (this); } + inline return_t dispatch (const T &obj) { return obj.apply (this); } static return_t default_return_value (void) { return false; } - bool stop_sublookup_iteration (const return_t r) const { return r; } + bool stop_sublookup_iteration (return_t r) const { return r; } return_t recurse (unsigned int lookup_index) { if (unlikely (nesting_level_left == 0 || !recurse_func)) @@ -255,132 +255,260 @@ struct hb_apply_context_t return ret; } + unsigned int table_index; /* GSUB/GPOS */ hb_font_t *font; hb_face_t *face; hb_buffer_t *buffer; 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; - unsigned int property; /* propety of first glyph */ const GDEF &gdef; bool has_glyph_classes; unsigned int debug_depth; - hb_apply_context_t (hb_font_t *font_, + hb_apply_context_t (unsigned int table_index_, + hb_font_t *font_, hb_buffer_t *buffer_, - hb_mask_t lookup_mask_) : + hb_mask_t lookup_mask_, + bool auto_zwj_) : + table_index (table_index_), font (font_), face (font->face), buffer (buffer_), direction (buffer_->props.direction), lookup_mask (lookup_mask_), + auto_zwj (auto_zwj_), recurse_func (NULL), nesting_level_left (MAX_NESTING_LEVEL), - lookup_props (0), property (0), + lookup_props (0), gdef (*hb_ot_layout_from_face (face)->gdef), has_glyph_classes (gdef.has_glyph_classes ()), debug_depth (0) {} - void set_recurse_func (recurse_func_t func) { recurse_func = func; } - void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; } - void set_lookup (const Lookup &l) { lookup_props = l.get_props (); } + inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } + inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; } + inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); } + + struct matcher_t + { + inline matcher_t (void) : + lookup_props (0), + ignore_zwnj (false), + ignore_zwj (false), + mask (-1), +#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */ + syllable arg1(0), +#undef arg1 + match_func (NULL), + match_data (NULL) {}; + + typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data); + + inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; } + inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; } + inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; } + inline void set_mask (hb_mask_t mask_) { mask = mask_; } + inline void set_syllable (uint8_t syllable_) { syllable = syllable_; } + inline void set_match_func (match_func_t match_func_, + const void *match_data_) + { match_func = match_func_; match_data = match_data_; } + + enum may_match_t { + MATCH_NO, + MATCH_YES, + MATCH_MAYBE + }; - struct mark_skipping_forward_iterator_t - { - inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_, - unsigned int start_index_, - unsigned int num_items_, - bool context_match = false) + inline may_match_t may_match (const hb_glyph_info_t &info, + const USHORT *glyph_data) const + { + if (!(info.mask & mask) || + (syllable && syllable != info.syllable ())) + return MATCH_NO; + + if (match_func) + return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO; + + return MATCH_MAYBE; + } + + enum may_skip_t { + SKIP_NO, + SKIP_YES, + SKIP_MAYBE + }; + + inline may_skip_t + may_skip (const hb_apply_context_t *c, + const hb_glyph_info_t &info) const { - c = c_; - idx = start_index_; - num_items = num_items_; - mask = context_match ? -1 : c->lookup_mask; - syllable = context_match ? 0 : c->buffer->cur().syllable (); - end = c->buffer->len; + unsigned int property; + + property = info.glyph_props(); + + if (!c->match_properties (info.codepoint, property, lookup_props)) + return SKIP_YES; + + if (unlikely (_hb_glyph_info_is_default_ignorable (&info) && + (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && + (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) && + !is_a_ligature (info))) + return SKIP_MAYBE; + + return SKIP_NO; } - inline bool has_no_chance (void) const + + protected: + unsigned int lookup_props; + bool ignore_zwnj; + bool ignore_zwj; + hb_mask_t mask; + uint8_t syllable; + match_func_t match_func; + const void *match_data; + }; + + struct skipping_forward_iterator_t + { + inline skipping_forward_iterator_t (hb_apply_context_t *c_, + unsigned int start_index_, + unsigned int num_items_, + bool context_match = false) : + idx (start_index_), + c (c_), + match_glyph_data (NULL), + num_items (num_items_), + end (c->buffer->len) { - return unlikely (num_items && idx + num_items >= end); + 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); + /* 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); + if (!context_match) + matcher.set_mask (c->lookup_mask); + matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); } - inline void reject (void) + inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); } + inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); } + inline void set_match_func (matcher_t::match_func_t match_func, + const void *match_data, + const USHORT glyph_data[]) { - num_items++; + matcher.set_match_func (match_func, match_data); + match_glyph_data = glyph_data; } - inline bool next (unsigned int *property_out, - unsigned int lookup_props) + + inline bool has_no_chance (void) const { return unlikely (num_items && idx + num_items >= end); } + inline void reject (void) { num_items++; match_glyph_data--; } + inline bool next (void) { assert (num_items > 0); - do + while (!has_no_chance ()) { - if (has_no_chance ()) - return false; idx++; - } while (c->should_skip_mark (&c->buffer->info[idx], lookup_props, property_out)); - num_items--; - return (c->buffer->info[idx].mask & mask) && (!syllable || syllable == c->buffer->info[idx].syllable ()); - } - inline bool next (unsigned int *property_out = NULL) - { - return next (property_out, c->lookup_props); + const hb_glyph_info_t &info = c->buffer->info[idx]; + + matcher_t::may_skip_t skip = matcher.may_skip (c, info); + if (unlikely (skip == matcher_t::SKIP_YES)) + continue; + + matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data); + if (match == matcher_t::MATCH_YES || + (match == matcher_t::MATCH_MAYBE && + skip == matcher_t::SKIP_NO)) + { + num_items--; + match_glyph_data++; + return true; + } + + if (skip == matcher_t::SKIP_NO) + return false; + } + return false; } unsigned int idx; protected: hb_apply_context_t *c; + matcher_t matcher; + const USHORT *match_glyph_data; + unsigned int num_items; - hb_mask_t mask; - uint8_t syllable; unsigned int end; }; - struct mark_skipping_backward_iterator_t + struct skipping_backward_iterator_t { - inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_, - unsigned int start_index_, - unsigned int num_items_, - hb_mask_t mask_ = 0, - bool match_syllable_ = true) - { - c = c_; - idx = start_index_; - num_items = num_items_; - mask = mask_ ? mask_ : c->lookup_mask; - syllable = match_syllable_ ? c->buffer->cur().syllable () : 0; - } - inline bool has_no_chance (void) const + inline skipping_backward_iterator_t (hb_apply_context_t *c_, + unsigned int start_index_, + unsigned int num_items_, + bool context_match = false) : + idx (start_index_), + c (c_), + match_glyph_data (NULL), + num_items (num_items_) { - return unlikely (idx < num_items); + 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); + /* 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); + if (!context_match) + matcher.set_mask (c->lookup_mask); + matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); } - inline void reject (void) + inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); } + inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); } + inline void set_match_func (matcher_t::match_func_t match_func, + const void *match_data, + const USHORT glyph_data[]) { - num_items++; + matcher.set_match_func (match_func, match_data); + match_glyph_data = glyph_data; } - inline bool prev (unsigned int *property_out, - unsigned int lookup_props) + + inline bool has_no_chance (void) const { return unlikely (idx < num_items); } + inline void reject (void) { num_items++; } + inline bool prev (void) { assert (num_items > 0); - do + while (!has_no_chance ()) { - if (has_no_chance ()) - return false; idx--; - } while (c->should_skip_mark (&c->buffer->out_info[idx], lookup_props, property_out)); - num_items--; - return (c->buffer->out_info[idx].mask & mask) && (!syllable || syllable == c->buffer->out_info[idx].syllable ()); - } - inline bool prev (unsigned int *property_out = NULL) - { - return prev (property_out, c->lookup_props); + const hb_glyph_info_t &info = c->buffer->out_info[idx]; + + matcher_t::may_skip_t skip = matcher.may_skip (c, info); + + if (unlikely (skip == matcher_t::SKIP_YES)) + continue; + + matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data); + if (match == matcher_t::MATCH_YES || + (match == matcher_t::MATCH_MAYBE && + skip == matcher_t::SKIP_NO)) + { + num_items--; + match_glyph_data++; + return true; + } + + if (skip == matcher_t::SKIP_NO) + return false; + } + return false; } unsigned int idx; protected: hb_apply_context_t *c; + matcher_t matcher; + const USHORT *match_glyph_data; + unsigned int num_items; - hb_mask_t mask; - uint8_t syllable; }; inline bool @@ -423,42 +551,15 @@ struct hb_apply_context_t inline bool check_glyph_property (hb_glyph_info_t *info, - unsigned int lookup_props, - unsigned int *property_out) const + unsigned int lookup_props) const { unsigned int property; property = info->glyph_props(); - *property_out = property; return match_properties (info->codepoint, property, lookup_props); } - inline bool - should_skip_mark (hb_glyph_info_t *info, - unsigned int lookup_props, - unsigned int *property_out) const - { - unsigned int property; - - property = info->glyph_props(); - if (property_out) - *property_out = property; - - /* If it's a mark, skip it if we don't accept it. */ - if (unlikely (property & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) - return !match_properties (info->codepoint, property, lookup_props); - - /* If not a mark, don't skip. */ - return false; - } - - - inline bool should_mark_skip_current_glyph (void) const - { - return should_skip_mark (&buffer->cur(), lookup_props, NULL); - } - inline void set_class (hb_codepoint_t glyph_index, unsigned int class_guess) const { if (likely (has_glyph_classes)) @@ -602,7 +703,8 @@ static inline bool match_input (hb_apply_context_t *c, { TRACE_APPLY (NULL); - hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); + skippy_iter.set_match_func (match_func, match_data, input); if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); /* @@ -623,7 +725,7 @@ static inline bool match_input (hb_apply_context_t *c, * ligate with a conjunct...) */ - bool is_mark_ligature = !!(c->property & HB_OT_LAYOUT_GLYPH_PROPS_MARK); + bool is_mark_ligature = !!(c->buffer->cur().glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); unsigned int total_component_count = 0; total_component_count += get_lig_num_comps (c->buffer->cur()); @@ -633,11 +735,7 @@ static inline bool match_input (hb_apply_context_t *c, for (unsigned int i = 1; i < count; i++) { - unsigned int property; - - if (!skippy_iter.next (&property)) return TRACE_RETURN (false); - - if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, input[i - 1], match_data))) return TRACE_RETURN (false); + if (!skippy_iter.next ()) return TRACE_RETURN (false); unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]); unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx]); @@ -656,7 +754,7 @@ static inline bool match_input (hb_apply_context_t *c, return TRACE_RETURN (false); } - is_mark_ligature = is_mark_ligature && (property & HB_OT_LAYOUT_GLYPH_PROPS_MARK); + is_mark_ligature = is_mark_ligature && (c->buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]); } @@ -673,13 +771,17 @@ static inline bool match_input (hb_apply_context_t *c, } static inline void ligate_input (hb_apply_context_t *c, unsigned int count, /* Including the first glyph (not matched) */ - const USHORT input[] HB_UNUSED, /* Array of input values--start with second glyph */ + const USHORT input[], /* Array of input values--start with second glyph */ + match_func_t match_func, + const void *match_data, hb_codepoint_t lig_glyph, - match_func_t match_func HB_UNUSED, - const void *match_data HB_UNUSED, bool is_mark_ligature, unsigned int total_component_count) { + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); + skippy_iter.set_match_func (match_func, match_data, input); + if (skippy_iter.has_no_chance ()) return; + /* * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave * the ligature to keep its old ligature id. This will allow it to attach to @@ -720,7 +822,9 @@ static inline void ligate_input (hb_apply_context_t *c, for (unsigned int i = 1; i < count; i++) { - while (c->should_mark_skip_current_glyph ()) + if (!skippy_iter.next ()) return; + + while (c->buffer->idx < skippy_iter.idx) { if (!is_mark_ligature) { unsigned int new_lig_comp = components_so_far - last_num_components + @@ -759,19 +863,14 @@ static inline bool match_backtrack (hb_apply_context_t *c, { TRACE_APPLY (NULL); - hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true); - if (skippy_iter.has_no_chance ()) - return TRACE_RETURN (false); + hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true); + skippy_iter.set_match_func (match_func, match_data, backtrack); + if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); for (unsigned int i = 0; i < count; i++) - { if (!skippy_iter.prev ()) return TRACE_RETURN (false); - if (likely (!match_func (c->buffer->out_info[skippy_iter.idx].codepoint, backtrack[i], match_data))) - return TRACE_RETURN (false); - } - return TRACE_RETURN (true); } @@ -784,19 +883,14 @@ static inline bool match_lookahead (hb_apply_context_t *c, { TRACE_APPLY (NULL); - hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true); - if (skippy_iter.has_no_chance ()) - return TRACE_RETURN (false); + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true); + skippy_iter.set_match_func (match_func, match_data, lookahead); + if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); for (unsigned int i = 0; i < count; i++) - { if (!skippy_iter.next ()) return TRACE_RETURN (false); - if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, lookahead[i], match_data))) - return TRACE_RETURN (false); - } - return TRACE_RETURN (true); } @@ -829,6 +923,9 @@ static inline void recurse_lookups (context_t *c, static inline bool apply_lookup (hb_apply_context_t *c, unsigned int count, /* Including the first glyph */ + const USHORT input[], /* Array of input values--start with second glyph */ + match_func_t match_func, + const void *match_data, unsigned int lookupCount, const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */) { @@ -845,17 +942,46 @@ static inline bool apply_lookup (hb_apply_context_t *c, * and we jump out of it. Not entirely disastrous. So we don't check * for reverse lookup here. */ - for (unsigned int i = 0; i < count; /* NOP */) + + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); + skippy_iter.set_match_func (match_func, match_data, input); + uint8_t syllable = c->buffer->cur().syllable(); + + unsigned int i = 0; + if (lookupCount && 0 == lookupRecord->sequenceIndex) { - if (unlikely (c->buffer->idx == end)) - return TRACE_RETURN (true); - while (c->should_mark_skip_current_glyph ()) + unsigned int old_pos = c->buffer->idx; + + /* Apply a lookup */ + bool done = c->recurse (lookupRecord->lookupListIndex); + + lookupRecord++; + lookupCount--; + /* Err, this is wrong if the lookup jumped over some glyphs */ + i += c->buffer->idx - old_pos; + + if (!done) + goto not_applied; + else { - /* No lookup applied for this index */ - c->buffer->next_glyph (); - if (unlikely (c->buffer->idx == end)) - return TRACE_RETURN (true); + /* Reinitialize iterator. */ + hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx - 1, count - i); + tmp.set_syllable (syllable); + skippy_iter = tmp; } + } + else + { + not_applied: + /* No lookup applied for this index */ + c->buffer->next_glyph (); + i++; + } + while (i < count) + { + if (!skippy_iter.next ()) return TRACE_RETURN (true); + while (c->buffer->idx < skippy_iter.idx) + c->buffer->next_glyph (); if (lookupCount && i == lookupRecord->sequenceIndex) { @@ -868,15 +994,20 @@ static inline bool apply_lookup (hb_apply_context_t *c, lookupCount--; /* Err, this is wrong if the lookup jumped over some glyphs */ i += c->buffer->idx - old_pos; - if (unlikely (c->buffer->idx == end)) - return TRACE_RETURN (true); if (!done) - goto not_applied; + goto not_applied2; + else + { + /* Reinitialize iterator. */ + hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx - 1, count - i); + tmp.set_syllable (syllable); + skippy_iter = tmp; + } } else { - not_applied: + not_applied2: /* No lookup applied for this index */ c->buffer->next_glyph (); i++; @@ -958,7 +1089,8 @@ static inline bool context_apply_lookup (hb_apply_context_t *c, inputCount, input, lookup_context.funcs.match, lookup_context.match_data) && apply_lookup (c, - inputCount, + inputCount, input, + lookup_context.funcs.match, lookup_context.match_data, lookupCount, lookupRecord); } @@ -1353,13 +1485,13 @@ struct ContextFormat3 struct Context { template <typename context_t> - inline typename context_t::return_t process (context_t *c) const + inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_PROCESS (this); + TRACE_DISPATCH (this); switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); - case 2: return TRACE_RETURN (c->process (u.format2)); - case 3: return TRACE_RETURN (c->process (u.format3)); + case 1: return TRACE_RETURN (c->dispatch (u.format1)); + case 2: return TRACE_RETURN (c->dispatch (u.format2)); + case 3: return TRACE_RETURN (c->dispatch (u.format3)); default:return TRACE_RETURN (c->default_return_value ()); } } @@ -1494,7 +1626,8 @@ static inline bool chain_context_apply_lookup (hb_apply_context_t *c, lookup_context.funcs.match, lookup_context.match_data[2], lookahead_offset) && apply_lookup (c, - inputCount, + inputCount, input, + lookup_context.funcs.match, lookup_context.match_data[1], lookupCount, lookupRecord); } @@ -1968,13 +2101,13 @@ struct ChainContextFormat3 struct ChainContext { template <typename context_t> - inline typename context_t::return_t process (context_t *c) const + inline typename context_t::return_t dispatch (context_t *c) const { - TRACE_PROCESS (this); + TRACE_DISPATCH (this); switch (u.format) { - case 1: return TRACE_RETURN (c->process (u.format1)); - case 2: return TRACE_RETURN (c->process (u.format2)); - case 3: return TRACE_RETURN (c->process (u.format3)); + case 1: return TRACE_RETURN (c->dispatch (u.format1)); + case 2: return TRACE_RETURN (c->dispatch (u.format2)); + case 3: return TRACE_RETURN (c->dispatch (u.format3)); default:return TRACE_RETURN (c->default_return_value ()); } } @@ -2048,9 +2181,9 @@ struct Extension } template <typename context_t> - inline typename context_t::return_t process (context_t *c) const + inline typename context_t::return_t dispatch (context_t *c) const { - return get_subtable<typename T::LookupSubTable> ().process (c, get_type ()); + return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()); } inline bool sanitize_self (hb_sanitize_context_t *c) { diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh index 49093de..4866c41 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh @@ -43,6 +43,58 @@ #define syllable() var1.u8[2] /* GSUB/GPOS shaping boundaries */ #define lig_props() var1.u8[3] /* GSUB/GPOS ligature tracking */ +/* buffer var allocations, used during the entire shaping process */ +#define unicode_props0() var2.u8[0] +#define unicode_props1() var2.u8[1] + + +inline void +_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode) +{ + info->unicode_props0() = ((unsigned int) unicode->general_category (info->codepoint)) | + (unicode->is_default_ignorable (info->codepoint) ? 0x80 : 0) | + (info->codepoint == 0x200C ? 0x40 : 0) | + (info->codepoint == 0x200D ? 0x20 : 0); + info->unicode_props1() = unicode->modified_combining_class (info->codepoint); +} + +inline hb_unicode_general_category_t +_hb_glyph_info_get_general_category (const hb_glyph_info_t *info) +{ + return (hb_unicode_general_category_t) (info->unicode_props0() & 0x1F); +} + +inline void +_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info, unsigned int modified_class) +{ + info->unicode_props1() = modified_class; +} + +inline unsigned int +_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info) +{ + return info->unicode_props1(); +} + +inline hb_bool_t +_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info) +{ + return !!(info->unicode_props0() & 0x80); +} + +inline hb_bool_t +_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info) +{ + return !!(info->unicode_props0() & 0x40); +} + +inline hb_bool_t +_hb_glyph_info_is_zwj (const hb_glyph_info_t *info) +{ + return !!(info->unicode_props0() & 0x20); +} + + #define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot) /* @@ -50,11 +102,11 @@ */ typedef enum { - HB_OT_LAYOUT_GLYPH_PROPS_UNCLASSIFIED = 0x0001, - HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH = 0x0002, - HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE = 0x0004, - HB_OT_LAYOUT_GLYPH_PROPS_MARK = 0x0008, - HB_OT_LAYOUT_GLYPH_PROPS_COMPONENT = 0x0010 + HB_OT_LAYOUT_GLYPH_PROPS_UNCLASSIFIED = 1 << HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED, + HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH = 1 << HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH, + HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE = 1 << HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE, + HB_OT_LAYOUT_GLYPH_PROPS_MARK = 1 << HB_OT_LAYOUT_GLYPH_CLASS_MARK, + HB_OT_LAYOUT_GLYPH_PROPS_COMPONENT = 1 << HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT } hb_ot_layout_glyph_class_mask_t; @@ -154,7 +206,8 @@ HB_INTERNAL hb_bool_t hb_ot_layout_substitute_lookup (hb_font_t *font, hb_buffer_t *buffer, unsigned int lookup_index, - hb_mask_t mask); + hb_mask_t mask, + hb_bool_t auto_zwj); /* Should be called after all the substitute_lookup's are done */ HB_INTERNAL void @@ -171,13 +224,13 @@ HB_INTERNAL hb_bool_t hb_ot_layout_position_lookup (hb_font_t *font, hb_buffer_t *buffer, unsigned int lookup_index, - hb_mask_t mask); + hb_mask_t mask, + hb_bool_t auto_zwj); /* Should be called after all the position_lookup's are done */ HB_INTERNAL void hb_ot_layout_position_finish (hb_font_t *font, - hb_buffer_t *buffer, - hb_bool_t zero_width_attached_marks); + hb_buffer_t *buffer); diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout.cc b/third_party/harfbuzz-ng/src/hb-ot-layout.cc index 5c266e6..8161ce3d 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-layout.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-layout.cc @@ -185,6 +185,8 @@ hb_ot_layout_table_get_script_tags (hb_face_t *face, return g.get_script_tags (start_offset, script_count, script_tags); } +#define HB_OT_TAG_LATIN_SCRIPT HB_TAG ('l', 'a', 't', 'n') + hb_bool_t hb_ot_layout_table_find_script (hb_face_t *face, hb_tag_t table_tag, @@ -206,6 +208,11 @@ hb_ot_layout_table_find_script (hb_face_t *face, if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) return false; + /* try with 'latn'; some old fonts put their features there even though + they're really trying to support Thai, for example :( */ + if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) + return false; + if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX; return false; } @@ -246,7 +253,6 @@ hb_ot_layout_table_choose_script (hb_face_t *face, /* try with 'latn'; some old fonts put their features there even though they're really trying to support Thai, for example :( */ -#define HB_OT_TAG_LATIN_SCRIPT HB_TAG ('l', 'a', 't', 'n') if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) { if (chosen_script) *chosen_script = HB_OT_TAG_LATIN_SCRIPT; @@ -660,11 +666,12 @@ hb_bool_t hb_ot_layout_substitute_lookup (hb_font_t *font, hb_buffer_t *buffer, unsigned int lookup_index, - hb_mask_t mask) + hb_mask_t mask, + hb_bool_t auto_zwj) { if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gsub_lookup_count)) return false; - OT::hb_apply_context_t c (font, buffer, mask); + OT::hb_apply_context_t c (0, font, buffer, mask, auto_zwj); const OT::SubstLookup& l = hb_ot_layout_from_face (font->face)->gsub->get_lookup (lookup_index); @@ -709,11 +716,12 @@ hb_bool_t hb_ot_layout_position_lookup (hb_font_t *font, hb_buffer_t *buffer, unsigned int lookup_index, - hb_mask_t mask) + hb_mask_t mask, + hb_bool_t auto_zwj) { if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gpos_lookup_count)) return false; - OT::hb_apply_context_t c (font, buffer, mask); + OT::hb_apply_context_t c (1, font, buffer, mask, auto_zwj); const OT::PosLookup& l = hb_ot_layout_from_face (font->face)->gpos->get_lookup (lookup_index); @@ -721,9 +729,9 @@ hb_ot_layout_position_lookup (hb_font_t *font, } void -hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer, hb_bool_t zero_width_attached_marks) +hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer) { - OT::GPOS::position_finish (font, buffer, zero_width_attached_marks); + OT::GPOS::position_finish (font, buffer); } hb_bool_t diff --git a/third_party/harfbuzz-ng/src/hb-ot-map-private.hh b/third_party/harfbuzz-ng/src/hb-ot-map-private.hh index b140207..a679fb5 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-map-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-map-private.hh @@ -49,14 +49,16 @@ struct hb_ot_map_t unsigned int shift; hb_mask_t mask; hb_mask_t _1_mask; /* mask for value=1, for quick access */ - hb_bool_t needs_fallback; + unsigned int needs_fallback : 1; + unsigned int auto_zwj : 1; static int cmp (const feature_map_t *a, const feature_map_t *b) { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; } }; struct lookup_map_t { - unsigned int index; + unsigned short index; + unsigned short auto_zwj : 1; hb_mask_t mask; static int cmp (const lookup_map_t *a, const lookup_map_t *b) @@ -136,7 +138,8 @@ struct hb_ot_map_t HB_INTERNAL void add_lookups (hb_face_t *face, unsigned int table_index, unsigned int feature_index, - hb_mask_t mask); + hb_mask_t mask, + bool auto_zwj); hb_mask_t global_mask; @@ -145,6 +148,30 @@ struct hb_ot_map_t hb_prealloced_array_t<pause_map_t, 1> pauses[2]; /* GSUB/GPOS */ }; +enum hb_ot_map_feature_flags_t { + F_NONE = 0x0000, + F_GLOBAL = 0x0001, + F_HAS_FALLBACK = 0x0002, + F_MANUAL_ZWJ = 0x0004 +}; +/* Macro version for where const is desired. */ +#define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r))) +inline hb_ot_map_feature_flags_t +operator | (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r) +{ return hb_ot_map_feature_flags_t ((unsigned int) l | (unsigned int) r); } +inline hb_ot_map_feature_flags_t +operator & (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r) +{ return hb_ot_map_feature_flags_t ((unsigned int) l & (unsigned int) r); } +inline hb_ot_map_feature_flags_t +operator ~ (hb_ot_map_feature_flags_t r) +{ return hb_ot_map_feature_flags_t (~(unsigned int) r); } +inline hb_ot_map_feature_flags_t& +operator |= (hb_ot_map_feature_flags_t &l, hb_ot_map_feature_flags_t r) +{ l = l | r; return l; } +inline hb_ot_map_feature_flags_t& +operator &= (hb_ot_map_feature_flags_t& l, hb_ot_map_feature_flags_t r) +{ l = l & r; return l; } + struct hb_ot_map_builder_t { @@ -153,10 +180,11 @@ struct hb_ot_map_builder_t HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_, const hb_segment_properties_t *props_); - HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value, bool global, bool has_fallback = false); + HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value, + hb_ot_map_feature_flags_t flags); - inline void add_bool_feature (hb_tag_t tag, bool global = true, bool has_fallback = false) - { add_feature (tag, 1, global, has_fallback); } + inline void add_global_bool_feature (hb_tag_t tag) + { add_feature (tag, 1, F_GLOBAL); } inline void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func) { add_pause (0, pause_func); } @@ -177,8 +205,7 @@ struct hb_ot_map_builder_t hb_tag_t tag; unsigned int seq; /* sequence#, used for stable sorting only */ unsigned int max_value; - bool global; /* whether the feature applies value to every glyph in the buffer */ - bool has_fallback; /* whether to allocate bits even if feature not found */ + hb_ot_map_feature_flags_t flags; unsigned int default_value; /* for non-global features, what should the unset glyphs take */ unsigned int stage[2]; /* GSUB/GPOS */ diff --git a/third_party/harfbuzz-ng/src/hb-ot-map.cc b/third_party/harfbuzz-ng/src/hb-ot-map.cc index 62f7904..85e6e16 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-map.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-map.cc @@ -33,7 +33,8 @@ void hb_ot_map_t::add_lookups (hb_face_t *face, unsigned int table_index, unsigned int feature_index, - hb_mask_t mask) + hb_mask_t mask, + bool auto_zwj) { unsigned int lookup_indices[32]; unsigned int offset, len; @@ -53,6 +54,7 @@ hb_ot_map_t::add_lookups (hb_face_t *face, return; lookup->mask = mask; lookup->index = lookup_indices[i]; + lookup->auto_zwj = auto_zwj; } offset += len; @@ -84,16 +86,16 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_, } } -void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, bool global, bool has_fallback) +void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, + hb_ot_map_feature_flags_t flags) { feature_info_t *info = feature_infos.push(); if (unlikely (!info)) return; info->tag = tag; info->seq = feature_infos.len; info->max_value = value; - info->global = global; - info->has_fallback = has_fallback; - info->default_value = global ? value : 0; + info->flags = flags; + info->default_value = (flags & F_GLOBAL) ? value : 0; info->stage[0] = current_stage[0]; info->stage[1] = current_stage[1]; } @@ -108,7 +110,10 @@ void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, h for (unsigned int pause_index = 0; pause_index < pauses[table_index].len; pause_index++) { const pause_map_t *pause = &pauses[table_index][pause_index]; for (; i < pause->num_lookups; i++) - hb_ot_layout_substitute_lookup (font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask); + hb_ot_layout_substitute_lookup (font, buffer, + lookups[table_index][i].index, + lookups[table_index][i].mask, + lookups[table_index][i].auto_zwj); buffer->clear_output (); @@ -117,7 +122,9 @@ void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, h } for (; i < lookups[table_index].len; i++) - hb_ot_layout_substitute_lookup (font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask); + hb_ot_layout_substitute_lookup (font, buffer, lookups[table_index][i].index, + lookups[table_index][i].mask, + lookups[table_index][i].auto_zwj); } void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const @@ -128,14 +135,18 @@ void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_ for (unsigned int pause_index = 0; pause_index < pauses[table_index].len; pause_index++) { const pause_map_t *pause = &pauses[table_index][pause_index]; for (; i < pause->num_lookups; i++) - hb_ot_layout_position_lookup (font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask); + hb_ot_layout_position_lookup (font, buffer, lookups[table_index][i].index, + lookups[table_index][i].mask, + lookups[table_index][i].auto_zwj); if (pause->callback) pause->callback (plan, font, buffer); } for (; i < lookups[table_index].len; i++) - hb_ot_layout_position_lookup (font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask); + hb_ot_layout_position_lookup (font, buffer, lookups[table_index][i].index, + lookups[table_index][i].mask, + lookups[table_index][i].auto_zwj); } void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const @@ -176,18 +187,18 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) if (feature_infos[i].tag != feature_infos[j].tag) feature_infos[++j] = feature_infos[i]; else { - if (feature_infos[i].global) { - feature_infos[j].global = true; + if (feature_infos[i].flags & F_GLOBAL) { + feature_infos[j].flags |= F_GLOBAL; feature_infos[j].max_value = feature_infos[i].max_value; feature_infos[j].default_value = feature_infos[i].default_value; } else { - feature_infos[j].global = false; + feature_infos[j].flags &= ~F_GLOBAL; feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_infos[i].max_value); + /* Inherit default_value from j */ } - feature_infos[j].has_fallback = feature_infos[j].has_fallback || feature_infos[i].has_fallback; + feature_infos[j].flags |= (feature_infos[i].flags & F_HAS_FALLBACK); feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_infos[i].stage[0]); feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_infos[i].stage[1]); - /* Inherit default_value from j */ } feature_infos.shrink (j + 1); } @@ -200,7 +211,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) unsigned int bits_needed; - if (info->global && info->max_value == 1) + if ((info->flags & F_GLOBAL) && info->max_value == 1) /* Uses the global bit */ bits_needed = 0; else @@ -219,7 +230,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) language_index[table_index], info->tag, &feature_index[table_index]); - if (!found && !info->has_fallback) + if (!found && !(info->flags & F_HAS_FALLBACK)) continue; @@ -232,7 +243,8 @@ 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]; - if (info->global && info->max_value == 1) { + 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; @@ -240,8 +252,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) map->shift = next_bit; map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit); next_bit += bits_needed; - if (info->global) - m.global_mask |= (info->default_value << map->shift) & map->mask; + m.global_mask |= (info->default_value << map->shift) & map->mask; } map->_1_mask = (1 << map->shift) & map->mask; map->needs_fallback = !found; @@ -264,7 +275,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) script_index[table_index], language_index[table_index], &required_feature_index)) - m.add_lookups (face, table_index, required_feature_index, 1); + m.add_lookups (face, table_index, required_feature_index, 1, true); unsigned int pause_index = 0; unsigned int last_num_lookups = 0; @@ -272,7 +283,10 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) { 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.add_lookups (face, table_index, + m.features[i].index[table_index], + m.features[i].mask, + m.features[i].auto_zwj); /* Sort lookups and merge duplicates */ if (last_num_lookups < m.lookups[table_index].len) @@ -284,7 +298,10 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) if (m.lookups[table_index][i].index != m.lookups[table_index][j].index) m.lookups[table_index][++j] = m.lookups[table_index][i]; else + { m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask; + m.lookups[table_index][j].auto_zwj &= m.lookups[table_index][i].auto_zwj; + } m.lookups[table_index].shrink (j + 1); } diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh index 4fcd0a2..5e151f7 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh @@ -244,7 +244,7 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan, { for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) if (fallback_plan->lookup_array[i]) { - OT::hb_apply_context_t c (font, buffer, fallback_plan->mask_array[i]); + OT::hb_apply_context_t c (0, font, buffer, fallback_plan->mask_array[i], true/*auto_zwj*/); fallback_plan->lookup_array[i]->apply_string (&c, &fallback_plan->digest_array[i]); } } diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc index 35356fe..18b3d02 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc @@ -37,17 +37,16 @@ */ enum { JOINING_TYPE_U = 0, - JOINING_TYPE_R = 1, - JOINING_TYPE_D = 2, + JOINING_TYPE_L = 1, + JOINING_TYPE_R = 2, + JOINING_TYPE_D = 3, JOINING_TYPE_C = JOINING_TYPE_D, - JOINING_GROUP_ALAPH = 3, - JOINING_GROUP_DALATH_RISH = 4, - NUM_STATE_MACHINE_COLS = 5, + JOINING_GROUP_ALAPH = 4, + JOINING_GROUP_DALATH_RISH = 5, + NUM_STATE_MACHINE_COLS = 6, - /* We deliberately don't have a JOINING_TYPE_L since that's unused in Unicode. */ - - JOINING_TYPE_T = 6, - JOINING_TYPE_X = 7 /* means: use general-category to choose between U or T. */ + JOINING_TYPE_T = 7, + JOINING_TYPE_X = 8 /* means: use general-category to choose between U or T. */ }; /* @@ -81,8 +80,7 @@ static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_categ if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xA840, 0xA872))) { if (unlikely (u == 0xA872)) - /* XXX Looks like this should be TYPE_L, but we don't support that yet! */ - return JOINING_TYPE_R; + return JOINING_TYPE_L; return JOINING_TYPE_D; } @@ -133,28 +131,28 @@ static const struct arabic_state_table_entry { uint16_t next_state; } arabic_state_table[][NUM_STATE_MACHINE_COLS] = { - /* jt_U, jt_R, jt_D, jg_ALAPH, jg_DALATH_RISH */ + /* jt_U, jt_L, jt_R, jt_D, jg_ALAPH, jg_DALATH_RISH */ /* State 0: prev was U, not willing to join. */ - { {NONE,NONE,0}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,6}, }, + { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,6}, }, /* State 1: prev was R or ISOL/ALAPH, not willing to join. */ - { {NONE,NONE,0}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN2,5}, {NONE,ISOL,6}, }, + { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN2,5}, {NONE,ISOL,6}, }, - /* State 2: prev was D/ISOL, willing to join. */ - { {NONE,NONE,0}, {INIT,FINA,1}, {INIT,FINA,3}, {INIT,FINA,4}, {INIT,FINA,6}, }, + /* State 2: prev was D/L in ISOL form, willing to join. */ + { {NONE,NONE,0}, {NONE,ISOL,2}, {INIT,FINA,1}, {INIT,FINA,3}, {INIT,FINA,4}, {INIT,FINA,6}, }, - /* State 3: prev was D/FINA, willing to join. */ - { {NONE,NONE,0}, {MEDI,FINA,1}, {MEDI,FINA,3}, {MEDI,FINA,4}, {MEDI,FINA,6}, }, + /* State 3: prev was D in FINA form, willing to join. */ + { {NONE,NONE,0}, {NONE,ISOL,2}, {MEDI,FINA,1}, {MEDI,FINA,3}, {MEDI,FINA,4}, {MEDI,FINA,6}, }, /* State 4: prev was FINA ALAPH, not willing to join. */ - { {NONE,NONE,0}, {MED2,ISOL,1}, {MED2,ISOL,2}, {MED2,FIN2,5}, {MED2,ISOL,6}, }, + { {NONE,NONE,0}, {NONE,ISOL,2}, {MED2,ISOL,1}, {MED2,ISOL,2}, {MED2,FIN2,5}, {MED2,ISOL,6}, }, /* State 5: prev was FIN2/FIN3 ALAPH, not willing to join. */ - { {NONE,NONE,0}, {ISOL,ISOL,1}, {ISOL,ISOL,2}, {ISOL,FIN2,5}, {ISOL,ISOL,6}, }, + { {NONE,NONE,0}, {NONE,ISOL,2}, {ISOL,ISOL,1}, {ISOL,ISOL,2}, {ISOL,FIN2,5}, {ISOL,ISOL,6}, }, /* State 6: prev was DALATH/RISH, not willing to join. */ - { {NONE,NONE,0}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN3,5}, {NONE,ISOL,6}, } + { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN3,5}, {NONE,ISOL,6}, } }; @@ -178,25 +176,25 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) * TODO: Add test cases for these two. */ - map->add_bool_feature (HB_TAG('c','c','m','p')); - map->add_bool_feature (HB_TAG('l','o','c','l')); + map->add_global_bool_feature (HB_TAG('c','c','m','p')); + map->add_global_bool_feature (HB_TAG('l','o','c','l')); map->add_gsub_pause (NULL); for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) - map->add_bool_feature (arabic_features[i], false, i < 4); /* The first four features have fallback. */ + map->add_feature (arabic_features[i], 1, i < 4 ? F_HAS_FALLBACK : F_NONE); /* The first four features have fallback. */ map->add_gsub_pause (NULL); - map->add_bool_feature (HB_TAG('r','l','i','g'), true, true); + map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK); map->add_gsub_pause (arabic_fallback_shape); - map->add_bool_feature (HB_TAG('c','a','l','t')); + map->add_global_bool_feature (HB_TAG('c','a','l','t')); map->add_gsub_pause (NULL); - map->add_bool_feature (HB_TAG('c','s','w','h')); - map->add_bool_feature (HB_TAG('d','l','i','g')); - map->add_bool_feature (HB_TAG('m','s','e','t')); + map->add_global_bool_feature (HB_TAG('c','s','w','h')); + map->add_global_bool_feature (HB_TAG('d','l','i','g')); + map->add_global_bool_feature (HB_TAG('m','s','e','t')); } #include "hb-ot-shape-complex-arabic-fallback.hh" @@ -354,6 +352,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = NULL, /* decompose */ NULL, /* compose */ setup_masks_arabic, - true, /* zero_width_attached_marks */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE, true, /* fallback_position */ }; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc index 5340293..fad57f6 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc @@ -68,7 +68,7 @@ collect_features_default (hb_ot_shape_planner_t *plan) } for (; script_features && *script_features; script_features++) - plan->map.add_bool_feature (*script_features); + plan->map.add_global_bool_feature (*script_features); } static hb_ot_shape_normalization_mode_t @@ -221,6 +221,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default = NULL, /* decompose */ compose_default, NULL, /* setup_masks */ - true, /* zero_width_attached_marks */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE, true, /* fallback_position */ }; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh index ed40b96..ada8891 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh @@ -1,5 +1,5 @@ -#line 1 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 1 "hb-ot-shape-complex-indic-machine.rl" /* * Copyright © 2011,2012 Google, Inc. * @@ -32,7 +32,7 @@ #include "hb-private.hh" -#line 36 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 36 "hb-ot-shape-complex-indic-machine.hh.tmp" static const unsigned char _indic_syllable_machine_trans_keys[] = { 1u, 16u, 13u, 13u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 5u, 7u, 5u, 7u, 7u, 7u, 4u, 4u, 6u, 6u, @@ -1245,11 +1245,11 @@ static const int indic_syllable_machine_error = -1; static const int indic_syllable_machine_en_main = 170; -#line 36 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 36 "hb-ot-shape-complex-indic-machine.rl" -#line 91 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 91 "hb-ot-shape-complex-indic-machine.rl" #define found_syllable(syllable_type) \ @@ -1265,11 +1265,11 @@ static const int indic_syllable_machine_en_main = 170; static void find_syllables (hb_buffer_t *buffer) { - unsigned int p, pe, eof, ts HB_UNUSED, te, act; + unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED; int cs; hb_glyph_info_t *info = buffer->info; -#line 1273 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1273 "hb-ot-shape-complex-indic-machine.hh.tmp" { cs = indic_syllable_machine_start; ts = 0; @@ -1277,7 +1277,7 @@ find_syllables (hb_buffer_t *buffer) act = 0; } -#line 112 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 112 "hb-ot-shape-complex-indic-machine.rl" p = 0; @@ -1286,7 +1286,7 @@ find_syllables (hb_buffer_t *buffer) unsigned int last = 0; unsigned int syllable_serial = 1; -#line 1290 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1290 "hb-ot-shape-complex-indic-machine.hh.tmp" { int _slen; int _trans; @@ -1300,7 +1300,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 1304 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1304 "hb-ot-shape-complex-indic-machine.hh.tmp" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -1323,59 +1323,59 @@ _eof_trans: {te = p+1;} break; case 14: -#line 83 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 83 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (consonant_syllable); }} break; case 16: -#line 84 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 84 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (vowel_syllable); }} break; case 21: -#line 85 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 85 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (standalone_cluster); }} break; case 18: -#line 86 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 86 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (broken_cluster); }} break; case 11: -#line 87 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 87 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (non_indic_cluster); }} break; case 13: -#line 83 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 83 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (consonant_syllable); }} break; case 15: -#line 84 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 84 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (vowel_syllable); }} break; case 20: -#line 85 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 85 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (standalone_cluster); }} break; case 17: -#line 86 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 86 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; case 19: -#line 87 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 87 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (non_indic_cluster); }} break; case 1: -#line 83 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 83 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (consonant_syllable); }} break; case 3: -#line 84 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 84 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (vowel_syllable); }} break; case 7: -#line 85 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 85 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (standalone_cluster); }} break; case 4: -#line 86 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 86 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (broken_cluster); }} break; case 5: @@ -1396,22 +1396,22 @@ _eof_trans: case 8: #line 1 "NONE" {te = p+1;} -#line 83 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 83 "hb-ot-shape-complex-indic-machine.rl" {act = 1;} break; case 6: #line 1 "NONE" {te = p+1;} -#line 86 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 86 "hb-ot-shape-complex-indic-machine.rl" {act = 4;} break; case 12: #line 1 "NONE" {te = p+1;} -#line 87 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 87 "hb-ot-shape-complex-indic-machine.rl" {act = 5;} break; -#line 1415 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1415 "hb-ot-shape-complex-indic-machine.hh.tmp" } _again: @@ -1420,7 +1420,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 1424 "../../src/hb-ot-shape-complex-indic-machine.hh.tmp" +#line 1424 "hb-ot-shape-complex-indic-machine.hh.tmp" } if ( ++p != pe ) @@ -1436,7 +1436,7 @@ _again: } -#line 121 "../../src/hb-ot-shape-complex-indic-machine.rl" +#line 121 "hb-ot-shape-complex-indic-machine.rl" } diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.rl b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.rl index 11115c9..f9f07d8 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.rl +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.rl @@ -103,7 +103,7 @@ main := |* static void find_syllables (hb_buffer_t *buffer) { - unsigned int p, pe, eof, ts HB_UNUSED, te, act; + unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED; int cs; hb_glyph_info_t *info = buffer->info; %%{ diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh index e36090e..39268b1 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh @@ -34,11 +34,6 @@ #include "hb-ot-shape-private.hh" /* XXX Remove */ -/* buffer var allocations */ -#define indic_category() complex_var_u8_0() /* indic_category_t */ -#define indic_position() complex_var_u8_1() /* indic_matra_category_t */ - - #define INDIC_TABLE_ELEMENT_TYPE uint16_t /* Cateories used in the OpenType spec: @@ -102,7 +97,7 @@ enum indic_syllabic_category_t { INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM, INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C, INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C, - INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_C, + INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM, INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C, INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM, INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_NBSP, @@ -150,239 +145,7 @@ enum indic_matra_category_t { ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \ ((M << 8) | S)) - -#include "hb-ot-shape-complex-indic-table.hh" - - -#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7F) == (Base)) - -#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900)) -#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980)) -#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00)) -#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80)) -#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00)) -#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80)) -#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00)) -#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80)) -#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00)) -#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80)) -#define IS_KHMR(u) (IN_HALF_BLOCK (u, 0x1780)) - - -#define MATRA_POS_LEFT(u) POS_PRE_M -#define MATRA_POS_RIGHT(u) ( \ - IS_DEVA(u) ? POS_AFTER_SUB : \ - IS_BENG(u) ? POS_AFTER_POST : \ - IS_GURU(u) ? POS_AFTER_POST : \ - IS_GUJR(u) ? POS_AFTER_POST : \ - IS_ORYA(u) ? POS_AFTER_POST : \ - IS_TAML(u) ? POS_AFTER_POST : \ - IS_TELU(u) ? (u <= 0x0C42 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \ - IS_KNDA(u) ? (u < 0x0CC3 || u > 0xCD6 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \ - IS_MLYM(u) ? POS_AFTER_POST : \ - IS_SINH(u) ? POS_AFTER_SUB : \ - IS_KHMR(u) ? POS_AFTER_POST : \ - /*default*/ POS_AFTER_SUB \ - ) -#define MATRA_POS_TOP(u) ( /* BENG and MLYM don't have top matras. */ \ - IS_DEVA(u) ? POS_AFTER_SUB : \ - IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \ - IS_GUJR(u) ? POS_AFTER_SUB : \ - IS_ORYA(u) ? POS_AFTER_MAIN : \ - IS_TAML(u) ? POS_AFTER_SUB : \ - IS_TELU(u) ? POS_BEFORE_SUB : \ - IS_KNDA(u) ? POS_BEFORE_SUB : \ - IS_SINH(u) ? POS_AFTER_SUB : \ - IS_KHMR(u) ? POS_AFTER_POST : \ - /*default*/ POS_AFTER_SUB \ - ) -#define MATRA_POS_BOTTOM(u) ( \ - IS_DEVA(u) ? POS_AFTER_SUB : \ - IS_BENG(u) ? POS_AFTER_SUB : \ - IS_GURU(u) ? POS_AFTER_POST : \ - IS_GUJR(u) ? POS_AFTER_POST : \ - IS_ORYA(u) ? POS_AFTER_SUB : \ - IS_TAML(u) ? POS_AFTER_POST : \ - IS_TELU(u) ? POS_BEFORE_SUB : \ - IS_KNDA(u) ? POS_BEFORE_SUB : \ - IS_MLYM(u) ? POS_AFTER_POST : \ - IS_SINH(u) ? POS_AFTER_SUB : \ - IS_KHMR(u) ? POS_AFTER_POST : \ - /*default*/ POS_AFTER_SUB \ - ) - - -static inline indic_position_t -matra_position (hb_codepoint_t u, indic_position_t side) -{ - switch ((int) side) - { - case POS_PRE_C: return MATRA_POS_LEFT (u); - case POS_POST_C: return MATRA_POS_RIGHT (u); - case POS_ABOVE_C: return MATRA_POS_TOP (u); - case POS_BELOW_C: return MATRA_POS_BOTTOM (u); - }; - return side; -} - - - -/* XXX - * This is a hack for now. We should move this data into the main Indic table. - * Or completely remove it and just check in the tables. - */ -static const hb_codepoint_t ra_chars[] = { - 0x0930, /* Devanagari */ - 0x09B0, /* Bengali */ - 0x09F0, /* Bengali */ - 0x0A30, /* Gurmukhi */ /* No Reph */ - 0x0AB0, /* Gujarati */ - 0x0B30, /* Oriya */ - 0x0BB0, /* Tamil */ /* No Reph */ - 0x0C30, /* Telugu */ /* Reph formed only with ZWJ */ - 0x0CB0, /* Kannada */ - 0x0D30, /* Malayalam */ /* No Reph, Logical Repha */ - - 0x0DBB, /* Sinhala */ /* Reph formed only with ZWJ */ - - 0x179A, /* Khmer */ /* No Reph, Visual Repha */ -}; - -static inline indic_position_t -consonant_position (hb_codepoint_t u) -{ - if ((u & ~0x007F) == 0x1780) - return POS_BELOW_C; /* In Khmer coeng model, post and below forms should not be reordered. */ - return POS_BASE_C; /* Will recategorize later based on font lookups. */ -} - -static inline bool -is_ra (hb_codepoint_t u) -{ - for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++) - if (u == ra_chars[i]) - return true; - return false; -} - - -static inline bool -is_one_of (const hb_glyph_info_t &info, unsigned int flags) -{ - /* If it ligated, all bets are off. */ - if (is_a_ligature (info)) return false; - return !!(FLAG (info.indic_category()) & flags); -} - -#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ)) -static inline bool -is_joiner (const hb_glyph_info_t &info) -{ - return is_one_of (info, JOINER_FLAGS); -} - -/* Note: - * - * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels - * cannot happen in a consonant syllable. The plus side however is, we can call the - * consonant syllable logic from the vowel syllable function and get it all right! */ -#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CM) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_DOTTEDCIRCLE)) -static inline bool -is_consonant (const hb_glyph_info_t &info) -{ - return is_one_of (info, CONSONANT_FLAGS); -} - -#define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng)) -static inline bool -is_halant_or_coeng (const hb_glyph_info_t &info) -{ - return is_one_of (info, HALANT_OR_COENG_FLAGS); -} - -static inline void -set_indic_properties (hb_glyph_info_t &info) -{ - hb_codepoint_t u = info.codepoint; - unsigned int type = get_indic_categories (u); - indic_category_t cat = (indic_category_t) (type & 0x7F); - indic_position_t pos = (indic_position_t) (type >> 8); - - - /* - * Re-assign category - */ - - - /* The spec says U+0952 is OT_A. However, testing shows that Uniscribe - * treats U+0951..U+0952 all as OT_VD. - * TESTS: - * U+092E,U+0947,U+0952 - * U+092E,U+0952,U+0947 - * U+092E,U+0947,U+0951 - * U+092E,U+0951,U+0947 - * */ - if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0951, 0x0954))) - cat = OT_VD; - - if (unlikely (u == 0x17D1)) - cat = OT_X; - if (cat == OT_X && - unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CB, 0x17D3))) /* Khmer Various signs */ - { - /* These are like Top Matras. */ - cat = OT_M; - pos = POS_ABOVE_C; - } - if (u == 0x17C6) /* Khmer Bindu doesn't like to be repositioned. */ - cat = OT_N; - - if (unlikely (u == 0x17D2)) cat = OT_Coeng; /* Khmer coeng */ - else if (unlikely (u == 0x200C)) cat = OT_ZWNJ; - else if (unlikely (u == 0x200D)) cat = OT_ZWJ; - else if (unlikely (u == 0x25CC)) cat = OT_DOTTEDCIRCLE; - else if (unlikely (u == 0x0A71)) cat = OT_SM; /* GURMUKHI ADDAK. More like consonant medial. like 0A75. */ - - if (cat == OT_Repha) { - /* There are two kinds of characters marked as Repha: - * - The ones that are GenCat=Mn are already positioned visually, ie. after base. (eg. Khmer) - * - The ones that are GenCat=Lo is encoded logically, ie. beginning of syllable. (eg. Malayalam) - * - * We recategorize the first kind to look like a Nukta and attached to the base directly. - */ - if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) - cat = OT_N; - } - - - - /* - * Re-assign position. - */ - - if ((FLAG (cat) & CONSONANT_FLAGS)) - { - pos = consonant_position (u); - if (is_ra (u)) - cat = OT_Ra; - } - else if (cat == OT_M) - { - pos = matra_position (u, pos); - } - else if (cat == OT_SM || cat == OT_VD) - { - pos = POS_SMVD; - } - - if (unlikely (u == 0x0B01)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */ - - - - info.indic_category() = cat; - info.indic_position() = pos; -} - - +HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE +hb_indic_get_categories (hb_codepoint_t u); #endif /* HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH */ diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc index 70765b6..18a022b 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc @@ -14,8 +14,7 @@ * # Date: 2012-05-14, 22:42:00 GMT [KW, LI] */ -#ifndef HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH -#define HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH +#include "hb-ot-shape-complex-indic-private.hh" #define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 11 chars; Avagraha */ @@ -807,8 +806,8 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { }; /* Table occupancy: 60% */ -static INDIC_TABLE_ELEMENT_TYPE -get_indic_categories (hb_codepoint_t u) +INDIC_TABLE_ELEMENT_TYPE +hb_indic_get_categories (hb_codepoint_t u) { if (0x0900 <= u && u <= 0x10A0) return indic_table[u - 0x0900 + indic_offset_0x0900]; if (0x1700 <= u && u <= 0x1800) return indic_table[u - 0x1700 + indic_offset_0x1700]; @@ -867,6 +866,4 @@ get_indic_categories (hb_codepoint_t u) #undef IMC_TR #undef IMC_VOL -#endif /* HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH */ - /* == End of generated table == */ diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc index 1bc8a77..eb1e0be 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc @@ -27,49 +27,245 @@ #include "hb-ot-shape-complex-indic-private.hh" #include "hb-ot-layout-private.hh" +/* buffer var allocations */ +#define indic_category() complex_var_u8_0() /* indic_category_t */ +#define indic_position() complex_var_u8_1() /* indic_position_t */ + /* - * Global Indic shaper options. + * Indic shaper. */ -struct indic_options_t + +#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7F) == (Base)) + +#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900)) +#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980)) +#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00)) +#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80)) +#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00)) +#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80)) +#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00)) +#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80)) +#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00)) +#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80)) +#define IS_KHMR(u) (IN_HALF_BLOCK (u, 0x1780)) + + +#define MATRA_POS_LEFT(u) POS_PRE_M +#define MATRA_POS_RIGHT(u) ( \ + IS_DEVA(u) ? POS_AFTER_SUB : \ + IS_BENG(u) ? POS_AFTER_POST : \ + IS_GURU(u) ? POS_AFTER_POST : \ + IS_GUJR(u) ? POS_AFTER_POST : \ + IS_ORYA(u) ? POS_AFTER_POST : \ + IS_TAML(u) ? POS_AFTER_POST : \ + IS_TELU(u) ? (u <= 0x0C42 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \ + IS_KNDA(u) ? (u < 0x0CC3 || u > 0xCD6 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \ + IS_MLYM(u) ? POS_AFTER_POST : \ + IS_SINH(u) ? POS_AFTER_SUB : \ + IS_KHMR(u) ? POS_AFTER_POST : \ + /*default*/ POS_AFTER_SUB \ + ) +#define MATRA_POS_TOP(u) ( /* BENG and MLYM don't have top matras. */ \ + IS_DEVA(u) ? POS_AFTER_SUB : \ + IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \ + IS_GUJR(u) ? POS_AFTER_SUB : \ + IS_ORYA(u) ? POS_AFTER_MAIN : \ + IS_TAML(u) ? POS_AFTER_SUB : \ + IS_TELU(u) ? POS_BEFORE_SUB : \ + IS_KNDA(u) ? POS_BEFORE_SUB : \ + IS_SINH(u) ? POS_AFTER_SUB : \ + IS_KHMR(u) ? POS_AFTER_POST : \ + /*default*/ POS_AFTER_SUB \ + ) +#define MATRA_POS_BOTTOM(u) ( \ + IS_DEVA(u) ? POS_AFTER_SUB : \ + IS_BENG(u) ? POS_AFTER_SUB : \ + IS_GURU(u) ? POS_AFTER_POST : \ + IS_GUJR(u) ? POS_AFTER_POST : \ + IS_ORYA(u) ? POS_AFTER_SUB : \ + IS_TAML(u) ? POS_AFTER_POST : \ + IS_TELU(u) ? POS_BEFORE_SUB : \ + IS_KNDA(u) ? POS_BEFORE_SUB : \ + IS_MLYM(u) ? POS_AFTER_POST : \ + IS_SINH(u) ? POS_AFTER_SUB : \ + IS_KHMR(u) ? POS_AFTER_POST : \ + /*default*/ POS_AFTER_SUB \ + ) + +static inline indic_position_t +matra_position (hb_codepoint_t u, indic_position_t side) { - int initialized : 1; - int uniscribe_bug_compatible : 1; -}; + switch ((int) side) + { + case POS_PRE_C: return MATRA_POS_LEFT (u); + case POS_POST_C: return MATRA_POS_RIGHT (u); + case POS_ABOVE_C: return MATRA_POS_TOP (u); + case POS_BELOW_C: return MATRA_POS_BOTTOM (u); + }; + return side; +} -union indic_options_union_t { - int i; - indic_options_t opts; +/* XXX + * This is a hack for now. We should move this data into the main Indic table. + * Or completely remove it and just check in the tables. + */ +static const hb_codepoint_t ra_chars[] = { + 0x0930, /* Devanagari */ + 0x09B0, /* Bengali */ + 0x09F0, /* Bengali */ + 0x0A30, /* Gurmukhi */ /* No Reph */ + 0x0AB0, /* Gujarati */ + 0x0B30, /* Oriya */ + 0x0BB0, /* Tamil */ /* No Reph */ + 0x0C30, /* Telugu */ /* Reph formed only with ZWJ */ + 0x0CB0, /* Kannada */ + 0x0D30, /* Malayalam */ /* No Reph, Logical Repha */ + + 0x0DBB, /* Sinhala */ /* Reph formed only with ZWJ */ + + 0x179A, /* Khmer */ /* No Reph, Visual Repha */ }; -ASSERT_STATIC (sizeof (int) == sizeof (indic_options_union_t)); -static indic_options_union_t -indic_options_init (void) +static inline indic_position_t +consonant_position (hb_codepoint_t u) +{ + if ((u & ~0x007F) == 0x1780) + return POS_BELOW_C; /* In Khmer coeng model, post and below forms should not be reordered. */ + return POS_BASE_C; /* Will recategorize later based on font lookups. */ +} + +static inline bool +is_ra (hb_codepoint_t u) +{ + for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++) + if (u == ra_chars[i]) + return true; + return false; +} + +static inline bool +is_one_of (const hb_glyph_info_t &info, unsigned int flags) { - indic_options_union_t u; - u.i = 0; - u.opts.initialized = 1; + /* If it ligated, all bets are off. */ + if (is_a_ligature (info)) return false; + return !!(FLAG (info.indic_category()) & flags); +} + +#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ)) +static inline bool +is_joiner (const hb_glyph_info_t &info) +{ + return is_one_of (info, JOINER_FLAGS); +} - char *c = getenv ("HB_OT_INDIC_OPTIONS"); - u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible"); +/* Note: + * + * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels + * cannot happen in a consonant syllable. The plus side however is, we can call the + * consonant syllable logic from the vowel syllable function and get it all right! */ +#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CM) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_DOTTEDCIRCLE)) +static inline bool +is_consonant (const hb_glyph_info_t &info) +{ + return is_one_of (info, CONSONANT_FLAGS); +} - return u; +#define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng)) +static inline bool +is_halant_or_coeng (const hb_glyph_info_t &info) +{ + return is_one_of (info, HALANT_OR_COENG_FLAGS); } -static inline indic_options_t -indic_options (void) +static inline void +set_indic_properties (hb_glyph_info_t &info) { - static indic_options_union_t options; + hb_codepoint_t u = info.codepoint; + unsigned int type = hb_indic_get_categories (u); + indic_category_t cat = (indic_category_t) (type & 0x7F); + indic_position_t pos = (indic_position_t) (type >> 8); + + + /* + * Re-assign category + */ - if (unlikely (!options.i)) { - /* This is idempotent and threadsafe. */ - options = indic_options_init (); + + /* The spec says U+0952 is OT_A. However, testing shows that Uniscribe + * treats U+0951..U+0952 all as OT_VD. + * TESTS: + * U+092E,U+0947,U+0952 + * U+092E,U+0952,U+0947 + * U+092E,U+0947,U+0951 + * U+092E,U+0951,U+0947 + * */ + if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0951, 0x0954))) + cat = OT_VD; + + if (unlikely (u == 0x17D1)) + cat = OT_X; + if (cat == OT_X && + unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CB, 0x17D3))) /* Khmer Various signs */ + { + /* These are like Top Matras. */ + cat = OT_M; + pos = POS_ABOVE_C; + } + if (u == 0x17C6) /* Khmer Bindu doesn't like to be repositioned. */ + cat = OT_N; + + if (unlikely (u == 0x17D2)) cat = OT_Coeng; /* Khmer coeng */ + else if (unlikely (u == 0x200C)) cat = OT_ZWNJ; + else if (unlikely (u == 0x200D)) cat = OT_ZWJ; + else if (unlikely (u == 0x25CC)) cat = OT_DOTTEDCIRCLE; + else if (unlikely (u == 0x0A71)) cat = OT_SM; /* GURMUKHI ADDAK. More like consonant medial. like 0A75. */ + + if (cat == OT_Repha) { + /* There are two kinds of characters marked as Repha: + * - The ones that are GenCat=Mn are already positioned visually, ie. after base. (eg. Khmer) + * - The ones that are GenCat=Lo is encoded logically, ie. beginning of syllable. (eg. Malayalam) + * + * We recategorize the first kind to look like a Nukta and attached to the base directly. + */ + if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + cat = OT_N; } - return options.opts; + + + /* + * Re-assign position. + */ + + if ((FLAG (cat) & CONSONANT_FLAGS)) + { + pos = consonant_position (u); + if (is_ra (u)) + cat = OT_Ra; + } + else if (cat == OT_M) + { + pos = matra_position (u, pos); + } + else if (cat == OT_SM || cat == OT_VD) + { + pos = POS_SMVD; + } + + if (unlikely (u == 0x0B01)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */ + + + + info.indic_category() = cat; + info.indic_position() = pos; } +/* + * Things above this line should ideally be moved to the Indic table itself. + */ + /* * Indic configurations. Note that we do not want to keep every single script-specific @@ -123,8 +319,6 @@ static const indic_config_t indic_configs[] = {HB_SCRIPT_MALAYALAM, true, 0x0D4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA}, {HB_SCRIPT_SINHALA, false,0x0DCA,BASE_POS_FIRST,REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT}, {HB_SCRIPT_KHMER, false,0x17D2,BASE_POS_FIRST,REPH_POS_DEFAULT, REPH_MODE_VIS_REPHA}, - /* Myanmar does not have the "old_indic" behavior, even though it has a "new" tag. */ - {HB_SCRIPT_MYANMAR, false,0x1039,BASE_POS_LAST, REPH_POS_DEFAULT, REPH_MODE_EXPLICIT}, }; @@ -135,7 +329,7 @@ static const indic_config_t indic_configs[] = struct feature_list_t { hb_tag_t tag; - hb_bool_t is_global; + hb_ot_map_feature_flags_t flags; }; static const feature_list_t @@ -145,32 +339,32 @@ indic_features[] = * Basic features. * These features are applied in order, one at a time, after initial_reordering. */ - {HB_TAG('n','u','k','t'), true}, - {HB_TAG('a','k','h','n'), true}, - {HB_TAG('r','p','h','f'), false}, - {HB_TAG('r','k','r','f'), true}, - {HB_TAG('p','r','e','f'), false}, - {HB_TAG('h','a','l','f'), false}, - {HB_TAG('b','l','w','f'), false}, - {HB_TAG('a','b','v','f'), false}, - {HB_TAG('p','s','t','f'), false}, - {HB_TAG('c','f','a','r'), false}, - {HB_TAG('c','j','c','t'), true}, - {HB_TAG('v','a','t','u'), true}, + {HB_TAG('n','u','k','t'), F_GLOBAL}, + {HB_TAG('a','k','h','n'), F_GLOBAL}, + {HB_TAG('r','p','h','f'), F_NONE}, + {HB_TAG('r','k','r','f'), F_GLOBAL}, + {HB_TAG('p','r','e','f'), F_NONE}, + {HB_TAG('b','l','w','f'), F_NONE}, + {HB_TAG('h','a','l','f'), F_NONE}, + {HB_TAG('a','b','v','f'), F_NONE}, + {HB_TAG('p','s','t','f'), F_NONE}, + {HB_TAG('c','f','a','r'), F_NONE}, + {HB_TAG('v','a','t','u'), F_GLOBAL}, + {HB_TAG('c','j','c','t'), F_GLOBAL}, /* * Other features. * These features are applied all at once, after final_reordering. */ - {HB_TAG('i','n','i','t'), false}, - {HB_TAG('p','r','e','s'), true}, - {HB_TAG('a','b','v','s'), true}, - {HB_TAG('b','l','w','s'), true}, - {HB_TAG('p','s','t','s'), true}, - {HB_TAG('h','a','l','n'), true}, + {HB_TAG('i','n','i','t'), F_NONE}, + {HB_TAG('p','r','e','s'), F_GLOBAL}, + {HB_TAG('a','b','v','s'), F_GLOBAL}, + {HB_TAG('b','l','w','s'), F_GLOBAL}, + {HB_TAG('p','s','t','s'), F_GLOBAL}, + {HB_TAG('h','a','l','n'), F_GLOBAL}, /* Positioning features, though we don't care about the types. */ - {HB_TAG('d','i','s','t'), true}, - {HB_TAG('a','b','v','m'), true}, - {HB_TAG('b','l','w','m'), true}, + {HB_TAG('d','i','s','t'), F_GLOBAL}, + {HB_TAG('a','b','v','m'), F_GLOBAL}, + {HB_TAG('b','l','w','m'), F_GLOBAL}, }; /* @@ -182,13 +376,13 @@ enum { RPHF, _RKRF, PREF, - HALF, BLWF, + HALF, ABVF, PSTF, CFAR, - _CJCT, _VATU, + _CJCT, INIT, _PRES, @@ -225,21 +419,21 @@ collect_features_indic (hb_ot_shape_planner_t *plan) /* Do this before any lookups have been applied. */ map->add_gsub_pause (setup_syllables); - map->add_bool_feature (HB_TAG('l','o','c','l')); + map->add_global_bool_feature (HB_TAG('l','o','c','l')); /* The Indic specs do not require ccmp, but we apply it here since if * there is a use of it, it's typically at the beginning. */ - map->add_bool_feature (HB_TAG('c','c','m','p')); + map->add_global_bool_feature (HB_TAG('c','c','m','p')); unsigned int i = 0; map->add_gsub_pause (initial_reordering); for (; i < INDIC_BASIC_FEATURES; i++) { - map->add_bool_feature (indic_features[i].tag, indic_features[i].is_global); + map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ); map->add_gsub_pause (NULL); } map->add_gsub_pause (final_reordering); for (; i < INDIC_NUM_FEATURES; i++) { - map->add_bool_feature (indic_features[i].tag, indic_features[i].is_global); + map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ); } } @@ -247,10 +441,10 @@ static void override_features_indic (hb_ot_shape_planner_t *plan) { /* Uniscribe does not apply 'kern'. */ - if (indic_options ().uniscribe_bug_compatible) - plan->map.add_feature (HB_TAG('k','e','r','n'), 0, true); + if (hb_options ().uniscribe_bug_compatible) + plan->map.add_feature (HB_TAG('k','e','r','n'), 0, F_GLOBAL); - plan->map.add_feature (HB_TAG('l','i','g','a'), 0, true); + plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL); } @@ -263,10 +457,10 @@ struct would_substitute_feature_t &lookups, &count); } - inline bool would_substitute (hb_codepoint_t *glyphs, - unsigned int glyphs_count, - bool zero_context, - hb_face_t *face) const + inline bool would_substitute (const hb_codepoint_t *glyphs, + unsigned int glyphs_count, + bool zero_context, + hb_face_t *face) const { for (unsigned int i = 0; i < count; i++) if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context)) @@ -338,7 +532,8 @@ data_create_indic (const hb_ot_shape_plan_t *plan) indic_plan->pstf.init (&plan->map, HB_TAG('p','s','t','f')); for (unsigned int i = 0; i < ARRAY_LENGTH (indic_plan->mask_array); i++) - indic_plan->mask_array[i] = indic_features[i].is_global ? 0 : plan->map.get_1_mask (indic_features[i].tag); + indic_plan->mask_array[i] = (indic_features[i].flags & F_GLOBAL) ? + 0 : plan->map.get_1_mask (indic_features[i].tag); return indic_plan; } @@ -351,13 +546,30 @@ data_destroy_indic (void *data) static indic_position_t consonant_position_from_face (const indic_shape_plan_t *indic_plan, - hb_codepoint_t *glyphs, unsigned int glyphs_len, - hb_face_t *face) + const hb_codepoint_t glyphs[2], + hb_face_t *face) { + /* For old-spec, the order of glyphs is Consonant,Virama, + * whereas for new-spec, it's Virama,Consonant. However, + * some broken fonts (like Free Sans) simply copied lookups + * from old-spec to new-spec without modification. + * And oddly enough, Uniscribe seems to respect those lookups. + * Eg. in the sequence U+0924,U+094D,U+0930, Uniscribe finds + * base at 0. The font however, only has lookups matching + * 930,94D in 'blwf', not the expected 94D,930 (with new-spec + * table). As such, we simply match both sequences. Seems + * to work. */ bool zero_context = indic_plan->is_old_spec ? false : true; - if (indic_plan->pref.would_substitute (glyphs, glyphs_len, zero_context, face)) return POS_BELOW_C; - if (indic_plan->blwf.would_substitute (glyphs, glyphs_len, zero_context, face)) return POS_BELOW_C; - if (indic_plan->pstf.would_substitute (glyphs, glyphs_len, zero_context, face)) return POS_POST_C; + hb_codepoint_t glyphs_r[2] = {glyphs[1], glyphs[0]}; + if (indic_plan->pref.would_substitute (glyphs , 2, zero_context, face) || + indic_plan->pref.would_substitute (glyphs_r, 2, zero_context, face)) + return POS_POST_C; + if (indic_plan->blwf.would_substitute (glyphs , 2, zero_context, face) || + indic_plan->blwf.would_substitute (glyphs_r, 2, zero_context, face)) + return POS_BELOW_C; + if (indic_plan->pstf.would_substitute (glyphs , 2, zero_context, face) || + indic_plan->pstf.would_substitute (glyphs_r, 2, zero_context, face)) + return POS_POST_C; return POS_BASE_C; } @@ -415,16 +627,15 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan, { const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data; - unsigned int consonant_pos = indic_plan->is_old_spec ? 0 : 1; hb_codepoint_t glyphs[2]; - if (indic_plan->get_virama_glyph (font, &glyphs[1 - consonant_pos])) + if (indic_plan->get_virama_glyph (font, &glyphs[0])) { hb_face_t *face = font->face; unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) if (buffer->info[i].indic_position() == POS_BASE_C) { - glyphs[consonant_pos] = buffer->info[i].codepoint; - buffer->info[i].indic_position() = consonant_position_from_face (indic_plan, glyphs, 2, face); + glyphs[1] = buffer->info[i].codepoint; + buffer->info[i].indic_position() = consonant_position_from_face (indic_plan, glyphs, face); } } } @@ -522,7 +733,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, * * IMPLEMENTATION NOTES: * - * Our pre-base reordering Ra's are marked POS_BELOW, so will be skipped + * Our pre-base reordering Ra's are marked POS_POST_C, so will be skipped * by the logic above already. */ @@ -577,15 +788,12 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, * base consonants. * * Only do this for unforced Reph. (ie. not for Ra,H,ZWJ. */ - if (has_reph && base == start && start - limit <= 2) { + if (has_reph && base == start && limit - base <= 2) { /* Have no other consonant, so Reph is not formed and Ra becomes base. */ has_reph = false; } } - if (base < end) - info[base].indic_position() = POS_BASE_C; - /* 2. Decompose and reorder Matras: * @@ -644,15 +852,16 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, info[start].indic_position() = POS_RA_TO_BECOME_REPH; /* For old-style Indic script tags, move the first post-base Halant after - * last consonant. */ + * last consonant. Only do this if there is *not* a Halant after last + * consonant. Otherwise it becomes messy. */ if (indic_plan->is_old_spec) { for (unsigned int i = base + 1; i < end; i++) if (info[i].indic_category() == OT_H) { unsigned int j; for (j = end - 1; j > i; j--) - if (is_consonant (info[j])) + if (is_consonant (info[j]) || info[j].indic_category() == OT_H) break; - if (j > i) { + if (info[j].indic_category() != OT_H && j > i) { /* Move Halant to after last consonant. */ hb_glyph_info_t t = info[i]; memmove (&info[i], &info[i + 1], (j - i) * sizeof (info[0])); @@ -745,6 +954,38 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, info[i].mask |= mask; } + if (indic_plan->is_old_spec && + buffer->props.script == HB_SCRIPT_DEVANAGARI) + { + /* Old-spec eye-lash Ra needs special handling. From the + * spec: + * + * "The feature 'below-base form' is applied to consonants + * having below-base forms and following the base consonant. + * The exception is vattu, which may appear below half forms + * as well as below the base glyph. The feature 'below-base + * form' will be applied to all such occurrences of Ra as well." + * + * Test case: U+0924,U+094D,U+0930,U+094d,U+0915 + * with Sanskrit 2003 font. + * + * However, note that Ra,Halant,ZWJ is the correct way to + * request eyelash form of Ra, so we wouldbn't inhibit it + * in that sequence. + * + * Test case: U+0924,U+094D,U+0930,U+094d,U+200D,U+0915 + */ + for (unsigned int i = start; i + 1 < base; i++) + if (info[i ].indic_category() == OT_Ra && + info[i+1].indic_category() == OT_H && + (i + 2 == base || + info[i+2].indic_category() != OT_ZWJ)) + { + info[i ].mask |= indic_plan->mask_array[BLWF]; + info[i+1].mask |= indic_plan->mask_array[BLWF]; + } + } + if (indic_plan->mask_array[PREF] && base + 2 < end) { /* Find a Halant,Ra sequence and mark it for pre-base reordering processing. */ @@ -778,8 +1019,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, do { j--; - /* A ZWJ disables CJCT, however, it's mere presence is enough - * to disable ligation. No explicit action needed. */ + /* ZWJ/ZWNJ should disable CJCT. They do that by simply + * being there, since we don't skip them for the CJCT + * feature (ie. F_MANUAL_ZWJ) */ /* A ZWNJ disables HALF. */ if (non_joiner) @@ -809,7 +1051,7 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan, /* We treat NBSP/dotted-circle as if they are consonants, so we should just chain. * Only if not in compatibility mode that is... */ - if (indic_options ().uniscribe_bug_compatible) + if (hb_options ().uniscribe_bug_compatible) { /* For dotted-circle, this is what Uniscribe does: * If dotted-circle is the last glyph, it just does nothing. @@ -962,6 +1204,13 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, base--; break; } + if (base == end && start < base && + info[base - 1].indic_category() != OT_ZWJ) + base--; + while (start < base && + (info[base].indic_category() == OT_H || + info[base].indic_category() == OT_N)) + base--; /* o Reorder matras: @@ -1013,6 +1262,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, hb_glyph_info_t tmp = info[old_pos]; memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0])); info[new_pos] = tmp; + if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */ + base--; new_pos--; } buffer->merge_clusters (new_pos, MIN (end, base + 1)); @@ -1071,7 +1322,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, while (new_reph_pos < base && !is_halant_or_coeng (info[new_reph_pos])) new_reph_pos++; - if (new_reph_pos < base && is_halant_or_coeng (info[new_reph_pos])) { + if (new_reph_pos < base && is_halant_or_coeng (info[new_reph_pos])) + { /* ->If ZWJ or ZWNJ are following this halant, position is moved after it. */ if (new_reph_pos + 1 < base && is_joiner (info[new_reph_pos + 1])) new_reph_pos++; @@ -1123,7 +1375,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, while (new_reph_pos < base && !is_halant_or_coeng (info[new_reph_pos])) new_reph_pos++; - if (new_reph_pos < base && is_halant_or_coeng (info[new_reph_pos])) { + if (new_reph_pos < base && is_halant_or_coeng (info[new_reph_pos])) + { /* ->If ZWJ or ZWNJ are following this halant, position is moved after it. */ if (new_reph_pos + 1 < base && is_joiner (info[new_reph_pos + 1])) new_reph_pos++; @@ -1145,7 +1398,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, * Uniscribe doesn't do this. * TEST: U+0930,U+094D,U+0915,U+094B,U+094D */ - if (!indic_options ().uniscribe_bug_compatible && + if (!hb_options ().uniscribe_bug_compatible && unlikely (is_halant_or_coeng (info[new_reph_pos]))) { for (unsigned int i = base + 1; i < new_reph_pos; i++) if (info[i].indic_category() == OT_M) { @@ -1165,6 +1418,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, hb_glyph_info_t reph = info[start]; memmove (&info[start], &info[start + 1], (new_reph_pos - start) * sizeof (info[0])); info[new_reph_pos] = reph; + if (start < base && base <= new_reph_pos) + base--; } } @@ -1220,9 +1475,11 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, } if (new_pos > start && is_halant_or_coeng (info[new_pos - 1])) + { /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */ if (new_pos < end && is_joiner (info[new_pos])) new_pos++; + } { unsigned int old_pos = i; @@ -1230,6 +1487,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, hb_glyph_info_t tmp = info[old_pos]; memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0])); info[new_pos] = tmp; + if (new_pos <= base && base < old_pos) + base++; } } @@ -1249,7 +1508,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, /* * Finish off the clusters and go home! */ - if (indic_options ().uniscribe_bug_compatible) + if (hb_options ().uniscribe_bug_compatible) { /* Uniscribe merges the entire cluster. * This means, half forms are submerged into the main consonants cluster. @@ -1365,7 +1624,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t glyph; - if (indic_options ().uniscribe_bug_compatible || + if (hb_options ().uniscribe_bug_compatible || (c->font->get_glyph (ab, 0, &glyph) && indic_plan->pstf.would_substitute (&glyph, 1, true, c->font->face))) { @@ -1408,6 +1667,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = decompose_indic, compose_indic, setup_masks_indic, - false, /* zero_width_attached_marks */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh new file mode 100644 index 0000000..9d6f62f --- /dev/null +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh @@ -0,0 +1,391 @@ + +#line 1 "hb-ot-shape-complex-myanmar-machine.rl" +/* + * 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_SHAPE_COMPLEX_MYANMAR_MACHINE_HH +#define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH + +#include "hb-private.hh" + + +#line 36 "hb-ot-shape-complex-myanmar-machine.hh.tmp" +static const unsigned char _myanmar_syllable_machine_trans_keys[] = { + 1u, 30u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, + 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, + 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, 5u, 8u, + 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, + 3u, 30u, 3u, 29u, 1u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, + 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 0 +}; + +static const char _myanmar_syllable_machine_key_spans[] = { + 30, 28, 25, 4, 25, 23, 21, 21, + 27, 27, 27, 27, 16, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 25, 4, + 25, 23, 21, 21, 27, 27, 27, 27, + 28, 27, 30, 27, 27, 27, 27, 27, + 27, 27, 27, 27 +}; + +static const short _myanmar_syllable_machine_index_offsets[] = { + 0, 31, 60, 86, 91, 117, 141, 163, + 185, 213, 241, 269, 297, 314, 342, 370, + 398, 426, 454, 482, 510, 538, 566, 592, + 597, 623, 647, 669, 691, 719, 747, 775, + 803, 832, 860, 891, 919, 947, 975, 1003, + 1031, 1059, 1087, 1115 +}; + +static const char _myanmar_syllable_machine_indicies[] = { + 1, 1, 2, 3, 4, 4, 0, 5, + 0, 6, 0, 1, 0, 0, 0, 7, + 0, 8, 1, 0, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 0, 20, + 21, 22, 22, 19, 23, 19, 24, 19, + 19, 19, 19, 19, 19, 19, 25, 19, + 19, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 19, 22, 22, 19, 23, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 36, 19, 19, 19, 19, 19, 19, + 30, 19, 19, 19, 34, 19, 22, 22, + 19, 23, 19, 22, 22, 19, 23, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 30, + 19, 19, 19, 34, 19, 37, 19, 22, + 22, 19, 23, 19, 30, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 30, 19, 22, 22, 19, + 23, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 38, 19, 19, 19, 19, 19, + 19, 30, 19, 22, 22, 19, 23, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 30, + 19, 20, 19, 22, 22, 19, 23, 19, + 24, 19, 19, 19, 19, 19, 19, 19, + 39, 19, 19, 39, 19, 19, 19, 30, + 40, 19, 19, 34, 19, 20, 19, 22, + 22, 19, 23, 19, 24, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 30, 19, 19, 19, 34, + 19, 20, 19, 22, 22, 19, 23, 19, + 24, 19, 19, 19, 19, 19, 19, 19, + 39, 19, 19, 19, 19, 19, 19, 30, + 40, 19, 19, 34, 19, 20, 19, 22, + 22, 19, 23, 19, 24, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 30, 40, 19, 19, 34, + 19, 1, 1, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 1, 19, 20, 19, 22, 22, 19, 23, + 19, 24, 19, 19, 19, 19, 19, 19, + 19, 25, 19, 19, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 19, 20, 19, + 22, 22, 19, 23, 19, 24, 19, 19, + 19, 19, 19, 19, 19, 33, 19, 19, + 19, 19, 19, 19, 30, 31, 32, 33, + 34, 19, 20, 19, 22, 22, 19, 23, + 19, 24, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 30, 31, 32, 33, 34, 19, 20, 19, + 22, 22, 19, 23, 19, 24, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 30, 31, 32, 19, + 34, 19, 20, 19, 22, 22, 19, 23, + 19, 24, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 30, 19, 32, 19, 34, 19, 20, 19, + 22, 22, 19, 23, 19, 24, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 26, 19, 28, 19, 30, 31, 32, 33, + 34, 19, 20, 19, 22, 22, 19, 23, + 19, 24, 19, 19, 19, 19, 19, 19, + 19, 33, 19, 19, 26, 19, 19, 19, + 30, 31, 32, 33, 34, 19, 20, 19, + 22, 22, 19, 23, 19, 24, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 26, 27, 28, 19, 30, 31, 32, 33, + 34, 19, 20, 21, 22, 22, 19, 23, + 19, 24, 19, 19, 19, 19, 19, 19, + 19, 25, 19, 19, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 19, 3, 3, + 41, 5, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 42, 41, 41, 41, 41, + 41, 41, 13, 41, 41, 41, 17, 41, + 3, 3, 41, 5, 41, 3, 3, 41, + 5, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, + 41, 13, 41, 41, 41, 17, 41, 43, + 41, 3, 3, 41, 5, 41, 13, 41, + 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 13, 41, 3, + 3, 41, 5, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 44, 41, 41, 41, + 41, 41, 41, 13, 41, 3, 3, 41, + 5, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, + 41, 13, 41, 2, 41, 3, 3, 41, + 5, 41, 6, 41, 41, 41, 41, 41, + 41, 41, 45, 41, 41, 45, 41, 41, + 41, 13, 46, 41, 41, 17, 41, 2, + 41, 3, 3, 41, 5, 41, 6, 41, + 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 13, 41, 41, + 41, 17, 41, 2, 41, 3, 3, 41, + 5, 41, 6, 41, 41, 41, 41, 41, + 41, 41, 45, 41, 41, 41, 41, 41, + 41, 13, 46, 41, 41, 17, 41, 2, + 41, 3, 3, 41, 5, 41, 6, 41, + 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 13, 46, 41, + 41, 17, 41, 20, 21, 22, 22, 19, + 23, 19, 24, 19, 19, 19, 19, 19, + 19, 19, 47, 19, 19, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 19, + 20, 48, 22, 22, 19, 23, 19, 24, + 19, 19, 19, 19, 19, 19, 19, 25, + 19, 19, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 19, 1, 1, 2, 3, + 3, 3, 41, 5, 41, 6, 41, 1, + 41, 41, 41, 1, 41, 8, 1, 41, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 41, 2, 41, 3, 3, 41, + 5, 41, 6, 41, 41, 41, 41, 41, + 41, 41, 8, 41, 41, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 41, 2, + 41, 3, 3, 41, 5, 41, 6, 41, + 41, 41, 41, 41, 41, 41, 16, 41, + 41, 41, 41, 41, 41, 13, 14, 15, + 16, 17, 41, 2, 41, 3, 3, 41, + 5, 41, 6, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, + 41, 13, 14, 15, 16, 17, 41, 2, + 41, 3, 3, 41, 5, 41, 6, 41, + 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 13, 14, 15, + 41, 17, 41, 2, 41, 3, 3, 41, + 5, 41, 6, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, + 41, 13, 41, 15, 41, 17, 41, 2, + 41, 3, 3, 41, 5, 41, 6, 41, + 41, 41, 41, 41, 41, 41, 41, 41, + 41, 9, 41, 11, 41, 13, 14, 15, + 16, 17, 41, 2, 41, 3, 3, 41, + 5, 41, 6, 41, 41, 41, 41, 41, + 41, 41, 16, 41, 41, 9, 41, 41, + 41, 13, 14, 15, 16, 17, 41, 2, + 41, 3, 3, 41, 5, 41, 6, 41, + 41, 41, 41, 41, 41, 41, 41, 41, + 41, 9, 10, 11, 41, 13, 14, 15, + 16, 17, 41, 2, 3, 3, 3, 41, + 5, 41, 6, 41, 41, 41, 41, 41, + 41, 41, 8, 41, 41, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 41, 0 +}; + +static const char _myanmar_syllable_machine_trans_targs[] = { + 0, 1, 22, 0, 0, 23, 29, 32, + 35, 36, 40, 41, 42, 25, 38, 39, + 37, 28, 43, 0, 2, 12, 0, 3, + 9, 13, 14, 18, 19, 20, 5, 16, + 17, 15, 8, 21, 4, 6, 7, 10, + 11, 0, 24, 26, 27, 30, 31, 33, + 34 +}; + +static const char _myanmar_syllable_machine_trans_actions[] = { + 3, 0, 0, 4, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 0, 0, 0, + 0 +}; + +static const char _myanmar_syllable_machine_to_state_actions[] = { + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; + +static const char _myanmar_syllable_machine_from_state_actions[] = { + 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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 _myanmar_syllable_machine_eof_trans[] = { + 0, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, + 20, 20, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42 +}; + +static const int myanmar_syllable_machine_start = 0; +static const int myanmar_syllable_machine_first_final = 0; +static const int myanmar_syllable_machine_error = -1; + +static const int myanmar_syllable_machine_en_main = 0; + + +#line 36 "hb-ot-shape-complex-myanmar-machine.rl" + + + +#line 90 "hb-ot-shape-complex-myanmar-machine.rl" + + +#define found_syllable(syllable_type) \ + HB_STMT_START { \ + if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ + for (unsigned int i = last; i < p+1; i++) \ + info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + last = p+1; \ + syllable_serial++; \ + if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ + } HB_STMT_END + +static void +find_syllables (hb_buffer_t *buffer) +{ + unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED; + int cs; + hb_glyph_info_t *info = buffer->info; + +#line 288 "hb-ot-shape-complex-myanmar-machine.hh.tmp" + { + cs = myanmar_syllable_machine_start; + ts = 0; + te = 0; + act = 0; + } + +#line 111 "hb-ot-shape-complex-myanmar-machine.rl" + + + p = 0; + pe = eof = buffer->len; + + unsigned int last = 0; + unsigned int syllable_serial = 1; + +#line 305 "hb-ot-shape-complex-myanmar-machine.hh.tmp" + { + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; +_resume: + switch ( _myanmar_syllable_machine_from_state_actions[cs] ) { + case 2: +#line 1 "NONE" + {ts = p;} + break; +#line 319 "hb-ot-shape-complex-myanmar-machine.hh.tmp" + } + + _keys = _myanmar_syllable_machine_trans_keys + (cs<<1); + _inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs]; + + _slen = _myanmar_syllable_machine_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) && + ( info[p].myanmar_category()) <= _keys[1] ? + ( info[p].myanmar_category()) - _keys[0] : _slen ]; + +_eof_trans: + cs = _myanmar_syllable_machine_trans_targs[_trans]; + + if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 ) + goto _again; + + switch ( _myanmar_syllable_machine_trans_actions[_trans] ) { + case 7: +#line 83 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (consonant_syllable); }} + break; + case 5: +#line 84 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (non_myanmar_cluster); }} + break; + case 4: +#line 85 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (broken_cluster); }} + break; + case 3: +#line 86 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (non_myanmar_cluster); }} + break; + case 6: +#line 83 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p;p--;{ found_syllable (consonant_syllable); }} + break; + case 8: +#line 85 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p;p--;{ found_syllable (broken_cluster); }} + break; +#line 361 "hb-ot-shape-complex-myanmar-machine.hh.tmp" + } + +_again: + switch ( _myanmar_syllable_machine_to_state_actions[cs] ) { + case 1: +#line 1 "NONE" + {ts = 0;} + break; +#line 370 "hb-ot-shape-complex-myanmar-machine.hh.tmp" + } + + if ( ++p != pe ) + goto _resume; + _test_eof: {} + if ( p == eof ) + { + if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) { + _trans = _myanmar_syllable_machine_eof_trans[cs] - 1; + goto _eof_trans; + } + } + + } + +#line 120 "hb-ot-shape-complex-myanmar-machine.rl" + +} + +#undef found_syllable + +#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH */ diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc new file mode 100644 index 0000000..ff13bdd --- /dev/null +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc @@ -0,0 +1,545 @@ +/* + * Copyright © 2011,2012,2013 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-ot-shape-complex-indic-private.hh" + +/* buffer var allocations */ +#define myanmar_category() complex_var_u8_0() /* myanmar_category_t */ +#define myanmar_position() complex_var_u8_1() /* myanmar_position_t */ + + +/* + * Myanmar shaper. + */ + +static const hb_tag_t +basic_features[] = +{ + /* + * Basic features. + * These features are applied in order, one at a time, after initial_reordering. + */ + HB_TAG('r','p','h','f'), + HB_TAG('p','r','e','f'), + HB_TAG('b','l','w','f'), + HB_TAG('p','s','t','f'), +}; +static const hb_tag_t +other_features[] = +{ + /* + * Other features. + * These features are applied all at once, after final_reordering. + */ + HB_TAG('p','r','e','s'), + HB_TAG('a','b','v','s'), + HB_TAG('b','l','w','s'), + HB_TAG('p','s','t','s'), + /* Positioning features, though we don't care about the types. */ + HB_TAG('d','i','s','t'), +}; + +static void +setup_syllables (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); +static void +initial_reordering (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); +static void +final_reordering (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); + +static void +collect_features_myanmar (hb_ot_shape_planner_t *plan) +{ + hb_ot_map_builder_t *map = &plan->map; + + /* Do this before any lookups have been applied. */ + map->add_gsub_pause (setup_syllables); + + map->add_global_bool_feature (HB_TAG('l','o','c','l')); + /* The Indic specs do not require ccmp, but we apply it here since if + * there is a use of it, it's typically at the beginning. */ + map->add_global_bool_feature (HB_TAG('c','c','m','p')); + + + map->add_gsub_pause (initial_reordering); + for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) + { + map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); + map->add_gsub_pause (NULL); + } + map->add_gsub_pause (final_reordering); + for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) + map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); +} + +static void +override_features_myanmar (hb_ot_shape_planner_t *plan) +{ + plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL); + + /* + * Note: + * + * Spec says 'mark' is used, and the mmrtext.ttf font from + * Windows 8 has lookups for it. But testing suggests that + * Windows 8 Uniscribe is NOT applying it. It *is* applying + * 'mkmk' however. + */ + if (hb_options ().uniscribe_bug_compatible) + plan->map.add_feature (HB_TAG('m','a','r','k'), 0, F_GLOBAL); +} + + +enum syllable_type_t { + consonant_syllable, + broken_cluster, + non_myanmar_cluster, +}; + +#include "hb-ot-shape-complex-myanmar-machine.hh" + + +/* Note: This enum is duplicated in the -machine.rl source file. + * Not sure how to avoid duplication. */ +enum myanmar_category_t { + OT_As = 18, /* Asat */ + OT_D = 19, /* Digits except zero */ + OT_D0 = 20, /* Digit zero */ + OT_DB = OT_N, /* Dot below */ + OT_GB = OT_DOTTEDCIRCLE, + OT_MH = 21, /* Various consonant medial types */ + OT_MR = 22, /* Various consonant medial types */ + OT_MW = 23, /* Various consonant medial types */ + OT_MY = 24, /* Various consonant medial types */ + OT_PT = 25, /* Pwo and other tones */ + OT_VAbv = 26, + OT_VBlw = 27, + OT_VPre = 28, + OT_VPst = 29, + OT_VS = 30 /* Variation selectors */ +}; + + +static inline bool +is_one_of (const hb_glyph_info_t &info, unsigned int flags) +{ + /* If it ligated, all bets are off. */ + if (is_a_ligature (info)) return false; + return !!(FLAG (info.myanmar_category()) & flags); +} + +/* Note: + * + * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels + * cannot happen in a consonant syllable. The plus side however is, we can call the + * consonant syllable logic from the vowel syllable function and get it all right! */ +#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CM) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_GB)) +static inline bool +is_consonant (const hb_glyph_info_t &info) +{ + return is_one_of (info, CONSONANT_FLAGS); +} + + +static inline void +set_myanmar_properties (hb_glyph_info_t &info) +{ + hb_codepoint_t u = info.codepoint; + unsigned int type = hb_indic_get_categories (u); + indic_category_t cat = (indic_category_t) (type & 0x7F); + indic_position_t pos = (indic_position_t) (type >> 8); + + /* Myanmar + * http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze + */ + if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00, 0xFE0F))) + cat = (indic_category_t) OT_VS; + else if (unlikely (u == 0x200C)) cat = (indic_category_t) OT_ZWNJ; + else if (unlikely (u == 0x200D)) cat = (indic_category_t) OT_ZWJ; + + switch (u) + { + case 0x002D: case 0x00A0: case 0x00D7: case 0x2012: + case 0x2013: case 0x2014: case 0x2015: case 0x2022: + case 0x25CC: case 0x25FB: case 0x25FC: case 0x25FD: + case 0x25FE: + cat = (indic_category_t) OT_GB; + break; + + case 0x1004: case 0x101B: case 0x105A: + cat = (indic_category_t) OT_Ra; + break; + + case 0x1032: case 0x1036: + cat = (indic_category_t) OT_A; + break; + + case 0x103A: + cat = (indic_category_t) OT_As; + break; + + case 0x1041: case 0x1042: case 0x1043: case 0x1044: + case 0x1045: case 0x1046: case 0x1047: case 0x1048: + case 0x1049: case 0x1090: case 0x1091: case 0x1092: + case 0x1093: case 0x1094: case 0x1095: case 0x1096: + case 0x1097: case 0x1098: case 0x1099: + cat = (indic_category_t) OT_D; + break; + + case 0x1040: + cat = (indic_category_t) OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */ + break; + + case 0x103E: case 0x1060: + cat = (indic_category_t) OT_MH; + break; + + case 0x103C: + cat = (indic_category_t) OT_MR; + break; + + case 0x103D: case 0x1082: + cat = (indic_category_t) OT_MW; + break; + + case 0x103B: case 0x105E: case 0x105F: + cat = (indic_category_t) OT_MY; + break; + + case 0x1063: case 0x1064: case 0x1069: case 0x106A: + case 0x106B: case 0x106C: case 0x106D: case 0xAA7B: + cat = (indic_category_t) OT_PT; + break; + + case 0x1038: case 0x1087: case 0x1088: case 0x1089: + case 0x108A: case 0x108B: case 0x108C: case 0x108D: + case 0x108F: case 0x109A: case 0x109B: case 0x109C: + cat = (indic_category_t) OT_SM; + break; + } + + if (cat == OT_M) + { + switch ((int) pos) + { + case POS_PRE_C: cat = (indic_category_t) OT_VPre; + pos = POS_PRE_M; break; + case POS_ABOVE_C: cat = (indic_category_t) OT_VAbv; break; + case POS_BELOW_C: cat = (indic_category_t) OT_VBlw; break; + case POS_POST_C: cat = (indic_category_t) OT_VPst; break; + } + } + + info.myanmar_category() = (myanmar_category_t) cat; + info.myanmar_position() = pos; +} + + + +static void +setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_buffer_t *buffer, + hb_font_t *font HB_UNUSED) +{ + HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_category); + HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_position); + + /* We cannot setup masks here. We save information about characters + * and setup masks later on in a pause-callback. */ + + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + set_myanmar_properties (buffer->info[i]); +} + +static void +setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) +{ + find_syllables (buffer); +} + +static int +compare_myanmar_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) +{ + int a = pa->myanmar_position(); + int b = pb->myanmar_position(); + + return a < b ? -1 : a == b ? 0 : +1; +} + + +/* Rules from: + * http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm */ + +static void +initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, + hb_face_t *face, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) +{ + hb_glyph_info_t *info = buffer->info; + + unsigned int base = end; + bool has_reph = false; + + { + unsigned int limit = start; + if (start + 3 <= end && + info[start ].myanmar_category() == OT_Ra && + info[start+1].myanmar_category() == OT_As && + info[start+2].myanmar_category() == OT_H) + { + limit += 3; + base = start; + has_reph = true; + } + + { + if (!has_reph) + base = limit; + + for (unsigned int i = limit; i < end; i++) + if (is_consonant (info[i])) + { + base = i; + break; + } + } + } + + /* Reorder! */ + { + unsigned int i = start; + for (; i < start + (has_reph ? 3 : 0); i++) + info[i].myanmar_position() = POS_AFTER_MAIN; + for (; i < base; i++) + info[i].myanmar_position() = POS_PRE_C; + if (i < end) + { + info[i].myanmar_position() = POS_BASE_C; + i++; + } + indic_position_t pos = POS_AFTER_MAIN; + /* The following loop may be ugly, but it implements all of + * Myanmar reordering! */ + for (; i < end; i++) + { + if (info[i].myanmar_category() == OT_MR) /* Pre-base reordering */ + { + info[i].myanmar_position() = POS_PRE_C; + continue; + } + if (info[i].myanmar_position() < POS_BASE_C) /* Left matra */ + { + continue; + } + + if (pos == POS_AFTER_MAIN && info[i].myanmar_category() == OT_VBlw) + { + pos = POS_BELOW_C; + info[i].myanmar_position() = pos; + continue; + } + + if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_A) + { + info[i].myanmar_position() = POS_BEFORE_SUB; + continue; + } + if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_VBlw) + { + info[i].myanmar_position() = pos; + continue; + } + if (pos == POS_BELOW_C && info[i].myanmar_category() != OT_A) + { + pos = POS_AFTER_SUB; + info[i].myanmar_position() = pos; + continue; + } + info[i].myanmar_position() = pos; + } + } + + buffer->merge_clusters (start, end); + /* Sit tight, rock 'n roll! */ + hb_bubble_sort (info + start, end - start, compare_myanmar_order); +} + +static void +initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan, + hb_face_t *face, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) +{ + /* We already inserted dotted-circles, so just call the consonant_syllable. */ + initial_reordering_consonant_syllable (plan, face, buffer, start, end); +} + +static void +initial_reordering_non_myanmar_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_face_t *face HB_UNUSED, + hb_buffer_t *buffer HB_UNUSED, + unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +{ + /* Nothing to do right now. If we ever switch to using the output + * buffer in the reordering process, we'd need to next_glyph() here. */ +} + + +static void +initial_reordering_syllable (const hb_ot_shape_plan_t *plan, + hb_face_t *face, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) +{ + syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); + switch (syllable_type) { + case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return; + case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return; + case non_myanmar_cluster: initial_reordering_non_myanmar_cluster (plan, face, buffer, start, end); return; + } +} + +static inline void +insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font, + hb_buffer_t *buffer) +{ + /* Note: This loop is extra overhead, but should not be measurable. */ + bool has_broken_syllables = false; + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) { + has_broken_syllables = true; + break; + } + if (likely (!has_broken_syllables)) + return; + + + hb_codepoint_t dottedcircle_glyph; + if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph)) + return; + + hb_glyph_info_t dottedcircle = {0}; + dottedcircle.codepoint = 0x25CC; + set_myanmar_properties (dottedcircle); + dottedcircle.codepoint = dottedcircle_glyph; + + buffer->clear_output (); + + buffer->idx = 0; + unsigned int last_syllable = 0; + while (buffer->idx < buffer->len) + { + unsigned int syllable = buffer->cur().syllable(); + syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F); + if (unlikely (last_syllable != syllable && syllable_type == broken_cluster)) + { + last_syllable = syllable; + + hb_glyph_info_t info = dottedcircle; + info.cluster = buffer->cur().cluster; + info.mask = buffer->cur().mask; + info.syllable() = buffer->cur().syllable(); + + buffer->output_info (info); + } + else + buffer->next_glyph (); + } + + buffer->swap_buffers (); +} + +static void +initial_reordering (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) +{ + insert_dotted_circles (plan, font, buffer); + + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + if (unlikely (!count)) return; + unsigned int last = 0; + unsigned int last_syllable = info[0].syllable(); + for (unsigned int i = 1; i < count; i++) + if (last_syllable != info[i].syllable()) { + initial_reordering_syllable (plan, font->face, buffer, last, i); + last = i; + last_syllable = info[last].syllable(); + } + initial_reordering_syllable (plan, font->face, buffer, last, count); +} + +static void +final_reordering (const hb_ot_shape_plan_t *plan, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) +{ + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + + /* Zero syllables now... */ + for (unsigned int i = 0; i < count; i++) + info[i].syllable() = 0; + + HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category); + HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position); +} + + +static hb_ot_shape_normalization_mode_t +normalization_preference_myanmar (const hb_segment_properties_t *props HB_UNUSED) +{ + return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; +} + + +const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = +{ + "myanmar", + collect_features_myanmar, + override_features_myanmar, + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ + normalization_preference_myanmar, + NULL, /* decompose */ + NULL, /* compose */ + setup_masks_myanmar, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF, + false, /* fallback_position */ +}; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh index 26871c2..3c9922d 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh @@ -39,12 +39,20 @@ #define complex_var_u8_1() var2.u8[3] +enum hb_ot_shape_zero_width_marks_type_t { + HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF +}; + /* Master OT shaper list */ #define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \ HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \ HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \ HB_COMPLEX_SHAPER_IMPLEMENT (indic) \ + HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \ + HB_COMPLEX_SHAPER_IMPLEMENT (sea) \ HB_COMPLEX_SHAPER_IMPLEMENT (thai) \ /* ^--- Add new shapers here */ @@ -130,7 +138,8 @@ struct hb_ot_complex_shaper_t hb_buffer_t *buffer, hb_font_t *font); - bool zero_width_attached_marks; + hb_ot_shape_zero_width_marks_type_t zero_width_marks; + bool fallback_position; }; @@ -254,13 +263,11 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) /* Unicode-4.1 additions */ case HB_SCRIPT_BUGINESE: - case HB_SCRIPT_NEW_TAI_LUE: /* Unicode-5.0 additions */ case HB_SCRIPT_BALINESE: /* Unicode-5.1 additions */ - case HB_SCRIPT_CHAM: case HB_SCRIPT_LEPCHA: case HB_SCRIPT_REJANG: case HB_SCRIPT_SUNDANESE: @@ -269,19 +276,22 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_JAVANESE: case HB_SCRIPT_KAITHI: case HB_SCRIPT_MEETEI_MAYEK: - case HB_SCRIPT_TAI_THAM: + /* Unicode-6.0 additions */ /* Unicode-6.1 additions */ case HB_SCRIPT_CHAKMA: case HB_SCRIPT_SHARADA: case HB_SCRIPT_TAKRI: - /* Only use Indic shaper if the font has Indic tables. */ - if (planner->map.found_script[0]) - return &_hb_ot_complex_shaper_indic; - else + /* If the designer designed the font for the 'DFLT' script, + * use the default shaper. Otherwise, use the Indic shaper. + * Note that for some simple scripts, there may not be *any* + * GSUB/GPOS needed, so there may be no scripts found! */ + if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T')) return &_hb_ot_complex_shaper_default; + else + return &_hb_ot_complex_shaper_indic; case HB_SCRIPT_KHMER: /* A number of Khmer fonts in the wild don't have a 'pref' feature, @@ -300,12 +310,30 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) return &_hb_ot_complex_shaper_default; case HB_SCRIPT_MYANMAR: - /* For Myanmar, we only want to use the Indic shaper if the "new" script + /* For Myanmar, we only want to use the Myanmar shaper if the "new" script * tag is found. For "old" script tag we want to use the default shaper. */ if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2')) - return &_hb_ot_complex_shaper_indic; + return &_hb_ot_complex_shaper_myanmar; else return &_hb_ot_complex_shaper_default; + + /* Unicode-4.1 additions */ + case HB_SCRIPT_NEW_TAI_LUE: + + /* Unicode-5.1 additions */ + case HB_SCRIPT_CHAM: + + /* Unicode-5.2 additions */ + case HB_SCRIPT_TAI_THAM: + + /* If the designer designed the font for the 'DFLT' script, + * use the default shaper. Otherwise, use the Indic shaper. + * Note that for some simple scripts, there may not be *any* + * GSUB/GPOS needed, so there may be no scripts found! */ + if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T')) + return &_hb_ot_complex_shaper_default; + else + return &_hb_ot_complex_shaper_sea; } } diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea-machine.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea-machine.hh new file mode 100644 index 0000000..dace050 --- /dev/null +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea-machine.hh @@ -0,0 +1,224 @@ + +#line 1 "hb-ot-shape-complex-sea-machine.rl" +/* + * Copyright © 2011,2012,2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH +#define HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH + +#include "hb-private.hh" + + +#line 36 "hb-ot-shape-complex-sea-machine.hh.tmp" +static const unsigned char _sea_syllable_machine_trans_keys[] = { + 1u, 1u, 1u, 1u, 1u, 29u, 3u, 29u, 3u, 29u, 1u, 1u, 0 +}; + +static const char _sea_syllable_machine_key_spans[] = { + 1, 1, 29, 27, 27, 1 +}; + +static const char _sea_syllable_machine_index_offsets[] = { + 0, 2, 4, 34, 62, 90 +}; + +static const char _sea_syllable_machine_indicies[] = { + 1, 0, 3, 2, 1, 1, 3, 5, + 4, 4, 4, 4, 4, 3, 4, 1, + 4, 4, 4, 4, 3, 4, 4, 4, + 4, 3, 4, 4, 4, 3, 3, 3, + 3, 4, 1, 7, 6, 6, 6, 6, + 6, 1, 6, 6, 6, 6, 6, 6, + 1, 6, 6, 6, 6, 1, 6, 6, + 6, 1, 1, 1, 1, 6, 3, 9, + 8, 8, 8, 8, 8, 3, 8, 8, + 8, 8, 8, 8, 3, 8, 8, 8, + 8, 3, 8, 8, 8, 3, 3, 3, + 3, 8, 3, 10, 0 +}; + +static const char _sea_syllable_machine_trans_targs[] = { + 2, 3, 2, 4, 2, 5, 2, 0, + 2, 1, 2 +}; + +static const char _sea_syllable_machine_trans_actions[] = { + 1, 2, 3, 2, 6, 0, 7, 0, + 8, 0, 9 +}; + +static const char _sea_syllable_machine_to_state_actions[] = { + 0, 0, 4, 0, 0, 0 +}; + +static const char _sea_syllable_machine_from_state_actions[] = { + 0, 0, 5, 0, 0, 0 +}; + +static const char _sea_syllable_machine_eof_trans[] = { + 1, 3, 0, 7, 9, 11 +}; + +static const int sea_syllable_machine_start = 2; +static const int sea_syllable_machine_first_final = 2; +static const int sea_syllable_machine_error = -1; + +static const int sea_syllable_machine_en_main = 2; + + +#line 36 "hb-ot-shape-complex-sea-machine.rl" + + + +#line 67 "hb-ot-shape-complex-sea-machine.rl" + + +#define found_syllable(syllable_type) \ + HB_STMT_START { \ + if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \ + for (unsigned int i = last; i < p+1; i++) \ + info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + last = p+1; \ + syllable_serial++; \ + if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ + } HB_STMT_END + +static void +find_syllables (hb_buffer_t *buffer) +{ + unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED; + int cs; + hb_glyph_info_t *info = buffer->info; + +#line 117 "hb-ot-shape-complex-sea-machine.hh.tmp" + { + cs = sea_syllable_machine_start; + ts = 0; + te = 0; + act = 0; + } + +#line 88 "hb-ot-shape-complex-sea-machine.rl" + + + p = 0; + pe = eof = buffer->len; + + unsigned int last = 0; + unsigned int syllable_serial = 1; + +#line 134 "hb-ot-shape-complex-sea-machine.hh.tmp" + { + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; +_resume: + switch ( _sea_syllable_machine_from_state_actions[cs] ) { + case 5: +#line 1 "NONE" + {ts = p;} + break; +#line 148 "hb-ot-shape-complex-sea-machine.hh.tmp" + } + + _keys = _sea_syllable_machine_trans_keys + (cs<<1); + _inds = _sea_syllable_machine_indicies + _sea_syllable_machine_index_offsets[cs]; + + _slen = _sea_syllable_machine_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].sea_category()) && + ( info[p].sea_category()) <= _keys[1] ? + ( info[p].sea_category()) - _keys[0] : _slen ]; + +_eof_trans: + cs = _sea_syllable_machine_trans_targs[_trans]; + + if ( _sea_syllable_machine_trans_actions[_trans] == 0 ) + goto _again; + + switch ( _sea_syllable_machine_trans_actions[_trans] ) { + case 2: +#line 1 "NONE" + {te = p+1;} + break; + case 6: +#line 63 "hb-ot-shape-complex-sea-machine.rl" + {te = p+1;{ found_syllable (non_sea_cluster); }} + break; + case 7: +#line 61 "hb-ot-shape-complex-sea-machine.rl" + {te = p;p--;{ found_syllable (consonant_syllable); }} + break; + case 8: +#line 62 "hb-ot-shape-complex-sea-machine.rl" + {te = p;p--;{ found_syllable (broken_cluster); }} + break; + case 9: +#line 63 "hb-ot-shape-complex-sea-machine.rl" + {te = p;p--;{ found_syllable (non_sea_cluster); }} + break; + case 1: +#line 61 "hb-ot-shape-complex-sea-machine.rl" + {{p = ((te))-1;}{ found_syllable (consonant_syllable); }} + break; + case 3: +#line 62 "hb-ot-shape-complex-sea-machine.rl" + {{p = ((te))-1;}{ found_syllable (broken_cluster); }} + break; +#line 194 "hb-ot-shape-complex-sea-machine.hh.tmp" + } + +_again: + switch ( _sea_syllable_machine_to_state_actions[cs] ) { + case 4: +#line 1 "NONE" + {ts = 0;} + break; +#line 203 "hb-ot-shape-complex-sea-machine.hh.tmp" + } + + if ( ++p != pe ) + goto _resume; + _test_eof: {} + if ( p == eof ) + { + if ( _sea_syllable_machine_eof_trans[cs] > 0 ) { + _trans = _sea_syllable_machine_eof_trans[cs] - 1; + goto _eof_trans; + } + } + + } + +#line 97 "hb-ot-shape-complex-sea-machine.rl" + +} + +#undef found_syllable + +#endif /* HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH */ diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc new file mode 100644 index 0000000..9c0c303 --- /dev/null +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc @@ -0,0 +1,384 @@ +/* + * Copyright © 2011,2012,2013 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-ot-shape-complex-indic-private.hh" + +/* buffer var allocations */ +#define sea_category() complex_var_u8_0() /* indic_category_t */ +#define sea_position() complex_var_u8_1() /* indic_position_t */ + + +/* + * South-East Asian shaper. + * Loosely based on the Myanmar spec / shaper. + * There is no OpenType spec for this. + */ + +static const hb_tag_t +basic_features[] = +{ + /* + * Basic features. + * These features are applied in order, one at a time, after initial_reordering. + */ + HB_TAG('p','r','e','f'), + HB_TAG('a','b','v','f'), + HB_TAG('b','l','w','f'), + HB_TAG('p','s','t','f'), +}; +static const hb_tag_t +other_features[] = +{ + /* + * Other features. + * These features are applied all at once, after final_reordering. + */ + HB_TAG('p','r','e','s'), + HB_TAG('a','b','v','s'), + HB_TAG('b','l','w','s'), + HB_TAG('p','s','t','s'), + /* Positioning features, though we don't care about the types. */ + HB_TAG('d','i','s','t'), +}; + +static void +setup_syllables (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); +static void +initial_reordering (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); +static void +final_reordering (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); + +static void +collect_features_sea (hb_ot_shape_planner_t *plan) +{ + hb_ot_map_builder_t *map = &plan->map; + + /* Do this before any lookups have been applied. */ + map->add_gsub_pause (setup_syllables); + + map->add_global_bool_feature (HB_TAG('l','o','c','l')); + /* The Indic specs do not require ccmp, but we apply it here since if + * there is a use of it, it's typically at the beginning. */ + map->add_global_bool_feature (HB_TAG('c','c','m','p')); + + map->add_gsub_pause (initial_reordering); + for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) + { + map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); + map->add_gsub_pause (NULL); + } + map->add_gsub_pause (final_reordering); + for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) + map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); +} + +static void +override_features_sea (hb_ot_shape_planner_t *plan) +{ + plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL); +} + + +enum syllable_type_t { + consonant_syllable, + broken_cluster, + non_sea_cluster, +}; + +#include "hb-ot-shape-complex-sea-machine.hh" + + +/* Note: This enum is duplicated in the -machine.rl source file. + * Not sure how to avoid duplication. */ +enum sea_category_t { +// OT_C = 1, + OT_GB = 12, /* Generic Base XXX DOTTED CIRCLE only for now */ +// OT_H = 4, /* Halant */ + OT_IV = 2, /* Independent Vowel */ + OT_MR = 22, /* Medial Ra */ +// OT_CM = 17, /* Consonant Medial */ + OT_VAbv = 26, + OT_VBlw = 27, + OT_VPre = 28, + OT_VPst = 29, + OT_T = 3, /* Tone Marks */ +// OT_A = 10, /* Anusvara */ +}; + +static inline void +set_sea_properties (hb_glyph_info_t &info) +{ + hb_codepoint_t u = info.codepoint; + unsigned int type = hb_indic_get_categories (u); + indic_category_t cat = (indic_category_t) (type & 0x7F); + indic_position_t pos = (indic_position_t) (type >> 8); + + /* Medial Ra */ + if (u == 0x1A55 || u == 0xAA34) + cat = (indic_category_t) OT_MR; + + if (cat == OT_M) + { + switch ((int) pos) + { + case POS_PRE_C: cat = (indic_category_t) OT_VPre; break; + case POS_ABOVE_C: cat = (indic_category_t) OT_VAbv; break; + case POS_BELOW_C: cat = (indic_category_t) OT_VBlw; break; + case POS_POST_C: cat = (indic_category_t) OT_VPst; break; + } + } + + info.sea_category() = (sea_category_t) cat; + info.sea_position() = pos; +} + + +static void +setup_masks_sea (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_buffer_t *buffer, + hb_font_t *font HB_UNUSED) +{ + HB_BUFFER_ALLOCATE_VAR (buffer, sea_category); + HB_BUFFER_ALLOCATE_VAR (buffer, sea_position); + + /* We cannot setup masks here. We save information about characters + * and setup masks later on in a pause-callback. */ + + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + set_sea_properties (buffer->info[i]); +} + +static void +setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) +{ + find_syllables (buffer); +} + +static int +compare_sea_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) +{ + int a = pa->sea_position(); + int b = pb->sea_position(); + + return a < b ? -1 : a == b ? 0 : +1; +} + + +static void +initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, + hb_face_t *face, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) +{ + hb_glyph_info_t *info = buffer->info; + unsigned int base = start; + + /* Reorder! */ + unsigned int i = start; + for (; i < base; i++) + info[i].sea_position() = POS_PRE_C; + if (i < end) + { + info[i].sea_position() = POS_BASE_C; + i++; + } + for (; i < end; i++) + { + if (info[i].sea_category() == OT_MR) /* Pre-base reordering */ + { + info[i].sea_position() = POS_PRE_C; + continue; + } + if (info[i].sea_category() == OT_VPre) /* Left matra */ + { + info[i].sea_position() = POS_PRE_M; + continue; + } + + info[i].sea_position() = POS_AFTER_MAIN; + } + + buffer->merge_clusters (start, end); + /* Sit tight, rock 'n roll! */ + hb_bubble_sort (info + start, end - start, compare_sea_order); +} + +static void +initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan, + hb_face_t *face, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) +{ + /* We already inserted dotted-circles, so just call the consonant_syllable. */ + initial_reordering_consonant_syllable (plan, face, buffer, start, end); +} + +static void +initial_reordering_non_sea_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_face_t *face HB_UNUSED, + hb_buffer_t *buffer HB_UNUSED, + unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +{ + /* Nothing to do right now. If we ever switch to using the output + * buffer in the reordering process, we'd need to next_glyph() here. */ +} + + +static void +initial_reordering_syllable (const hb_ot_shape_plan_t *plan, + hb_face_t *face, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) +{ + syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); + switch (syllable_type) { + case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return; + case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return; + case non_sea_cluster: initial_reordering_non_sea_cluster (plan, face, buffer, start, end); return; + } +} + +static inline void +insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font, + hb_buffer_t *buffer) +{ + /* Note: This loop is extra overhead, but should not be measurable. */ + bool has_broken_syllables = false; + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) { + has_broken_syllables = true; + break; + } + if (likely (!has_broken_syllables)) + return; + + + hb_codepoint_t dottedcircle_glyph; + if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph)) + return; + + hb_glyph_info_t dottedcircle = {0}; + dottedcircle.codepoint = 0x25CC; + set_sea_properties (dottedcircle); + dottedcircle.codepoint = dottedcircle_glyph; + + buffer->clear_output (); + + buffer->idx = 0; + unsigned int last_syllable = 0; + while (buffer->idx < buffer->len) + { + unsigned int syllable = buffer->cur().syllable(); + syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F); + if (unlikely (last_syllable != syllable && syllable_type == broken_cluster)) + { + last_syllable = syllable; + + hb_glyph_info_t info = dottedcircle; + info.cluster = buffer->cur().cluster; + info.mask = buffer->cur().mask; + info.syllable() = buffer->cur().syllable(); + + buffer->output_info (info); + } + else + buffer->next_glyph (); + } + + buffer->swap_buffers (); +} + +static void +initial_reordering (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) +{ + insert_dotted_circles (plan, font, buffer); + + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + if (unlikely (!count)) return; + unsigned int last = 0; + unsigned int last_syllable = info[0].syllable(); + for (unsigned int i = 1; i < count; i++) + if (last_syllable != info[i].syllable()) { + initial_reordering_syllable (plan, font->face, buffer, last, i); + last = i; + last_syllable = info[last].syllable(); + } + initial_reordering_syllable (plan, font->face, buffer, last, count); +} + +static void +final_reordering (const hb_ot_shape_plan_t *plan, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) +{ + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + + /* Zero syllables now... */ + for (unsigned int i = 0; i < count; i++) + info[i].syllable() = 0; + + HB_BUFFER_DEALLOCATE_VAR (buffer, sea_category); + HB_BUFFER_DEALLOCATE_VAR (buffer, sea_position); +} + + +static hb_ot_shape_normalization_mode_t +normalization_preference_sea (const hb_segment_properties_t *props HB_UNUSED) +{ + return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; +} + + +const hb_ot_complex_shaper_t _hb_ot_complex_shaper_sea = +{ + "sea", + collect_features_sea, + override_features_sea, + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ + normalization_preference_sea, + NULL, /* decompose */ + NULL, /* compose */ + setup_masks_sea, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, + false, /* fallback_position */ +}; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc index 24d476a..5cbb6e3 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc @@ -373,6 +373,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai = NULL, /* decompose */ NULL, /* compose */ NULL, /* setup_masks */ - true, /* zero_width_attached_marks */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE, false,/* fallback_position */ }; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-fallback-private.hh index 5e9cb06..ec65351 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-fallback-private.hh @@ -41,4 +41,9 @@ HB_INTERNAL void _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_ hb_buffer_t *buffer); +HB_INTERNAL void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); + + #endif /* HB_OT_SHAPE_FALLBACK_PRIVATE_HH */ diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc index 6f3426e..3341825 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc @@ -25,6 +25,7 @@ */ #include "hb-ot-shape-fallback-private.hh" +#include "hb-ot-layout-gsubgpos-private.hh" static unsigned int recategorize_combining_class (hb_codepoint_t u, @@ -407,3 +408,48 @@ _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan, } position_cluster (plan, font, buffer, start, count); } + + +/* Performs old-style TrueType kerning. */ +void +_hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) +{ + unsigned int count = buffer->len; + hb_mask_t kern_mask = plan->map.get_1_mask (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ? + HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n')); + + OT::hb_apply_context_t c (1, font, buffer, kern_mask, true/*auto_zwj*/); + c.set_lookup_props (OT::LookupFlag::IgnoreMarks); + + for (buffer->idx = 0; buffer->idx < count;) + { + OT::hb_apply_context_t::skipping_forward_iterator_t skippy_iter (&c, buffer->idx, 1); + if (!skippy_iter.next ()) + { + buffer->idx++; + continue; + } + + hb_position_t x_kern, y_kern, kern1, kern2; + font->get_glyph_kerning_for_direction (buffer->info[buffer->idx].codepoint, + buffer->info[skippy_iter.idx].codepoint, + buffer->props.direction, + &x_kern, &y_kern); + + kern1 = x_kern >> 1; + kern2 = x_kern - kern1; + buffer->pos[buffer->idx].x_advance += kern1; + buffer->pos[skippy_iter.idx].x_advance += kern2; + buffer->pos[skippy_iter.idx].x_offset += kern2; + + kern1 = y_kern >> 1; + kern2 = y_kern - kern1; + buffer->pos[buffer->idx].y_advance += kern1; + buffer->pos[skippy_iter.idx].y_advance += kern2; + buffer->pos[skippy_iter.idx].y_offset += kern2; + + buffer->idx = skippy_iter.idx; + } +} diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc index c5325e4..344c0ff 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc @@ -192,30 +192,23 @@ decompose_compatibility (const hb_ot_shape_normalize_context_t *c, hb_codepoint_ } /* Returns true if recomposition may be benefitial. */ -static inline bool +static inline void decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shortest) { hb_buffer_t * const buffer = c->buffer; hb_codepoint_t glyph; - unsigned int len = 1; /* Kind of a cute waterfall here... */ if (shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph)) next_char (buffer, glyph); - else if ((len = decompose (c, shortest, buffer->cur().codepoint))) + else if (decompose (c, shortest, buffer->cur().codepoint)) skip_char (buffer); else if (!shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph)) next_char (buffer, glyph); - else if ((len = decompose_compatibility (c, buffer->cur().codepoint))) + else if (decompose_compatibility (c, buffer->cur().codepoint)) skip_char (buffer); else next_char (buffer, glyph); /* glyph is initialized in earlier branches. */ - - /* - * A recomposition would only be useful if we decomposed into at least three - * characters... - */ - return len > 2; } static inline void @@ -239,7 +232,7 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, uns } /* Returns true if recomposition may be benefitial. */ -static inline bool +static inline void decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end) { hb_buffer_t * const buffer = c->buffer; @@ -247,23 +240,20 @@ decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned for (unsigned int i = buffer->idx; i < end; i++) if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) { handle_variation_selector_cluster (c, end); - return false; + return; } while (buffer->idx < end) decompose_current_character (c, false); - /* We can be smarter here and only return true if there are at least two ccc!=0 marks. - * But does not matter. */ - return true; } -static inline bool +static inline void decompose_cluster (const hb_ot_shape_normalize_context_t *c, bool short_circuit, unsigned int end) { if (likely (c->buffer->idx + 1 == end)) - return decompose_current_character (c, short_circuit); + decompose_current_character (c, short_circuit); else - return decompose_multi_char_cluster (c, end); + decompose_multi_char_cluster (c, end); } @@ -296,7 +286,6 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, bool short_circuit = mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED && mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; - bool can_use_recompose = false; unsigned int count; /* We do a fairly straightforward yet custom normalization process in three @@ -317,15 +306,11 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, if (buffer->cur().cluster != buffer->info[end].cluster) break; - can_use_recompose = decompose_cluster (&c, short_circuit, end) || can_use_recompose; + decompose_cluster (&c, short_circuit, end); } buffer->swap_buffers (); - if (mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL && !can_use_recompose) - return; /* Done! */ - - /* Second round, reorder (inplace) */ count = buffer->len; @@ -369,9 +354,11 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, { hb_codepoint_t composed, glyph; if (/* If mode is NOT COMPOSED_FULL (ie. it's COMPOSED_DIACRITICS), we don't try to - * compose a CCC=0 character with it's preceding starter. */ + * compose a non-mark character with it's preceding starter. This is just an + * optimization to avoid trying to compose every two neighboring glyphs in most + * scripts. */ (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL || - _hb_glyph_info_get_modified_combining_class (&buffer->cur()) != 0) && + HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur()))) && /* If there's anything between the starter and this char, they should have CCC * smaller than this character's. */ (starter == buffer->out_len - 1 || diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh index 23e80b7..9599f8e 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh @@ -33,10 +33,6 @@ -/* buffer var allocations, used during the entire shaping process */ -#define unicode_props0() var2.u8[0] -#define unicode_props1() var2.u8[1] - struct hb_ot_shape_plan_t @@ -89,37 +85,4 @@ struct hb_ot_shape_planner_t }; - -inline void -_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode) -{ - info->unicode_props0() = ((unsigned int) unicode->general_category (info->codepoint)) | - (unicode->is_default_ignorable (info->codepoint) ? 0x80 : 0); - info->unicode_props1() = unicode->modified_combining_class (info->codepoint); -} - -inline hb_unicode_general_category_t -_hb_glyph_info_get_general_category (const hb_glyph_info_t *info) -{ - return (hb_unicode_general_category_t) (info->unicode_props0() & 0x7F); -} - -inline void -_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info, unsigned int modified_class) -{ - info->unicode_props1() = modified_class; -} - -inline unsigned int -_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info) -{ - return info->unicode_props1(); -} - -inline hb_bool_t -_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info) -{ - return !!(info->unicode_props0() & 0x80); -} - #endif /* HB_OT_SHAPE_PRIVATE_HH */ diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape.cc b/third_party/harfbuzz-ng/src/hb-ot-shape.cc index 96461d7..f65861f 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape.cc @@ -83,12 +83,12 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, switch (props->direction) { case HB_DIRECTION_LTR: - map->add_bool_feature (HB_TAG ('l','t','r','a')); - map->add_bool_feature (HB_TAG ('l','t','r','m')); + map->add_global_bool_feature (HB_TAG ('l','t','r','a')); + map->add_global_bool_feature (HB_TAG ('l','t','r','m')); break; case HB_DIRECTION_RTL: - map->add_bool_feature (HB_TAG ('r','t','l','a')); - map->add_bool_feature (HB_TAG ('r','t','l','m'), false); + map->add_global_bool_feature (HB_TAG ('r','t','l','a')); + map->add_feature (HB_TAG ('r','t','l','m'), 1, F_NONE); break; case HB_DIRECTION_TTB: case HB_DIRECTION_BTT: @@ -97,30 +97,31 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, break; } -#define ADD_FEATURES(array) \ - HB_STMT_START { \ - for (unsigned int i = 0; i < ARRAY_LENGTH (array); i++) \ - map->add_bool_feature (array[i]); \ - } HB_STMT_END - if (planner->shaper->collect_features) planner->shaper->collect_features (planner); - ADD_FEATURES (common_features); + for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++) + map->add_global_bool_feature (common_features[i]); if (HB_DIRECTION_IS_HORIZONTAL (props->direction)) - ADD_FEATURES (horizontal_features); + for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++) + map->add_feature (horizontal_features[i], 1, F_GLOBAL | + (horizontal_features[i] == HB_TAG('k','e','r','n') ? + F_HAS_FALLBACK : F_NONE)); else - ADD_FEATURES (vertical_features); + for (unsigned int i = 0; i < ARRAY_LENGTH (vertical_features); i++) + map->add_feature (vertical_features[i], 1, F_GLOBAL | + (vertical_features[i] == HB_TAG('v','k','r','n') ? + F_HAS_FALLBACK : F_NONE)); if (planner->shaper->override_features) planner->shaper->override_features (planner); -#undef ADD_FEATURES - for (unsigned int i = 0; i < num_user_features; i++) { const hb_feature_t *feature = &user_features[i]; - map->add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1)); + map->add_feature (feature->tag, feature->value, + (feature->start == 0 && feature->end == (unsigned int) -1) ? + F_GLOBAL : F_NONE); } } @@ -405,7 +406,8 @@ hb_ot_position_default (hb_ot_shape_context_t *c) hb_ot_layout_position_start (c->font, c->buffer); unsigned int count = c->buffer->len; - for (unsigned int i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) + { c->font->get_glyph_advance_for_direction (c->buffer->info[i].codepoint, c->buffer->props.direction, &c->buffer->pos[i].x_advance, @@ -414,6 +416,26 @@ hb_ot_position_default (hb_ot_shape_context_t *c) c->buffer->props.direction, &c->buffer->pos[i].x_offset, &c->buffer->pos[i].y_offset); + + } + + /* Zero'ing mark widths by GDEF (as used in Myanmar spec) happens + * *before* GPOS. */ + switch (c->plan->shaper->zero_width_marks) + { + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF: + for (unsigned int i = 0; i < count; i++) + if ((c->buffer->info[i].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) + { + c->buffer->pos[i].x_advance = 0; + c->buffer->pos[i].y_advance = 0; + } + break; + + default: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE: + break; } } @@ -421,12 +443,12 @@ static inline bool hb_ot_position_complex (hb_ot_shape_context_t *c) { bool ret = false; + unsigned int count = c->buffer->len; if (hb_ot_layout_has_positioning (c->face)) { /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ - unsigned int count = c->buffer->len; for (unsigned int i = 0; i < count; i++) { c->font->add_glyph_origin_for_direction (c->buffer->info[i].codepoint, HB_DIRECTION_LTR, @@ -446,34 +468,28 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) ret = true; } - hb_ot_layout_position_finish (c->font, c->buffer, c->plan->shaper->zero_width_attached_marks); - - return ret; -} + /* Zero'ing mark widths by Unicode happens + * *after* GPOS. */ + switch (c->plan->shaper->zero_width_marks) + { + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE: + for (unsigned int i = 0; i < count; i++) + if (_hb_glyph_info_get_general_category (&c->buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + { + c->buffer->pos[i].x_advance = 0; + c->buffer->pos[i].y_advance = 0; + } + break; -static inline void -hb_ot_truetype_kern (hb_ot_shape_context_t *c) -{ - /* TODO Check for kern=0 */ - unsigned int count = c->buffer->len; - for (unsigned int i = 1; i < count; i++) { - hb_position_t x_kern, y_kern, kern1, kern2; - c->font->get_glyph_kerning_for_direction (c->buffer->info[i - 1].codepoint, c->buffer->info[i].codepoint, - c->buffer->props.direction, - &x_kern, &y_kern); - - kern1 = x_kern >> 1; - kern2 = x_kern - kern1; - c->buffer->pos[i - 1].x_advance += kern1; - c->buffer->pos[i].x_advance += kern2; - c->buffer->pos[i].x_offset += kern2; - - kern1 = y_kern >> 1; - kern2 = y_kern - kern1; - c->buffer->pos[i - 1].y_advance += kern1; - c->buffer->pos[i].y_advance += kern2; - c->buffer->pos[i].y_offset += kern2; + default: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF: + break; } + + hb_ot_layout_position_finish (c->font, c->buffer); + + return ret; } static inline void @@ -492,7 +508,7 @@ hb_ot_position (hb_ot_shape_context_t *c) /* Visual fallback goes here. */ if (fallback) - hb_ot_truetype_kern (c); + _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); } @@ -611,8 +627,6 @@ hb_ot_shape_glyphs_closure (hb_font_t *font, { hb_ot_shape_plan_t plan; - buffer->guess_segment_properties (); - const char *shapers[] = {"ot", NULL}; hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shapers); diff --git a/third_party/harfbuzz-ng/src/hb-private.hh b/third_party/harfbuzz-ng/src/hb-private.hh index be0d505..ff1e85d 100644 --- a/third_party/harfbuzz-ng/src/hb-private.hh +++ b/third_party/harfbuzz-ng/src/hb-private.hh @@ -376,6 +376,14 @@ struct hb_prealloced_array_t } }; +#define HB_AUTO_ARRAY_PREALLOCED 64 +template <typename Type> +struct hb_auto_array_t : hb_prealloced_array_t <Type, HB_AUTO_ARRAY_PREALLOCED> +{ + hb_auto_array_t (void) { hb_prealloced_array_t<Type, HB_AUTO_ARRAY_PREALLOCED>::init (); } + ~hb_auto_array_t (void) { hb_prealloced_array_t<Type, HB_AUTO_ARRAY_PREALLOCED>::finish (); } +}; + #define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT} template <typename item_t, typename lock_t> @@ -516,10 +524,12 @@ static inline uint32_t hb_uint32_swap (const uint32_t v) /* ASCII tag/character handling */ -static inline unsigned char ISALPHA (unsigned char c) +static inline bool ISALPHA (unsigned char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } -static inline unsigned char ISALNUM (unsigned char c) +static inline bool ISALNUM (unsigned char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); } +static inline bool ISSPACE (unsigned char c) +{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; } static inline unsigned char TOUPPER (unsigned char c) { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; } static inline unsigned char TOLOWER (unsigned char c) @@ -594,6 +604,8 @@ _hb_debug_msg_va (const char *what, if (func) { + unsigned int func_len = strlen (func); +#ifndef HB_DEBUG_VERBOSE /* Skip "typename" */ if (0 == strncmp (func, "typename ", 9)) func += 9; @@ -603,7 +615,9 @@ _hb_debug_msg_va (const char *what, func = space + 1; /* Skip parameter list */ const char *paren = strchr (func, '('); - unsigned int func_len = paren ? paren - func : strlen (func); + if (paren) + func_len = paren - func; +#endif fprintf (stderr, "%.*s: ", func_len, func); } @@ -841,8 +855,9 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o { /* Pain because we don't know whether s is nul-terminated. */ char buf[64]; - strncpy (buf, s, MIN (ARRAY_LENGTH (buf) - 1, len)); - buf[MIN (ARRAY_LENGTH (buf) - 1, len)] = '\0'; + len = MIN (ARRAY_LENGTH (buf) - 1, len); + strncpy (buf, s, len); + buf[len] = '\0'; char *end; errno = 0; @@ -854,4 +869,33 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o } +/* Global runtime options. */ + +struct hb_options_t +{ + int initialized : 1; + int uniscribe_bug_compatible : 1; +}; + +union hb_options_union_t { + int i; + hb_options_t opts; +}; +ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t)); + +HB_INTERNAL void +_hb_options_init (void); + +extern HB_INTERNAL hb_options_union_t _hb_options; + +static inline hb_options_t +hb_options (void) +{ + if (unlikely (!_hb_options.i)) + _hb_options_init (); + + return _hb_options.opts; +} + + #endif /* HB_PRIVATE_HH */ diff --git a/third_party/harfbuzz-ng/src/hb-shape-plan.cc b/third_party/harfbuzz-ng/src/hb-shape-plan.cc index 22a226f..a6d2d26 100644 --- a/third_party/harfbuzz-ng/src/hb-shape-plan.cc +++ b/third_party/harfbuzz-ng/src/hb-shape-plan.cc @@ -27,6 +27,7 @@ #include "hb-shape-plan-private.hh" #include "hb-shaper-private.hh" #include "hb-font-private.hh" +#include "hb-buffer-private.hh" #define HB_SHAPER_IMPLEMENT(shaper) \ HB_SHAPER_DATA_ENSURE_DECLARE(shaper, face) \ @@ -178,9 +179,14 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, const hb_feature_t *features, unsigned int num_features) { - if (unlikely (shape_plan->face != font->face)) + if (unlikely (hb_object_is_inert (shape_plan) || + hb_object_is_inert (font) || + hb_object_is_inert (buffer))) return false; + assert (shape_plan->face == font->face); + assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props)); + #define HB_SHAPER_EXECUTE(shaper) \ HB_STMT_START { \ return HB_SHAPER_DATA (shaper, shape_plan) && \ diff --git a/third_party/harfbuzz-ng/src/hb-shape.cc b/third_party/harfbuzz-ng/src/hb-shape.cc index 389ce3e..67ef7e6 100644 --- a/third_party/harfbuzz-ng/src/hb-shape.cc +++ b/third_party/harfbuzz-ng/src/hb-shape.cc @@ -38,10 +38,8 @@ static void parse_space (const char **pp, const char *end) { char c; -#define ISSPACE(c) ((c)==' '||(c)=='\f'||(c)=='\n'||(c)=='\r'||(c)=='\t'||(c)=='\v') while (*pp < end && (c = **pp, ISSPACE (c))) (*pp)++; -#undef ISSPACE } static hb_bool_t @@ -60,16 +58,19 @@ static hb_bool_t parse_uint (const char **pp, const char *end, unsigned int *pv) { char buf[32]; - strncpy (buf, *pp, end - *pp); - buf[ARRAY_LENGTH (buf) - 1] = '\0'; + 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 (p == pend) + if (errno || p == pend) return false; *pv = v; @@ -202,7 +203,7 @@ hb_feature_to_string (hb_feature_t *feature, static const char **static_shaper_list; -static +static inline void free_static_shaper_list (void) { free (static_shaper_list); @@ -255,8 +256,6 @@ hb_shape_full (hb_font_t *font, assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE); - buffer->guess_segment_properties (); - hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list); hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features); hb_shape_plan_destroy (shape_plan); diff --git a/third_party/harfbuzz-ng/src/hb-shaper-private.hh b/third_party/harfbuzz-ng/src/hb-shaper-private.hh index 9d30c1e..29c4493 100644 --- a/third_party/harfbuzz-ng/src/hb-shaper-private.hh +++ b/third_party/harfbuzz-ng/src/hb-shaper-private.hh @@ -95,7 +95,10 @@ hb_##shaper##_shaper_##object##_data_ensure (hb_##object##_t *object) \ if (unlikely (!data)) \ data = (HB_SHAPER_DATA_TYPE (shaper, object) *) HB_SHAPER_DATA_INVALID; \ if (!hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), NULL, data)) { \ - HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \ + if (data && \ + data != HB_SHAPER_DATA_INVALID && \ + data != HB_SHAPER_DATA_SUCCEEDED) \ + HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \ goto retry; \ } \ } \ diff --git a/third_party/harfbuzz-ng/src/hb-shaper.cc b/third_party/harfbuzz-ng/src/hb-shaper.cc index 1c1aed9..44f718a 100644 --- a/third_party/harfbuzz-ng/src/hb-shaper.cc +++ b/third_party/harfbuzz-ng/src/hb-shaper.cc @@ -40,7 +40,7 @@ static const hb_shaper_pair_t all_shapers[] = { static const hb_shaper_pair_t *static_shapers; -static +static inline void free_static_shapers (void) { if (unlikely (static_shapers != all_shapers)) diff --git a/third_party/harfbuzz-ng/src/hb-unicode-private.hh b/third_party/harfbuzz-ng/src/hb-unicode-private.hh index 7be4b04..155a8a3 100644 --- a/third_party/harfbuzz-ng/src/hb-unicode-private.hh +++ b/third_party/harfbuzz-ng/src/hb-unicode-private.hh @@ -107,6 +107,9 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE unsigned int modified_combining_class (hb_codepoint_t unicode) { + /* XXX This hack belongs to the Myanmar shaper. */ + if (unicode == 0x1037) unicode = 0x103A; + return _hb_modified_combining_class[combining_class (unicode)]; } @@ -126,6 +129,11 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * be. That has been reported to the Unicode Technical Committee for * consideration. As such, we include it here, since Uniscribe removes it. * + * Note: While U+115F and U+1160 are Default_Ignorable, we do NOT want to + * hide them, as the way Uniscribe has implemented them is with regular + * spacing glyphs, and that's the way fonts are made to work. As such, + * we make exceptions for those two. + * * Gathered from: * http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:DI:]&abb=on&ucd=on&esc=on * @@ -138,8 +146,8 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * * 00AD ;SOFT HYPHEN * 034F ;COMBINING GRAPHEME JOINER - * 115F ;HANGUL CHOSEONG FILLER - * 1160 ;HANGUL JUNGSEONG FILLER + * #115F ;HANGUL CHOSEONG FILLER + * #1160 ;HANGUL JUNGSEONG FILLER * 17B4 ;KHMER VOWEL INHERENT AQ * 17B5 ;KHMER VOWEL INHERENT AA * 180B..180D ;MONGOLIAN FREE VARIATION SELECTOR THREE @@ -165,7 +173,6 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE switch (page) { case 0x00: return unlikely (ch == 0x00AD); case 0x03: return unlikely (ch == 0x034F); - case 0x11: return hb_in_range<hb_codepoint_t> (ch, 0x115F, 0x1160); case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4, 0x17B5); case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180B, 0x180E); case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200B, 0x200F, diff --git a/third_party/harfbuzz-ng/src/hb-version.h b/third_party/harfbuzz-ng/src/hb-version.h index c5a4e62..dadcde2 100644 --- a/third_party/harfbuzz-ng/src/hb-version.h +++ b/third_party/harfbuzz-ng/src/hb-version.h @@ -38,9 +38,9 @@ HB_BEGIN_DECLS #define HB_VERSION_MAJOR 0 #define HB_VERSION_MINOR 9 -#define HB_VERSION_MICRO 5 +#define HB_VERSION_MICRO 14 -#define HB_VERSION_STRING "0.9.5" +#define HB_VERSION_STRING "0.9.14" #define HB_VERSION_CHECK(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) >= \ diff --git a/third_party/harfbuzz-ng/src/hb-warning.cc b/third_party/harfbuzz-ng/src/hb-warning.cc index 01adcea..4f1f65f 100644 --- a/third_party/harfbuzz-ng/src/hb-warning.cc +++ b/third_party/harfbuzz-ng/src/hb-warning.cc @@ -29,11 +29,38 @@ #if defined(HB_ATOMIC_INT_NIL) -#pragma message("Could not find any system to define atomic_int macros, library may NOT be thread-safe.") +#ifdef _MSC_VER +#pragma message("Could not find any system to define atomic_int macros, library may NOT be thread-safe") +#else +#warning "Could not find any system to define atomic_int macros, library may NOT be thread-safe" #endif +#endif + #if defined(HB_MUTEX_IMPL_NIL) -#pragma message("Could not find any system to define mutex macros, library may NOT be thread-safe.") +#ifdef _MSC_VER +#pragma message("Could not find any system to define mutex macros, library may NOT be thread-safe") +#else +#warning "Could not find any system to define mutex macros, library may NOT be thread-safe" +#endif #endif + #if defined(HB_ATOMIC_INT_NIL) || defined(HB_MUTEX_IMPL_NIL) -#pragma message("To suppress these warnings, define HB_NO_MT.") +#ifdef _MSC_VER +#pragma message("To suppress these warnings, define HB_NO_MT") +#else +#warning "To suppress these warnings, define HB_NO_MT" +#endif +#endif + + +#include "hb-unicode-private.hh" + +#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL) +#ifdef _MSC_VER +#pragma message("Could not find any Unicode functions implementation, you have to provide your own") +#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS") +#else +#warning "Could not find any Unicode functions implementation, you have to provide your own" +#warning "To suppress this warning, define HB_NO_UNICODE_FUNCS" +#endif #endif diff --git a/third_party/harfbuzz-ng/src/test-buffer-serialize.cc b/third_party/harfbuzz-ng/src/test-buffer-serialize.cc new file mode 100644 index 0000000..3577dbf --- /dev/null +++ b/third_party/harfbuzz-ng/src/test-buffer-serialize.cc @@ -0,0 +1,126 @@ +/* + * Copyright © 2010,2011,2013 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 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "hb.h" +#ifdef HAVE_FREETYPE +#include "hb-ft.h" +#endif + +#ifdef HAVE_GLIB +#include <glib.h> +#endif +#include <stdlib.h> +#include <stdio.h> + +int +main (int argc, char **argv) +{ + hb_blob_t *blob = NULL; + + if (argc != 2) { + fprintf (stderr, "usage: %s font-file\n", argv[0]); + exit (1); + } + + /* Create the blob */ + { + const char *font_data; + unsigned int len; + hb_destroy_func_t destroy; + void *user_data; + hb_memory_mode_t mm; + +#ifdef HAVE_GLIB + GMappedFile *mf = g_mapped_file_new (argv[1], false, NULL); + font_data = g_mapped_file_get_contents (mf); + len = g_mapped_file_get_length (mf); + destroy = (hb_destroy_func_t) g_mapped_file_unref; + user_data = (void *) mf; + mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE; +#else + FILE *f = fopen (argv[1], "rb"); + fseek (f, 0, SEEK_END); + len = ftell (f); + fseek (f, 0, SEEK_SET); + font_data = (const char *) malloc (len); + if (!font_data) len = 0; + len = fread ((char *) font_data, 1, len, f); + destroy = free; + user_data = (void *) font_data; + fclose (f); + mm = HB_MEMORY_MODE_WRITABLE; +#endif + + blob = hb_blob_create (font_data, len, mm, user_data, destroy); + } + + hb_face_t *face = hb_face_create (blob, 0 /* first face */); + hb_blob_destroy (blob); + blob = NULL; + + unsigned int upem = hb_face_get_upem (face); + hb_font_t *font = hb_font_create (face); + hb_face_destroy (face); + hb_font_set_scale (font, upem, upem); +#ifdef HAVE_FREETYPE + hb_ft_font_set_funcs (font); +#endif + + hb_buffer_t *buf; + buf = hb_buffer_create (); + + bool ret = true; + char line[BUFSIZ], out[BUFSIZ]; + while (fgets (line, sizeof(line), stdin) != 0) + { + hb_buffer_clear_contents (buf); + + const char *p = line; + while (hb_buffer_deserialize_glyphs (buf, + p, -1, &p, + font, + HB_BUFFER_SERIALIZE_FORMAT_JSON)) + ; + if (*p && *p != '\n') + ret = false; + + hb_buffer_serialize_glyphs (buf, 0, hb_buffer_get_length (buf), + out, sizeof (out), NULL, + font, HB_BUFFER_SERIALIZE_FORMAT_JSON, + HB_BUFFER_SERIALIZE_FLAGS_DEFAULT); + puts (out); + } + + hb_buffer_destroy (buf); + + hb_font_destroy (font); + + return !ret; +} |