src/hb-aat-layout-common-private.hh | 58 +++ src/hb-aat-layout-morx-table.hh | 170 +++++++--- test/shaping/CMakeLists.txt | 4 test/shaping/data/text-rendering-tests/DISABLED | 4 test/shaping/data/text-rendering-tests/Makefile.sources | 12 test/shaping/data/text-rendering-tests/fonts/TestMORXEleven.ttf |binary test/shaping/data/text-rendering-tests/fonts/TestMORXTen.ttf |binary test/shaping/data/text-rendering-tests/tests/MORX-10.tests | 1 test/shaping/data/text-rendering-tests/tests/MORX-11.tests | 1 9 files changed, 204 insertions(+), 46 deletions(-)
New commits: commit f6be730994434e706cc27d68b796492d876e82b6 Author: Behdad Esfahbod <[email protected]> Date: Thu Jan 11 15:23:24 2018 +0100 [aat] In NoncontextualSubtable, handle MarkLast with end-of-line transition Fixes MORX-11 test. diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 80164af0..5dec189f 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -91,8 +91,8 @@ struct RearrangementSubtable last_zero_before_start = last_zero; } - if (flags & MarkLast && i < count) - end = i + 1; + if (flags & MarkLast) + end = MIN (i + 1, count); if ((flags & Verb) && start < end) { commit 1d20d109a07bf9c775ab91dfbbb55f7bd80fd9d6 Author: Behdad Esfahbod <[email protected]> Date: Thu Jan 11 15:18:22 2018 +0100 [test/text-rendering-tests] Update from upstream diff --git a/test/shaping/data/text-rendering-tests/DISABLED b/test/shaping/data/text-rendering-tests/DISABLED index 0e1b89b3..610e1957 100644 --- a/test/shaping/data/text-rendering-tests/DISABLED +++ b/test/shaping/data/text-rendering-tests/DISABLED @@ -1,7 +1,7 @@ # Non-Unicode cmap tests/CMAP-3.tests -# Not implemented +# Not hooked up tests/MORX-1.tests tests/MORX-2.tests tests/MORX-3.tests @@ -12,6 +12,7 @@ tests/MORX-7.tests tests/MORX-8.tests tests/MORX-9.tests tests/MORX-10.tests +tests/MORX-11.tests # Rounding differences tests/SHARAN-1.tests diff --git a/test/shaping/data/text-rendering-tests/Makefile.sources b/test/shaping/data/text-rendering-tests/Makefile.sources index 8e0f4318..0c210fa8 100644 --- a/test/shaping/data/text-rendering-tests/Makefile.sources +++ b/test/shaping/data/text-rendering-tests/Makefile.sources @@ -28,13 +28,14 @@ TESTS = \ tests/HVAR-2.tests \ tests/KERN-1.tests \ tests/KERN-2.tests \ - tests/MORX-10.tests \ + tests/MORX-11.tests \ tests/SHBALI-3.tests \ tests/SHKNDA-1.tests \ $(NULL) DISBALED_TESTS = \ tests/CMAP-3.tests \ + tests/MORX-10.tests \ tests/MORX-1.tests \ tests/MORX-2.tests \ tests/MORX-3.tests \ diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXEleven.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXEleven.ttf new file mode 100644 index 00000000..92b889ca Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXEleven.ttf differ diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-11.tests b/test/shaping/data/text-rendering-tests/tests/MORX-11.tests new file mode 100644 index 00000000..1fce69bc --- /dev/null +++ b/test/shaping/data/text-rendering-tests/tests/MORX-11.tests @@ -0,0 +1 @@ +../fonts/TestMORXEleven.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0042,U+0041,U+0042,U+0042,U+0041,U+0041,U+0042,U+0058:[B|A@650,0|B@1288,0|B@1938,0|A@2588,0|X@3226,0|A@3812,0|B@4450,0] commit f9be673814aeb2c8abab52a672598576c6ed20c2 Author: Behdad Esfahbod <[email protected]> Date: Thu Jan 11 15:15:07 2018 +0100 [aat] Implement ContextualSubtable Tested with Zapfino and text "2nd". Sascha will create tests later. diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 6c9c5154..80164af0 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -200,8 +200,70 @@ struct ContextualSubtable inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - /* TODO */ - return_trace (false); + + bool ret = false; + unsigned int num_glyphs = c->face->get_num_glyphs (); + + const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT> &subs = this+substitutionTables; + + unsigned int state = 0; + unsigned int last_zero = 0; + unsigned int last_zero_before_mark = 0; + unsigned int mark = 0; + + hb_glyph_info_t *info = c->buffer->info; + unsigned int count = c->buffer->len; + + for (unsigned int i = 0; i <= count; i++) + { + if (!state) + last_zero = i; + + unsigned int klass = i < count ? + machine.get_class (info[i].codepoint, num_glyphs) : + 0 /* End of text */; + const Entry<EntryData> *entry = machine.get_entry (state, klass); + if (unlikely (!entry)) + break; + + unsigned int flags = entry->flags; + + if (flags & SetMark) + { + mark = i; + last_zero_before_mark = last_zero; + } + + if (entry->data.markIndex != 0xFFFF) + { + const Lookup<GlyphID> &lookup = subs[entry->data.markIndex]; // XXX bounds + const GlyphID *replacement = lookup.get_value (info[mark].codepoint, num_glyphs); + if (replacement) + { + c->buffer->unsafe_to_break (last_zero_before_mark, MIN (i + 1, count)); + info[mark].codepoint = *replacement; + ret = true; + } + } + if (entry->data.currentIndex != 0xFFFF) + { + const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex]; // XXX bounds + const GlyphID *replacement = lookup.get_value (info[i].codepoint, num_glyphs); + if (replacement) + { + c->buffer->unsafe_to_break (last_zero, MIN (i + 1, count)); + info[i].codepoint = *replacement; + ret = true; + } + } + + if (false/* XXX */ && flags & DontAdvance) + i--; /* XXX Detect infinite loop. */ + + state = entry->newState; + } + + return_trace (ret); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -233,7 +295,7 @@ struct LigatureSubtable { TRACE_SANITIZE (this); /* TODO */ - return_trace (false); + return_trace (true); } }; @@ -288,7 +350,7 @@ struct InsertionSubtable { TRACE_SANITIZE (this); /* TODO */ - return_trace (false); + return_trace (true); } }; commit 335a9c1fe489db53549801b4996dd0f6f5eded62 Author: Behdad Esfahbod <[email protected]> Date: Thu Jan 11 14:50:47 2018 +0100 [aat] Towards implementing ContextualSubtable diff --git a/src/hb-aat-layout-common-private.hh b/src/hb-aat-layout-common-private.hh index 32ba6326..887350bb 100644 --- a/src/hb-aat-layout-common-private.hh +++ b/src/hb-aat-layout-common-private.hh @@ -151,6 +151,7 @@ struct UnsizedArrayOf inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const { TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c, count))) return_trace (false); /* Note: for structs that do not reference other structs, * we do not need to call their sanitize() as we already did @@ -159,8 +160,34 @@ struct UnsizedArrayOf * pointed to do have a simple sanitize(), ie. they do not * reference other structs via offsets. */ - (void) (false && count && arrayZ->sanitize (c)); + (void) (false && arrayZ[0].sanitize (c)); + return_trace (true); + } + inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c, count))) return_trace (false); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!arrayZ[i].sanitize (c, base))) + return_trace (false); + return_trace (true); + } + template <typename T> + inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c, count))) return_trace (false); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!arrayZ[i].sanitize (c, base, user_data))) + return_trace (false); + return_trace (true); + } + + private: + inline bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const + { + TRACE_SANITIZE (this); return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count)); } @@ -170,6 +197,32 @@ struct UnsizedArrayOf DEFINE_SIZE_ARRAY (0, arrayZ); }; +/* Unsized array of offset's */ +template <typename Type, typename OffsetType> +struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType> > {}; + +/* Unsized array of offsets relative to the beginning of the array itself. */ +template <typename Type, typename OffsetType> +struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType> +{ + inline const Type& operator [] (unsigned int i) const + { + return this+this->arrayZ[i]; + } + + inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const + { + TRACE_SANITIZE (this); + return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this))); + } + template <typename T> + inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const + { + TRACE_SANITIZE (this); + return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this, user_data))); + } +}; + /* * Lookup Table @@ -507,10 +560,9 @@ struct StateTable return &entries[entry]; /* XXX bound check. */ } - inline bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (true); return_trace (c->check_struct (this)); /* XXX */ } diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 86e78b54..6c9c5154 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -42,11 +42,17 @@ using namespace OT; template <typename Types> struct RearrangementSubtable { - enum { - MarkFirst = 0x8000, - DontAdvance = 0x4000, - MarkLast = 0x2000, - Verb = 0x000F, + enum Flags { + MarkFirst = 0x8000, /* If set, make the current glyph the first + * glyph to be rearranged. */ + DontAdvance = 0x4000, /* If set, don't advance to the next glyph + * before going to the new state. This means + * that the glyph index doesn't change, even + * if the glyph at that index has changed. */ + MarkLast = 0x2000, /* If set, make the current glyph the last + * glyph to be rearranged. */ + Reserved = 0x1FF0, /* These bits are reserved and should be set to 0. */ + Verb = 0x000F, /* The type of rearrangement specified. */ }; inline bool apply (hb_apply_context_t *c) const @@ -161,7 +167,7 @@ struct RearrangementSubtable inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (machine.sanitize (c, 0/*XXX*/)); + return_trace (machine.sanitize (c)); } protected: @@ -170,8 +176,27 @@ struct RearrangementSubtable DEFINE_SIZE_MIN (2); }; +template <typename Types> struct ContextualSubtable { + typedef typename Types::HBUINT HBUINT; + + enum Flags { + SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */ + DontAdvance = 0x4000, /* If set, don't advance to the next glyph before + * going to the new state. */ + Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */ + }; + + /* XXX the following is different in mort: it's directly index to sublookups. */ + struct EntryData + { + HBUINT16 markIndex; /* Index of the substitution table for the + * marked glyph (use 0xFFFF for none). */ + HBUINT16 currentIndex; /* Index of the substitution table for the + * current glyph (use 0xFFFF for none). */ + }; + inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); @@ -182,11 +207,19 @@ struct ContextualSubtable inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - /* TODO */ - return_trace (false); + return_trace (machine.sanitize (c) && + substitutionTables.sanitize (c, this, 0U/*XXX count*/)); } + + protected: + StateTable<Types, EntryData> machine; + OffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT>, HBUINT> + substitutionTables; + public: + DEFINE_SIZE_MIN (2); }; +template <typename Types> struct LigatureSubtable { inline bool apply (hb_apply_context_t *c) const @@ -204,6 +237,7 @@ struct LigatureSubtable } }; +template <typename Types> struct NoncontextualSubtable { inline bool apply (hb_apply_context_t *c) const @@ -240,6 +274,7 @@ struct NoncontextualSubtable DEFINE_SIZE_MIN (2); }; +template <typename Types> struct InsertionSubtable { inline bool apply (hb_apply_context_t *c) const @@ -334,12 +369,11 @@ struct ChainSubtable HBUINT coverage; /* Coverage flags and subtable type. */ HBUINT32 subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */ union { - RearrangementSubtable<Types> - rearrangement; - ContextualSubtable contextual; - LigatureSubtable ligature; - NoncontextualSubtable noncontextual; - InsertionSubtable insertion; + RearrangementSubtable<Types> rearrangement; + ContextualSubtable<Types> contextual; + LigatureSubtable<Types> ligature; + NoncontextualSubtable<Types> noncontextual; + InsertionSubtable<Types> insertion; } u; public: DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4); @@ -455,8 +489,22 @@ struct mortmorx DEFINE_SIZE_MIN (8); }; +struct MortTypes +{ + static const bool extended = false; + typedef HBUINT16 HBUINT; + typedef HBUINT8 HBUSHORT; + struct ClassType : ClassTable + { + inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs HB_UNUSED) const + { + return ClassTable::get_class (glyph_id); + } + }; +}; struct MorxTypes { + static const bool extended = true; typedef HBUINT32 HBUINT; typedef HBUINT16 HBUSHORT; struct ClassType : Lookup<HBUINT16> @@ -468,18 +516,6 @@ struct MorxTypes } }; }; -struct MortTypes -{ - typedef HBUINT16 HBUINT; - typedef HBUINT8 HBUSHORT; - struct ClassType : ClassTable - { - inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs HB_UNUSED) const - { - return ClassTable::get_class (glyph_id); - } - }; -}; struct mort : mortmorx<MortTypes> { commit 62348f647f7b1604e008dbed46a54eff245fc106 Author: Behdad Esfahbod <[email protected]> Date: Thu Jan 11 12:00:28 2018 +0100 [aat] Implement end-of-text in state machine Passes MORX-10 test now. diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 520ae752..86e78b54 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -65,12 +65,14 @@ struct RearrangementSubtable hb_glyph_info_t *info = c->buffer->info; unsigned int count = c->buffer->len; - for (unsigned int i = 0; i < count; i++) + for (unsigned int i = 0; i <= count; i++) { if (!state) last_zero = i; - unsigned int klass = machine.get_class (info[i].codepoint, num_glyphs); + unsigned int klass = i < count ? + machine.get_class (info[i].codepoint, num_glyphs) : + 0 /* End of text */; const Entry<void> *entry = machine.get_entry (state, klass); if (unlikely (!entry)) break; @@ -83,7 +85,7 @@ struct RearrangementSubtable last_zero_before_start = last_zero; } - if (flags & MarkLast) + if (flags & MarkLast && i < count) end = i + 1; if ((flags & Verb) && start < end) @@ -120,7 +122,7 @@ struct RearrangementSubtable if (end - start >= l + r) { - c->buffer->unsafe_to_break (last_zero_before_start, i + 1); + c->buffer->unsafe_to_break (last_zero_before_start, MIN (i + 1, count)); c->buffer->merge_clusters (start, end); hb_glyph_info_t buf[4]; commit fc405b7ca77088135cb7de11cb32c254b85272fd Author: Behdad Esfahbod <[email protected]> Date: Thu Jan 11 11:55:29 2018 +0100 [test/text-rendering-tests] Update from upstream diff --git a/test/shaping/data/text-rendering-tests/DISABLED b/test/shaping/data/text-rendering-tests/DISABLED index 7d63246c..0e1b89b3 100644 --- a/test/shaping/data/text-rendering-tests/DISABLED +++ b/test/shaping/data/text-rendering-tests/DISABLED @@ -11,6 +11,7 @@ tests/MORX-6.tests tests/MORX-7.tests tests/MORX-8.tests tests/MORX-9.tests +tests/MORX-10.tests # Rounding differences tests/SHARAN-1.tests diff --git a/test/shaping/data/text-rendering-tests/Makefile.sources b/test/shaping/data/text-rendering-tests/Makefile.sources index 913d4195..8e0f4318 100644 --- a/test/shaping/data/text-rendering-tests/Makefile.sources +++ b/test/shaping/data/text-rendering-tests/Makefile.sources @@ -28,11 +28,7 @@ TESTS = \ tests/HVAR-2.tests \ tests/KERN-1.tests \ tests/KERN-2.tests \ - tests/MORX-5.tests \ - tests/MORX-6.tests \ - tests/MORX-7.tests \ - tests/MORX-8.tests \ - tests/MORX-9.tests \ + tests/MORX-10.tests \ tests/SHBALI-3.tests \ tests/SHKNDA-1.tests \ $(NULL) @@ -43,6 +39,11 @@ DISBALED_TESTS = \ tests/MORX-2.tests \ tests/MORX-3.tests \ tests/MORX-4.tests \ + tests/MORX-5.tests \ + tests/MORX-6.tests \ + tests/MORX-7.tests \ + tests/MORX-8.tests \ + tests/MORX-9.tests \ tests/SHARAN-1.tests \ tests/SHBALI-1.tests \ tests/SHBALI-2.tests \ diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXTen.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXTen.ttf new file mode 100644 index 00000000..5827ec5a Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXTen.ttf differ diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-10.tests b/test/shaping/data/text-rendering-tests/tests/MORX-10.tests new file mode 100644 index 00000000..a6a5444f --- /dev/null +++ b/test/shaping/data/text-rendering-tests/tests/MORX-10.tests @@ -0,0 +1 @@ +../fonts/TestMORXTen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0041,U+0042,U+0041,U+0042:[A|B@638,0|A@1288,0|B@1926,0|B@2576,0|A@3226,0] commit 9adbd938fafe1de4e279489fc37ae33c900e22f0 Author: Behdad Esfahbod <[email protected]> Date: Thu Jan 11 11:55:10 2018 +0100 Minor diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 8c62b174..520ae752 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -147,7 +147,7 @@ struct RearrangementSubtable } } - if (false/* XXX*/ && flags & DontAdvance) + if (false/* XXX */ && flags & DontAdvance) i--; /* XXX Detect infinite loop. */ state = entry->newState; commit 4177f646aa60180f094e064a53e54c5402fe53c6 Author: Ebrahim Byagowi <[email protected]> Date: Thu Jan 11 15:43:23 2018 +0330 [cmake] Update and unbreak (#700) diff --git a/test/shaping/CMakeLists.txt b/test/shaping/CMakeLists.txt index b79d5328..4bdc5c9e 100644 --- a/test/shaping/CMakeLists.txt +++ b/test/shaping/CMakeLists.txt @@ -1,5 +1,5 @@ if (HB_BUILD_UTILS) - file (READ "${CMAKE_CURRENT_SOURCE_DIR}/data/in-house/Makefile.am" INHOUSE) + file (READ "${CMAKE_CURRENT_SOURCE_DIR}/data/in-house/Makefile.sources" INHOUSE) extract_make_variable (TESTS ${INHOUSE}) foreach (test IN ITEMS ${TESTS}) add_test (NAME ${test} @@ -7,7 +7,7 @@ if (HB_BUILD_UTILS) WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endforeach () - file (READ "${CMAKE_CURRENT_SOURCE_DIR}/data/text-rendering-tests/Makefile.am" TEXTRENDERING) + file (READ "${CMAKE_CURRENT_SOURCE_DIR}/data/text-rendering-tests/Makefile.sources" TEXTRENDERING) extract_make_variable (TESTS ${TEXTRENDERING}) foreach (test IN ITEMS ${TESTS}) add_test (NAME ${test} _______________________________________________ HarfBuzz mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/harfbuzz
