Merge branch 'master' into cff-subset

This commit is contained in:
Michiharu Ariza 2018-10-25 13:05:06 -07:00
commit 2ebf360102
20 changed files with 296 additions and 51 deletions

View File

@ -28,25 +28,19 @@ environment:
MINGW_CHOST: i686-w64-mingw32 MINGW_CHOST: i686-w64-mingw32
MSYS2_ARCH: i686 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: 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" - 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%"=="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: 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" md build'
- 'if "%compiler%"=="msvc" cd 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 "%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 ../' - '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" msbuild harfbuzz.sln /p:Configuration=%configuration% /p:Platform=%platform%'
- 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" ctest --output-on-failure -C %configuration%' - '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 "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%"=="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"'
- '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"'
cache: cache:
- c:\tools\vcpkg\installed\ - c:\tools\vcpkg\installed\
@ -75,5 +63,8 @@ notifications:
on_build_failure: true on_build_failure: true
on_build_status_changed: true on_build_status_changed: true
# Do not build feature branch with open Pull Requests
skip_branch_with_pr: true
# disable automatic tests # disable automatic tests
test: off test: off

21
azure-pipelines.yml Normal file
View File

@ -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

View File

@ -106,6 +106,8 @@ HB_OT_sources = \
hb-aat-layout-trak-table.hh \ hb-aat-layout-trak-table.hh \
hb-aat-layout.hh \ hb-aat-layout.hh \
hb-aat-ltag-table.hh \ hb-aat-ltag-table.hh \
hb-aat-map.cc \
hb-aat-map.hh \
hb-ot-face.hh \ hb-ot-face.hh \
hb-ot-face.cc \ hb-ot-face.cc \
hb-ot-font.cc \ hb-ot-font.cc \

View File

@ -104,7 +104,7 @@ class ConstraintSet (object):
s.append ('{}{{\n'.format (indent)) s.append ('{}{{\n'.format (indent))
for i in range (len (self._c)): for i in range (len (self._c)):
s.append ('{}buffer->next_glyph ();\n'.format (self._indent (depth + 1))) 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)) s.append ('{}}}\n'.format (indent))
else: else:
s.append ('{}switch (buffer->cur ({}).codepoint)\n'.format(indent, index or '')) 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 ('#include "hb-ot-shape-complex-vowel-constraints.hh"')
print () print ()
print ('static void') print ('static void')
print ('_output_with_dotted_circle (hb_buffer_t *buffer)') print ('_output_dotted_circle (hb_buffer_t *buffer)')
print ('{') print ('{')
print (' hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu);') print (' hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu);')
print (' _hb_glyph_info_reset_continuation (&dottedcircle);') print (' _hb_glyph_info_reset_continuation (&dottedcircle);')
print ('}')
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 (' buffer->next_glyph ();')
print ('}') print ('}')
print () print ()

View File

@ -30,6 +30,7 @@
#include "hb-open-type.hh" #include "hb-open-type.hh"
#include "hb-aat-layout-common.hh" #include "hb-aat-layout-common.hh"
#include "hb-ot-layout-common.hh" #include "hb-ot-layout-common.hh"
#include "hb-aat-map.hh"
/* /*
* morx -- Extended Glyph Metamorphosis * morx -- Extended Glyph Metamorphosis
@ -398,9 +399,6 @@ struct LigatureSubtable
if (unlikely (!match_length)) if (unlikely (!match_length))
return true; return true;
/* TODO Only when ligation happens? */
buffer->merge_out_clusters (match_positions[0], buffer->out_len);
unsigned int cursor = match_length; unsigned int cursor = match_length;
do do
{ {
@ -436,6 +434,7 @@ struct LigatureSubtable
bool (action & LigActionLast)); bool (action & LigActionLast));
if (action & (LigActionStore | LigActionLast)) if (action & (LigActionStore | LigActionLast))
{ {
const GlyphID &ligatureData = ligature[ligature_idx]; const GlyphID &ligatureData = ligature[ligature_idx];
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false; if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false;
hb_codepoint_t lig = ligatureData; hb_codepoint_t lig = ligatureData;
@ -451,6 +450,9 @@ struct LigatureSubtable
buffer->skip_glyph (); buffer->skip_glyph ();
end--; end--;
} }
buffer->move_to (end + 1);
buffer->merge_out_clusters (match_positions[cursor], buffer->out_len);
} }
action_idx++; action_idx++;
@ -839,9 +841,9 @@ struct ChainSubtable
struct Chain 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 /* Compute applicable flags. TODO Should move this to planning
* stage and take user-requested features into account. */ * stage and take user-requested features into account. */
@ -849,14 +851,22 @@ struct Chain
for (unsigned i = 0; i < count; i++) for (unsigned i = 0; i < count; i++)
{ {
const Feature &feature = featureZ[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.disableFlags;
flags |= feature.enableFlags; flags |= feature.enableFlags;
} }
} }
} }
return flags;
}
inline void apply (hb_aat_apply_context_t *c,
hb_mask_t flags) const
{
const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount); const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount);
unsigned int count = subtableCount; unsigned int count = subtableCount;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
@ -976,6 +986,18 @@ struct morx
inline bool has_data (void) const { return version != 0; } 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> (*chain);
}
}
inline void apply (hb_aat_apply_context_t *c) const inline void apply (hb_aat_apply_context_t *c) const
{ {
if (unlikely (!c->buffer->successful)) return; if (unlikely (!c->buffer->successful)) return;
@ -984,7 +1006,7 @@ struct morx
unsigned int count = chainCount; unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++) 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; if (unlikely (!c->buffer->successful)) return;
chain = &StructAfter<Chain> (*chain); chain = &StructAfter<Chain> (*chain);
} }

View File

@ -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_bool_t
hb_aat_layout_has_substitution (hb_face_t *face) hb_aat_layout_has_substitution (hb_face_t *face)
{ {

View File

@ -52,6 +52,9 @@ struct hb_aat_feature_mapping_t
HB_INTERNAL const hb_aat_feature_mapping_t * HB_INTERNAL const hb_aat_feature_mapping_t *
hb_aat_layout_find_feature_mapping (hb_tag_t tag); 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_INTERNAL hb_bool_t
hb_aat_layout_has_substitution (hb_face_t *face); hb_aat_layout_has_substitution (hb_face_t *face);

62
src/hb-aat-map.cc Normal file
View File

@ -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);
}

106
src/hb-aat-map.hh Normal file
View File

@ -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<hb_mask_t, 1> 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<feature_info_t, 32> features;
};
#endif /* HB_AAT_MAP_HH */

View File

@ -118,7 +118,7 @@ static inline Type& StructAfter(TObject &X)
#define DEFINE_SIZE_ARRAY_SIZED(size, array) \ #define DEFINE_SIZE_ARRAY_SIZED(size, array) \
DEFINE_SIZE_ARRAY(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 DEFINE_SIZE_ARRAY2(size, array1, array2) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \

View File

@ -199,8 +199,8 @@ struct hmtxvmtx
#define USE_TYPO_METRICS (1u<<7) #define USE_TYPO_METRICS (1u<<7)
if (0 != (os2_table->fsSelection & USE_TYPO_METRICS)) if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
{ {
ascender = os2_table->sTypoAscender; ascender = abs (os2_table->sTypoAscender);
descender = os2_table->sTypoDescender; descender = -abs (os2_table->sTypoDescender);
line_gap = os2_table->sTypoLineGap; line_gap = os2_table->sTypoLineGap;
got_font_extents = (ascender | descender) != 0; got_font_extents = (ascender | descender) != 0;
} }
@ -212,8 +212,8 @@ struct hmtxvmtx
num_advances = _hea_table->numberOfLongMetrics; num_advances = _hea_table->numberOfLongMetrics;
if (!got_font_extents) if (!got_font_extents)
{ {
ascender = _hea_table->ascender; ascender = abs (_hea_table->ascender);
descender = _hea_table->descender; descender = -abs (_hea_table->descender);
line_gap = _hea_table->lineGap; line_gap = _hea_table->lineGap;
got_font_extents = (ascender | descender) != 0; got_font_extents = (ascender | descender) != 0;
} }

View File

@ -79,8 +79,8 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag,
hb_ot_map_feature_flags_t flags, hb_ot_map_feature_flags_t flags,
unsigned int value) unsigned int value)
{ {
feature_info_t *info = feature_infos.push();
if (unlikely (!tag)) return; if (unlikely (!tag)) return;
feature_info_t *info = feature_infos.push();
info->tag = tag; info->tag = tag;
info->seq = feature_infos.len; info->seq = feature_infos.len;
info->max_value = value; info->max_value = value;
@ -175,6 +175,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
} }
/* Sort features and merge duplicates */ /* Sort features and merge duplicates */
if (feature_infos.len)
{ {
feature_infos.qsort (); feature_infos.qsort ();
unsigned int j = 0; unsigned int j = 0;

View File

@ -162,7 +162,7 @@ struct hb_ot_map_t
hb_mask_t global_mask; hb_mask_t global_mask;
hb_vector_t<feature_map_t, 8> features; hb_vector_t<feature_map_t, 8> features;
hb_vector_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */ hb_vector_t<lookup_map_t, 16> lookups[2]; /* GSUB/GPOS */
hb_vector_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */ hb_vector_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */
}; };

View File

@ -16,11 +16,16 @@
#include "hb-ot-shape-complex-vowel-constraints.hh" #include "hb-ot-shape-complex-vowel-constraints.hh"
static void 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_t &dottedcircle = buffer->output_glyph (0x25CCu);
_hb_glyph_info_reset_continuation (&dottedcircle); _hb_glyph_info_reset_continuation (&dottedcircle);
}
static void
_output_with_dotted_circle (hb_buffer_t *buffer)
{
_output_dotted_circle (buffer);
buffer->next_glyph (); 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->next_glyph (); buffer->next_glyph ();
buffer->output_glyph (0x25CCu); _output_dotted_circle (buffer);
} }
break; break;
} }

View File

@ -53,6 +53,16 @@ _hb_apply_morx (hb_face_t *face)
hb_aat_layout_has_substitution (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 void
hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
const int *coords, const int *coords,
@ -61,6 +71,8 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
plan.props = props; plan.props = props;
plan.shaper = shaper; plan.shaper = shaper;
map.compile (plan.map, coords, num_coords); 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.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')); 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. * 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. * 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->end == HB_FEATURE_GLOBAL_END) ? F_GLOBAL : F_NONE,
feature->value); 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); 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, hb_ot_shape_collect_features (&planner, &shape_plan->props,
user_features, num_user_features); user_features, num_user_features);

View File

@ -30,6 +30,7 @@
#include "hb.hh" #include "hb.hh"
#include "hb-ot-map.hh" #include "hb-ot-map.hh"
#include "hb-aat-map.hh"
#include "hb-shape-plan.hh" #include "hb-shape-plan.hh"
@ -39,6 +40,7 @@ struct hb_ot_shape_plan_t
hb_segment_properties_t props; hb_segment_properties_t props;
const struct hb_ot_complex_shaper_t *shaper; const struct hb_ot_complex_shaper_t *shaper;
hb_ot_map_t map; hb_ot_map_t map;
hb_aat_map_t aat_map;
const void *data; const void *data;
hb_mask_t frac_mask, numr_mask, dnom_mask; hb_mask_t frac_mask, numr_mask, dnom_mask;
hb_mask_t rtlm_mask; hb_mask_t rtlm_mask;
@ -77,9 +79,11 @@ struct hb_ot_shape_plan_t
{ {
memset (this, 0, sizeof (*this)); memset (this, 0, sizeof (*this));
map.init (); map.init ();
aat_map.init ();
} }
void fini (void) { void fini (void) {
map.fini (); map.fini ();
aat_map.fini ();
} }
}; };
@ -88,14 +92,12 @@ struct hb_ot_shape_planner_t
/* In the order that they are filled in. */ /* In the order that they are filled in. */
hb_face_t *face; hb_face_t *face;
hb_segment_properties_t props; hb_segment_properties_t props;
const struct hb_ot_complex_shaper_t *shaper;
hb_ot_map_builder_t map; 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) : HB_INTERNAL 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 void compile (hb_ot_shape_plan_t &plan, HB_INTERNAL void compile (hb_ot_shape_plan_t &plan,
const int *coords, const int *coords,

View File

@ -669,7 +669,7 @@ struct hb_set_t
return nullptr; return nullptr;
pages[map.index].init0 (); 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; page_map[i] = map;
} }
return &pages[page_map[i].index]; return &pages[page_map[i].index];

View File

@ -1,5 +1,6 @@
TESTS = \ TESTS = \
tests/aat-trak.tests \ tests/aat-trak.tests \
tests/aat-morx.tests \
tests/arabic-fallback-shaping.tests \ tests/arabic-fallback-shaping.tests \
tests/arabic-feature-order.tests \ tests/arabic-feature-order.tests \
tests/arabic-like-joining.tests \ tests/arabic-like-joining.tests \

View File

@ -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]