From 7810bb1a59ea71afeed7ea489400801ebdf642e4 Mon Sep 17 00:00:00 2001 From: Sascha Brawer Date: Thu, 4 Oct 2018 09:24:08 +0200 Subject: [PATCH 01/32] [morx] Only insert glyphs at mark when a mark has been set before This reverts commit f4072e8cb81072cd6d51a2607efedb76c02e7db1. https://github.com/harfbuzz/harfbuzz/issues/1195 --- src/hb-aat-layout-morx-table.hh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index c58e6744d..85f1f5794 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -592,6 +592,7 @@ struct InsertionSubtable hb_aat_apply_context_t *c_) : ret (false), c (c_), + mark_set (false), mark (0), insertionAction (table+table->insertionAction) {} @@ -607,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; @@ -668,7 +669,10 @@ struct InsertionSubtable } if (flags & SetMark) + { + mark_set = true; mark = buffer->out_len; + } return true; } @@ -677,6 +681,7 @@ struct InsertionSubtable bool ret; private: hb_aat_apply_context_t *c; + bool mark_set; unsigned int mark; const UnsizedArrayOf &insertionAction; }; From 1f14107f71a6c3da8270ed21c3588f945fa91733 Mon Sep 17 00:00:00 2001 From: Sascha Brawer Date: Thu, 4 Oct 2018 09:17:08 +0200 Subject: [PATCH 02/32] Minor: Fix autoconf warning Before this change, autoconf was emitting the following warnings: ``` configure.ac:22: warning: AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is expanded from... configure.ac:22: the top level configure.ac:22: warning: AC_RUN_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is expanded from... configure.ac:22: the top level configure.ac:22: warning: AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is expanded from... configure.ac:22: the top level configure.ac:22: warning: AC_RUN_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is expanded from... configure.ac:22: the top level configure.ac:22: warning: AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is expanded from... configure.ac:22: the top level configure.ac:22: warning: AC_RUN_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is expanded from... configure.ac:22: the top level configure.ac:22: warning: AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is expanded from... configure.ac:22: the top level configure.ac:22: warning: AC_RUN_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is expanded from... configure.ac:22: the top level ``` --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 4ebb21dfe..3aa41ff21 100644 --- a/configure.ac +++ b/configure.ac @@ -12,6 +12,7 @@ AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([1.13.0 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability]) AM_SILENT_RULES([yes]) AX_CODE_COVERAGE +AC_USE_SYSTEM_EXTENSIONS # Initialize libtool m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) @@ -19,7 +20,6 @@ LT_PREREQ([2.2]) LT_INIT([disable-static]) # Check for programs -AC_USE_SYSTEM_EXTENSIONS AC_PROG_CC AC_PROG_CC_C99 AM_PROG_CC_C_O From 3417037eb13a59dce6add0b1691ddb1b2b54c1e4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 4 Oct 2018 11:08:15 +0200 Subject: [PATCH 03/32] [aat] Add +hb_aat_layout_has_substitution --- src/hb-aat-layout-morx-table.hh | 2 ++ src/hb-aat-layout.cc | 6 ++++++ src/hb-aat-layout.hh | 2 ++ 3 files changed, 10 insertions(+) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 85f1f5794..e9869036c 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -947,6 +947,8 @@ struct morx { static const hb_tag_t tableTag = HB_AAT_TAG_morx; + inline bool has_data (void) const { return version != 0; } + inline void apply (hb_aat_apply_context_t *c) const { if (unlikely (!c->buffer->successful)) return; diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index a5e36a40a..faf418d6e 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -55,6 +55,12 @@ _get_morx (hb_face_t *face, hb_blob_t **blob = nullptr) return morx; } +hb_bool_t +hb_aat_layout_has_substitution (hb_face_t *face) +{ + return _get_morx (face).has_data (); +} + void hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer) { diff --git a/src/hb-aat-layout.hh b/src/hb-aat-layout.hh index ac9c53539..553832f1e 100644 --- a/src/hb-aat-layout.hh +++ b/src/hb-aat-layout.hh @@ -33,6 +33,8 @@ #include "hb-buffer.hh" #include "hb-open-type.hh" +HB_INTERNAL hb_bool_t +hb_aat_layout_has_substitution (hb_face_t *face); HB_INTERNAL void hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer); From 14ff3cbe0f30dea24e1bb175b1e8e41039f6afdc Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 4 Oct 2018 11:34:21 +0200 Subject: [PATCH 04/32] Apply morx if there's no GSUB! --- src/hb-ot-shape.cc | 23 +++++++++---- src/hb-ot-shape.hh | 5 +++ .../data/text-rendering-tests/DISABLED | 32 ------------------- .../text-rendering-tests/Makefile.sources | 14 ++++---- 4 files changed, 29 insertions(+), 45 deletions(-) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 748af9693..9e87b300b 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -63,9 +63,14 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.kerning_requested = !!plan.kern_mask; plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k')); + plan.apply_morx = !hb_ot_layout_has_substitution (face) && + hb_aat_layout_has_substitution (face); + bool disable_gpos = plan.shaper->gpos_tag && plan.shaper->gpos_tag != plan.map.chosen_script[1]; - plan.fallback_positioning = disable_gpos || !hb_ot_layout_has_positioning (face); + plan.apply_gpos = !disable_gpos && hb_ot_layout_has_positioning (face); + + plan.fallback_positioning = !plan.apply_gpos; plan.fallback_glyph_classes = !hb_ot_layout_has_glyph_classes (face); } @@ -217,7 +222,13 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, hb_ot_shape_planner_t planner (shape_plan); - planner.shaper = hb_ot_shape_complex_categorize (&planner); + /* Ugly that we have to do this here... + * If we are going to apply morx, choose default shaper. */ + if (!hb_ot_layout_has_substitution (planner.face) && + hb_aat_layout_has_substitution (planner.face)) + planner.shaper = &_hb_ot_complex_shaper_default; + else + planner.shaper = hb_ot_shape_complex_categorize (&planner); hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features); @@ -661,10 +672,10 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c) if (c->plan->fallback_glyph_classes) hb_synthesize_glyph_classes (c); - c->plan->substitute (c->font, buffer); - - if (0) /* XXX Call morx instead. */ + if (unlikely (c->plan->apply_morx)) hb_aat_layout_substitute (c->font, c->buffer); + else + c->plan->substitute (c->font, buffer); } static inline void @@ -784,7 +795,7 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) break; } - if (likely (!c->plan->fallback_positioning)) + if (c->plan->apply_gpos) c->plan->position (c->font, c->buffer); switch (c->plan->shaper->zero_width_marks) diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh index 88c72dc15..23c385aa1 100644 --- a/src/hb-ot-shape.hh +++ b/src/hb-ot-shape.hh @@ -49,6 +49,11 @@ struct hb_ot_shape_plan_t bool fallback_positioning : 1; bool fallback_glyph_classes : 1; + bool apply_morx : 1; + + bool apply_gpos : 1; + + inline void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const { unsigned int table_index; diff --git a/test/shaping/data/text-rendering-tests/DISABLED b/test/shaping/data/text-rendering-tests/DISABLED index 1ce62e072..8539c0ee1 100644 --- a/test/shaping/data/text-rendering-tests/DISABLED +++ b/test/shaping/data/text-rendering-tests/DISABLED @@ -1,38 +1,6 @@ # Non-Unicode cmap tests/CMAP-3.tests -# Not hooked up -tests/MORX-1.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/MORX-10.tests -tests/MORX-11.tests -tests/MORX-12.tests -tests/MORX-13.tests -tests/MORX-14.tests -tests/MORX-16.tests -tests/MORX-17.tests -tests/MORX-18.tests -tests/MORX-19.tests -tests/MORX-20.tests -tests/MORX-21.tests -tests/MORX-22.tests -tests/MORX-23.tests -tests/MORX-25.tests -tests/MORX-26.tests -tests/MORX-27.tests -tests/MORX-28.tests -tests/MORX-29.tests -tests/MORX-30.tests -tests/MORX-31.tests -tests/MORX-32.tests - # Rounding differences tests/SHARAN-1.tests tests/SHBALI-1.tests diff --git a/test/shaping/data/text-rendering-tests/Makefile.sources b/test/shaping/data/text-rendering-tests/Makefile.sources index 5c8cd03f9..6fe174e49 100644 --- a/test/shaping/data/text-rendering-tests/Makefile.sources +++ b/test/shaping/data/text-rendering-tests/Makefile.sources @@ -28,12 +28,6 @@ TESTS = \ tests/HVAR-2.tests \ tests/KERN-1.tests \ tests/KERN-2.tests \ - tests/SHBALI-3.tests \ - tests/SHKNDA-1.tests \ - $(NULL) - -DISBALED_TESTS = \ - tests/CMAP-3.tests \ tests/MORX-10.tests \ tests/MORX-11.tests \ tests/MORX-12.tests \ @@ -56,7 +50,6 @@ DISBALED_TESTS = \ tests/MORX-2.tests \ tests/MORX-30.tests \ tests/MORX-31.tests \ - tests/MORX-32.tests \ tests/MORX-3.tests \ tests/MORX-4.tests \ tests/MORX-5.tests \ @@ -64,9 +57,16 @@ DISBALED_TESTS = \ tests/MORX-7.tests \ tests/MORX-8.tests \ tests/MORX-9.tests \ + tests/SHBALI-3.tests \ + tests/SHKNDA-1.tests \ + $(NULL) + +DISBALED_TESTS = \ + tests/CMAP-3.tests \ tests/SHARAN-1.tests \ tests/SHBALI-1.tests \ tests/SHBALI-2.tests \ tests/SHKNDA-2.tests \ tests/SHKNDA-3.tests \ + tests/MORX-32.tests \ $(NULL) From 6ff8a8a10b62a54a87d53b0af66ccaba5d58b107 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 4 Oct 2018 12:09:45 +0200 Subject: [PATCH 05/32] Minor --- test/shaping/data/text-rendering-tests/extract-tests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/shaping/data/text-rendering-tests/extract-tests.py b/test/shaping/data/text-rendering-tests/extract-tests.py index 36963e5e1..2292cf45d 100755 --- a/test/shaping/data/text-rendering-tests/extract-tests.py +++ b/test/shaping/data/text-rendering-tests/extract-tests.py @@ -33,7 +33,7 @@ for elt in html.findall(".//*[@class='expected'][@ft:id]", namespaces): name = elt.get(ns('ft:id')) text = elt.get(ns('ft:render')) font = elt.get(ns('ft:font')) - vars = elt.get(ns('ft:var'), '').replace(':', '=').replace(';', ',') + variations = elt.get(ns('ft:var'), '').replace(':', '=').replace(';', ',') glyphs = [] for use in elt.findall(".//use"): x = int(use.get('x')) @@ -43,8 +43,8 @@ for elt in html.findall(".//*[@class='expected'][@ft:id]", namespaces): glyphname = '.'.join(href[1:].split('/')[1].split('.')[1:]) glyphs.append((glyphname, x, y)) opts = '--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft' - if vars: - opts = opts + ' --variations=%s' % vars + if variations: + opts = opts + ' --variations=%s' % variations print ("../fonts/%s:%s:%s:%s" % (font, opts, unistr(text), glyphstr(glyphs))) sys.exit(0 if found else 1) From 55468ca01b4cdf274900fb752fbf9ae05a78705e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 4 Oct 2018 12:13:55 +0200 Subject: [PATCH 06/32] [test/text-rendering-tests] Update from upstream --- .../data/text-rendering-tests/Makefile.sources | 6 +++++- .../data/text-rendering-tests/extract-tests.py | 12 ++++++++++++ .../text-rendering-tests/fonts/TestGSUBThree.ttf | Bin 0 -> 1504 bytes .../fonts/TestMORXThirtyfour.ttf | Bin 0 -> 3608 bytes .../fonts/TestMORXThirtythree.ttf | Bin 0 -> 1520 bytes .../fonts/TestMORXTwentyfour.ttf | Bin 0 -> 1828 bytes .../data/text-rendering-tests/tests/GSUB-3.tests | 1 + .../text-rendering-tests/tests/MORX-24.tests | 1 + .../text-rendering-tests/tests/MORX-32.tests | 8 ++++---- .../text-rendering-tests/tests/MORX-33.tests | 3 +++ .../text-rendering-tests/tests/MORX-34.tests | 1 + test/shaping/run-tests.py | 15 +++++++++------ 12 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 test/shaping/data/text-rendering-tests/fonts/TestGSUBThree.ttf create mode 100644 test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfour.ttf create mode 100644 test/shaping/data/text-rendering-tests/fonts/TestMORXThirtythree.ttf create mode 100644 test/shaping/data/text-rendering-tests/fonts/TestMORXTwentyfour.ttf create mode 100644 test/shaping/data/text-rendering-tests/tests/GSUB-3.tests create mode 100644 test/shaping/data/text-rendering-tests/tests/MORX-24.tests create mode 100644 test/shaping/data/text-rendering-tests/tests/MORX-33.tests create mode 100644 test/shaping/data/text-rendering-tests/tests/MORX-34.tests diff --git a/test/shaping/data/text-rendering-tests/Makefile.sources b/test/shaping/data/text-rendering-tests/Makefile.sources index 6fe174e49..79f22adb4 100644 --- a/test/shaping/data/text-rendering-tests/Makefile.sources +++ b/test/shaping/data/text-rendering-tests/Makefile.sources @@ -15,6 +15,7 @@ TESTS = \ tests/GPOS-5.tests \ tests/GSUB-1.tests \ tests/GSUB-2.tests \ + tests/GSUB-3.tests \ tests/GVAR-1.tests \ tests/GVAR-2.tests \ tests/GVAR-3.tests \ @@ -42,6 +43,7 @@ TESTS = \ tests/MORX-21.tests \ tests/MORX-22.tests \ tests/MORX-23.tests \ + tests/MORX-24.tests \ tests/MORX-25.tests \ tests/MORX-26.tests \ tests/MORX-27.tests \ @@ -50,6 +52,9 @@ TESTS = \ tests/MORX-2.tests \ tests/MORX-30.tests \ tests/MORX-31.tests \ + tests/MORX-32.tests \ + tests/MORX-33.tests \ + tests/MORX-34.tests \ tests/MORX-3.tests \ tests/MORX-4.tests \ tests/MORX-5.tests \ @@ -68,5 +73,4 @@ DISBALED_TESTS = \ tests/SHBALI-2.tests \ tests/SHKNDA-2.tests \ tests/SHKNDA-3.tests \ - tests/MORX-32.tests \ $(NULL) diff --git a/test/shaping/data/text-rendering-tests/extract-tests.py b/test/shaping/data/text-rendering-tests/extract-tests.py index 2292cf45d..27d568615 100755 --- a/test/shaping/data/text-rendering-tests/extract-tests.py +++ b/test/shaping/data/text-rendering-tests/extract-tests.py @@ -28,6 +28,7 @@ def glyphstr(glyphs): html = ET.fromstring(sys.stdin.read()) found = False + for elt in html.findall(".//*[@class='expected'][@ft:id]", namespaces): found = True name = elt.get(ns('ft:id')) @@ -47,4 +48,15 @@ for elt in html.findall(".//*[@class='expected'][@ft:id]", namespaces): opts = opts + ' --variations=%s' % variations print ("../fonts/%s:%s:%s:%s" % (font, opts, unistr(text), glyphstr(glyphs))) +for elt in html.findall(".//*[@class='should-not-crash'][@ft:id]", namespaces): + found = True + name = elt.get(ns('ft:id')) + text = elt.get(ns('ft:render')) + font = elt.get(ns('ft:font')) + variations = elt.get(ns('ft:var'), '').replace(':', '=').replace(';', ',') + opts = '' + if variations: + opts = '--variations=%s' % variations + print ("../fonts/%s:%s:%s:*" % (font, opts, unistr(text))) + sys.exit(0 if found else 1) diff --git a/test/shaping/data/text-rendering-tests/fonts/TestGSUBThree.ttf b/test/shaping/data/text-rendering-tests/fonts/TestGSUBThree.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8fce4ac4dd893ef65fa6f504c69c77f616f7e146 GIT binary patch literal 1504 zcma)6&uk!*c)%ujn`Tm zL0loh0kuLxLRDM!Pbdd^se0qoL&c%zRy|cMsG?FYAXu4|^+(jdacryca^mU};+vFdhs35!m?VBc+2O2q&nGJQjrN~Y-|BjG3s=#g{yX)} ztJe88I(UP+-e0w>Rr}%kPY(e}e{!Pjb-LJ!OMt2EcR|Naxp?a2?b_h%9}vb}GWg-g z#COqnxP?q`$52wow+T|SY+Pg94QA-`H1=(LYScnc(OlGc8@v-b^l4`n`&8*46UT^)L+@H(k*Y8c{a+7j!q$dYR-tT2{c{z~R zGxzg6xImTOZ}7$$YjLPJR6Q;qt?LN)1%Jw&aui$eDw82OHab2&wRgH$NT-L*bg?i! z#XY&D-1%W=&O30q`(}Ip#{2W-cNP}P<+nci_~3;Tm#-cC;6%;yYBkrb>EmDkUp_lu zhPu8N-EZM*MOgCPUyregVH9GVB%X_LKe9L#<86%lg1%w1pPpvJ%FtL~JF`0CCHMV4 z#wPRdPK=Y-B?e;Lj}ogUvfqZJ=pFLfYyL{p>8k6hkl!<-s;!l}*RXTyXsbT4Xm`50 z{uUkIw##<&tZVsy@-vv*b0D)oQ4U)u}s{D*4tq+jl(|hv1=& zHTYOT6Arq}nCp}RvuF>qLhj__J5-PM0%b66KtoX;*m6w2zebBo&xF%{q+C< literal 0 HcmV?d00001 diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfour.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfour.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a70dadccf471cb7799126548a82d5f72060acef3 GIT binary patch literal 3608 zcmeHJYfM|$9si$Wa}A*ojC~CO=3HZ9^DxG*d+iWHD1HDjU}JD`N*?x%@pZy0##u3u z2wlFltJF11RVk{pb^XvzO216&mu=FjeTgb<*`}gsmk-PG*1CRhp)7iDmCj1=kBmX1hr}L}j zm12?P0H^~%`#{cRmRsIzIEuO-;3vr_&>f|(BK-)z9(k>_{mdP54ej4R-nP1t&D7u0 z-9r0kkTiT>YN&#dLN7wOE-tC$!jr}>EWH7 zgME6+;cy-74>=q|^l;Y>ZARh49katln_W!v(1pdK;H-X5enTzj)rR|+c)itbD08=Ok-USAp(`=>3P*0k^RjDH}w6r+~s z&R1?sJNjo5@kOmh2>On+j2k*Dp9H*v{n1$$s}&-T9zksI0IfPNdiSuM^*-E;&0hX? z9oKQjm&q<}KOan`$iB6&|6IQEZL;`c?tJBs^zo-Gc6ar2+DLy1O>hK3|0HU~nN|r^ ziJqs8u0pcBH6$muzf#!^&c(yw_+0Se+o>PlF1@|@!FxAe`}#Lt!+~*~K_q19hk&QV zqQ?SooK9!=d-bG=(w0ucwDW^0^4Wl|tHq=rJ@NX1#L$B$g4WY}tS?^CKT5w)GtA1! zT<{j&^?fmFiv+~kzM=lL&~nL{@ZThbsUJ!UarcRnJ;DjAdnFb4a$3BhjWe%q142ww4^sB+S;Sz!4uKbCw<4eJ4Vco;mY0ETW>|l{fafl@;IgB@gbgJ zhAtyR))!J>*fLmniw+?`_O8FO8%SGv@7Xery;M6FsahGdi1-#M|D zLZ4c=44B3gK2CATZr$fuQ0GIS>%I@rM*f}!=0f|Fhl)oO4$ zGp!W`kDKJTu~R2`IVHe0NeP##?Y7%dOs;Mp8$ITj9N4>9y4n}Ai<5!$$>S00NRMwK zGJNy&%+yRG)G{8X_fqo%V{U`V7jZvd$St|1e68l>xHR26A$pE^tSzQd$s-;-3Wxo^ za0mCLNz8(R2P0%iRw@b2wAL%HXOuDo)b0d!x=ehJdKs_?ZB|;}Iq_o7D7Dz#ktL~} zVkMtFdpVE~ht|g`KZ^w;u39Olv6OXn(I#iCFx>6FoR6*!hhM(5pI8XT>?6X!0=qk# z;XSNpZ7|H#XacPmRgI?jp14$63mteP*W?`1b1L0{cfuu=HehDk?1t7hpuZ7dyvXN2)$=7n5Q&Oi`0 zU=zwvgaW=AGL%4ock%OJW!(4%33$V^&z12ITI3V9h< z7Ew}$6=>)FHBejZeR`I{G5dH_7!GExs$KAFtMj2-T#&PEiynvAu6^Z&EqWV4c z^;JRgx2YK^4TK;H2E4a;FhLu%+sEZ@_*J;edS;Qt;6e+6DE BG#&r| literal 0 HcmV?d00001 diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtythree.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtythree.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5cab73e5a59088653a171dea221450a4159f540d GIT binary patch literal 1520 zcmbVM+iN3L82`!UBaYU+isk;X>JX&XlWLqblXZVCcBHVLo#L}&4o$U zHeD2N_^=NmEQsRMBBG0zHx~q7h5ZZMM=z)>ULLlt;>$Mv&SX$nRuIqdo$vQu&v(xG z&OiZhKVE{0`17ey{3+^`aj_YB?CA-t1;MKZY>Es_tg$*?P0)YBWrFF$#GYJ{rrOn<~yJ zZ=w&!#3fOnZl%YSA`*%refm7dyV>?iehrJzVXHc8xXzld(?{+F%55P}Qtws9{1Ee) z70+RtT3NkH3UQX+A!vw`ALA!&I!xHz?mwveZTCv|-CkyDT>wfKF4H^9EVIML|)Wd#^DQ7(#gr>A|jb_KGR_wNZRZqm{v-)#|8?NZF)M? zbVxRl#czXD;qPacZSDNW82x`m&D<5W$rW3y)F#)l#MMpgu^PwKxNnCO(EW_tz1PsF zRB;+Bw`=m&27^(VdEV@8==?l z_xawR=e*~9FBE{ycoQ~Mg~FBoSaEC;P&eQftr+@n4xnqIIX$(Oa^un-44tcwgq z->t}|B$;K{Z2QzakxhC|cTwM;UR4BsRW1f%{HW2f|6mLEY+$d=Acq^|e1mqf7pMnX zDru0}K}003euHxyrf!FyY)xGblNNFS!pz0Dc)E~5Tq;o++emm@E~_2)Zx^v%_P&UQWjWU%r!GmyJ( zXRcfnksFl1(CxB2-17E%ody2dnrffd>vje*lB$?H-n9GdOyaM*UHig^j?TXvYKxrE zi)}r-!jES^J#W6M7n8T@g7ww+k{6pAf{om#pC{hJ6PG(>ce@G${vB?+-TREMrneR@=^;=266ky)1s*tu3fzT!}%*cb2Ag>sZ*CP>%~hKPRy>}I{B`gD!tVTy*C2^ zr^mhanCfJ5NqLiZRE=H?{n(NU$?qD%^b?<;EL9k%oM0re z4YMB2Ttlp**ghP&c|!yPotAH$sN^lzo6ebS_#)bSO*CG#Y8VPO!H ztc_^3*z z8=1z}qf}(})yT^4!3)@%?i}pImw2xpHQ0A}D@#xcAIjLrq`S$#lb*9&1ySs6G88+S x^fvjvHhPV;E|@f47iS4)6=wtgTun4<{UK Date: Thu, 4 Oct 2018 13:00:37 +0200 Subject: [PATCH 07/32] Enable two OpenType features, 'Harf' and 'Buzz' One early, before script-specific features, one late, after. Allows font developers to detect us and behave differently if needed. --- src/hb-ot-shape.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 9e87b300b..7d22720e4 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -132,9 +132,13 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, /* Random! */ map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE); + map->enable_feature (HB_TAG('H','a','r','f')); + if (planner->shaper->collect_features) planner->shaper->collect_features (planner); + map->enable_feature (HB_TAG('B','u','z','z')); + for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++) map->add_feature (common_features[i]); From c93d379bf2414eb6ee6d38fb9753ddf818a777ea Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 4 Oct 2018 13:28:13 +0200 Subject: [PATCH 08/32] [TODO] Clean up --- TODO | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/TODO b/TODO index 6dac0be52..d2c5812a0 100644 --- a/TODO +++ b/TODO @@ -1,9 +1,3 @@ -General fixes: -============= - -- Implement 'rand' feature. - - API issues: =========== @@ -19,12 +13,10 @@ API additions - Add hb-cairo glue -- Add sanitize API (and a cached version, that saves result on blob user-data) +- Add sanitize API. - BCP 47 language handling / API (language_matches?) -- Add hb_font_create_unscaled()? - - Add query / enumeration API for aalt-like features? - Add segmentation API From 0abce58139bb58b8b97171db6387d2ac7eebdee0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 4 Oct 2018 16:23:42 +0200 Subject: [PATCH 09/32] [test] Choose 'ot' shaper specifically Now that we added morx support, our OS X bot is running them through CoreText and failing (with a DoS / infinite loop no less!). Always run tests through our own shaper. --- 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 5592aea58..18b2118dc 100755 --- a/test/shaping/run-tests.py +++ b/test/shaping/run-tests.py @@ -46,7 +46,7 @@ for filename in args: cwd = os.path.dirname(filename) fontfile = os.path.normpath (os.path.join (cwd, fontfile)) - extra_options = [] + extra_options = ["--shaper=ot"] glyphs_expected = glyphs_expected.strip() if glyphs_expected != '*': extra_options.append("--verify") From 310bdac4a08b99a25de6a16a20464873f90b52e4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 4 Oct 2018 16:31:14 +0200 Subject: [PATCH 10/32] Fix a warning --- util/view-cairo.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/view-cairo.hh b/util/view-cairo.hh index 677f74b38..5be3523ad 100644 --- a/util/view-cairo.hh +++ b/util/view-cairo.hh @@ -46,7 +46,7 @@ struct view_cairo_t void init (hb_buffer_t *buffer, const font_options_t *font_opts) { lines = g_array_new (false, false, sizeof (helper_cairo_line_t)); - scale_bits = -font_opts->subpixel_bits; + scale_bits = - (int) font_opts->subpixel_bits; } void new_line (void) { From 7b3ae5ffd202346cb3742fe0f8cfafe8c36a4bd5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 4 Oct 2018 16:36:42 +0200 Subject: [PATCH 11/32] More bot fixes --- test/shaping/run-tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/shaping/run-tests.py b/test/shaping/run-tests.py index 18b2118dc..0b27872fc 100755 --- a/test/shaping/run-tests.py +++ b/test/shaping/run-tests.py @@ -65,7 +65,7 @@ for filename in args: unicodes] + (options.split (' ') if options else [])) if returncode: - print ("hb-shape --font-funcs=ft failed.") # file=sys.stderr + print ("ERROR: hb-shape --font-funcs=ft failed.") # file=sys.stderr fails = fails + 1 #continue @@ -78,7 +78,7 @@ for filename in args: fails = fails + 1 #continue - if glyphs1 != glyphs2: + if glyphs1 != glyphs2 and glyphs_expected != '*': print ("FT funcs: " + glyphs1) # file=sys.stderr print ("OT funcs: " + glyphs2) # file=sys.stderr fails = fails + 1 From a62f37d6fa412b799b7247b813f6e65a968e7645 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 5 Oct 2018 02:49:29 +0200 Subject: [PATCH 12/32] Change vendor features from Harf/Buzz to HARF/BUZZ https://github.com/harfbuzz/harfbuzz/commit/a01194aaf4c15160330b4042066263b2c963b658#commitcomment-30772041 "The tag space of tags consisting of four uppercase letters (A-Z) with no punctuation, spaces, or numbers, is reserved as a vendor space. Font vendors may use such tags to identify private features." --- src/hb-ot-shape.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 7d22720e4..453d995a2 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -132,12 +132,12 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, /* Random! */ map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE); - map->enable_feature (HB_TAG('H','a','r','f')); + map->enable_feature (HB_TAG('H','A','R','F')); if (planner->shaper->collect_features) planner->shaper->collect_features (planner); - map->enable_feature (HB_TAG('B','u','z','z')); + map->enable_feature (HB_TAG('B','U','Z','Z')); for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++) map->add_feature (common_features[i]); From 5a41cf6be69adb0b5b29976a33c4c6dd6ce7afc5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 5 Oct 2018 11:33:19 +0200 Subject: [PATCH 13/32] [test/text-rendering-tests] Update from upstream --- test/shaping/data/text-rendering-tests/DISABLED | 3 +++ .../data/text-rendering-tests/Makefile.sources | 2 ++ .../fonts/TestMORXThirtyfive.ttf | Bin 0 -> 1968 bytes .../fonts/TestMORXThirtysix.ttf | Bin 0 -> 1836 bytes .../text-rendering-tests/tests/MORX-35.tests | 2 ++ .../text-rendering-tests/tests/MORX-36.tests | 1 + 6 files changed, 8 insertions(+) create mode 100644 test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfive.ttf create mode 100644 test/shaping/data/text-rendering-tests/fonts/TestMORXThirtysix.ttf create mode 100644 test/shaping/data/text-rendering-tests/tests/MORX-35.tests create mode 100644 test/shaping/data/text-rendering-tests/tests/MORX-36.tests diff --git a/test/shaping/data/text-rendering-tests/DISABLED b/test/shaping/data/text-rendering-tests/DISABLED index 8539c0ee1..4e8b1cf24 100644 --- a/test/shaping/data/text-rendering-tests/DISABLED +++ b/test/shaping/data/text-rendering-tests/DISABLED @@ -1,3 +1,6 @@ +# https://github.com/harfbuzz/harfbuzz/issues/1224 +tests/MORX-35.tests + # Non-Unicode cmap tests/CMAP-3.tests diff --git a/test/shaping/data/text-rendering-tests/Makefile.sources b/test/shaping/data/text-rendering-tests/Makefile.sources index 79f22adb4..29d064b70 100644 --- a/test/shaping/data/text-rendering-tests/Makefile.sources +++ b/test/shaping/data/text-rendering-tests/Makefile.sources @@ -55,6 +55,7 @@ TESTS = \ tests/MORX-32.tests \ tests/MORX-33.tests \ tests/MORX-34.tests \ + tests/MORX-36.tests \ tests/MORX-3.tests \ tests/MORX-4.tests \ tests/MORX-5.tests \ @@ -67,6 +68,7 @@ TESTS = \ $(NULL) DISBALED_TESTS = \ + tests/MORX-35.tests \ tests/CMAP-3.tests \ tests/SHARAN-1.tests \ tests/SHBALI-1.tests \ diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfive.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfive.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f15706317d0f697d27b22af6a6a8bb8df82c05f2 GIT binary patch literal 1968 zcmbVNZERCj7=F&VTgw7$G;IeeA-8sPnDAvg3eE*#>Vhy<*~S=O8<(xDn0=)!u$hP^ zGKCq#_$2|C$f7YM8Vm_BOCXUDm6VY11CbvLK{SCF7feuN$Zmb!+YZ6-!+35^-;eWt zJnwtodkO_$D&B&D#j%D(;l%93dw^O-?Y6cqs~1~wi}Gp8FLiYG@3=p3=Nmx#s2fkj zt@aru17Gq?&Z7w`T<@x%$lv2GOLV3C{MCx*>afV2J#Chru0NnZMfkd`zFzcU1+>$ztz@-fPC*@~U>56j`F*94 z@KV3a6?{6hq#_!PgiB|-LqX-=_eTHPmU&H;$3A`aXy?-SGi6P+df>=A`w!2qD=9wr zdDkafN`1BE(sjW+Ow3c@;b03+2Jwf8(}Agn&z=1C+Q+9`2lwr=4jmdD)tOVr5A2_~ zbntz7)AUw%={*&Qcmn>($5IFF3o2-jsUbMSKT=C zRqL@o-g3H*PZ8G*8y-xlo5A%QcEclmC1GA-wF+pmgnwc%^Are6#7*o{N zu%d3K-Uf0z$n9}3#(9>r=p=2US2ykBtlnfD-A)&h6x)X**FF-# zL=!ENjJDIsZL-4)oozmZ>(Q)}SS)taqM!6}JAWnf9?F8kq)xJ~#5#vhqmoqKWtx~O zv51d!L*8*Obtz^Q44tGs)OPSZM*rFeKB>Hy%to&M9@d_8y77Bmzu>}${tV=wWOB(FmlId5FeL*;6FN_M!fZKNY?)P(2y}jIWyP%9(iXNo zfIbWzi-z%H2rz?Y#_(WFP#!S6ATg3IBzrLG0}~aE#3vrm#F(}I&esl@Au--Br}vz5 z&!68p_x3;mScf-Z!?sX&oj+O;odDDhYF`_Snd6wm0m`3KZW2q+pZ^``hX+`3Iz`Xe>Ed@}>HWwr43CSJh&IIy~CWT@v%e_>#@M|ex7fGU?+VM-g#%Bxakkr zZ18W;loMCl79Z}KrqE4*@1A1uXf|V2cguX?)VxZdN z@T!3F+I+qmyTcJsi|Jo`_p9Y!{sP0>HK+lS>IX-=zQ0UPdC+l&kV$_dzh;T z<-`W%FLS%>4!8Vzz0Oj9u%X`P^}3yb9H+L-o@{HqIGz0ahyGpN`;X1N8tMw4(y6Y2 zm%5+I-#BN!u2boy=bIYq@1`%eH8-`ePCswFgEzi`wc6dTvVecP+iv$(`Wotk!GOQ4 z+~M;o_w@0pJ>kuLjURlx_x#BA$g@>_?fT@ow`R^(bQBle_$2nxfihQnjdWTt&l7V2 zoP5-RlR?}*;{?i;Tx`tAU(-Wvxg4*?gkRPIy=uRI@?M%*35JA+qLfW2F3l068H; A!2kdN literal 0 HcmV?d00001 diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-35.tests b/test/shaping/data/text-rendering-tests/tests/MORX-35.tests new file mode 100644 index 000000000..1061034d3 --- /dev/null +++ b/test/shaping/data/text-rendering-tests/tests/MORX-35.tests @@ -0,0 +1,2 @@ +../fonts/TestMORXThirtyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041:[A|B@639,0|C@1265,0] +../fonts/TestMORXThirtyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0058,U+0041,U+0059:[X|A@586,0|B@1225,0|C@1851,0|E@2447,0|Y@3003,0] diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-36.tests b/test/shaping/data/text-rendering-tests/tests/MORX-36.tests new file mode 100644 index 000000000..6b2340e6d --- /dev/null +++ b/test/shaping/data/text-rendering-tests/tests/MORX-36.tests @@ -0,0 +1 @@ +../fonts/TestMORXThirtysix.ttf::U+0041:* From 4831e615d173be9c7e140be0fa9017e4d9e499af Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 5 Oct 2018 18:14:13 +0200 Subject: [PATCH 14/32] [morx] Fix memory access issue If buffer was enlarged, info was being outdated. Fixes https://github.com/harfbuzz/harfbuzz/issues/1225 --- src/hb-aat-layout-common.hh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index b0faa1db5..c6b519d81 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -546,8 +546,6 @@ struct StateTableDriver template inline void drive (context_t *c) { - hb_glyph_info_t *info = buffer->info; - if (!c->in_place) buffer->clear_output (); @@ -556,7 +554,7 @@ struct StateTableDriver for (buffer->idx = 0;;) { unsigned int klass = buffer->idx < buffer->len ? - machine.get_class (info[buffer->idx].codepoint, num_glyphs) : + machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) : (unsigned) StateTable::CLASS_END_OF_TEXT; const Entry *entry = machine.get_entryZ (state, klass); if (unlikely (!entry)) From 5469d80707d32c733b1c60f79ab2f217e879de55 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 5 Oct 2018 18:21:08 +0200 Subject: [PATCH 15/32] Add hb_vector_t::fini_deep () --- src/hb-vector.hh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hb-vector.hh b/src/hb-vector.hh index da548cbb1..270875381 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -227,6 +227,14 @@ struct hb_vector_t return false; } + inline void fini_deep (void) + { + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + arrayZ[i].fini (); + fini (); + } + inline void fini (void) { if (arrayZ != static_array) From 341206eb609202e4b2f0d03d29cb577ebe8390b9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 5 Oct 2018 18:39:48 +0200 Subject: [PATCH 16/32] [vector] Make hb_vector_t relocatable / nestable Ugly, but... Fixes https://github.com/harfbuzz/harfbuzz/issues/1227 --- src/hb-face.cc | 2 +- src/hb-machinery.hh | 2 +- src/hb-ot-cmap-table.hh | 2 +- src/hb-ot-post-table.hh | 2 +- src/hb-set.hh | 4 +- src/hb-subset.cc | 2 +- src/hb-vector.hh | 94 ++++++++++++++++++++++++++--------------- 7 files changed, 66 insertions(+), 42 deletions(-) diff --git a/src/hb-face.cc b/src/hb-face.cc index 3916a4e24..bba1ee3fa 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -634,7 +634,7 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data) unsigned int face_length = table_count * 16 + 12; for (unsigned int i = 0; i < table_count; i++) - face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables.arrayZ[i].blob)); + face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob)); char *buf = (char *) malloc (face_length); if (unlikely (!buf)) diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh index f80cfdb2e..9c73df2ca 100644 --- a/src/hb-machinery.hh +++ b/src/hb-machinery.hh @@ -591,7 +591,7 @@ struct Supplier } inline Supplier (const hb_vector_t *v) { - head = v->arrayZ; + head = v->arrayZ(); len = v->len; stride = sizeof (Type); } diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index 3f5fa01f5..52b4db6a9 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -495,7 +495,7 @@ struct CmapSubtableLongSegmented { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - Supplier supplier (group_data.arrayZ, group_data.len); + Supplier supplier (group_data.arrayZ(), group_data.len); if (unlikely (!groups.serialize (c, supplier, group_data.len))) return_trace (false); return true; } diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh index f81de37d5..bd049f9ab 100644 --- a/src/hb-ot-post-table.hh +++ b/src/hb-ot-post-table.hh @@ -242,7 +242,7 @@ struct post if (index >= index_to_offset.len) return hb_bytes_t (); - unsigned int offset = index_to_offset.arrayZ[index]; + unsigned int offset = index_to_offset[index]; const uint8_t *data = pool + offset; unsigned int name_length = *data; diff --git a/src/hb-set.hh b/src/hb-set.hh index 353403e92..7ca329761 100644 --- a/src/hb-set.hh +++ b/src/hb-set.hh @@ -368,8 +368,8 @@ struct hb_set_t if (!resize (count)) return; population = other->population; - memcpy (pages.arrayZ, other->pages.arrayZ, count * sizeof (pages.arrayZ[0])); - memcpy (page_map.arrayZ, other->page_map.arrayZ, count * sizeof (page_map.arrayZ[0])); + memcpy (pages.arrayZ(), other->pages.arrayZ(), count * sizeof (pages.arrayZ()[0])); + memcpy (page_map.arrayZ(), other->page_map.arrayZ(), count * sizeof (page_map.arrayZ()[0])); } inline bool is_equal (const hb_set_t *other) const diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 2bed35868..9f14b89ba 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -77,7 +77,7 @@ _subset2 (hb_subset_plan_t *plan) return false; } retry: - hb_serialize_context_t serializer (buf.arrayZ, buf_size); + hb_serialize_context_t serializer (buf.arrayZ(), buf_size); hb_subset_context_t c (plan, &serializer); result = table->subset (&c); if (serializer.ran_out_of_room) diff --git a/src/hb-vector.hh b/src/hb-vector.hh index 270875381..766e5fb8e 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -35,35 +35,42 @@ template struct hb_vector_t { unsigned int len; + private: unsigned int allocated; /* == 0 means allocation failed. */ - Type *arrayZ; + Type *arrayZ_; Type static_array[StaticSize]; + public: void init (void) { len = 0; allocated = ARRAY_LENGTH (static_array); - arrayZ = static_array; + arrayZ_ = nullptr; } + inline Type * arrayZ (void) + { return arrayZ_ ? arrayZ_ : static_array; } + inline const Type * arrayZ (void) const + { return arrayZ_ ? arrayZ_ : static_array; } + inline Type& operator [] (unsigned int i) { if (unlikely (i >= len)) return Crap (Type); - return arrayZ[i]; + return arrayZ()[i]; } inline const Type& operator [] (unsigned int i) const { if (unlikely (i >= len)) return Null(Type); - return arrayZ[i]; + return arrayZ()[i]; } inline Type *push (void) { if (unlikely (!resize (len + 1))) return &Crap(Type); - return &arrayZ[len - 1]; + return &arrayZ()[len - 1]; } inline Type *push (const Type& v) { @@ -91,17 +98,17 @@ struct hb_vector_t Type *new_array = nullptr; - if (arrayZ == static_array) + if (!arrayZ_) { new_array = (Type *) calloc (new_allocated, sizeof (Type)); if (new_array) - memcpy (new_array, arrayZ, len * sizeof (Type)); + memcpy (new_array, static_array, len * sizeof (Type)); } else { bool overflows = (new_allocated < allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type)); if (likely (!overflows)) - new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type)); + new_array = (Type *) realloc (arrayZ_, new_allocated * sizeof (Type)); } if (unlikely (!new_array)) @@ -110,7 +117,7 @@ struct hb_vector_t return false; } - arrayZ = new_array; + arrayZ_ = new_array; allocated = new_allocated; return true; @@ -123,7 +130,7 @@ struct hb_vector_t return false; if (size > len) - memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ)); + memset (arrayZ() + len, 0, (size - len) * sizeof (*arrayZ())); len = size; return true; @@ -137,12 +144,13 @@ struct hb_vector_t inline void remove (unsigned int i) { - if (unlikely (i >= len)) - return; - memmove (static_cast (&arrayZ[i]), - static_cast (&arrayZ[i + 1]), - (len - i - 1) * sizeof (Type)); - len--; + if (unlikely (i >= len)) + return; + Type *array = arrayZ(); + memmove (static_cast (&array[i]), + static_cast (&array[i + 1]), + (len - i - 1) * sizeof (Type)); + len--; } inline void shrink (int size_) @@ -153,41 +161,55 @@ struct hb_vector_t } template - inline Type *find (T v) { + inline Type *find (T v) + { + Type *array = arrayZ(); for (unsigned int i = 0; i < len; i++) - if (arrayZ[i] == v) - return &arrayZ[i]; + if (array[i] == v) + return &array[i]; return nullptr; } template - inline const Type *find (T v) const { + inline const Type *find (T v) const + { + const Type *array = arrayZ(); for (unsigned int i = 0; i < len; i++) - if (arrayZ[i] == v) - return &arrayZ[i]; + if (array[i] == v) + return &array[i]; return nullptr; } inline void qsort (int (*cmp)(const void*, const void*)) { - ::qsort (arrayZ, len, sizeof (Type), cmp); + ::qsort (arrayZ(), len, sizeof (Type), cmp); } inline void qsort (void) { - ::qsort (arrayZ, len, sizeof (Type), Type::cmp); + ::qsort (arrayZ(), len, sizeof (Type), Type::cmp); } inline void qsort (unsigned int start, unsigned int end) { - ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp); + ::qsort (arrayZ() + start, end - start, sizeof (Type), Type::cmp); } template inline Type *lsearch (const T &x) { + Type *array = arrayZ(); for (unsigned int i = 0; i < len; i++) - if (0 == this->arrayZ[i].cmp (&x)) - return &arrayZ[i]; + if (0 == array[i].cmp (&x)) + return &array[i]; + return nullptr; + } + template + inline const Type *lsearch (const T &x) const + { + const Type *array = arrayZ(); + for (unsigned int i = 0; i < len; i++) + if (0 == array[i].cmp (&x)) + return &array[i]; return nullptr; } @@ -195,22 +217,23 @@ struct hb_vector_t inline Type *bsearch (const T &x) { unsigned int i; - return bfind (x, &i) ? &arrayZ[i] : nullptr; + return bfind (x, &i) ? &arrayZ()[i] : nullptr; } template inline const Type *bsearch (const T &x) const { unsigned int i; - return bfind (x, &i) ? &arrayZ[i] : nullptr; + return bfind (x, &i) ? &arrayZ()[i] : nullptr; } template inline bool bfind (const T &x, unsigned int *i) const { int min = 0, max = (int) this->len - 1; + const Type *array = this->arrayZ(); while (min <= max) { int mid = (min + max) / 2; - int c = this->arrayZ[mid].cmp (&x); + int c = array[mid].cmp (&x); if (c < 0) max = mid - 1; else if (c > 0) @@ -221,7 +244,7 @@ struct hb_vector_t return true; } } - if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0)) + if (max < 0 || (max < (int) this->len && array[max].cmp (&x) > 0)) max++; *i = max; return false; @@ -229,17 +252,18 @@ struct hb_vector_t inline void fini_deep (void) { + Type *array = arrayZ(); unsigned int count = len; for (unsigned int i = 0; i < count; i++) - arrayZ[i].fini (); + array[i].fini (); fini (); } inline void fini (void) { - if (arrayZ != static_array) - free (arrayZ); - arrayZ = nullptr; + if (arrayZ_) + free (arrayZ_); + arrayZ_ = nullptr; allocated = len = 0; } }; From 0816a549789a1b647443c2b33cfda3f4400a0f87 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 6 Oct 2018 02:40:57 +0200 Subject: [PATCH 17/32] [uniscribe/coretext] Fix for previous change --- src/hb-coretext.cc | 2 +- src/hb-uniscribe.cc | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index ab04d72f6..cd3ebae43 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -768,7 +768,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, } else { active_feature_t *feature = active_features.find (&event->feature); if (feature) - active_features.remove (feature - active_features.arrayZ); + active_features.remove (feature - active_features.arrayZ()); } } } diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index b77baa2fe..44a67ae4c 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -717,7 +717,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, { active_feature_t *feature = active_features.find (&event->feature); if (feature) - active_features.remove (feature - active_features.arrayZ); + active_features.remove (feature - active_features.arrayZ()); } } @@ -728,7 +728,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, for (unsigned int i = 0; i < range_records.len; i++) { range_record_t *range = &range_records[i]; - range->props.potfRecords = feature_records.arrayZ + reinterpret_cast (range->props.potfRecords); + range->props.potfRecords = feature_records.arrayZ() + reinterpret_cast (range->props.potfRecords); } } @@ -902,8 +902,8 @@ retry: &items[i].a, script_tags[i], language_tag, - range_char_counts.arrayZ, - range_properties.arrayZ, + range_char_counts.arrayZ(), + range_properties.arrayZ(), range_properties.len, pchars + chars_offset, item_chars_len, @@ -943,8 +943,8 @@ retry: &items[i].a, script_tags[i], language_tag, - range_char_counts.arrayZ, - range_properties.arrayZ, + range_char_counts.arrayZ(), + range_properties.arrayZ(), range_properties.len, pchars + chars_offset, log_clusters + chars_offset, From e9abe33963739f753cdfb007eed40101ce33f550 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 6 Oct 2018 12:19:33 +0330 Subject: [PATCH 18/32] Use tempfile in run-tests as a fix for Windows CI fails (#1228) --- test/shaping/run-tests.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/shaping/run-tests.py b/test/shaping/run-tests.py index 0b27872fc..f77a17c3d 100755 --- a/test/shaping/run-tests.py +++ b/test/shaping/run-tests.py @@ -2,16 +2,16 @@ from __future__ import print_function, division, absolute_import -import sys, os, subprocess +import sys, os, subprocess, tempfile def cmd(command): - p = subprocess.Popen ( - command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - p.wait () - print (p.stderr.read ().decode ("utf-8").strip ()) # file=sys.stderr - return p.stdout.read ().decode ("utf-8").strip (), p.returncode - + # https://stackoverflow.com/a/4408409 + with tempfile.TemporaryFile() as tempf: + p = subprocess.Popen (command, stdout=tempf, stderr=sys.stdout) + p.wait () + tempf.seek(0) + return tempf.read().decode ("utf-8").strip (), p.returncode args = sys.argv[1:] if not args or sys.argv[1].find('hb-shape') == -1 or not os.path.exists (sys.argv[1]): From f58c5175890e666503b6f140d238e1abca91598e Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 6 Oct 2018 22:42:56 +0330 Subject: [PATCH 19/32] Make msan output a little more readable --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index af443ad92..69520b014 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -126,7 +126,7 @@ jobs: - run: update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.lld" 10 - run: wget https://ftp.gnome.org/pub/gnome/sources/glib/2.58/glib-2.58.1.tar.xz && tar xf glib-2.58.1.tar.xz && cd glib-2.58.1 && ./autogen.sh --with-pcre CPPFLAGS="-fsanitize=memory" LDFLAGS="-fsanitize=memory" CFLAGS="-fsanitize=memory" CXXFLAGS="-fsanitize=memory" LD=ld.lld CC=clang CXX=clang++ && make -j32 && make install && cd .. - run: wget http://download.savannah.gnu.org/releases/freetype/freetype-2.9.tar.bz2 && tar xf freetype-2.9.tar.bz2 && cd freetype-2.9 && ./autogen.sh && ./configure CPPFLAGS="-fsanitize=memory" LDFLAGS="-fsanitize=memory -O1 -g -fno-omit-frame-pointer" CFLAGS="-fsanitize=memory -O1 -g -fno-omit-frame-pointer" CXXFLAGS="-fsanitize=memory -O1 -g -fno-omit-frame-pointer" LD=ld.lld CC=clang CXX=clang++ && make -j32 && make install && cd .. - - run: CPPFLAGS="-fsanitize=memory" LDFLAGS="-fsanitize=memory -O1 -g -fno-omit-frame-pointer" CFLAGS="-fsanitize=memory -O1 -g -fno-omit-frame-pointer" CXXFLAGS="-fsanitize=memory -O1 -g -fno-omit-frame-pointer" LD=ld.lld CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --without-icu + - run: CPPFLAGS="-fsanitize=memory -fsanitize-memory-track-origins" LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins -O1 -g -fno-omit-frame-pointer" CFLAGS="-fsanitize=memory -fsanitize-memory-track-origins -O1 -g -fno-omit-frame-pointer" CXXFLAGS="-fsanitize=memory -fsanitize-memory-track-origins -O1 -g -fno-omit-frame-pointer" LD=ld.lld CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --without-icu - run: make -j32 && MSAN_OPTIONS=exitcode=42 make check || .ci/fail.sh | asan_symbolize | c++filt clang-tsan: From 7ee50af8366547c382047a30a94f7f5f739aabcb Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 6 Oct 2018 21:31:44 +0200 Subject: [PATCH 20/32] [morx] Fix memory access issues with unsafe_to_break --- src/hb-aat-layout-common.hh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index c6b519d81..97866919a 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -561,15 +561,17 @@ struct StateTableDriver break; /* Unsafe-to-break before this if not in state 0, as things might - * go differently if we start from state 0 here. */ - if (state && buffer->idx) + * go differently if we start from state 0 here. + * + * Ugh. The indexing here is ugly... */ + if (state && buffer->backtrack_len () && buffer->idx < buffer->len) { /* 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 == StateTable::STATE_START_OF_TEXT && entry->flags == context_t::DontAdvance)) - buffer->unsafe_to_break (buffer->idx - 1, buffer->idx + 1); + buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1); } /* Unsafe-to-break if end-of-text would kick in here. */ From b2e398c077cf9437298bfe2ee53b7407a5865c14 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2018 16:31:33 +0200 Subject: [PATCH 21/32] [coretext] Fix OS X check Fixes https://github.com/harfbuzz/harfbuzz/issues/1230 --- src/hb-coretext.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index cd3ebae43..9bebb2be6 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -210,7 +210,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) } CFURLRef original_url = nullptr; -#if TARGET_OS_MAC && MAC_OS_X_VERSION_MIN_REQUIRED < 1060 +#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060 ATSFontRef atsFont; FSRef fsref; OSStatus status; @@ -240,7 +240,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) * process in Blink. This can be detected by the new file URL location * that the newly found font points to. */ CFURLRef new_url = nullptr; -#if TARGET_OS_MAC && MAC_OS_X_VERSION_MIN_REQUIRED < 1060 +#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060 atsFont = CTFontGetPlatformFont (new_ct_font, NULL); status = ATSFontGetFileReference (atsFont, &fsref); if (status == noErr) From f92330b5e0b1a5a61768494bd7081e3fc235b182 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2018 17:51:50 +0200 Subject: [PATCH 22/32] Minor --- test/api/test-multithread.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/api/test-multithread.c b/test/api/test-multithread.c index 72a1a178c..58a637cae 100644 --- a/test/api/test-multithread.c +++ b/test/api/test-multithread.c @@ -135,7 +135,7 @@ main (int argc, char **argv) gchar *default_path = g_strdup (font_path); #endif - char *path = argc > 1 ? argv[1] : (char *) default_path; + char *path = argc > 1 && *argv[1] ? argv[1] : (char *) default_path; if (argc > 2) num_threads = atoi (argv[2]); if (argc > 3) @@ -143,8 +143,8 @@ main (int argc, char **argv) if (argc > 4) text = argv[4]; - // Dummy call to alleviate _guess_segment_properties thread safety-ness - // https://github.com/harfbuzz/harfbuzz/issues/1191 + /* Dummy call to alleviate _guess_segment_properties thread safety-ness + * https://github.com/harfbuzz/harfbuzz/issues/1191 */ hb_language_get_default (); hb_blob_t *blob = hb_blob_create_from_file (path); From 856db4c9184e39c0457cc07c815f90058937c8a2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2018 18:21:15 +0200 Subject: [PATCH 23/32] Minor --- src/hb-ot-font.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 280ade5b6..637814d96 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -187,7 +187,7 @@ hb_ot_get_font_v_extents (hb_font_t *font, static void free_static_ot_funcs (void); #endif -static struct hb_ot_face_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t +static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t { static inline hb_font_funcs_t *create (void) { From 13da3be0b342e8e2f060eba8753c6957c477c4ee Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2018 18:23:45 +0200 Subject: [PATCH 24/32] [ot-font] Load hmtx/vmtx lazily Since we have get_*_advanes() API now, the overhead is once per shape, not once per glyph. Only cmap is warmed-up at set_funcs() time now. --- src/hb-ot-font.cc | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 637814d96..fa8d5a3ce 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -73,7 +73,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, void *user_data HB_UNUSED) { const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; - const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx.get_relaxed (); + const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx.get (); for (unsigned int i = 0; i < count; i++) { @@ -93,7 +93,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, void *user_data HB_UNUSED) { const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; - const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx.get_relaxed (); + const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx.get (); for (unsigned int i = 0; i < count; i++) { @@ -162,11 +162,12 @@ hb_ot_get_font_h_extents (hb_font_t *font, void *user_data HB_UNUSED) { const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; - metrics->ascender = font->em_scale_y (ot_face->hmtx.get_relaxed ()->ascender); - metrics->descender = font->em_scale_y (ot_face->hmtx.get_relaxed ()->descender); - metrics->line_gap = font->em_scale_y (ot_face->hmtx.get_relaxed ()->line_gap); + const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx.get (); + metrics->ascender = font->em_scale_y (hmtx.ascender); + metrics->descender = font->em_scale_y (hmtx.descender); + metrics->line_gap = font->em_scale_y (hmtx.line_gap); // TODO Hook up variations. - return ot_face->hmtx.get_relaxed ()->has_font_extents; + return hmtx.has_font_extents; } static hb_bool_t @@ -176,11 +177,12 @@ hb_ot_get_font_v_extents (hb_font_t *font, void *user_data HB_UNUSED) { const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; - metrics->ascender = font->em_scale_x (ot_face->vmtx.get_relaxed ()->ascender); - metrics->descender = font->em_scale_x (ot_face->vmtx.get_relaxed ()->descender); - metrics->line_gap = font->em_scale_x (ot_face->vmtx.get_relaxed ()->line_gap); + const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx.get (); + metrics->ascender = font->em_scale_x (vmtx.ascender); + metrics->descender = font->em_scale_x (vmtx.descender); + metrics->line_gap = font->em_scale_x (vmtx.line_gap); // TODO Hook up variations. - return ot_face->vmtx.get_relaxed ()->has_font_extents; + return vmtx.has_font_extents; } #ifdef HB_USE_ATEXIT @@ -244,10 +246,8 @@ hb_ot_font_set_funcs (hb_font_t *font) if (unlikely (!hb_ot_shaper_face_data_ensure (font->face))) return; hb_ot_face_data_t *ot_face = hb_ot_face_data (font->face); - /* Load them lazies. We access them with get_relaxed() for performance. */ + /* Load them lazy. We access it with get_relaxed() for performance. */ ot_face->cmap.get (); - ot_face->hmtx.get (); - ot_face->vmtx.get (); hb_font_set_funcs (font, _hb_ot_get_font_funcs (), From 71b65eb27dd0867f51d9906887b9e372eb37f54a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2018 18:41:52 +0200 Subject: [PATCH 25/32] Add API for setting invisible-codepoint Fixes https://github.com/harfbuzz/harfbuzz/issues/1216 New API: hb_buffer_set_invisible_codepoint() hb_buffer_get_invisible_codepoint() hb-shape / hb-view --invisible-codepoint --- docs/harfbuzz-sections.txt | 2 ++ src/hb-buffer.cc | 42 ++++++++++++++++++++++++++++++++++++++ src/hb-buffer.h | 7 +++++++ src/hb-buffer.hh | 1 + src/hb-ot-shape.cc | 8 ++++---- util/options.cc | 1 + util/options.hh | 3 +++ 7 files changed, 60 insertions(+), 4 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index b69c16860..7426a43a3 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -67,6 +67,8 @@ hb_buffer_set_user_data hb_buffer_get_user_data hb_buffer_get_glyph_infos hb_buffer_get_glyph_positions +hb_buffer_get_invisible_codepoint +hb_buffer_set_invisible_codepoint hb_buffer_set_replacement_codepoint hb_buffer_get_replacement_codepoint hb_buffer_normalize_glyphs diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index b93b243c9..0b8593f84 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -219,6 +219,7 @@ hb_buffer_t::reset (void) unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ()); flags = HB_BUFFER_FLAG_DEFAULT; replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; + invisible = 0; clear (); } @@ -665,6 +666,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) = HB_BUFFER_FLAG_DEFAULT, HB_BUFFER_CLUSTER_LEVEL_DEFAULT, HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, + 0, /* invisible */ HB_BUFFER_SCRATCH_FLAG_DEFAULT, HB_BUFFER_MAX_LEN_DEFAULT, HB_BUFFER_MAX_OPS_DEFAULT, @@ -1166,6 +1168,46 @@ hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer) } +/** + * hb_buffer_set_invisible_codepoint: + * @buffer: an #hb_buffer_t. + * @invisible: the invisible #hb_codepoint_t + * + * Sets the #hb_codepoint_t that replaces invisible characters in + * the shaping result. If set to zero (default), the glyph for the + * U+0020 SPACE character is used. Otherwise, this value is used + * verbatim. + * + * Since: REPLACEME + **/ +void +hb_buffer_set_invisible_codepoint (hb_buffer_t *buffer, + hb_codepoint_t invisible) +{ + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->invisible = invisible; +} + +/** + * hb_buffer_get_invisible_codepoint: + * @buffer: an #hb_buffer_t. + * + * See hb_buffer_set_invisible_codepoint(). + * + * Return value: + * The @buffer invisible #hb_codepoint_t. + * + * Since: REPLACEME + **/ +hb_codepoint_t +hb_buffer_get_invisible_codepoint (hb_buffer_t *buffer) +{ + return buffer->invisible; +} + + /** * hb_buffer_reset: * @buffer: an #hb_buffer_t. diff --git a/src/hb-buffer.h b/src/hb-buffer.h index 4c746f401..d99ae7d64 100644 --- a/src/hb-buffer.h +++ b/src/hb-buffer.h @@ -341,6 +341,13 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, HB_EXTERN hb_codepoint_t hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer); +HB_EXTERN void +hb_buffer_set_invisible_codepoint (hb_buffer_t *buffer, + hb_codepoint_t invisible); + +HB_EXTERN hb_codepoint_t +hb_buffer_get_invisible_codepoint (hb_buffer_t *buffer); + HB_EXTERN void hb_buffer_reset (hb_buffer_t *buffer); diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh index 33ddcbc87..9126822eb 100644 --- a/src/hb-buffer.hh +++ b/src/hb-buffer.hh @@ -93,6 +93,7 @@ struct hb_buffer_t hb_buffer_flags_t flags; /* BOT / EOT / etc. */ hb_buffer_cluster_level_t cluster_level; hb_codepoint_t replacement; /* U+FFFD or something else. */ + hb_codepoint_t invisible; /* 0 or something else. */ hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ unsigned int max_len; /* Maximum allowed len. */ int max_ops; /* Maximum allowed operations. */ diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 453d995a2..3b79ef460 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -548,15 +548,15 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) if (i == count) return; - hb_codepoint_t space; + hb_codepoint_t invisible = c->buffer->invisible; if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) && - c->font->get_nominal_glyph (' ', &space)) + (invisible || c->font->get_nominal_glyph (' ', &invisible))) { - /* Replace default-ignorables with a zero-advance space glyph. */ + /* Replace default-ignorables with a zero-advance invisible glyph. */ for (/*continue*/; i < count; i++) { if (_hb_glyph_info_is_default_ignorable (&info[i])) - info[i].codepoint = space; + info[i].codepoint = invisible; } } else diff --git a/util/options.cc b/util/options.cc index bfb11b457..8e17df2a6 100644 --- a/util/options.cc +++ b/util/options.cc @@ -415,6 +415,7 @@ shape_options_t::add_options (option_parser_t *parser) {"eot", 0, 0, G_OPTION_ARG_NONE, &this->eot, "Treat text as end-of-paragraph", nullptr}, {"preserve-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->preserve_default_ignorables, "Preserve Default-Ignorable characters", nullptr}, {"remove-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->remove_default_ignorables, "Remove Default-Ignorable characters", nullptr}, + {"invisible-codepoint",0, 0, G_OPTION_ARG_INT, &this->invisible_codepoint, "Value to replace Default-Ignorables with", nullptr}, {"utf8-clusters", 0, 0, G_OPTION_ARG_NONE, &this->utf8_clusters, "Use UTF8 byte indices, not char indices", nullptr}, {"cluster-level", 0, 0, G_OPTION_ARG_INT, &this->cluster_level, "Cluster merging level (default: 0)", "0/1/2"}, {"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", nullptr}, diff --git a/util/options.hh b/util/options.hh index 40e1ab892..3d7b96dd9 100644 --- a/util/options.hh +++ b/util/options.hh @@ -155,6 +155,7 @@ struct shape_options_t : option_group_t num_features = 0; shapers = nullptr; utf8_clusters = false; + invisible_codepoint = 0; cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT; normalize_glyphs = false; verify = false; @@ -185,6 +186,7 @@ struct shape_options_t : option_group_t (preserve_default_ignorables ? HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES : 0) | (remove_default_ignorables ? HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES : 0) | 0)); + hb_buffer_set_invisible_codepoint (buffer, invisible_codepoint); hb_buffer_set_cluster_level (buffer, cluster_level); hb_buffer_guess_segment_properties (buffer); } @@ -435,6 +437,7 @@ struct shape_options_t : option_group_t unsigned int num_features; char **shapers; hb_bool_t utf8_clusters; + hb_codepoint_t invisible_codepoint; hb_buffer_cluster_level_t cluster_level; hb_bool_t normalize_glyphs; hb_bool_t verify; From fdce1e15434f14b7f4802edd67f7af737cf2b075 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2018 14:01:33 -0400 Subject: [PATCH 26/32] [kerx] Clean up kerx and KerxTable structures --- src/hb-aat-layout-kerx-table.hh | 171 +++++++++++++++++++++----------- src/hb-aat-layout-morx-table.hh | 2 +- 2 files changed, 114 insertions(+), 59 deletions(-) diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 615a8f8d4..21fd26b4f 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -30,7 +30,6 @@ #include "hb-open-type.hh" #include "hb-aat-layout-common.hh" -#include "hb-aat-layout-ankr-table.hh" /* * kerx -- Extended Kerning @@ -71,6 +70,14 @@ struct KerxSubTableFormat0 // return 0; // return pairs[i].get_kerning (); // } + inline bool apply (hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + /* TODO */ + + return_trace (true); + } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -96,6 +103,15 @@ struct KerxSubTableFormat0 struct KerxSubTableFormat1 { + inline bool apply (hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + /* TODO */ + + return_trace (true); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -145,6 +161,15 @@ struct KerxSubTableFormat2 return *v; } + inline bool apply (hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + /* TODO */ + + return_trace (true); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -172,6 +197,15 @@ struct KerxSubTableFormat2 struct KerxSubTableFormat4 { + inline bool apply (hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + /* TODO */ + + return_trace (true); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -199,6 +233,15 @@ struct KerxSubTableFormat4 struct KerxSubTableFormat6 { + inline bool apply (hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + /* TODO */ + + return_trace (true); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -221,47 +264,55 @@ struct KerxSubTableFormat6 DEFINE_SIZE_STATIC (24); }; -enum coverage_flags_t -{ - COVERAGE_VERTICAL_FLAG = 0x80u, - COVERAGE_CROSSSTREAM_FLAG = 0x40u, - COVERAGE_VARIATION_FLAG = 0x20u, - COVERAGE_PROCESS_DIRECTION = 0x10u, -}; - struct KerxTable { - inline bool apply (hb_aat_apply_context_t *c, const AAT::ankr *ankr) const - { - TRACE_APPLY (this); - /* TODO */ - return_trace (false); - } - inline unsigned int get_size (void) const { return length; } + inline unsigned int get_type (void) const { return coverage & SubtableType; } + + enum Coverage + { + Vertical = 0x80000000, /* Set if table has vertical kerning values. */ + CrossStream = 0x40000000, /* Set if table has cross-stream kerning values. */ + Variation = 0x20000000, /* Set if table has variation kerning values. */ + ProcessDirection = 0x10000000, /* If clear, process the glyphs forwards, that + * is, from first to last in the glyph stream. + * If we, process them from last to first. + * This flag only applies to state-table based + * 'kerx' subtables (types 1 and 4). */ + Reserved = 0x0FFFFF00, /* Reserved, set to zero. */ + SubtableType = 0x000000FF, /* Subtable type. */ + }; + + template + inline typename context_t::return_t dispatch (context_t *c) const + { + unsigned int subtable_type = get_type (); + TRACE_DISPATCH (this, subtable_type); + switch (subtable_type) { + case 0 : return_trace (c->dispatch (u.format0)); + case 1 : return_trace (c->dispatch (u.format1)); + case 2 : return_trace (c->dispatch (u.format2)); + case 4 : return_trace (c->dispatch (u.format4)); + case 6 : return_trace (c->dispatch (u.format6)); + default: return_trace (c->default_return_value ()); + } + } inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) + if (!length.sanitize (c) || + length < min_size || + !c->check_range (this, length)) return_trace (false); - switch (format) { - case 0: return u.format0.sanitize (c); - case 1: return u.format1.sanitize (c); - case 2: return u.format2.sanitize (c); - case 4: return u.format4.sanitize (c); - case 6: return u.format6.sanitize (c); - default:return_trace (false); - } + return_trace (dispatch (c)); } protected: HBUINT32 length; - HBUINT8 coverage; - HBUINT16 unused; - HBUINT8 format; - HBUINT32 tupleIndex; + HBUINT32 coverage; + HBUINT32 tupleCount; union { KerxSubTableFormat0 format0; KerxSubTableFormat1 format1; @@ -273,7 +324,7 @@ public: DEFINE_SIZE_MIN (12); }; -struct SubtableGlyphCoverageArray +struct SubtableXXX { inline bool sanitize (hb_sanitize_context_t *c) const { @@ -289,55 +340,59 @@ struct SubtableGlyphCoverageArray DEFINE_SIZE_STATIC (12); }; + +/* + * The 'kerx' Table + */ + struct kerx { static const hb_tag_t tableTag = HB_AAT_TAG_kerx; - inline bool apply (hb_aat_apply_context_t *c, const AAT::ankr *ankr) const + inline bool has_data (void) const { return version != 0; } + + inline void apply (hb_aat_apply_context_t *c) const { - TRACE_APPLY (this); - const KerxTable &table = StructAfter (*this); - return_trace (table.apply (c, ankr)); + c->set_lookup_index (0); + const KerxTable *table = &firstTable; + unsigned int count = tableCount; + for (unsigned int i = 0; i < count; i++) + { + table->dispatch (c); + table = &StructAfter (*table); + } } inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (unlikely (!(c->check_struct (this)))) - return_trace (false); - - /* TODO: Something like `morx`s ChainSubtable should be done here instead */ - const KerxTable *table = &StructAfter (*this); - if (unlikely (!(table->sanitize (c)))) + if (!version.sanitize (c) || version < 2 || + !tableCount.sanitize (c)) return_trace (false); - for (unsigned int i = 0; i < nTables - 1; ++i) + const KerxTable *table = &firstTable; + unsigned int count = tableCount; + for (unsigned int i = 0; i < count; i++) { + if (!table->sanitize (c)) + return_trace (false); table = &StructAfter (*table); - if (unlikely (!(table->sanitize (c)))) - return_trace (false); } - // If version is less than 3, we are done here; otherwise better to check footer also - if (version < 3) - return_trace (true); - - // TODO: Investigate why this just work on some fonts no matter of version - // const SubtableGlyphCoverageArray &footer = - // StructAfter (*table); - // return_trace (footer.sanitize (c)); - return_trace (true); } protected: - HBUINT16 version; - HBUINT16 padding; - HBUINT32 nTables; -/*KerxTable tablesZ[VAR]; XXX ArrayOf??? */ -/*SubtableGlyphCoverageArray coverage_array;*/ + HBUINT16 version; /* The version number of the extended kerning table + * (currently 2, 3, or 4). */ + HBUINT16 unused; /* Set to 0. */ + HBUINT32 tableCount; /* The number of subtables included in the extended kerning + * table. */ + KerxTable firstTable; /* Subtables. */ +/*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */ + public: - DEFINE_SIZE_STATIC (8); + DEFINE_SIZE_MIN (8); }; } /* namespace AAT */ diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index e9869036c..63b937ba1 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -940,7 +940,7 @@ struct Chain /* - * The 'mort'/'morx' Tables + * The 'morx' Table */ struct morx From c07b91b812dc66b38b11329cd6a93258a3769f9e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2018 18:00:14 -0400 Subject: [PATCH 27/32] [test/text-rendering-tests] Update from upstream --- .../data/text-rendering-tests/Makefile.sources | 6 +++++- .../text-rendering-tests/fonts/TestMORXForty.ttf | Bin 0 -> 2408 bytes .../fonts/TestMORXThirtyeight.ttf | Bin 0 -> 2444 bytes .../fonts/TestMORXThirtynine.ttf | Bin 0 -> 2436 bytes .../fonts/TestMORXThirtyseven.ttf | Bin 0 -> 2444 bytes .../text-rendering-tests/tests/MORX-35.tests | 4 ++-- .../text-rendering-tests/tests/MORX-37.tests | 4 ++++ .../text-rendering-tests/tests/MORX-38.tests | 4 ++++ .../text-rendering-tests/tests/MORX-39.tests | 4 ++++ .../text-rendering-tests/tests/MORX-40.tests | 4 ++++ 10 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 test/shaping/data/text-rendering-tests/fonts/TestMORXForty.ttf create mode 100644 test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyeight.ttf create mode 100644 test/shaping/data/text-rendering-tests/fonts/TestMORXThirtynine.ttf create mode 100644 test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyseven.ttf create mode 100644 test/shaping/data/text-rendering-tests/tests/MORX-37.tests create mode 100644 test/shaping/data/text-rendering-tests/tests/MORX-38.tests create mode 100644 test/shaping/data/text-rendering-tests/tests/MORX-39.tests create mode 100644 test/shaping/data/text-rendering-tests/tests/MORX-40.tests diff --git a/test/shaping/data/text-rendering-tests/Makefile.sources b/test/shaping/data/text-rendering-tests/Makefile.sources index 29d064b70..5a3d20a6c 100644 --- a/test/shaping/data/text-rendering-tests/Makefile.sources +++ b/test/shaping/data/text-rendering-tests/Makefile.sources @@ -56,7 +56,11 @@ TESTS = \ tests/MORX-33.tests \ tests/MORX-34.tests \ tests/MORX-36.tests \ + tests/MORX-37.tests \ + tests/MORX-38.tests \ + tests/MORX-39.tests \ tests/MORX-3.tests \ + tests/MORX-40.tests \ tests/MORX-4.tests \ tests/MORX-5.tests \ tests/MORX-6.tests \ @@ -68,8 +72,8 @@ TESTS = \ $(NULL) DISBALED_TESTS = \ - tests/MORX-35.tests \ tests/CMAP-3.tests \ + tests/MORX-35.tests \ tests/SHARAN-1.tests \ tests/SHBALI-1.tests \ tests/SHBALI-2.tests \ diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXForty.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXForty.ttf new file mode 100644 index 0000000000000000000000000000000000000000..37d0b637778833a1f9c3c16b21e3025e0bab48e0 GIT binary patch literal 2408 zcma)8Uu;uV82`?>y=@0$ShlW=EnVx~R-9Yede?T0Wp)FGclV1j}p#LWlvMTroV2V;D|L?yKT&TWSqMdP_S_k7=X zzCXY3JLjHri4oCKIzbXuwFcLCB1OXz5vzrCfA^3!O8bl*;ID$;&^I{I`)l#%W+Glh zB<+fXwH}Ln?I`9xMfXJ@FddPe2mJuOBr+5qxBbFxus;jFY;dGoGicH@>L=OhO(+yI6f z&=UxWJ>a5}4rIHRI)#KEN1r4OT5Y0p_~&-A3mT8Ef*00|^6(a3@_@MtqZyCL*g;M5 zTr#Osjq+?VnfxL7*^btK|#jK8vvx|^&fr0(WXW-dHli#Fk6f}?-nM0 z40SNuPL}@?m(Ass*~RND-|qO1-+H8qJT!#ejfl@s0X+*(o_uSb(PXuA42ojO_4vFs zWr||8sA-B-o}6rMs%$Ag8GHDB$HrjCp{cIT+q&Q6Gdr{wg4wdUtl6&(@R`Kyy1I4h zy~M|x>uWcPNNwqzkxL3;&l=p^ThqW*j|i2+70KuGmwDByJjAxy6q8@IsgfeG^V4I2 zz}WPjJ?U||F^4n8vX)5s`>G3HE9{?~nDht6&V)kK(Lf+N9SWTp3$W|C^((l<4B2HR zOSfGJh1lst6zjAYLro?Mzn-Pb>r16=$yGgiA*`xi7)8mzQ?RMkU0k$!^X^kxX?;QQ zbCu4*LWes8(d`DGd$oy~%3amfi8x#DTCs9dQJ%FBB_|Kopn~tfo*;jX&+k%meO|9B z*1@JoMypk+4XiyraHpj`u=doz&n@leyN=jDNnEZtb@rXEiQ?;QZ{_RwfEm6R;xha! zhaaa!ESp!rwy0L8oxRZDpPB9L-kvB3GIz5t*xsGE8Wel(pPH0s*2Cqk@!M1v%HdT6 zAeUk@0#Qa4LbkV~2VA8Gva{bBYcDO$Oh49O|LPTMTW#OV&gz_-N3CtXkwvkw_nzDl zey`%K!PXNwSe49}Gd1s>J6pVJE;Cs0(qzzH@&VFA%c7|GQVm(4>(Ns*qgCKiG^ZTe zlco(+jx#4EH-bK$rn8`bB~345cKSL^=g@ZcTbjb(20Vd02hY0gEWXQHu@iW zj{mJ$`GjT=o?}1}!H6>qQ8YS?s3KYfcw>+XJi~fMK~TM*4(oWrm`iC4>Y0V16@zUL zM%cz66|o(tpWuphf%Cn9GL284IWVqv5KRR#Sm3s7{n;nq!070sK?gF zHnFsoSp8J~Bgj1pAK?Wyi;>12d#Oz4)riWA>Nn!Xnw96oy(Q0L*NU43EqPg-7EftQ zAd{$sN*QMoGcpr1Fj;PNYlCsQNxYXH9PY33Zm3#7R}0#dmZ!&R_({cLphOopq>!-r zyBRl{xZT9ue0vu^4DX5&pJPziojH z6F?)Pi!swUBoT>;#Dp)z82Kb0z-Yh`;^qhRgG$7x#27yzi4t0W_qBtKVxsruzI*Pu z=lss^oOj>7#E57q9V3YE~ z-Y0u6cP+2|lO*XjG<4(0t2QxybMx-kM2Rn@DM?rwhzl(mX435ha@6dZG^HUW*OKoH zO|yjDB$x^hPF9j3^=NarO3$(>XpDT4w?Vf#IkHZ2u`*#Jj33tmn|E&`AKBzN$p#Kr z!9ipz7!td~MI~*>b~kkj4L^!LNkLe(iOzw~tz;E49?b+Vd^5_yTcG5Ca|K2t9+9z) z8sxb|LX+y{*+e4oW8(7Po@7L5MKj}BOT+XL-D8EUhK;jx&~m|n{l#a1Y#_?Eo9x9V zyQ!1C8xOO-_%%Lr-=p%L`=^tY`y7{zrRAB0>rCHn|DIpJuZlc^2-}K?Pf#8`2_#ppIY)0WTR8?rF=e|v z?y3?+F`Lws#LACPHa3(ul^&1Y`=Mi_zvJLkSM%1;YkX#V@EL!mY%FQ?1_$^|e0E*U zI`yac$IZ3X8%3nH)XvBzg|KIJPVTO%b#Nqjc9plwpkb}M_P&O0-^KeR2L=V#7FkH0+>zvLHt?qN+z)9c}IS9vX}1Lbfl zf{;V8=)owh3IWTTk#0wEcV_16W9`Mo>FG!7tY5uoZmaHn-d>q??FDn2XJk=q?7c^K zgx9UOtFZM%4rV1i=1kQ)r%x5GnoAGnKR@ZW7JY#9&@w0@{#0ECK@_JT#h;^^iYI$r-eYzDvo=n3e9PX+4bqVFFS6sh9dFh7;i& zx(la7B~?QT;Lq=;5bSy=Ol8nCK@%b;&gL*h;jxukXeZ8_R`~Y=DF(do1H7G(d+7iT z;_r?8M;{yT{=ZlGBVK+)jDl$&Mx1kq9;8FS6)XhPD71~pYgo(L4{1N7LmJO8){+*3 z7(?(HhJ6?{upyUWtrii;F(3(BKdQ0?V+*P&Y!@PLS%hGtU9gA%tzV06L!F&kw=Lkc zIO;r?ARPp|eyx_>c#Ft~Fc&OrT9%DePdhX@Ml~447ma~a4Xwc=sv*AgD0ERo6&waJ zjzHUs^%m4)%LAWi%1i8!Wd0+_J)%|Pq0eHb(FZ8ysl4h@c~Sj(+-kG(oVeTMS?p|a z`=BK*h!f>8Z3%P|6;UzcOk#RwU^*tt_0Hg6Ol}bGr3Z%lE8H6@7RZ%CHl*~au@X4R zSPYWr;uaMeHh+KP))P0NSetKexw-kUEPHUtHek6Ik^YuD;mt(aG3fj>HX4gJb^UxB`_Q2w64=q7 z>+QVWy|V5PlBB!f(9NT-TgCkKtv|mdN`5I#OF~jlTyW8_lI|uEqbkp&Y1L9{FEwVV zoMq%DfmCR4vXB;3pSp&s^gNpe$H1p}J9yhtGwUKJs}M3m_(?6WZQoAvkySe{S%Kji zFkFM2KuGK!7n!so+I`d|IQ$s;6a^vGE;@&OZXt`H@u?yhaAuT;QCP_X<|@nvd?I2i zHEQRRNtJ5Q&Lxw{ACjN{?MZnAS2Pp8^%S9x={_rFwQPc20GA64>@PkG%X*?*o6%Nk zv>ChD`-y%wn7GboA9xhr_uyloD~{_QMdbc zVd74plbLt3{1>^_P+pl`yutX*uJ8Db2a1Rz2)AwU_!Je;)3D^sH|6Q{CJV^mjR8wPRbNR{G{qH-s_&X0xcem^ay}@U91vmP$wT7}LZ*YjuCgwKO zZcu(qe9}@^vqgAnPv4AOk_mTKUvwrAI6dxTS99xDafxZN z%Sx8-I3EbGw-QmD(^3qsOcY)5p4P3O=~o|C3?DWAVUn`o5AXcAt-G(dwC$BS?Q z-HBJCnrc7=;2}&Q$n{Y_Re;kBPKX?MoBJsSjUCiVd+^@0K|c&jao7_&5$x|lAE1LY zjDI)!pERuhL#OgF9Y4IqfN>BrUO0FT(qSMG2n5C$xJ`&CqQ>h7bpX_16=Og4QWC?M zL(qyqz8}$B5l2MLLKJiymV~Sy`Ph!R6?qi0i!E+p$eh%+7oF9xpy!!YJi za0js8ihOK;s1r+TiMx@Ce-yDt)oeV{S&B6F&`M=Gt_EaYWWNFRY)(5bs+x8#RSi&i zFNv4r32m8r>r1GVaV9Yx(=!dzY8xEE;kdR@jLQ#3!d33gRg36qLF?1}^jr-)qQZ%{ zCe=mt6dbltw^8jx7#NHnW7ye*iq0#$Nyc literal 0 HcmV?d00001 diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyseven.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyseven.ttf new file mode 100644 index 0000000000000000000000000000000000000000..22057f18cc8c94699919107bf8d4e96db43744d6 GIT binary patch literal 2444 zcmbVNZETZO6h8O9{Ths6*}5{ebZ>pP73WsAzH2+i0^NY&#>arJFgD%jwz3cR*%sI^ z0W>1I7&DDS5(!2nCj24BgkNfci3A)WZizvEs6>oPjL|=6qJ-AxzI}%q#l(1<``&ZU zJ?A;kIrsKnVnno*j*~$UNSh+9X5oeY4{s3&m9Vn zkJ1rp!TL(f<)M-2xLp6-1tQB;%s(9t4@H_T5Bx@C9EH!%qa(3+L&uM|u>K_02S{*7 z|M;D^FLo}k{hcJ~HZ*kO=!>!#zr6WHB~kJ-X-X27X5vDNhM9Cbi5xY1CQWHbskPKM zL(?oFFA1i?gOh`dkb1N^T%{-26f_n-$y=e@ni^RLd03gS5ylT|p{;v&P=I9PoFs$8 zRd5j53Wmh)a8XGa+3uwdq2b5SCn*f8R?#`|xq}=+#!oZB2YW_2_zIL9aIU~;!B1o? zQ@wF6DRxPwI^%3InfxyK$zMLr7D}zz$VO{vnBJ$mtdP~PadsYhE;z71`3#WFMA=TO zv)JmicCa@S5!RQu#%J#NRNiy%OscZ{D8Eh_WQC8LyG$mtS+zUO3R9WF_DfmI3>K?t z*RA}-521Eu-^FsD;zmnpd1m1{>sLF!;n(k}B9Ab_wjkmolt+&O$&+i#F_~=+jzLkZ z*&d&_szgz2R#lf+`H9Jf`truo6S2GBwr>u$ADZfH+TQ&VpV=AS5X>}MN*es(0X~zM zU01VC{XX$QQ*HHT5vf%_8QG)|&aA=By;bYE>Jg!`xFY#{{t~ZRk%QQFyJGgMc2!a& zc6NF!5Ez@@vqvA7o3c1#EMtk3yRS0;`TYLLiAjH8>{KW;9SsDc)1lC*u>iZ0UAuxy z%#c}9v~>HqP>8*fh+>}>bEryZ;n%Wsd3~w0t=XzaD}+te3Zp1#eDbz5y9*0eH?^D$ z7uV($K349`&zIe4jBc#=xmTN+xztrznTWHEt`#e{6y(_QQF8KN56bvXoC)$*`TQ<5 z+voMFVjt{^WU|?m>cHA#12-Gn0&7nW{M6WXw)2SN!^Fk1lc!(noG84)_LjeJPT)9z zV+77};5e;f+q{CdRkb-CY{Pp0%cZQY4WL2>5(sYz*iJzU-@zg=~q z99~5baw&Eb7^PJqWPdf<iA?;<_442p_>sv!e%EqY33RDxMb z=9EQUx@;gHjq0)q@_V|RL96I%U0%i<^oK5I(GITN1i;UxT;4?+X#@xph}uuR)JJjL z1Lx5_xFss78d3=V{C?_&T@OX544Ou0y2*{ZIYKdbY^P@0jr*nr{{29T122ZPL+Ha; zi2(T^4dUM${f|EK|MDt-z$=J|F);1JhF8)et*93SA6Q1&2Y5 zBhdC@y&3-7?)$`aFL6Rr`Hvv?C@>-md=@i}-A5_c^QuGTMfL0Os?8eb#M@?^#mN@0 z4_fk~xKSR`mOv*_5fwAeBxYh}W?)8RojW`jH`a^q(u2eO72Zu13*<^6n{~ZD;+5B9 zF-W3|S5!o2^Y1raJ@EpHwfXkCoSF-r2|WiLH!!LrUU?Hd4S0nF3Wp@&K^HnR88sxR awYCsZXQ9Pn$4QSlZ)x}!ObakG1m@pV Date: Sun, 7 Oct 2018 18:52:12 -0400 Subject: [PATCH 28/32] Remove some code We use scratch-flags to short-circuit this function. No need for previous early loop. --- src/hb-ot-shape.cc | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 3b79ef460..4e5bd4e9b 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -537,23 +537,13 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; hb_glyph_position_t *pos = buffer->pos; - unsigned int i = 0; - for (i = 0; i < count; i++) - { - if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i]))) - break; - } - - /* No default-ignorables found; return. */ - if (i == count) - return; hb_codepoint_t invisible = c->buffer->invisible; if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) && (invisible || c->font->get_nominal_glyph (' ', &invisible))) { /* Replace default-ignorables with a zero-advance invisible glyph. */ - for (/*continue*/; i < count; i++) + for (unsigned int i = 0; i < count; i++) { if (_hb_glyph_info_is_default_ignorable (&info[i])) info[i].codepoint = invisible; @@ -563,8 +553,8 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) { /* Merge clusters and delete default-ignorables. * NOTE! We can't use out-buffer as we have positioning data. */ - unsigned int j = i; - for (; i < count; i++) + unsigned int j = 0; + for (unsigned int i = 0; i < count; i++) { if (_hb_glyph_info_is_default_ignorable (&info[i])) { From f62f6e90ad1f1a83f77771ad65ee1ffb79470a8a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2018 18:06:53 -0400 Subject: [PATCH 29/32] [morx] Fix MORX-35 Fixes https://github.com/harfbuzz/harfbuzz/issues/1224 --- src/hb-aat-layout-morx-table.hh | 14 ++++++++++---- test/shaping/data/text-rendering-tests/DISABLED | 3 --- .../data/text-rendering-tests/Makefile.sources | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 63b937ba1..b9dddb2ac 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -661,11 +661,17 @@ struct InsertionSubtable * 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. + * So, if DontAdvance *is* set, we move to "end", such that newly + * inserted glyphs are visible. + * + * If DontAdvance is *not* set, if inserted before, move past them, + * such that original current glyph will be skipped over by the driver. + * Otherwise, again, just move to "end" such that current glyph will + * be skipped over by driver. + * + * https://github.com/harfbuzz/harfbuzz/issues/1224 */ - buffer->move_to ((flags & DontAdvance) ? end : end + count); + buffer->move_to ((flags & DontAdvance) || !before ? end : end + count); } if (flags & SetMark) diff --git a/test/shaping/data/text-rendering-tests/DISABLED b/test/shaping/data/text-rendering-tests/DISABLED index 4e8b1cf24..8539c0ee1 100644 --- a/test/shaping/data/text-rendering-tests/DISABLED +++ b/test/shaping/data/text-rendering-tests/DISABLED @@ -1,6 +1,3 @@ -# https://github.com/harfbuzz/harfbuzz/issues/1224 -tests/MORX-35.tests - # Non-Unicode cmap tests/CMAP-3.tests diff --git a/test/shaping/data/text-rendering-tests/Makefile.sources b/test/shaping/data/text-rendering-tests/Makefile.sources index 5a3d20a6c..c7f487600 100644 --- a/test/shaping/data/text-rendering-tests/Makefile.sources +++ b/test/shaping/data/text-rendering-tests/Makefile.sources @@ -55,6 +55,7 @@ TESTS = \ tests/MORX-32.tests \ tests/MORX-33.tests \ tests/MORX-34.tests \ + tests/MORX-35.tests \ tests/MORX-36.tests \ tests/MORX-37.tests \ tests/MORX-38.tests \ @@ -73,7 +74,6 @@ TESTS = \ DISBALED_TESTS = \ tests/CMAP-3.tests \ - tests/MORX-35.tests \ tests/SHARAN-1.tests \ tests/SHBALI-1.tests \ tests/SHBALI-2.tests \ From 14ebf8af0c04efcae6ca788ac85601bfe462f28d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2018 20:35:06 -0400 Subject: [PATCH 30/32] [buffer] Improve shift_forward() "Improve" is a strong word in this case though, I understand. --- src/hb-buffer.cc | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 0b8593f84..2b7b88646 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -182,7 +182,11 @@ hb_buffer_t::shift_forward (unsigned int count) if (idx + count > len) { /* Under memory failure we might expose this area. At least - * clean it up. Oh well... */ + * clean it up. Oh well... + * + * Ideally, we should at least set Default_Ignorable bits on + * these, as well as consistent cluster values. But the former + * is layering violation... */ memset (info + len, 0, (idx + count - len) * sizeof (info[0])); } len += count; @@ -399,8 +403,14 @@ hb_buffer_t::move_to (unsigned int i) unsigned int count = out_len - i; /* This will blow in our face if memory allocation fails later - * in this same lookup... */ - if (unlikely (idx < count && !shift_forward (count + 32))) return false; + * in this same lookup... + * + * We used to shift with extra 32 items, instead of the 0 below. + * But that would leave empty slots in the buffer in case of allocation + * failures. Setting to zero for now to avoid other problems (see + * comments in shift_forward(). This can cause O(N^2) behavior more + * severely than adding 32 empty slots can... */ + if (unlikely (idx < count && !shift_forward (count + 0))) return false; assert (idx >= count); From 2a5cb37fdb43230217e055f3d7c770a35cfd5c21 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2018 20:36:46 -0400 Subject: [PATCH 31/32] Revert "[morx] Fix MORX-35" This reverts commit f62f6e90ad1f1a83f77771ad65ee1ffb79470a8a. --- src/hb-aat-layout-morx-table.hh | 14 +++++--------- test/shaping/data/text-rendering-tests/DISABLED | 3 +++ .../data/text-rendering-tests/Makefile.sources | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index b9dddb2ac..cf08d7961 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -661,17 +661,13 @@ struct InsertionSubtable * current glyph, the next glyph processed would in fact be the first * one inserted." * - * So, if DontAdvance *is* set, we move to "end", such that newly - * inserted glyphs are visible. + * 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. * - * If DontAdvance is *not* set, if inserted before, move past them, - * such that original current glyph will be skipped over by the driver. - * Otherwise, again, just move to "end" such that current glyph will - * be skipped over by driver. - * - * https://github.com/harfbuzz/harfbuzz/issues/1224 + * https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417 */ - buffer->move_to ((flags & DontAdvance) || !before ? end : end + count); + buffer->move_to ((flags & DontAdvance) ? end : end + count); } if (flags & SetMark) diff --git a/test/shaping/data/text-rendering-tests/DISABLED b/test/shaping/data/text-rendering-tests/DISABLED index 8539c0ee1..4e8b1cf24 100644 --- a/test/shaping/data/text-rendering-tests/DISABLED +++ b/test/shaping/data/text-rendering-tests/DISABLED @@ -1,3 +1,6 @@ +# https://github.com/harfbuzz/harfbuzz/issues/1224 +tests/MORX-35.tests + # Non-Unicode cmap tests/CMAP-3.tests diff --git a/test/shaping/data/text-rendering-tests/Makefile.sources b/test/shaping/data/text-rendering-tests/Makefile.sources index c7f487600..5a3d20a6c 100644 --- a/test/shaping/data/text-rendering-tests/Makefile.sources +++ b/test/shaping/data/text-rendering-tests/Makefile.sources @@ -55,7 +55,6 @@ TESTS = \ tests/MORX-32.tests \ tests/MORX-33.tests \ tests/MORX-34.tests \ - tests/MORX-35.tests \ tests/MORX-36.tests \ tests/MORX-37.tests \ tests/MORX-38.tests \ @@ -74,6 +73,7 @@ TESTS = \ DISBALED_TESTS = \ tests/CMAP-3.tests \ + tests/MORX-35.tests \ tests/SHARAN-1.tests \ tests/SHBALI-1.tests \ tests/SHBALI-2.tests \ From e42cd58c997adafca5517faa9aacf651b90520f5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2018 20:46:11 -0400 Subject: [PATCH 32/32] Rename invisible_codepoint to invisible_glyph in API Deleted recently added API: hb_buffer_set_invisible_codepoint() hb_buffer_get_invisible_codepoint() hb-shape / hb-view --invisible-codepoint New API: hb_buffer_set_invisible_glyph() hb_buffer_get_invisible_glyph() hb-shape / hb-view --invisible-glyph Fixes https://github.com/harfbuzz/harfbuzz/issues/1216 --- docs/harfbuzz-sections.txt | 4 ++-- src/hb-buffer.cc | 12 ++++++------ src/hb-buffer.h | 6 +++--- util/options.cc | 2 +- util/options.hh | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 7426a43a3..455e4f50a 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -67,8 +67,8 @@ hb_buffer_set_user_data hb_buffer_get_user_data hb_buffer_get_glyph_infos hb_buffer_get_glyph_positions -hb_buffer_get_invisible_codepoint -hb_buffer_set_invisible_codepoint +hb_buffer_get_invisible_glyph +hb_buffer_set_invisible_glyph hb_buffer_set_replacement_codepoint hb_buffer_get_replacement_codepoint hb_buffer_normalize_glyphs diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 2b7b88646..2d75d7264 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -1179,7 +1179,7 @@ hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer) /** - * hb_buffer_set_invisible_codepoint: + * hb_buffer_set_invisible_glyph: * @buffer: an #hb_buffer_t. * @invisible: the invisible #hb_codepoint_t * @@ -1191,8 +1191,8 @@ hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer) * Since: REPLACEME **/ void -hb_buffer_set_invisible_codepoint (hb_buffer_t *buffer, - hb_codepoint_t invisible) +hb_buffer_set_invisible_glyph (hb_buffer_t *buffer, + hb_codepoint_t invisible) { if (unlikely (hb_object_is_inert (buffer))) return; @@ -1201,10 +1201,10 @@ hb_buffer_set_invisible_codepoint (hb_buffer_t *buffer, } /** - * hb_buffer_get_invisible_codepoint: + * hb_buffer_get_invisible_glyph: * @buffer: an #hb_buffer_t. * - * See hb_buffer_set_invisible_codepoint(). + * See hb_buffer_set_invisible_glyph(). * * Return value: * The @buffer invisible #hb_codepoint_t. @@ -1212,7 +1212,7 @@ hb_buffer_set_invisible_codepoint (hb_buffer_t *buffer, * Since: REPLACEME **/ hb_codepoint_t -hb_buffer_get_invisible_codepoint (hb_buffer_t *buffer) +hb_buffer_get_invisible_glyph (hb_buffer_t *buffer) { return buffer->invisible; } diff --git a/src/hb-buffer.h b/src/hb-buffer.h index d99ae7d64..d0aed02d5 100644 --- a/src/hb-buffer.h +++ b/src/hb-buffer.h @@ -342,11 +342,11 @@ HB_EXTERN hb_codepoint_t hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer); HB_EXTERN void -hb_buffer_set_invisible_codepoint (hb_buffer_t *buffer, - hb_codepoint_t invisible); +hb_buffer_set_invisible_glyph (hb_buffer_t *buffer, + hb_codepoint_t invisible); HB_EXTERN hb_codepoint_t -hb_buffer_get_invisible_codepoint (hb_buffer_t *buffer); +hb_buffer_get_invisible_glyph (hb_buffer_t *buffer); HB_EXTERN void diff --git a/util/options.cc b/util/options.cc index 8e17df2a6..090a9c254 100644 --- a/util/options.cc +++ b/util/options.cc @@ -415,7 +415,7 @@ shape_options_t::add_options (option_parser_t *parser) {"eot", 0, 0, G_OPTION_ARG_NONE, &this->eot, "Treat text as end-of-paragraph", nullptr}, {"preserve-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->preserve_default_ignorables, "Preserve Default-Ignorable characters", nullptr}, {"remove-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->remove_default_ignorables, "Remove Default-Ignorable characters", nullptr}, - {"invisible-codepoint",0, 0, G_OPTION_ARG_INT, &this->invisible_codepoint, "Value to replace Default-Ignorables with", nullptr}, + {"invisible-glyph", 0, 0, G_OPTION_ARG_INT, &this->invisible_glyph, "Glyph value to replace Default-Ignorables with", nullptr}, {"utf8-clusters", 0, 0, G_OPTION_ARG_NONE, &this->utf8_clusters, "Use UTF8 byte indices, not char indices", nullptr}, {"cluster-level", 0, 0, G_OPTION_ARG_INT, &this->cluster_level, "Cluster merging level (default: 0)", "0/1/2"}, {"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", nullptr}, diff --git a/util/options.hh b/util/options.hh index 3d7b96dd9..5088adaba 100644 --- a/util/options.hh +++ b/util/options.hh @@ -155,7 +155,7 @@ struct shape_options_t : option_group_t num_features = 0; shapers = nullptr; utf8_clusters = false; - invisible_codepoint = 0; + invisible_glyph = 0; cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT; normalize_glyphs = false; verify = false; @@ -186,7 +186,7 @@ struct shape_options_t : option_group_t (preserve_default_ignorables ? HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES : 0) | (remove_default_ignorables ? HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES : 0) | 0)); - hb_buffer_set_invisible_codepoint (buffer, invisible_codepoint); + hb_buffer_set_invisible_glyph (buffer, invisible_glyph); hb_buffer_set_cluster_level (buffer, cluster_level); hb_buffer_guess_segment_properties (buffer); } @@ -437,7 +437,7 @@ struct shape_options_t : option_group_t unsigned int num_features; char **shapers; hb_bool_t utf8_clusters; - hb_codepoint_t invisible_codepoint; + hb_codepoint_t invisible_glyph; hb_buffer_cluster_level_t cluster_level; hb_bool_t normalize_glyphs; hb_bool_t verify;