diff --git a/appveyor.yml b/appveyor.yml index bf982199b..21d4ea798 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,25 +28,19 @@ environment: MINGW_CHOST: i686-w64-mingw32 MSYS2_ARCH: i686 - - compiler: cygwin - CYGWIN_PREFIX: C:\Cygwin64 - CYGWIN_ARCH: x86_64 - # Lots of test failures here! - #- compiler: cygwin - # CYGWIN_PREFIX: C:\Cygwin - # CYGWIN_ARCH: x86 - install: - - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --force --noconfirm -Sy && pacman --noconfirm --force -S pacman-mirrors && pacman --force -Syu --noconfirm"' +# - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -Sy && pacman --noconfirm --force -S pacman-mirrors && pacman --force -Syu --noconfirm"' + - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -S --needed mingw-w64-$MSYS2_ARCH-{gcc,freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2}"' - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel" + - set PATH=%PATH%;C:\msys64\mingw64\bin # msys2 is added just for having "ragel" on PATH - 'if "%compiler%"=="cygwin" %CYGWIN_PREFIX%\setup-%CYGWIN_ARCH%.exe -g -q -P cygwin-devel,libfreetype-devel,libcairo-devel,libicu-devel,gcc,gcc-g++,gobject-introspection,libglib2.0-devel,libgraphite2-devel,pkg-config,python2' + - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" vcpkg install glib:%triplet% freetype:%triplet% cairo:%triplet%' build_script: - - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" vcpkg install glib:%triplet% freetype:%triplet% cairo:%triplet%' - 'if "%compiler%"=="msvc" md build' - 'if "%compiler%"=="msvc" cd build' - - 'if "%compiler%"=="msvc" set PATH=%PATH%;C:\Program Files (x86)\MSBuild\14.0\Bin;c:\msys64\mingw64\bin' # msys2 is added just for having "ragel" on PATH + - 'if "%compiler%"=="msvc" set PATH=%PATH%;C:\Program Files (x86)\MSBuild\14.0\Bin' - 'if "%compiler%"=="msvc" if "%platform%"=="ARM" cmake -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -G "%generator%" ../' - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" cmake -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -DHB_BUILD_UTILS=ON -G "%generator%" -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake ../' @@ -54,14 +48,8 @@ build_script: - 'if "%compiler%"=="msvc" msbuild harfbuzz.sln /p:Configuration=%configuration% /p:Platform=%platform%' - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" ctest --output-on-failure -C %configuration%' - - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -Syyu mingw-w64-$MSYS2_ARCH-gcc"' - - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -S --needed mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2}"' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "curl https://raw.githubusercontent.com/mirror/mingw-w64/023eb04c396d4e8d8fcf604cfababc53dae13398/mingw-w64-headers/include/dwrite_1.h > %MINGW_PREFIX%/%MINGW_CHOST%/include/dwrite_1.h"' - - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make; make check || .ci/fail.sh"' - - - 'if "%compiler%"=="cygwin" set PATH=%PATH%;c:\msys64\mingw64\bin' # msys2 is added just for having "ragel" on PATH - - 'if "%compiler%"=="cygwin" curl https://raw.githubusercontent.com/mirror/mingw-w64/023eb04c396d4e8d8fcf604cfababc53dae13398/mingw-w64-headers/include/dwrite_1.h -o %CYGWIN_PREFIX%\usr\include\dwrite_1.h' - - 'if "%compiler%"=="cygwin" %CYGWIN_PREFIX%\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite; make; make check || .ci/fail.sh"' + - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make -j3 check || .ci/fail.sh"' cache: - c:\tools\vcpkg\installed\ @@ -75,5 +63,8 @@ notifications: on_build_failure: true on_build_status_changed: true +# Do not build feature branch with open Pull Requests +skip_branch_with_pr: true + # disable automatic tests test: off diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 000000000..88c0a984a --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,21 @@ +pool: + vmImage: 'VS2017-Win2016' + +variables: + buildPlatform: 'x86' + buildConfiguration: 'Debug' + triplet: 'x86-windows' + +steps: +- script: | + git clone https://github.com/Microsoft/vcpkg + cd vcpkg + .\bootstrap-vcpkg.bat + .\vcpkg integrate install + .\vcpkg install glib:x86-windows freetype:x86-windows cairo:x86-windows + cd .. + cmake -Bbuild -H. -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -DHB_BUILD_UTILS=ON -G "%generator%" -DCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake ../ + msbuild harfbuzz.sln /p:Configuration=Debug /p:Platform=Win32 + cd build + ctest --output-on-failure -C Debug + displayName: Build and test diff --git a/src/Makefile.sources b/src/Makefile.sources index b1cc8946c..07713cc84 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -106,6 +106,8 @@ HB_OT_sources = \ hb-aat-layout-trak-table.hh \ hb-aat-layout.hh \ hb-aat-ltag-table.hh \ + hb-aat-map.cc \ + hb-aat-map.hh \ hb-ot-face.hh \ hb-ot-face.cc \ hb-ot-font.cc \ diff --git a/src/gen-vowel-constraints.py b/src/gen-vowel-constraints.py index 19629abeb..02a338fa5 100755 --- a/src/gen-vowel-constraints.py +++ b/src/gen-vowel-constraints.py @@ -104,7 +104,7 @@ class ConstraintSet (object): s.append ('{}{{\n'.format (indent)) for i in range (len (self._c)): s.append ('{}buffer->next_glyph ();\n'.format (self._indent (depth + 1))) - s.append ('{}buffer->output_glyph (0x25CCu);\n'.format (self._indent (depth + 1))) + s.append ('{}_output_dotted_circle (buffer);\n'.format (self._indent (depth + 1))) s.append ('{}}}\n'.format (indent)) else: s.append ('{}switch (buffer->cur ({}).codepoint)\n'.format(indent, index or '')) @@ -161,11 +161,16 @@ print () print ('#include "hb-ot-shape-complex-vowel-constraints.hh"') print () print ('static void') -print ('_output_with_dotted_circle (hb_buffer_t *buffer)') +print ('_output_dotted_circle (hb_buffer_t *buffer)') print ('{') print (' hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu);') print (' _hb_glyph_info_reset_continuation (&dottedcircle);') +print ('}') print () +print ('static void') +print ('_output_with_dotted_circle (hb_buffer_t *buffer)') +print ('{') +print (' _output_dotted_circle (buffer);') print (' buffer->next_glyph ();') print ('}') print () diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 5577efe86..c663fcc84 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -30,6 +30,7 @@ #include "hb-open-type.hh" #include "hb-aat-layout-common.hh" #include "hb-ot-layout-common.hh" +#include "hb-aat-map.hh" /* * morx -- Extended Glyph Metamorphosis @@ -398,9 +399,6 @@ struct LigatureSubtable if (unlikely (!match_length)) return true; - /* TODO Only when ligation happens? */ - buffer->merge_out_clusters (match_positions[0], buffer->out_len); - unsigned int cursor = match_length; do { @@ -436,6 +434,7 @@ struct LigatureSubtable bool (action & LigActionLast)); if (action & (LigActionStore | LigActionLast)) { + const GlyphID &ligatureData = ligature[ligature_idx]; if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false; hb_codepoint_t lig = ligatureData; @@ -451,6 +450,9 @@ struct LigatureSubtable buffer->skip_glyph (); end--; } + + buffer->move_to (end + 1); + buffer->merge_out_clusters (match_positions[cursor], buffer->out_len); } action_idx++; @@ -839,9 +841,9 @@ struct ChainSubtable struct Chain { - inline void apply (hb_aat_apply_context_t *c) const + inline hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const { - uint32_t flags = defaultFlags; + hb_mask_t flags = defaultFlags; { /* Compute applicable flags. TODO Should move this to planning * stage and take user-requested features into account. */ @@ -849,14 +851,22 @@ struct Chain for (unsigned i = 0; i < count; i++) { const Feature &feature = featureZ[i]; - if (false) /* XXX Check if feature enabled... */ + uint16_t type = feature.featureType; + uint16_t setting = feature.featureSetting; + const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type); + if (info && info->setting == setting) { flags &= feature.disableFlags; flags |= feature.enableFlags; } } } + return flags; + } + inline void apply (hb_aat_apply_context_t *c, + hb_mask_t flags) const + { const ChainSubtable *subtable = &StructAtOffset (&featureZ, featureZ[0].static_size * featureCount); unsigned int count = subtableCount; for (unsigned int i = 0; i < count; i++) @@ -976,6 +986,18 @@ struct morx inline bool has_data (void) const { return version != 0; } + inline void compile_flags (const hb_aat_map_builder_t *mapper, + hb_aat_map_t *map) const + { + const Chain *chain = &firstChain; + unsigned int count = chainCount; + for (unsigned int i = 0; i < count; i++) + { + map->chain_flags.push (chain->compile_flags (mapper)); + chain = &StructAfter (*chain); + } + } + inline void apply (hb_aat_apply_context_t *c) const { if (unlikely (!c->buffer->successful)) return; @@ -984,7 +1006,7 @@ struct morx unsigned int count = chainCount; for (unsigned int i = 0; i < count; i++) { - chain->apply (c); + chain->apply (c, c->plan->aat_map.chain_flags[i]); if (unlikely (!c->buffer->successful)) return; chain = &StructAfter (*chain); } diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index e9da850b3..1e1c7b4f4 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -183,6 +183,14 @@ _get_trak (hb_face_t *face) } +void +hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, + hb_aat_map_t *map) +{ + _get_morx (mapper->face).compile_flags (mapper, map); +} + + hb_bool_t hb_aat_layout_has_substitution (hb_face_t *face) { diff --git a/src/hb-aat-layout.hh b/src/hb-aat-layout.hh index d0eb0190d..aea545689 100644 --- a/src/hb-aat-layout.hh +++ b/src/hb-aat-layout.hh @@ -52,6 +52,9 @@ struct hb_aat_feature_mapping_t HB_INTERNAL const hb_aat_feature_mapping_t * hb_aat_layout_find_feature_mapping (hb_tag_t tag); +HB_INTERNAL void +hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, + hb_aat_map_t *map); HB_INTERNAL hb_bool_t hb_aat_layout_has_substitution (hb_face_t *face); diff --git a/src/hb-aat-map.cc b/src/hb-aat-map.cc new file mode 100644 index 000000000..f2736bfd1 --- /dev/null +++ b/src/hb-aat-map.cc @@ -0,0 +1,62 @@ +/* + * Copyright © 2009,2010 Red Hat, Inc. + * Copyright © 2010,2011,2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-aat-map.hh" + +#include "hb-aat-layout.hh" + + +void hb_aat_map_builder_t::add_feature (hb_tag_t tag, + unsigned int value) +{ + const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag); + if (!mapping) return; + + feature_info_t *info = features.push(); + info->type = mapping->aatFeatureType; + info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable; +} + +void +hb_aat_map_builder_t::compile (hb_aat_map_t &m, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) +{ + /* Sort features and merge duplicates */ + if (features.len) + { + features.qsort (); + unsigned int j = 0; + for (unsigned int i = 1; i < features.len; i++) + if (features[i].type != features[j].type) + features[++j] = features[i]; + features.shrink (j + 1); + } + + hb_aat_layout_compile_map (this, &m); +} diff --git a/src/hb-aat-map.hh b/src/hb-aat-map.hh new file mode 100644 index 000000000..846cdc1a9 --- /dev/null +++ b/src/hb-aat-map.hh @@ -0,0 +1,106 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_AAT_MAP_HH +#define HB_AAT_MAP_HH + +#include "hb.hh" + + +struct hb_ot_shape_plan_t; + +struct hb_aat_map_t +{ + friend struct hb_aat_map_builder_t; + + public: + + inline void init (void) + { + memset (this, 0, sizeof (*this)); + chain_flags.init (); + } + inline void fini (void) + { + chain_flags.fini (); + } + + public: + hb_vector_t chain_flags; +}; + +struct hb_aat_map_builder_t +{ + public: + + HB_INTERNAL hb_aat_map_builder_t (hb_face_t *face_, + const hb_segment_properties_t *props_ HB_UNUSED) : + face (face_) + { + features.init (); + } + + ~hb_aat_map_builder_t (void) + { + features.fini (); + } + + HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1); + + HB_INTERNAL void compile (hb_aat_map_t &m, + const int *coords, + unsigned int num_coords); + + public: + struct feature_info_t + { + uint16_t type; + uint16_t setting; + unsigned seq; /* For stable sorting only. */ + + static int cmp (const void *pa, const void *pb) + { + const feature_info_t *a = (const feature_info_t *) pa; + const feature_info_t *b = (const feature_info_t *) pb; + return (a->type != b->type) ? (a->type < b->type ? -1 : 1) : + (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); + } + + int cmp (const short unsigned int *ty) const + { + return (type != *ty) ? (type < *ty ? -1 : 1) : 0; + } + }; + + public: + hb_face_t *face; + + public: + hb_vector_t features; +}; + + +#endif /* HB_AAT_MAP_HH */ diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh index ae34c92f4..19245e89b 100644 --- a/src/hb-machinery.hh +++ b/src/hb-machinery.hh @@ -118,7 +118,7 @@ static inline Type& StructAfter(TObject &X) #define DEFINE_SIZE_ARRAY_SIZED(size, array) \ DEFINE_SIZE_ARRAY(size, array); \ - inline unsigned int get_size (void) const { return (size - array[0].min_size + array.get_size ()); } + inline unsigned int get_size (void) const { return (size - array.min_size + array.get_size ()); } #define DEFINE_SIZE_ARRAY2(size, array1, array2) \ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh index 5293fdada..935ddd720 100644 --- a/src/hb-ot-hmtx-table.hh +++ b/src/hb-ot-hmtx-table.hh @@ -199,8 +199,8 @@ struct hmtxvmtx #define USE_TYPO_METRICS (1u<<7) if (0 != (os2_table->fsSelection & USE_TYPO_METRICS)) { - ascender = os2_table->sTypoAscender; - descender = os2_table->sTypoDescender; + ascender = abs (os2_table->sTypoAscender); + descender = -abs (os2_table->sTypoDescender); line_gap = os2_table->sTypoLineGap; got_font_extents = (ascender | descender) != 0; } @@ -212,8 +212,8 @@ struct hmtxvmtx num_advances = _hea_table->numberOfLongMetrics; if (!got_font_extents) { - ascender = _hea_table->ascender; - descender = _hea_table->descender; + ascender = abs (_hea_table->ascender); + descender = -abs (_hea_table->descender); line_gap = _hea_table->lineGap; got_font_extents = (ascender | descender) != 0; } diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 45d7dbdcf..fd8109950 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -79,8 +79,8 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, hb_ot_map_feature_flags_t flags, unsigned int value) { - feature_info_t *info = feature_infos.push(); if (unlikely (!tag)) return; + feature_info_t *info = feature_infos.push(); info->tag = tag; info->seq = feature_infos.len; info->max_value = value; @@ -175,6 +175,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, } /* Sort features and merge duplicates */ + if (feature_infos.len) { feature_infos.qsort (); unsigned int j = 0; diff --git a/src/hb-ot-map.hh b/src/hb-ot-map.hh index 40b9921fd..fde85b1dd 100644 --- a/src/hb-ot-map.hh +++ b/src/hb-ot-map.hh @@ -162,7 +162,7 @@ struct hb_ot_map_t hb_mask_t global_mask; hb_vector_t features; - hb_vector_t lookups[2]; /* GSUB/GPOS */ + hb_vector_t lookups[2]; /* GSUB/GPOS */ hb_vector_t stages[2]; /* GSUB/GPOS */ }; diff --git a/src/hb-ot-shape-complex-vowel-constraints.cc b/src/hb-ot-shape-complex-vowel-constraints.cc index e50233924..aae5936a2 100644 --- a/src/hb-ot-shape-complex-vowel-constraints.cc +++ b/src/hb-ot-shape-complex-vowel-constraints.cc @@ -16,11 +16,16 @@ #include "hb-ot-shape-complex-vowel-constraints.hh" static void -_output_with_dotted_circle (hb_buffer_t *buffer) +_output_dotted_circle (hb_buffer_t *buffer) { hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu); _hb_glyph_info_reset_continuation (&dottedcircle); +} +static void +_output_with_dotted_circle (hb_buffer_t *buffer) +{ + _output_dotted_circle (buffer); buffer->next_glyph (); } @@ -83,7 +88,7 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan, { buffer->next_glyph (); buffer->next_glyph (); - buffer->output_glyph (0x25CCu); + _output_dotted_circle (buffer); } break; } diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index e05a67706..065b4d4bf 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -53,6 +53,16 @@ _hb_apply_morx (hb_face_t *face) hb_aat_layout_has_substitution (face); } +hb_ot_shape_planner_t::hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) : + face (master_plan->face_unsafe), + props (master_plan->props), + map (face, &props), + aat_map (face, &props), + apply_morx (_hb_apply_morx (face)), + shaper (apply_morx ? + &_hb_ot_complex_shaper_default : + hb_ot_shape_complex_categorize (this)) {} + void hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, const int *coords, @@ -61,6 +71,8 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.props = props; plan.shaper = shaper; map.compile (plan.map, coords, num_coords); + if (apply_morx) + aat_map.compile (plan.aat_map, coords, num_coords); plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r')); @@ -89,7 +101,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, * Decide who does substitutions. GSUB, morx, or fallback. */ - plan.apply_morx = _hb_apply_morx (face); + plan.apply_morx = apply_morx; /* * Decide who does positioning. GPOS, kerx, kern, or fallback. @@ -217,6 +229,16 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, feature->end == HB_FEATURE_GLOBAL_END) ? F_GLOBAL : F_NONE, feature->value); } + + if (planner->apply_morx) + { + hb_aat_map_builder_t *aat_map = &planner->aat_map; + for (unsigned int i = 0; i < num_user_features; i++) + { + const hb_feature_t *feature = &user_features[i]; + aat_map->add_feature (feature->tag, feature->value); + } + } } @@ -278,13 +300,6 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, hb_ot_shape_planner_t planner (shape_plan); - /* Ugly that we have to do this here... - * If we are going to apply morx, choose default shaper. */ - if (_hb_apply_morx (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); diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh index 93fce2d97..e7d6204a8 100644 --- a/src/hb-ot-shape.hh +++ b/src/hb-ot-shape.hh @@ -30,6 +30,7 @@ #include "hb.hh" #include "hb-ot-map.hh" +#include "hb-aat-map.hh" #include "hb-shape-plan.hh" @@ -39,6 +40,7 @@ struct hb_ot_shape_plan_t hb_segment_properties_t props; const struct hb_ot_complex_shaper_t *shaper; hb_ot_map_t map; + hb_aat_map_t aat_map; const void *data; hb_mask_t frac_mask, numr_mask, dnom_mask; hb_mask_t rtlm_mask; @@ -77,9 +79,11 @@ struct hb_ot_shape_plan_t { memset (this, 0, sizeof (*this)); map.init (); + aat_map.init (); } void fini (void) { map.fini (); + aat_map.fini (); } }; @@ -88,14 +92,12 @@ struct hb_ot_shape_planner_t /* In the order that they are filled in. */ hb_face_t *face; hb_segment_properties_t props; - const struct hb_ot_complex_shaper_t *shaper; hb_ot_map_builder_t map; + hb_aat_map_builder_t aat_map; + bool apply_morx : 1; + const struct hb_ot_complex_shaper_t *shaper; - hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) : - face (master_plan->face_unsafe), - props (master_plan->props), - shaper (nullptr), - map (face, &props) {} + HB_INTERNAL hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan); HB_INTERNAL void compile (hb_ot_shape_plan_t &plan, const int *coords, diff --git a/src/hb-set.hh b/src/hb-set.hh index 7ca329761..5fdad2b71 100644 --- a/src/hb-set.hh +++ b/src/hb-set.hh @@ -669,7 +669,7 @@ struct hb_set_t return nullptr; pages[map.index].init0 (); - memmove (&page_map[i + 1], &page_map[i], (page_map.len - 1 - i) * sizeof (page_map[0])); + memmove (&page_map[i] + 1, &page_map[i], (page_map.len - 1 - i) * sizeof (page_map[0])); page_map[i] = map; } return &pages[page_map[i].index]; diff --git a/test/shaping/data/in-house/Makefile.sources b/test/shaping/data/in-house/Makefile.sources index 6e21ddd4c..e5f105c78 100644 --- a/test/shaping/data/in-house/Makefile.sources +++ b/test/shaping/data/in-house/Makefile.sources @@ -1,5 +1,6 @@ TESTS = \ tests/aat-trak.tests \ + tests/aat-morx.tests \ tests/arabic-fallback-shaping.tests \ tests/arabic-feature-order.tests \ tests/arabic-like-joining.tests \ diff --git a/test/shaping/data/in-house/fonts/TestMORXTwentyeight.ttf b/test/shaping/data/in-house/fonts/TestMORXTwentyeight.ttf new file mode 100644 index 000000000..edabb439c Binary files /dev/null and b/test/shaping/data/in-house/fonts/TestMORXTwentyeight.ttf differ diff --git a/test/shaping/data/in-house/tests/aat-morx.tests b/test/shaping/data/in-house/tests/aat-morx.tests new file mode 100644 index 000000000..4153091d0 --- /dev/null +++ b/test/shaping/data/in-house/tests/aat-morx.tests @@ -0,0 +1 @@ +../fonts/TestMORXTwentyeight.ttf::U+0041,U+0078,U+0045,U+0079,U+0044,U+0079,U+0079:[A_E_D=0+1394|x=0+529|y=0+510|y=5+510|y=6+510]