From 041a08de3d0ca74d3e2fdccfa5311ff26a8b97e4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Sep 2018 16:02:56 -0400 Subject: [PATCH 01/23] [morx] Improve buffer position in Insertion w DontAdvance and wo Just speculation. Needs tests to determine which is correct behavior. --- src/hb-aat-layout-morx-table.hh | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 5d3b9b14a..03f310243 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -610,12 +610,12 @@ struct InsertionSubtable if (entry->data.markedInsertIndex != 0xFFFF) { - unsigned int count = (entry->flags & MarkedInsertCount); + unsigned int count = (flags & MarkedInsertCount); unsigned int start = entry->data.markedInsertIndex; const GlyphID *glyphs = &insertionAction[start]; if (unlikely (!c->sanitizer.check_array (glyphs, count))) return false; - bool before = entry->flags & MarkedInsertBefore; + bool before = flags & MarkedInsertBefore; if (unlikely (!mark_set)) return false; @@ -635,12 +635,12 @@ struct InsertionSubtable if (entry->data.currentInsertIndex != 0xFFFF) { - unsigned int count = (entry->flags & CurrentInsertCount) >> 5; + unsigned int count = (flags & CurrentInsertCount) >> 5; unsigned int start = entry->data.currentInsertIndex; const GlyphID *glyphs = &insertionAction[start]; if (unlikely (!c->sanitizer.check_array (glyphs, count))) return false; - bool before = entry->flags & CurrentInsertBefore; + bool before = flags & CurrentInsertBefore; unsigned int end = buffer->out_len; @@ -652,7 +652,20 @@ struct InsertionSubtable if (!before) buffer->skip_glyph (); - buffer->move_to (end); + /* Humm. Not sure where to move to. There's this wording under + * DontAdvance flag: + * + * "If set, don't update the glyph index before going to the new state. + * This does not mean that the glyph pointed to is the same one as + * before. If you've made insertions immediately downstream of the + * current glyph, the next glyph processed would in fact be the first + * one inserted." + * + * This suggests that if DontAdvance is NOT set, we should move to + * end+count. If it *was*, then move to end, such that newly inserted + * glyphs are now visible. + */ + buffer->move_to ((flags & DontAdvance) ? end : end + count); } if (flags & SetMark) From 3bccd62196b5dff70d446c3fe053b1b47bb9c19e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Sep 2018 16:24:34 -0400 Subject: [PATCH 02/23] [morx] Implement horiz-only/vert-only subtables --- src/hb-aat-layout-morx-table.hh | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 03f310243..03bb4d531 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -743,8 +743,25 @@ struct ChainSubtable friend struct Chain; inline unsigned int get_size (void) const { return length; } - inline unsigned int get_type (void) const { return coverage & 0xFF; } + inline unsigned int get_type (void) const { return coverage & SubtableType; } + enum Coverage + { + Vertical = 0x80000000, /* If set, this subtable will only be applied + * to vertical text. If clear, this subtable + * will only be applied to horizontal text. */ + Descending = 0x40000000, /* If set, this subtable will process glyphs + * in descending order. If clear, it will + * process the glyphs in ascending order. */ + AllDirections = 0x20000000, /* If set, this subtable will be applied to + * both horizontal and vertical text (i.e. + * the state of bit 0x80000000 is ignored). */ + Logical = 0x10000000, /* If set, this subtable will process glyphs + * in logical order (or reverse logical order, + * depending on the value of bit 0x80000000). */ + Reserved = 0x0FFFFF00, /* Reserved, set to zero. */ + SubtableType = 0x000000FF, /* Subtable type; see following table. */ + }; enum Type { Rearrangement = 0, @@ -822,6 +839,11 @@ struct Chain if (!(subtable->subFeatureFlags & flags)) goto skip; + if (!(subtable->coverage & ChainSubtable::AllDirections) && + HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) != + bool (subtable->coverage & ChainSubtable::Vertical)) + goto skip; + if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index)) goto skip; From dc8ed45292ce4e522c3bda03fd83873da7b6591e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Sep 2018 16:46:41 -0400 Subject: [PATCH 03/23] [morx] Implement forward/backward processing We reverse too many times. Can be optimized. But I doubt many fonts use reverse lookups, so doesn't matter. Other than not applying user features, this completes morx table implementation. --- src/hb-aat-layout-morx-table.hh | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 03bb4d531..0a2d62b56 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -836,6 +836,8 @@ struct Chain unsigned int count = subtableCount; for (unsigned int i = 0; i < count; i++) { + bool reverse; + if (!(subtable->subFeatureFlags & flags)) goto skip; @@ -844,11 +846,49 @@ struct Chain bool (subtable->coverage & ChainSubtable::Vertical)) goto skip; + /* Buffer contents is always in logical direction. Determine if + * we need to reverse before applying this subtable. We reverse + * back after if we did reverse indeed. + * + * Quoting the spac: + * """ + * Bits 28 and 30 of the coverage field control the order in which + * glyphs are processed when the subtable is run by the layout engine. + * Bit 28 is used to indicate if the glyph processing direction is + * the same as logical order or layout order. Bit 30 is used to + * indicate whether glyphs are processed forwards or backwards within + * that order. + + Bit 30 Bit 28 Interpretation for Horizontal Text + 0 0 The subtable is processed in layout order + (the same order as the glyphs, which is + always left-to-right). + 1 0 The subtable is processed in reverse layout order + (the order opposite that of the glyphs, which is + always right-to-left). + 0 1 The subtable is processed in logical order + (the same order as the characters, which may be + left-to-right or right-to-left). + 1 1 The subtable is processed in reverse logical order + (the order opposite that of the characters, which + may be right-to-left or left-to-right). + */ + reverse = subtable->coverage & ChainSubtable::Logical ? + bool (subtable->coverage & ChainSubtable::Descending) : + bool (subtable->coverage & ChainSubtable::Descending) != + HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction); + if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index)) goto skip; + if (reverse) + c->buffer->reverse (); + subtable->dispatch (c); + if (reverse) + c->buffer->reverse (); + (void) c->buffer->message (c->font, "end chain subtable %d", c->lookup_index); skip: From 7671cb9b04770d50b1b2a05a24f6fadc35993cd1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Sep 2018 17:10:26 -0400 Subject: [PATCH 04/23] [coretext] Minor --- src/hb-coretext.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index a7ba85f83..f921e3a02 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -515,12 +515,14 @@ struct range_record_t { #define kUpperCaseType 38 /* Table data courtesy of Apple. */ -static const struct feature_mapping_t { - FourCharCode otFeatureTag; +static const struct feature_mapping_t +{ + hb_tag_t otFeatureTag; uint16_t aatFeatureType; uint16_t selectorToEnable; uint16_t selectorToDisable; -} feature_mappings[] = { +} feature_mappings[] = +{ { 'c2pc', kUpperCaseType, kUpperCasePetiteCapsSelector, kDefaultUpperCaseSelector }, { 'c2sc', kUpperCaseType, kUpperCaseSmallCapsSelector, kDefaultUpperCaseSelector }, { 'calt', kContextualAlternatesType, kContextualAlternatesOnSelector, kContextualAlternatesOffSelector }, @@ -601,7 +603,7 @@ static const struct feature_mapping_t { static int _hb_feature_mapping_cmp (const void *key_, const void *entry_) { - unsigned int key = * (unsigned int *) key_; + hb_tag_t key = * (unsigned int *) key_; const feature_mapping_t * entry = (const feature_mapping_t *) entry_; return key < entry->otFeatureTag ? -1 : key > entry->otFeatureTag ? 1 : From 0739b28169eb63332b31420deb5bf58b5446f154 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Sep 2018 17:32:21 -0400 Subject: [PATCH 05/23] [aat] Minor --- src/hb-aat-layout-common.hh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 57374b0bc..052aad7fc 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -569,7 +569,8 @@ struct StateTableDriver /* If there's no action and we're just epsilon-transitioning to state 0, * safe to break. */ if (c->is_actionable (this, entry) || - !(entry->newState == 0 && entry->flags == context_t::DontAdvance)) + !(entry->newState == StateTable::STATE_START_OF_TEXT && + entry->flags == context_t::DontAdvance)) buffer->unsafe_to_break (buffer->idx - 1, buffer->idx + 1); } From 5fd8bce945e7efaa48d0c29eb8b2700027bd3c0b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Sep 2018 22:34:09 -0400 Subject: [PATCH 06/23] [morx] Fix mark_set check --- src/hb-aat-layout-morx-table.hh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 0a2d62b56..a8b287fde 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -608,7 +608,7 @@ struct InsertionSubtable hb_buffer_t *buffer = driver->buffer; unsigned int flags = entry->flags; - if (entry->data.markedInsertIndex != 0xFFFF) + if (entry->data.markedInsertIndex != 0xFFFF && mark_set) { unsigned int count = (flags & MarkedInsertCount); unsigned int start = entry->data.markedInsertIndex; @@ -617,8 +617,6 @@ struct InsertionSubtable bool before = flags & MarkedInsertBefore; - if (unlikely (!mark_set)) return false; - unsigned int end = buffer->out_len; buffer->move_to (mark); From ef9307fd2227bf0f750d8f7fafae466affc81454 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 22 Sep 2018 16:45:31 +0330 Subject: [PATCH 07/23] Fix test-font leak issue See also https://github.com/harfbuzz/harfbuzz/pull/1169 --- test/api/test-font.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/api/test-font.c b/test/api/test-font.c index 527dfcdc1..4a2393ec6 100644 --- a/test/api/test-font.c +++ b/test/api/test-font.c @@ -361,6 +361,7 @@ test_fontfuncs_subclassing (void) hb_font_destroy (font3); + hb_font_destroy (font2); } From 669ac81ac52e9d559324db851a9ee46ef651e7b0 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 22 Sep 2018 16:49:23 +0330 Subject: [PATCH 08/23] Fix test-set leak issue See also https://github.com/harfbuzz/harfbuzz/pull/1169 --- test/api/test-set.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/api/test-set.c b/test/api/test-set.c index 338a610c9..eb2f22ece 100644 --- a/test/api/test-set.c +++ b/test/api/test-set.c @@ -262,6 +262,7 @@ test_set_algebra (void) hb_set_destroy (s); hb_set_destroy (o); + hb_set_destroy (o2); } static void From f6ebe1f4dc95a7c4b3a0af23086873a11867c1d9 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 22 Sep 2018 17:05:52 +0330 Subject: [PATCH 09/23] Fix test-ot-math leak issue See also https://github.com/harfbuzz/harfbuzz/pull/1169 --- test/api/test-ot-math.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index d071c8895..7f500157e 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -100,10 +100,14 @@ test_has_data (void) hb_face = hb_face_get_empty (); hb_font = hb_font_create (hb_face); g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available + hb_font_destroy (hb_font); + hb_face_destroy (hb_face); hb_font = hb_font_get_empty (); hb_face = hb_font_get_face (hb_font); g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available + hb_font_destroy (hb_font); + hb_face_destroy (hb_face); cleanupFreeType(); } From 403019482b0d7f17fbdb5def2be5f43e28bafcf3 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 22 Sep 2018 17:24:03 +0330 Subject: [PATCH 10/23] Fix test-subset-* leak issues See also https://github.com/harfbuzz/harfbuzz/pull/1169 --- test/api/hb-subset-test.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/api/hb-subset-test.h b/test/api/hb-subset-test.h index afd553a0d..0318fa7bb 100644 --- a/test/api/hb-subset-test.h +++ b/test/api/hb-subset-test.h @@ -51,12 +51,18 @@ static inline hb_face_t * hb_subset_test_open_font (const char *font_path) { #if GLIB_CHECK_VERSION(2,37,2) - char* path = g_test_build_filename(G_TEST_DIST, font_path, NULL); + char* path = g_test_build_filename (G_TEST_DIST, font_path, NULL); #else - char* path = g_strdup(font_path); + char* path = g_strdup (font_path); #endif - return hb_face_create (hb_blob_create_from_file (path), 0); + hb_blob_t* blob = hb_blob_create_from_file (path); + hb_face_t* face = hb_face_create (blob, 0); + hb_blob_destroy (blob); + + g_free (path); + + return face; } static inline hb_subset_input_t * From b7f1bbc2f8b14a402fa9e42e88919dc0173373ce Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sat, 22 Sep 2018 16:41:56 +0200 Subject: [PATCH 11/23] [test] Fix printing subprocess error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decode the string as Python 3 returns bytes string, and also don’t assume that it ends with a new line. --- test/shaping/run-tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/shaping/run-tests.py b/test/shaping/run-tests.py index 73b61c21a..915536b97 100755 --- a/test/shaping/run-tests.py +++ b/test/shaping/run-tests.py @@ -9,7 +9,7 @@ def cmd(command): p = subprocess.Popen ( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p.wait () - print (p.stderr.read (), end="") # file=sys.stderr + print (p.stderr.read ().decode ("utf-8").strip ()) # file=sys.stderr return p.stdout.read ().decode ("utf-8").strip (), p.returncode From 24dd6c1a9d8d571c30dce4d39c1975b1d1cedc2a Mon Sep 17 00:00:00 2001 From: Matt Oliver Date: Sun, 23 Sep 2018 18:08:30 +1000 Subject: [PATCH 12/23] src/hb-blob.cc: Fix mmap functionality with UWP. --- src/hb-blob.cc | 27 +++++++++++++++++++++++++++ src/hb.hh | 4 +++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/hb-blob.cc b/src/hb-blob.cc index a335df308..fca3c910b 100644 --- a/src/hb-blob.cc +++ b/src/hb-blob.cc @@ -574,18 +574,45 @@ fail_without_close: wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size); if (unlikely (wchar_file_name == nullptr)) goto fail_without_close; mbstowcs (wchar_file_name, file_name, size); +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) + { + CREATEFILE2_EXTENDED_PARAMETERS ceparams = { 0 }; + ceparams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + ceparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0xFFFF; + ceparams.dwFileFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0xFFF00000; + ceparams.dwSecurityQosFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0x000F0000; + ceparams.lpSecurityAttributes = nullptr; + ceparams.hTemplateFile = nullptr; + fd = CreateFile2 (wchar_file_name, GENERIC_READ, FILE_SHARE_READ, + OPEN_EXISTING, &ceparams); + } +#else fd = CreateFileW (wchar_file_name, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, nullptr); +#endif free (wchar_file_name); if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close; +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) + { + LARGE_INTEGER length; + GetFileSizeEx (fd, &length); + file->length = length.LowPart; + file->mapping = CreateFileMappingFromApp (fd, nullptr, PAGE_READONLY, length.QuadPart, nullptr); + } +#else file->length = (unsigned long) GetFileSize (fd, nullptr); file->mapping = CreateFileMapping (fd, nullptr, PAGE_READONLY, 0, 0, nullptr); +#endif if (unlikely (file->mapping == nullptr)) goto fail; +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) + file->contents = (char *) MapViewOfFileFromApp (file->mapping, FILE_MAP_READ, 0, 0); +#else file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0); +#endif if (unlikely (file->contents == nullptr)) goto fail; CloseHandle (fd); diff --git a/src/hb.hh b/src/hb.hh index 557ae6b35..631592def 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -237,7 +237,9 @@ struct _hb_alignof # undef _WIN32_WINNT # endif # ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0600 +# if !defined(WINAPI_FAMILY) || !(WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) +# define _WIN32_WINNT 0x0600 +# endif # endif # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN 1 From ae39a53f55e6b812defb4c7b48562651c9eb13a3 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 22 Sep 2018 14:22:17 +0330 Subject: [PATCH 13/23] Add bots with address- and thread-sanitizer --- .circleci/config.yml | 52 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5ad1ae135..671f49d78 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -79,6 +79,54 @@ jobs: - run: make - run: LD_LIBRARY_PATH="$PWD/freetype-2.9/objs/.libs" make check || .ci/fail.sh + clang-asan: + docker: + - image: ubuntu:18.04 + steps: + - checkout + - run: apt update || true + - run: apt install -y clang-6.0 binutils libtool autoconf automake make pkg-config gtk-doc-tools ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip + - run: pip install fonttools + - run: CPPFLAGS="-fsanitize=address" LDFLAGS="-fsanitize=address" CC=clang-6.0 CXX=clang++-6.0 ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2 + - run: make + - run: make check || .ci/fail.sh + + clang-msan: + docker: + - image: ubuntu:18.04 + steps: + - checkout + - run: apt update || true + - run: apt install -y clang-6.0 binutils libtool autoconf automake make pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip + - run: pip install fonttools + - run: CPPFLAGS="-fsanitize=memory" LDFLAGS="-fsanitize=memory" CC=clang-6.0 CXX=clang++-6.0 ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2 + - run: make + - run: make check || .ci/fail.sh + + clang-tsan: + docker: + - image: ubuntu:18.04 + steps: + - checkout + - run: apt update || true + - run: apt install -y clang-6.0 binutils libtool autoconf automake make pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip + - run: pip install fonttools + - run: CPPFLAGS="-fsanitize=thread" LDFLAGS="-fsanitize=thread" CC=clang-6.0 CXX=clang++-6.0 ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2 + - run: make + - run: make check || .ci/fail.sh + + clang-ubsan: + docker: + - image: ubuntu:18.04 + steps: + - checkout + - run: apt update || true + - run: apt install -y clang-6.0 binutils libtool autoconf automake make pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip + - run: pip install fonttools + - run: CPPFLAGS="-fsanitize=undefined" LDFLAGS="-fsanitize=undefined" CC=clang-6.0 CXX=clang++-6.0 ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2 + - run: make + - run: make check || .ci/fail.sh + fedora-outoftreebuild: docker: - image: fedora @@ -200,6 +248,10 @@ workflows: - alpine-O3-NOMMAP - archlinux-debug-O0-py3 - clang-O3-O0 + - clang-asan + - clang-msan + - clang-tsan + - clang-ubsan - fedora-outoftreebuild # cmake based builds From d7f21777e6a797758ab234555f5f7e07c87278f9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 23 Sep 2018 19:12:52 -0400 Subject: [PATCH 14/23] [ot-font] Fix leak Fixes https://github.com/harfbuzz/harfbuzz/issues/1171 I'm glad we have leak-detector bots now. --- src/hb-ot-post-table.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh index 5f27fd504..f81de37d5 100644 --- a/src/hb-ot-post-table.hh +++ b/src/hb-ot-post-table.hh @@ -131,6 +131,7 @@ struct post { index_to_offset.fini (); free (gids_sorted_by_name.get ()); + hb_blob_destroy (blob); } inline bool get_glyph_name (hb_codepoint_t glyph, From 62d1e0852a5549a1b510ad46a4b89f12730bb708 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 23 Sep 2018 21:32:18 -0400 Subject: [PATCH 15/23] Prefer decomposed form if font has GPOS mark feature Fixes https://github.com/harfbuzz/harfbuzz/issues/653 --- src/hb-ot-shape-complex-hebrew.cc | 2 +- src/hb-ot-shape-normalize.cc | 126 ++++++++++++++++-------------- src/hb-ot-shape-normalize.hh | 7 +- 3 files changed, 72 insertions(+), 63 deletions(-) diff --git a/src/hb-ot-shape-complex-hebrew.cc b/src/hb-ot-shape-complex-hebrew.cc index ba25258a3..5ad8daf77 100644 --- a/src/hb-ot-shape-complex-hebrew.cc +++ b/src/hb-ot-shape-complex-hebrew.cc @@ -70,7 +70,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c, bool found = (bool) c->unicode->compose (a, b, ab); - if (!found && !c->plan->has_mark) + if (!found) { /* Special-case Hebrew presentation forms that are excluded from * standard normalization, but wanted for old fonts. */ diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index fd0b63aec..487fd96a7 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -294,6 +294,14 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, _hb_buffer_assert_unicode_vars (buffer); hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference; + if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_AUTO) + { + if (plan->has_mark) + mode = HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED; + else + mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS; + } + const hb_ot_shape_normalize_context_t c = { plan, buffer, @@ -358,65 +366,6 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, i = end; } - - - if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE || - mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED) - return; - - /* Third round, recompose */ - - /* As noted in the comment earlier, we don't try to combine - * ccc=0 chars with their previous Starter. */ - - buffer->clear_output (); - count = buffer->len; - unsigned int starter = 0; - buffer->next_glyph (); - while (buffer->idx < count && buffer->successful) - { - hb_codepoint_t composed, glyph; - if (/* We don't try to compose a non-mark character with it's preceding starter. - * This is both an optimization to avoid trying to compose every two neighboring - * glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul - * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */ - HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur()))) - { - if (/* If there's anything between the starter and this char, they should have CCC - * smaller than this character's. */ - (starter == buffer->out_len - 1 || - info_cc (buffer->prev()) < info_cc (buffer->cur())) && - /* And compose. */ - c.compose (&c, - buffer->out_info[starter].codepoint, - buffer->cur().codepoint, - &composed) && - /* And the font has glyph for the composite. */ - font->get_nominal_glyph (composed, &glyph)) - { - /* Composes. */ - buffer->next_glyph (); /* Copy to out-buffer. */ - if (unlikely (!buffer->successful)) - return; - buffer->merge_out_clusters (starter, buffer->out_len); - buffer->out_len--; /* Remove the second composable. */ - /* Modify starter and carry on. */ - buffer->out_info[starter].codepoint = composed; - buffer->out_info[starter].glyph_index() = glyph; - _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); - - continue; - } - } - - /* Blocked, or doesn't compose. */ - buffer->next_glyph (); - - if (info_cc (buffer->prev()) == 0) - starter = buffer->out_len - 1; - } - buffer->swap_buffers (); - if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_CGJ) { /* For all CGJ, check if it prevented any reordering at all. @@ -430,4 +379,63 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, _hb_glyph_info_unhide (&buffer->info[i]); } } + + + /* Third round, recompose */ + + if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS || + mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT) + return; + { + /* As noted in the comment earlier, we don't try to combine + * ccc=0 chars with their previous Starter. */ + + buffer->clear_output (); + count = buffer->len; + unsigned int starter = 0; + buffer->next_glyph (); + while (buffer->idx < count && buffer->successful) + { + hb_codepoint_t composed, glyph; + if (/* We don't try to compose a non-mark character with it's preceding starter. + * This is both an optimization to avoid trying to compose every two neighboring + * glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul + * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */ + HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur()))) + { + if (/* If there's anything between the starter and this char, they should have CCC + * smaller than this character's. */ + (starter == buffer->out_len - 1 || + info_cc (buffer->prev()) < info_cc (buffer->cur())) && + /* And compose. */ + c.compose (&c, + buffer->out_info[starter].codepoint, + buffer->cur().codepoint, + &composed) && + /* And the font has glyph for the composite. */ + font->get_nominal_glyph (composed, &glyph)) + { + /* Composes. */ + buffer->next_glyph (); /* Copy to out-buffer. */ + if (unlikely (!buffer->successful)) + return; + buffer->merge_out_clusters (starter, buffer->out_len); + buffer->out_len--; /* Remove the second composable. */ + /* Modify starter and carry on. */ + buffer->out_info[starter].codepoint = composed; + buffer->out_info[starter].glyph_index() = glyph; + _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); + + continue; + } + } + + /* Blocked, or doesn't compose. */ + buffer->next_glyph (); + + if (info_cc (buffer->prev()) == 0) + starter = buffer->out_len - 1; + } + buffer->swap_buffers (); + } } diff --git a/src/hb-ot-shape-normalize.hh b/src/hb-ot-shape-normalize.hh index 4aea640b1..80755f775 100644 --- a/src/hb-ot-shape-normalize.hh +++ b/src/hb-ot-shape-normalize.hh @@ -38,10 +38,11 @@ struct hb_ot_shape_plan_t; enum hb_ot_shape_normalization_mode_t { HB_OT_SHAPE_NORMALIZATION_MODE_NONE, HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED, - HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */ - HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* always fully decomposes and then recompose back */ + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* Never composes base-to-base */ + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* Always fully decomposes and then recompose back */ - HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS + HB_OT_SHAPE_NORMALIZATION_MODE_AUTO, /* Choose decomposed if GPOS mark feature available, compose otherwise. */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_AUTO }; HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper, From 9516cbd3df7ccdb40b27a7ba99a1e0da8a6b170c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 23 Sep 2018 22:00:34 -0400 Subject: [PATCH 16/23] Reinit skippy iters when auto_zwj / auto_zwnj change Ouch. How did we not hit this bug before... --- src/hb-ot-layout-gsubgpos.hh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index ff9783edc..6ff19e232 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -508,19 +508,20 @@ struct hb_ot_apply_context_t : random (false), random_state (1) {} - inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } - inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } - inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; } - inline void set_random (bool random_) { random = random_; } - inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } - inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; } - inline void set_lookup_props (unsigned int lookup_props_) + inline void reinit_iters (void) { - lookup_props = lookup_props_; iter_input.init (this, false); iter_context.init (this, true); } + inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } + inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; reinit_iters (); } + inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; reinit_iters (); } + inline void set_random (bool random_) { random = random_; } + inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } + inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; } + inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; reinit_iters (); } + inline uint32_t random_number (void) { /* http://www.cplusplus.com/reference/random/minstd_rand/ */ From 3583fb03b14a10ec5ab5f9c480e150934101fd0b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 23 Sep 2018 22:33:38 -0400 Subject: [PATCH 17/23] Simplify ZWJ-skipping a bit Towards disabling ZWJ-skipping in certain GPOS contexts. Part of https://github.com/flutter/flutter/issues/16886 --- src/hb-ot-layout-gsubgpos.hh | 6 +++--- src/hb-ot-shape-complex-indic.cc | 21 ++++++++++++++++----- src/hb-ot-shape-complex-khmer.cc | 21 ++++++++++++++------- src/hb-ot-shape-complex-myanmar.cc | 15 ++++++++++++++- src/hb-ot-shape-complex-use.cc | 15 +++++++++++++-- 5 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 6ff19e232..031b39b9b 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -344,10 +344,10 @@ struct hb_ot_apply_context_t : match_glyph_data = nullptr; matcher.set_match_func (nullptr, nullptr); matcher.set_lookup_props (c->lookup_props); - /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ + /* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */ matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj)); - /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */ - matcher.set_ignore_zwj (c->table_index == 1 || (context_match || c->auto_zwj)); + /* Ignore ZWJ if we are matching context, or asked to. */ + matcher.set_ignore_zwj (context_match || c->auto_zwj); matcher.set_mask (context_match ? -1 : c->lookup_mask); } inline void set_lookup_props (unsigned int lookup_props) diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 369078cb2..c1aa1d0fe 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -95,7 +95,8 @@ static const indic_config_t indic_configs[] = * Indic shaper. */ -struct feature_list_t { +struct feature_list_t +{ hb_tag_t tag; hb_ot_map_feature_flags_t flags; }; @@ -130,7 +131,10 @@ indic_features[] = {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. */ + /* + * Positioning features. + * We don't care about the types. + */ {HB_TAG('d','i','s','t'), F_GLOBAL}, {HB_TAG('a','b','v','m'), F_GLOBAL}, {HB_TAG('b','l','w','m'), F_GLOBAL}, @@ -158,12 +162,14 @@ enum { _BLWS, _PSTS, _HALN, + _DIST, _ABVM, _BLWM, INDIC_NUM_FEATURES, - INDIC_BASIC_FEATURES = INIT /* Don't forget to update this! */ + INDIC_BASIC_FEATURES = INIT, /* Don't forget to update this! */ + INDIC_SUBST_FEATURES = _DIST /* Don't forget to update this! */ }; static void @@ -199,14 +205,19 @@ collect_features_indic (hb_ot_shape_planner_t *plan) unsigned int i = 0; map->add_gsub_pause (initial_reordering); + for (; i < INDIC_BASIC_FEATURES; i++) { map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); map->add_gsub_pause (nullptr); } + map->add_gsub_pause (final_reordering); - for (; i < INDIC_NUM_FEATURES; i++) { + + for (; i < INDIC_SUBST_FEATURES; i++) map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); - } + + for (; i < INDIC_NUM_FEATURES; i++) + map->add_feature (indic_features[i].tag, 1, indic_features[i].flags); map->add_global_bool_feature (HB_TAG('c','a','l','t')); map->add_global_bool_feature (HB_TAG('c','l','i','g')); diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc index 0b5b50a97..7a88aaa25 100644 --- a/src/hb-ot-shape-complex-khmer.cc +++ b/src/hb-ot-shape-complex-khmer.cc @@ -32,7 +32,8 @@ * Khmer shaper. */ -struct feature_list_t { +struct feature_list_t +{ hb_tag_t tag; hb_ot_map_feature_flags_t flags; }; @@ -57,7 +58,10 @@ khmer_features[] = {HB_TAG('a','b','v','s'), F_GLOBAL}, {HB_TAG('b','l','w','s'), F_GLOBAL}, {HB_TAG('p','s','t','s'), F_GLOBAL}, - /* Positioning features, though we don't care about the types. */ + /* + * Positioning features. + * We don't care about the types. + */ {HB_TAG('d','i','s','t'), F_GLOBAL}, {HB_TAG('a','b','v','m'), F_GLOBAL}, {HB_TAG('b','l','w','m'), F_GLOBAL}, @@ -77,12 +81,14 @@ enum { _ABVS, _BLWS, _PSTS, + _DIST, _ABVM, _BLWM, KHMER_NUM_FEATURES, - KHMER_BASIC_FEATURES = _PRES /* Don't forget to update this! */ + KHMER_BASIC_FEATURES = _PRES, /* Don't forget to update this! */ + KHMER_SUBST_FEATURES = _DIST, /* Don't forget to update this! */ }; static void @@ -121,15 +127,16 @@ collect_features_khmer (hb_ot_shape_planner_t *plan) map->add_global_bool_feature (HB_TAG('c','c','m','p')); unsigned int i = 0; - for (; i < KHMER_BASIC_FEATURES; i++) { + for (; i < KHMER_BASIC_FEATURES; i++) map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); - } map->add_gsub_pause (clear_syllables); - for (; i < KHMER_NUM_FEATURES; i++) { + for (; i < KHMER_SUBST_FEATURES; i++) map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); - } + + for (; i < KHMER_NUM_FEATURES; i++) + map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags); map->add_global_bool_feature (HB_TAG('c','a','l','t')); map->add_global_bool_feature (HB_TAG('c','l','i','g')); diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc index 8466f8129..8069e3d99 100644 --- a/src/hb-ot-shape-complex-myanmar.cc +++ b/src/hb-ot-shape-complex-myanmar.cc @@ -54,7 +54,14 @@ other_features[] = 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. */ +}; +static const hb_tag_t +positioning_features[] = +{ + /* + * Positioning features. + * We don't care about the types. + */ HB_TAG('d','i','s','t'), /* Pre-release version of Windows 8 Myanmar font had abvm,blwm * features. The released Windows 8 version of the font (as well @@ -96,14 +103,20 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan) 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 (nullptr); } + 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); + + for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++) + map->add_feature (positioning_features[i], 1, F_GLOBAL); } static void diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index 676b15b6e..62aef7e6f 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -86,7 +86,14 @@ other_features[] = HB_TAG('h','a','l','n'), HB_TAG('p','r','e','s'), HB_TAG('p','s','t','s'), - /* Positioning features, though we don't care about the types. */ +}; +static const hb_tag_t +positioning_features[] = +{ + /* + * Positioning features. + * We don't care about the types. + */ HB_TAG('d','i','s','t'), HB_TAG('a','b','v','m'), HB_TAG('b','l','w','m'), @@ -146,9 +153,13 @@ collect_features_use (hb_ot_shape_planner_t *plan) map->add_feature (arabic_features[i], 1, F_NONE); map->add_gsub_pause (nullptr); - /* "Standard typographic presentation" and "Positional feature application" */ + /* "Standard typographic presentation" */ for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); + + /* "Positional feature application" */ + for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++) + map->add_feature (positioning_features[i], 1, F_GLOBAL); } struct use_shape_plan_t From a6f4b2f7cd088aeb44e1aac672434641f4f9e484 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 24 Sep 2018 09:54:37 -0400 Subject: [PATCH 18/23] Fix normalization https://github.com/harfbuzz/harfbuzz/commit/62d1e0852a5549a1b510ad46a4b89f12730bb708#commitcomment-30613091 --- src/hb-ot-shape-normalize.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index 487fd96a7..90b76404d 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -385,7 +385,6 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS || mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT) - return; { /* As noted in the comment earlier, we don't try to combine * ccc=0 chars with their previous Starter. */ From 7f335390f3a498119319a0e6c3ce7656a3902066 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 24 Sep 2018 09:56:18 -0400 Subject: [PATCH 19/23] Revert change that would decompose text if GPOS mark feature is available https://github.com/harfbuzz/harfbuzz/issues/653#issuecomment-423905920 --- src/hb-ot-shape-normalize.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index 90b76404d..2f0cba184 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -297,7 +297,9 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_AUTO) { if (plan->has_mark) - mode = HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED; + // https://github.com/harfbuzz/harfbuzz/issues/653#issuecomment-423905920 + //mode = HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED; + mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS; else mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS; } From 57fa2c23de8b6b66894d6872d192ac90ec8bf05a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 24 Sep 2018 09:57:52 -0400 Subject: [PATCH 20/23] Readjust Hebrew composition again --- src/hb-ot-shape-complex-hebrew.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-shape-complex-hebrew.cc b/src/hb-ot-shape-complex-hebrew.cc index 5ad8daf77..ba25258a3 100644 --- a/src/hb-ot-shape-complex-hebrew.cc +++ b/src/hb-ot-shape-complex-hebrew.cc @@ -70,7 +70,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c, bool found = (bool) c->unicode->compose (a, b, ab); - if (!found) + if (!found && !c->plan->has_mark) { /* Special-case Hebrew presentation forms that are excluded from * standard normalization, but wanted for old fonts. */ From 55bae6825ed2058255a512a73293e3cdff0e78a4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 24 Sep 2018 10:43:06 -0400 Subject: [PATCH 21/23] [docs] A few improvements If we wrote just this much every day... --- src/hb-buffer.cc | 4 ++++ src/hb-buffer.h | 20 +++++++++++++++----- src/hb-face.cc | 11 +++++++---- src/hb-font.cc | 12 +++++++----- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 536ab5d53..8fecea721 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -1887,6 +1887,10 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g /** * hb_buffer_diff: + * @buffer: a buffer. + * @reference: other buffer to compare to. + * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1. + * @position_fuzz: allowed absolute difference in position values. * * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most diff --git a/src/hb-buffer.h b/src/hb-buffer.h index 8a2d3e869..4ed458fbb 100644 --- a/src/hb-buffer.h +++ b/src/hb-buffer.h @@ -44,7 +44,6 @@ HB_BEGIN_DECLS * hb_glyph_info_t: * @codepoint: either a Unicode code point (before shaping) or a glyph index * (after shaping). - * @mask: * @cluster: the index of the character in the original text that corresponds * to this #hb_glyph_info_t, or whatever the client passes to * hb_buffer_add(). More than one #hb_glyph_info_t can have the same @@ -59,11 +58,13 @@ HB_BEGIN_DECLS * * The #hb_glyph_info_t is the structure that holds information about the * glyphs and their relation to input text. - * */ -typedef struct hb_glyph_info_t { +typedef struct hb_glyph_info_t +{ hb_codepoint_t codepoint; - hb_mask_t mask; /* Holds hb_glyph_flags_t after hb_shape(), plus other things. */ + /*< private >*/ + hb_mask_t mask; + /*< public >*/ uint32_t cluster; /*< private >*/ @@ -92,6 +93,7 @@ typedef struct hb_glyph_info_t { typedef enum { /*< flags >*/ HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001, + /*< private >*/ HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */ } hb_glyph_flags_t; @@ -298,7 +300,15 @@ hb_buffer_set_flags (hb_buffer_t *buffer, HB_EXTERN hb_buffer_flags_t hb_buffer_get_flags (hb_buffer_t *buffer); -/* +/** + * hb_buffer_cluster_level_t: + * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES: Return cluster values grouped by graphemes into + * monotone order. + * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS: Return cluster values grouped into monotone order. + * @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: Don't group cluster values. + * @HB_BUFFER_CLUSTER_LEVEL_DEFAULT: Default cluster level, + * equal to @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES. + * * Since: 0.9.42 */ typedef enum { diff --git a/src/hb-face.cc b/src/hb-face.cc index 922fd8fd0..19eea4d34 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -36,12 +36,12 @@ /** - * hb_face_count: Get number of faces on the blob - * @blob: + * hb_face_count: + * @blob: a blob. * + * Get number of faces in a blob. * - * - * Return value: Number of faces on the blob + * Return value: Number of faces in @blob * * Since: 1.7.7 **/ @@ -488,6 +488,9 @@ hb_face_get_glyph_count (const hb_face_t *face) /** * hb_face_get_table_tags: * @face: a face. + * @start_offset: index of first tag to return. + * @table_count: input length of @table_tags array, output number of items written. + * @table_tags: array to write tags into. * * Retrieves table tags for a face, if possible. * diff --git a/src/hb-font.cc b/src/hb-font.cc index bc831dd53..9dcf6c123 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1703,9 +1703,11 @@ hb_font_get_ppem (hb_font_t *font, /** * hb_font_set_ptem: * @font: a font. - * @ptem: + * @ptem: font size in points. * - * Sets "point size" of the font. + * Sets "point size" of the font. Set to 0 to unset. + * + * There are 72 points in an inch. * * Since: 1.6.0 **/ @@ -1931,9 +1933,9 @@ hb_font_get_variation_glyph_trampoline (hb_font_t *font, /** * hb_font_funcs_set_glyph_func: * @ffuncs: font functions. - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: + * @func: (closure user_data) (destroy destroy) (scope notified): callback function. + * @user_data: data to pass to @func. + * @destroy: function to call when @user_data is not needed anymore. * * Deprecated. Use hb_font_funcs_set_nominal_glyph_func() and * hb_font_funcs_set_variation_glyph_func() instead. From 2d93148a0f915bb52433ecc9d66845191a2f9135 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 24 Sep 2018 11:52:22 -0400 Subject: [PATCH 22/23] Ignore weak symbols in check-symbols.sh Some clang versions leave a std::round(float) weak symbol around... --- src/check-symbols.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/check-symbols.sh b/src/check-symbols.sh index d4eca5079..6e9382b1a 100755 --- a/src/check-symbols.sh +++ b/src/check-symbols.sh @@ -26,7 +26,7 @@ for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do symprefix= if test $suffix = dylib; then symprefix=_; fi - EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`" + EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTV] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`" prefix=$symprefix`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'` From 45f5aa97905996e3486c6dbba8493b11cfa0cf15 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 24 Sep 2018 12:43:29 -0400 Subject: [PATCH 23/23] [circleci] Disable msan and ubsan builds https://github.com/harfbuzz/harfbuzz/issues/1174 https://github.com/harfbuzz/harfbuzz/issues/1175 --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 671f49d78..7baebb1c8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -249,9 +249,9 @@ workflows: - archlinux-debug-O0-py3 - clang-O3-O0 - clang-asan - - clang-msan + #- clang-msan - clang-tsan - - clang-ubsan + #- clang-ubsan - fedora-outoftreebuild # cmake based builds