Merge branch 'master' into cff-subset
This commit is contained in:
commit
2ebf360102
27
appveyor.yml
27
appveyor.yml
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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 \
|
||||||
|
|
|
@ -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 ()
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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 */
|
|
@ -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])); \
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
Binary file not shown.
|
@ -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]
|
Loading…
Reference in New Issue