Merge with master
This commit is contained in:
commit
101850f9e6
@ -3,6 +3,8 @@
|
|||||||
set -x
|
set -x
|
||||||
set -o errexit -o nounset
|
set -o errexit -o nounset
|
||||||
|
|
||||||
|
if test "x$TRAVIS_SECURE_ENV_VARS" != xtrue; then exit; fi
|
||||||
|
|
||||||
BRANCH="$TRAVIS_BRANCH"
|
BRANCH="$TRAVIS_BRANCH"
|
||||||
if test "x$BRANCH" != xmaster; then exit; fi
|
if test "x$BRANCH" != xmaster; then exit; fi
|
||||||
|
|
||||||
@ -16,18 +18,19 @@ mkdir $DOCSDIR
|
|||||||
cd $DOCSDIR
|
cd $DOCSDIR
|
||||||
|
|
||||||
cp ../docs/html/* .
|
cp ../docs/html/* .
|
||||||
|
#cp ../docs/CNAME .
|
||||||
|
|
||||||
git init
|
git init
|
||||||
git config user.name "Travis CI"
|
git config user.name "Travis CI"
|
||||||
git config user.email "travis@harfbuzz.org"
|
git config user.email "travis@harfbuzz.org"
|
||||||
set +x
|
set +x
|
||||||
echo "git remote add upstream \"https://\$GH_TOKEN@github.com/$TRAVIS_REPO_SLUG.git\""
|
echo "git remote add upstream \"https://\$GH_TOKEN@github.com/harfbuzz/harfbuzz.github.io.git\""
|
||||||
git remote add upstream "https://$GH_TOKEN@github.com/$TRAVIS_REPO_SLUG.git"
|
git remote add upstream "https://$GH_TOKEN@github.com/harfbuzz/harfbuzz.github.io.git"
|
||||||
set -x
|
set -x
|
||||||
git fetch upstream
|
git fetch upstream
|
||||||
git reset upstream/gh-pages
|
git reset upstream/master
|
||||||
|
|
||||||
touch .
|
touch .
|
||||||
git add -A .
|
git add -A .
|
||||||
git commit -m "Rebuild docs for $REVISION"
|
git commit -m "Rebuild docs for https://github.com/harfbuzz/harfbuzz/commit/$REVISION"
|
||||||
git push -q upstream HEAD:gh-pages
|
git push -q upstream HEAD:master
|
||||||
|
18
.ci/fail.sh
Executable file
18
.ci/fail.sh
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
for f in $(find . -name '*.log' -not -name 'config.log'); do
|
||||||
|
last=$(tail -1 $f)
|
||||||
|
if [[ $last = FAIL* ]]; then
|
||||||
|
echo '====' $f '===='
|
||||||
|
cat $f
|
||||||
|
elif [[ $last = PASS* ]]; then
|
||||||
|
# Do nothing.
|
||||||
|
true
|
||||||
|
else
|
||||||
|
# Travis Linux images has an old automake that does not match the
|
||||||
|
# patterns above, so in case of doubt just print the file.
|
||||||
|
cat $f
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 1
|
14
.ci/run-coveralls.sh
Executable file
14
.ci/run-coveralls.sh
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -x
|
||||||
|
set -o errexit -o nounset
|
||||||
|
|
||||||
|
if test "x$TRAVIS_SLUG" != x"harfbuzz/harfbuzz"; then exit; fi
|
||||||
|
|
||||||
|
pip install --user nose
|
||||||
|
pip install --user cpp-coveralls
|
||||||
|
export PATH=$HOME/.local/bin:$PATH
|
||||||
|
|
||||||
|
rm -f src/.libs/NONE.gcov
|
||||||
|
touch src/NONE
|
||||||
|
coveralls -e docs
|
13
.ci/trigger-coverity.sh
Normal file
13
.ci/trigger-coverity.sh
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -x
|
||||||
|
set -o errexit -o nounset
|
||||||
|
|
||||||
|
if test "x$TRAVIS_EVENT_TYPE" != x"cron"; then exit; fi
|
||||||
|
|
||||||
|
BRANCH="$TRAVIS_BRANCH"
|
||||||
|
if test "x$BRANCH" != xmaster; then exit; fi
|
||||||
|
|
||||||
|
git fetch --unshallow
|
||||||
|
git remote add upstream "https://$GH_TOKEN@github.com/harfbuzz/harfbuzz.git"
|
||||||
|
git push -q upstream master:coverity_scan
|
190
.circleci/config.yml
Normal file
190
.circleci/config.yml
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
distcheck:
|
||||||
|
docker:
|
||||||
|
- image: ubuntu:17.10
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apt update && apt install -y ninja-build binutils libtool autoconf automake make cmake gcc g++ pkg-config ragel gtk-doc-tools libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
|
||||||
|
- run: pip install fonttools
|
||||||
|
- run: ./autogen.sh
|
||||||
|
- run: make
|
||||||
|
- run: make distcheck || .ci/fail.sh
|
||||||
|
- run: rm -rf harfbuzz-*
|
||||||
|
- run: make distdir && cd harfbuzz-* && cmake -DHB_CHECK=ON -Bbuild -H. -GNinja && ninja -Cbuild && CTEST_OUTPUT_ON_FAILURE=1 ninja -Cbuild test && ninja -Cbuild install
|
||||||
|
|
||||||
|
alpine-O3:
|
||||||
|
docker:
|
||||||
|
- image: alpine
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apk update && apk add ragel make pkgconfig libtool autoconf automake gettext gcc g++ glib-dev freetype-dev cairo-dev
|
||||||
|
# C??FLAGS are not needed for a regular build
|
||||||
|
- run: CFLAGS="-O3" CXXFLAGS="-O3" ./autogen.sh
|
||||||
|
- run: make
|
||||||
|
- run: make check || .ci/fail.sh
|
||||||
|
|
||||||
|
archlinux-debug-O0:
|
||||||
|
docker:
|
||||||
|
- image: base/devel
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: pacman --noconfirm -Syu freetype2 cairo icu gettext gobject-introspection gcc gcc-libs glib2 graphite pkg-config ragel python
|
||||||
|
# C??FLAGS are not needed for a regular build
|
||||||
|
- run: CFLAGS="-O0" CXXFLAGS="-O0" CPPFLAGS="-DHB_DEBUG" ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2
|
||||||
|
- run: make
|
||||||
|
- run: make check || .ci/fail.sh
|
||||||
|
|
||||||
|
clang-O3-O0:
|
||||||
|
docker:
|
||||||
|
- image: multiarch/crossbuild
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apt update && apt install -y ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
|
||||||
|
- run: pip install fonttools
|
||||||
|
- 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 && make -j4 && cd ..
|
||||||
|
- run: CFLAGS="-O3" CXXFLAGS="-O3" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2
|
||||||
|
- run: make
|
||||||
|
- run: LD_LIBRARY_PATH="$PWD/freetype-2.9/objs/.libs" make check || .ci/fail.sh
|
||||||
|
- run: CFLAGS="-O0" CXXFLAGS="-O0" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2
|
||||||
|
- run: make
|
||||||
|
- run: LD_LIBRARY_PATH="$PWD/freetype-2.9/objs/.libs" make check || .ci/fail.sh
|
||||||
|
|
||||||
|
fedora-outoftreebuild:
|
||||||
|
docker:
|
||||||
|
- image: fedora
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python || true
|
||||||
|
- run: NOCONFIGURE=1 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2
|
||||||
|
- run: mkdir build && cd build && ../configure && make && (make check || ../.ci/fail.sh)
|
||||||
|
|
||||||
|
cmake-gcc:
|
||||||
|
docker:
|
||||||
|
- image: ubuntu:17.10
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apt update && apt install -y ninja-build binutils cmake gcc g++ pkg-config ragel gtk-doc-tools libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
|
||||||
|
- run: pip install fonttools
|
||||||
|
- run: cmake -DHB_CHECK=ON -Bbuild -H. -GNinja
|
||||||
|
- run: ninja -Cbuild
|
||||||
|
- run: CTEST_OUTPUT_ON_FAILURE=1 ninja -Cbuild test
|
||||||
|
- run: ninja -Cbuild install
|
||||||
|
|
||||||
|
cmake-oracledeveloperstudio:
|
||||||
|
docker:
|
||||||
|
- image: fedora
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: dnf install -y gcc ragel cmake make which glib2-devel freetype-devel cairo-devel libicu-devel graphite2-devel wget tar bzip2 python || true
|
||||||
|
- run: wget http://$ODSUSER:$ODSPASS@behdad.org/harfbuzz-private/OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 && tar xf OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 --owner root --group root --no-same-owner
|
||||||
|
- run: CC=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/suncc CXX=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/sunCC cmake -DHB_HAVE_GRAPHITE2=ON -DHB_BUILTIN_UCDN=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_ICU=ON -DHB_HAVE_FREETYPE=ON -Bbuild -H.
|
||||||
|
- run: make -Cbuild
|
||||||
|
- run: CTEST_OUTPUT_ON_FAILURE=1 make -Cbuild test
|
||||||
|
- run: make -Cbuild install
|
||||||
|
|
||||||
|
crosscompile-notest-djgpp:
|
||||||
|
docker:
|
||||||
|
- image: quay.io/ebraminio/djgpp
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apt update && apt install -y ragel pkg-config libtool autoconf
|
||||||
|
- run: CFLAGS="-Wno-attributes" CXXFLAGS="-Wno-attributes" ./autogen.sh --prefix=/usr/local/djgpp --host=i586-pc-msdosdjgpp
|
||||||
|
- run: make
|
||||||
|
|
||||||
|
crosscompile-notest-freebsd9:
|
||||||
|
docker:
|
||||||
|
- image: donbowman/freebsd-cross-build
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apt update && apt install -y pkg-config ragel
|
||||||
|
- run: ./autogen.sh --prefix=/freebsd --host=x86_64-pc-freebsd9
|
||||||
|
- run: make
|
||||||
|
|
||||||
|
crosscompile-notest-psvita:
|
||||||
|
docker:
|
||||||
|
- image: dockcross/base
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apt update && apt install ragel
|
||||||
|
- run: git clone https://github.com/vitasdk/vdpm && cd vdpm && ./bootstrap-vitasdk.sh
|
||||||
|
- run: ./autogen.sh --prefix=/usr/local/vitasdk/arm-vita-eabi --host=arm-vita-eabi
|
||||||
|
- run: make
|
||||||
|
|
||||||
|
crosscompile-cmake-notest-android-arm:
|
||||||
|
docker:
|
||||||
|
- image: dockcross/android-arm
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apt update && apt install ragel
|
||||||
|
- run: cmake -Bbuild -H. -GNinja
|
||||||
|
- run: ninja -Cbuild
|
||||||
|
|
||||||
|
crosscompile-cmake-notest-browser-asmjs:
|
||||||
|
docker:
|
||||||
|
- image: dockcross/browser-asmjs
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apt update && apt install ragel
|
||||||
|
- run: cmake -Bbuild -H. -GNinja
|
||||||
|
- run: ninja -Cbuild
|
||||||
|
|
||||||
|
crosscompile-cmake-notest-linux-arm64:
|
||||||
|
docker:
|
||||||
|
- image: dockcross/linux-arm64
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apt update && apt install ragel
|
||||||
|
- run: cmake -Bbuild -H. -GNinja
|
||||||
|
- run: ninja -Cbuild
|
||||||
|
|
||||||
|
crosscompile-cmake-notest-linux-mips:
|
||||||
|
docker:
|
||||||
|
- image: dockcross/linux-mips
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apt update && apt install ragel
|
||||||
|
- run: cmake -Bbuild -H. -GNinja
|
||||||
|
- run: ninja -Cbuild
|
||||||
|
|
||||||
|
crosscompile-cmake-notest-windows-x64:
|
||||||
|
docker:
|
||||||
|
- image: dockcross/windows-x64
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: apt update && apt install ragel
|
||||||
|
- run: cmake -Bbuild -H. -GNinja
|
||||||
|
- run: ninja -Cbuild
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
version: 2
|
||||||
|
build:
|
||||||
|
jobs:
|
||||||
|
# both autotools and cmake
|
||||||
|
- distcheck
|
||||||
|
|
||||||
|
# autotools based builds
|
||||||
|
- alpine-O3
|
||||||
|
- archlinux-debug-O0
|
||||||
|
- clang-O3-O0
|
||||||
|
- fedora-outoftreebuild
|
||||||
|
|
||||||
|
# cmake based builds
|
||||||
|
- cmake-gcc
|
||||||
|
- cmake-oracledeveloperstudio
|
||||||
|
|
||||||
|
# crosscompiles
|
||||||
|
# they can't be test thus are without tests
|
||||||
|
## autotools
|
||||||
|
- crosscompile-notest-djgpp
|
||||||
|
- crosscompile-notest-freebsd9
|
||||||
|
- crosscompile-notest-psvita
|
||||||
|
|
||||||
|
## cmake
|
||||||
|
- crosscompile-cmake-notest-android-arm
|
||||||
|
- crosscompile-cmake-notest-browser-asmjs
|
||||||
|
- crosscompile-cmake-notest-linux-arm64
|
||||||
|
- crosscompile-cmake-notest-linux-mips
|
||||||
|
- crosscompile-cmake-notest-windows-x64
|
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{c,cc,h,hh}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
tab_width = 8
|
||||||
|
|
||||||
|
[*.{py,sh}]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[{CMakeLists.txt,*.cmake}]
|
||||||
|
indent_size = 2
|
96
.travis.yml
96
.travis.yml
@ -1,40 +1,68 @@
|
|||||||
# Build Configuration for Travis
|
# Build Configuration for Travis
|
||||||
sudo: required # For Trusty beta
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
dist: trusty
|
dist: trusty
|
||||||
|
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler:
|
|
||||||
- clang
|
|
||||||
- gcc
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- CPPFLAGS=""
|
- CPPFLAGS=""
|
||||||
- CFLAGS="-Werror --coverage"
|
- CFLAGS="-Werror -Werror=unused-function --coverage"
|
||||||
- CXXFLAGS="-Werror -Wno-deprecated-register --coverage" # glib uses register and clang raises a warning
|
- CXXFLAGS="-Werror -Werror=unused-function -Wno-deprecated-register --coverage" # glib uses register and clang raises a warning
|
||||||
- LDFLAGS="--coverage"
|
- LDFLAGS="--coverage"
|
||||||
install:
|
- CONFIGURE_OPTS="--with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2"
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then pip install --user nose; fi
|
- NOCONFIGURE=1
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then pip install --user cpp-coveralls; fi # for coveralls.io code coverage tracking
|
# COVERITY_SCAN_TOKEN
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then export PATH=$HOME/.local/bin:$PATH; fi # Make sure we can find the above Python packages
|
- secure: "Vw1UUHsAr4t3xuvOqqBsFAORptmNcQRrcGJnzSX7jDODBIRNfnU2LIBTagrPNKfSUhyQgCHqt1gX9iWNWvVfy3sDOXr2MXZeoqmF6Y1mS35J0rA/EPJgRHsdkxygkmFnXVeQkEuI55BINkaSoOpAeunmXKJNw1p9JVw368Fm/tU="
|
||||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; fi;
|
|
||||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ragel freetype glib gobject-introspection cairo icu4c graphite2; fi
|
matrix:
|
||||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew link --force icu4c; fi # icu4c is keg-only
|
include:
|
||||||
script:
|
- os: linux
|
||||||
- NOCONFIGURE=1 ./autogen.sh
|
compiler: gcc
|
||||||
- export CONFIGURE_OPTS="--with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2"
|
script:
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" -a "$CC" == "gcc" ]; then export CONFIGURE_OPTS="$CONFIGURE_OPTS --enable-gtk-doc"; fi
|
# Remove these two lines when Travis updated its distro
|
||||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then export CONFIGURE_OPTS="$CONFIGURE_OPTS --with-coretext"; fi
|
- 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 && make -j4 && cd ..
|
||||||
- ./configure $CONFIGURE_OPTS
|
- export LD_LIBRARY_PATH="$PWD/freetype-2.9/objs/.libs"
|
||||||
- make
|
|
||||||
- make check
|
- ./autogen.sh
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" -a "$CC" == "gcc" -a "$TRAVIS_SLUG" == "behdad/harfbuzz" ]; then rm -f src/.libs/NONE.gcov; touch src/NONE; coveralls -e docs; fi
|
- ./configure $CONFIGURE_OPTS --enable-gtk-doc
|
||||||
after_success:
|
- make
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" -a "$CC" == "gcc" -a "$TRAVIS_SECURE_ENV_VARS" == "true" ]; then bash .ci/deploy-docs.sh; fi
|
- make check || .ci/fail.sh
|
||||||
|
after_success:
|
||||||
|
- bash .ci/run-coveralls.sh # for coveralls.io code coverage tracking
|
||||||
|
- bash .ci/deploy-docs.sh
|
||||||
|
- bash .ci/trigger-coverity.sh
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
script:
|
||||||
|
# Remove these two lines when Travis updated its distro
|
||||||
|
- 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 && make -j4 && cd ..
|
||||||
|
- export LD_LIBRARY_PATH="$PWD/freetype-2.9/objs/.libs"
|
||||||
|
|
||||||
|
- ./autogen.sh
|
||||||
|
- ./configure $CONFIGURE_OPTS
|
||||||
|
- make
|
||||||
|
- make check || .ci/fail.sh
|
||||||
|
|
||||||
|
- os: osx
|
||||||
|
compiler: clang
|
||||||
|
install:
|
||||||
|
# https://github.com/harfbuzz/harfbuzz/issues/345
|
||||||
|
- export CXXFLAGS="$CXXFLAGS -Wno-deprecated-declarations"
|
||||||
|
- brew update;
|
||||||
|
# Workaround Travis/brew bug
|
||||||
|
- brew uninstall libtool && brew install libtool
|
||||||
|
- brew install ragel freetype glib gobject-introspection cairo icu4c graphite2
|
||||||
|
- brew link --force icu4c # icu4c is keg-only
|
||||||
|
script:
|
||||||
|
- ./autogen.sh
|
||||||
|
- ./configure $CONFIGURE_OPTS --with-coretext
|
||||||
|
- make
|
||||||
|
- make check || .ci/fail.sh
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
irc: "irc.freenode.org#harfbuzz"
|
irc: "irc.freenode.org#harfbuzz"
|
||||||
email: harfbuzz@lists.freedesktop.org
|
email: harfbuzz-bots-chatter@googlegroups.com
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
@ -47,4 +75,14 @@ addons:
|
|||||||
- libcairo2-dev # for utils
|
- libcairo2-dev # for utils
|
||||||
- libicu-dev # for extra unicode functions
|
- libicu-dev # for extra unicode functions
|
||||||
- libgraphite2-dev # for extra shapers
|
- libgraphite2-dev # for extra shapers
|
||||||
- # libgirepository1.0-dev # for gobject-introspection
|
#- libgirepository1.0-dev # for gobject-introspection
|
||||||
|
|
||||||
|
coverity_scan:
|
||||||
|
project:
|
||||||
|
name: HarfBuzz
|
||||||
|
version: 1.0
|
||||||
|
description: HarfBuzz OpenType text shaping engine
|
||||||
|
notification_email: harfbuzz-bots-chatter@googlegroups.com
|
||||||
|
build_command_prepend: ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2
|
||||||
|
build_command: make
|
||||||
|
branch_pattern: coverity_scan
|
||||||
|
107
Android.mk
107
Android.mk
@ -1,107 +0,0 @@
|
|||||||
##
|
|
||||||
## Copyright (C) 2012 The Android Open Source Project
|
|
||||||
##
|
|
||||||
## Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
## you may not use this file except in compliance with the License.
|
|
||||||
## You may obtain a copy of the License at
|
|
||||||
##
|
|
||||||
## http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
##
|
|
||||||
## Unless required by applicable law or agreed to in writing, software
|
|
||||||
## distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
## See the License for the specific language governing permissions and
|
|
||||||
## limitations under the License.
|
|
||||||
##
|
|
||||||
|
|
||||||
#############################################################
|
|
||||||
# Note:
|
|
||||||
#
|
|
||||||
# This file is used to build HarfBuzz within the Android
|
|
||||||
# platform itself. If you need to compile HarfBuzz to
|
|
||||||
# ship with your Android NDK app, you can use the autotools
|
|
||||||
# build system to do so. To do that you need to install a
|
|
||||||
# "standalone" toolchain with the NDK, eg:
|
|
||||||
#
|
|
||||||
# ndk/build/tools/make-standalone-toolchain.sh \
|
|
||||||
# --platform=android-18 \
|
|
||||||
# --install-dir=/prefix
|
|
||||||
#
|
|
||||||
# Set PLATFORM_PREFIX eng var to that prefix and make sure
|
|
||||||
# the cross-compile tools from PLATFORM_PREFIX are in path.
|
|
||||||
# Configure and install HarfBuzz:
|
|
||||||
#
|
|
||||||
# ./configure --host=arm-linux-androideabi \
|
|
||||||
# --prefix=$PLATFORM_PREFIX \
|
|
||||||
# --enable-static \
|
|
||||||
# --with-freetype \
|
|
||||||
# PKG_CONFIG_LIBDIR=$PLATFORM_PREFIX/lib/pkgconfig
|
|
||||||
# make install
|
|
||||||
#
|
|
||||||
# You can first build FreeType the same way:
|
|
||||||
#
|
|
||||||
# ./configure --host=arm-linux-androideabi \
|
|
||||||
# --prefix=$PLATFORM_PREFIX \
|
|
||||||
# --enable-static \
|
|
||||||
# --without-png \
|
|
||||||
# PKG_CONFIG_LIBDIR=$PLATFORM_PREFIX/lib/pkgconfig
|
|
||||||
# make install
|
|
||||||
#
|
|
||||||
|
|
||||||
LOCAL_PATH:= $(call my-dir)
|
|
||||||
|
|
||||||
HARFBUZZ_SRC_FILES = \
|
|
||||||
src/hb-blob.cc \
|
|
||||||
src/hb-buffer-serialize.cc \
|
|
||||||
src/hb-buffer.cc \
|
|
||||||
src/hb-common.cc \
|
|
||||||
src/hb-face.cc \
|
|
||||||
src/hb-font.cc \
|
|
||||||
src/hb-ot-tag.cc \
|
|
||||||
src/hb-set.cc \
|
|
||||||
src/hb-shape.cc \
|
|
||||||
src/hb-shape-plan.cc \
|
|
||||||
src/hb-shaper.cc \
|
|
||||||
src/hb-unicode.cc \
|
|
||||||
src/hb-warning.cc \
|
|
||||||
src/hb-ot-font.cc \
|
|
||||||
src/hb-ot-layout.cc \
|
|
||||||
src/hb-ot-map.cc \
|
|
||||||
src/hb-ot-shape.cc \
|
|
||||||
src/hb-ot-shape-complex-arabic.cc \
|
|
||||||
src/hb-ot-shape-complex-default.cc \
|
|
||||||
src/hb-ot-shape-complex-hangul.cc \
|
|
||||||
src/hb-ot-shape-complex-hebrew.cc \
|
|
||||||
src/hb-ot-shape-complex-indic.cc \
|
|
||||||
src/hb-ot-shape-complex-indic-table.cc \
|
|
||||||
src/hb-ot-shape-complex-myanmar.cc \
|
|
||||||
src/hb-ot-shape-complex-thai.cc \
|
|
||||||
src/hb-ot-shape-complex-tibetan.cc \
|
|
||||||
src/hb-ot-shape-complex-use.cc \
|
|
||||||
src/hb-ot-shape-complex-use-table.cc \
|
|
||||||
src/hb-ot-shape-normalize.cc \
|
|
||||||
src/hb-ot-shape-fallback.cc \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
#############################################################
|
|
||||||
# build the harfbuzz shared library
|
|
||||||
#
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_ARM_MODE := arm
|
|
||||||
LOCAL_MODULE_TAGS := optional
|
|
||||||
LOCAL_SRC_FILES:= \
|
|
||||||
$(HARFBUZZ_SRC_FILES) \
|
|
||||||
src/hb-icu.cc
|
|
||||||
LOCAL_CPP_EXTENSION := .cc
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
|
||||||
libcutils \
|
|
||||||
libicuuc \
|
|
||||||
libicui18n \
|
|
||||||
libutils \
|
|
||||||
liblog
|
|
||||||
LOCAL_C_INCLUDES += \
|
|
||||||
$(LOCAL_PATH)/src
|
|
||||||
LOCAL_CFLAGS += -DHB_NO_MT -DHAVE_OT -DHAVE_ICU -DHAVE_ICU_BUILTIN \
|
|
||||||
-Wno-unused-parameter -Wno-missing-field-initializers
|
|
||||||
LOCAL_MODULE:= libharfbuzz_ng
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
|
46
BUILD.md
46
BUILD.md
@ -1,36 +1,50 @@
|
|||||||
On Linux, install the development packages for FreeType,
|
On Linux, install the development packages for FreeType,
|
||||||
Cairo, and GLib. For example, on Ubuntu / Debian, you would do:
|
Cairo, and GLib. For example, on Ubuntu / Debian, you would do:
|
||||||
* sudo apt-get install gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev
|
|
||||||
|
sudo apt-get install gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev
|
||||||
|
|
||||||
whereas on Fedora, RHEL, CentOS, and other Red Hat based systems you would do:
|
whereas on Fedora, RHEL, CentOS, and other Red Hat based systems you would do:
|
||||||
* sudo yum install gcc gcc-c++ freetype-devel glib2-devel cairo-devel
|
|
||||||
|
|
||||||
on the Mac, using MacPorts:
|
sudo yum install gcc gcc-c++ freetype-devel glib2-devel cairo-devel
|
||||||
* sudo port install freetype glib2 cairo
|
|
||||||
|
on Windows, consider using [vcpkg](https://github.com/Microsoft/vcpkg),
|
||||||
|
provided by Microsoft, for building HarfBuzz and other open-source libraries
|
||||||
|
but if you need to build harfbuzz from source, put ragel binary on your
|
||||||
|
PATH and follow appveyor CI's cmake
|
||||||
|
[build steps](https://github.com/harfbuzz/harfbuzz/blob/master/appveyor.yml).
|
||||||
|
|
||||||
|
on macOS, using MacPorts:
|
||||||
|
|
||||||
|
sudo port install freetype glib2 cairo
|
||||||
|
|
||||||
or using Homebrew:
|
or using Homebrew:
|
||||||
* brew install freetype glib cairo
|
|
||||||
|
brew install freetype glib cairo
|
||||||
|
|
||||||
If you are using a tarball, you can now proceed to running configure and make
|
If you are using a tarball, you can now proceed to running configure and make
|
||||||
as with any other standard package. That should leave you with a shared
|
as with any other standard package. That should leave you with a shared
|
||||||
library in src/, and a few utility programs including hb-view and hb-shape
|
library in `src/`, and a few utility programs including `hb-view` and `hb-shape`
|
||||||
under util/. From the tarball, NMake Makefiles are also provided in win32/,
|
under `util/`.
|
||||||
which supports building HarfBuzz using Visual Studio, with a README.txt that
|
|
||||||
gives instructions on building using NMake.
|
|
||||||
If you are bootstraping from git, you need a few more tools before you can
|
If you are bootstraping from git, you need a few more tools before you can
|
||||||
run autogen.sh for the first time. Namely, pkg-config and ragel. Again,
|
run `autogen.sh` for the first time. Namely, `pkg-config` and `ragel`.
|
||||||
on Ubuntu / Debian:
|
|
||||||
* sudo apt-get install autoconf automake libtool pkg-config ragel gtk-doc-tools
|
Again, on Ubuntu / Debian:
|
||||||
|
|
||||||
|
sudo apt-get install autoconf automake libtool pkg-config ragel gtk-doc-tools
|
||||||
|
|
||||||
and on Fedora, RHEL, CentOS:
|
and on Fedora, RHEL, CentOS:
|
||||||
* sudo yum install autoconf automake libtool pkgconfig ragel gtk-doc
|
|
||||||
|
sudo yum install autoconf automake libtool pkgconfig ragel gtk-doc
|
||||||
|
|
||||||
on the Mac, using MacPorts:
|
on the Mac, using MacPorts:
|
||||||
* sudo port install autoconf automake libtool pkgconfig ragel gtk-doc
|
|
||||||
|
sudo port install autoconf automake libtool pkgconfig ragel gtk-doc
|
||||||
|
|
||||||
or using Homebrew:
|
or using Homebrew:
|
||||||
* brew install autoconf automake libtool pkgconfig ragel gtk-doc
|
|
||||||
|
brew install autoconf automake libtool pkgconfig ragel gtk-doc
|
||||||
|
|
||||||
To build the Python bindings, you also need:
|
To build the Python bindings, you also need:
|
||||||
|
|
||||||
* brew install pygobject3
|
brew install pygobject3
|
||||||
|
860
CMakeLists.txt
Normal file
860
CMakeLists.txt
Normal file
@ -0,0 +1,860 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8.0)
|
||||||
|
project(harfbuzz)
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
## Limit framework build to Xcode generator
|
||||||
|
if (BUILD_FRAMEWORK)
|
||||||
|
# for a framework build on macOS, use:
|
||||||
|
# cmake -DBUILD_FRAMEWORK=ON -Bbuild -H. -GXcode && cmake --build build
|
||||||
|
if (NOT "${CMAKE_GENERATOR}" STREQUAL "Xcode")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"You should use Xcode generator with BUILD_FRAMEWORK enabled")
|
||||||
|
endif ()
|
||||||
|
set (CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)")
|
||||||
|
set (CMAKE_MACOSX_RPATH ON)
|
||||||
|
set (BUILD_SHARED_LIBS ON)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## Disallow in-source builds, as CMake generated make files can collide with autotools ones
|
||||||
|
if (NOT MSVC AND "${PROJECT_BINARY_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"
|
||||||
|
In-source builds are not permitted! Make a separate folder for"
|
||||||
|
" building, e.g.,"
|
||||||
|
"
|
||||||
|
mkdir build; cd build; cmake .."
|
||||||
|
"
|
||||||
|
Before that, remove the files created by this failed run with"
|
||||||
|
"
|
||||||
|
rm -rf CMakeCache.txt CMakeFiles")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## HarfBuzz build configurations
|
||||||
|
option(HB_HAVE_FREETYPE "Enable freetype interop helpers" OFF)
|
||||||
|
option(HB_HAVE_GRAPHITE2 "Enable Graphite2 complementary shaper" OFF)
|
||||||
|
option(HB_BUILTIN_UCDN "Use HarfBuzz provided UCDN" ON)
|
||||||
|
option(HB_HAVE_GLIB "Enable glib unicode functions" OFF)
|
||||||
|
option(HB_HAVE_ICU "Enable icu unicode functions" OFF)
|
||||||
|
if (APPLE)
|
||||||
|
option(HB_HAVE_CORETEXT "Enable CoreText shaper backend on macOS" ON)
|
||||||
|
set (CMAKE_MACOSX_RPATH ON)
|
||||||
|
endif ()
|
||||||
|
if (WIN32)
|
||||||
|
option(HB_HAVE_UNISCRIBE "Enable Uniscribe shaper backend on Windows" OFF)
|
||||||
|
option(HB_HAVE_DIRECTWRITE "Enable DirectWrite shaper backend on Windows" OFF)
|
||||||
|
endif ()
|
||||||
|
option(HB_BUILD_UTILS "Build harfbuzz utils, needs cairo, freetype, and glib properly be installed" OFF)
|
||||||
|
if (HB_BUILD_UTILS)
|
||||||
|
set (HB_HAVE_GLIB ON)
|
||||||
|
set (HB_HAVE_FREETYPE ON)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
option(HB_HAVE_GOBJECT "Enable GObject Bindings" OFF)
|
||||||
|
if (HB_HAVE_GOBJECT)
|
||||||
|
set (HB_HAVE_GLIB ON)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
option(HB_HAVE_INTROSPECTION "Enable building introspection (.gir/.typelib) files" OFF)
|
||||||
|
if (HB_HAVE_INTROSPECTION)
|
||||||
|
set (HB_HAVE_GOBJECT ON)
|
||||||
|
set (HB_HAVE_GLIB ON)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
option(HB_DISABLE_TEST_PROGS OFF "Do not build some of the test programs, useful for continuous builds")
|
||||||
|
option(HB_CHECK OFF "Do a configuration suitable for testing (shared library and enable all options)")
|
||||||
|
if (HB_CHECK)
|
||||||
|
set (BUILD_SHARED_LIBS ON)
|
||||||
|
set (HB_BUILD_UTILS ON)
|
||||||
|
set (HB_BUILTIN_UCDN ON)
|
||||||
|
set (HB_HAVE_ICU)
|
||||||
|
set (HB_HAVE_GLIB ON)
|
||||||
|
#set (HB_HAVE_GOBJECT ON)
|
||||||
|
#set (HB_HAVE_INTROSPECTION ON)
|
||||||
|
set (HB_HAVE_FREETYPE ON)
|
||||||
|
set (HB_HAVE_GRAPHITE2 ON)
|
||||||
|
if (WIN32)
|
||||||
|
set (HB_HAVE_UNISCRIBE ON)
|
||||||
|
set (HB_HAVE_DIRECTWRITE ON)
|
||||||
|
elseif (APPLE)
|
||||||
|
set (HB_HAVE_CORETEXT ON)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
include_directories(AFTER
|
||||||
|
${PROJECT_SOURCE_DIR}/src
|
||||||
|
${PROJECT_BINARY_DIR}/src
|
||||||
|
)
|
||||||
|
|
||||||
|
add_definitions(-DHAVE_OT)
|
||||||
|
add_definitions(-DHAVE_FALLBACK)
|
||||||
|
|
||||||
|
|
||||||
|
## Functions and headers
|
||||||
|
include (CheckFunctionExists)
|
||||||
|
include (CheckIncludeFile)
|
||||||
|
macro (check_funcs) # Similar to AC_CHECK_FUNCS of autotools
|
||||||
|
foreach (func_name ${ARGN})
|
||||||
|
string(TOUPPER ${func_name} definiton_to_add)
|
||||||
|
check_function_exists(${func_name} HAVE_${definiton_to_add})
|
||||||
|
if (${HAVE_${definiton_to_add}})
|
||||||
|
add_definitions(-DHAVE_${definiton_to_add})
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
endmacro ()
|
||||||
|
check_funcs(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l)
|
||||||
|
check_include_file(unistd.h HAVE_UNISTD_H)
|
||||||
|
if (${HAVE_UNISTD_H})
|
||||||
|
add_definitions(-DHAVE_UNISTD_H)
|
||||||
|
endif ()
|
||||||
|
check_include_file(sys/mman.h HAVE_SYS_MMAN_H)
|
||||||
|
if (${HAVE_SYS_MMAN_H})
|
||||||
|
add_definitions(-DHAVE_SYS_MMAN_H)
|
||||||
|
endif ()
|
||||||
|
check_include_file(xlocale.h HAVE_XLOCALE_H)
|
||||||
|
if (${HAVE_XLOCALE_H})
|
||||||
|
add_definitions(-DHAVE_XLOCALE_H)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
add_definitions(-wd4244 -wd4267 -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
if (WIN32 AND NOT MINGW)
|
||||||
|
add_definitions("-DHB_EXTERN=__declspec(dllexport) extern")
|
||||||
|
else ()
|
||||||
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## Detect if we are running inside a distribution or regular repository folder
|
||||||
|
set (IN_HB_DIST FALSE)
|
||||||
|
if (EXISTS "${PROJECT_SOURCE_DIR}/ChangeLog")
|
||||||
|
# perhaps we are on dist directory
|
||||||
|
set (IN_HB_DIST TRUE)
|
||||||
|
#set (HB_VERSION_H "${PROJECT_SOURCE_DIR}/src/hb-version.h")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## Extract variables from Makefile files
|
||||||
|
function (extract_make_variable variable makefile_source)
|
||||||
|
string(REGEX MATCH "${variable} = ([^$]+)\\$" temp ${makefile_source})
|
||||||
|
string(REGEX MATCHALL "[^ \n\t\\]+" listVar ${CMAKE_MATCH_1})
|
||||||
|
set (${variable} ${listVar} PARENT_SCOPE)
|
||||||
|
endfunction ()
|
||||||
|
|
||||||
|
# http://stackoverflow.com/a/27630120
|
||||||
|
function (add_prefix_to_list var prefix)
|
||||||
|
set (listVar "")
|
||||||
|
foreach (f ${${var}})
|
||||||
|
list(APPEND listVar "${prefix}${f}")
|
||||||
|
endforeach ()
|
||||||
|
set (${var} "${listVar}" PARENT_SCOPE)
|
||||||
|
endfunction ()
|
||||||
|
|
||||||
|
file(READ ${PROJECT_SOURCE_DIR}/src/Makefile.sources SRCSOURCES)
|
||||||
|
file(READ ${PROJECT_SOURCE_DIR}/util/Makefile.sources UTILSOURCES)
|
||||||
|
file(READ ${PROJECT_SOURCE_DIR}/src/hb-ucdn/Makefile.sources UCDNSOURCES)
|
||||||
|
|
||||||
|
extract_make_variable(HB_BASE_sources ${SRCSOURCES})
|
||||||
|
add_prefix_to_list(HB_BASE_sources "${PROJECT_SOURCE_DIR}/src/")
|
||||||
|
extract_make_variable(HB_BASE_headers ${SRCSOURCES})
|
||||||
|
add_prefix_to_list(HB_BASE_headers "${PROJECT_SOURCE_DIR}/src/")
|
||||||
|
extract_make_variable(HB_FALLBACK_sources ${SRCSOURCES})
|
||||||
|
add_prefix_to_list(HB_FALLBACK_sources "${PROJECT_SOURCE_DIR}/src/")
|
||||||
|
extract_make_variable(HB_OT_sources ${SRCSOURCES})
|
||||||
|
add_prefix_to_list(HB_OT_sources "${PROJECT_SOURCE_DIR}/src/")
|
||||||
|
extract_make_variable(HB_OT_headers ${SRCSOURCES})
|
||||||
|
add_prefix_to_list(HB_OT_headers "${PROJECT_SOURCE_DIR}/src/")
|
||||||
|
|
||||||
|
extract_make_variable(HB_SUBSET_sources ${SRCSOURCES})
|
||||||
|
add_prefix_to_list(HB_SUBSET_sources "${PROJECT_SOURCE_DIR}/src/")
|
||||||
|
|
||||||
|
extract_make_variable(HB_SUBSET_headers ${SRCSOURCES})
|
||||||
|
add_prefix_to_list(HB_SUBSET_headers "${PROJECT_SOURCE_DIR}/src/")
|
||||||
|
|
||||||
|
extract_make_variable(HB_BASE_RAGEL_GENERATED_sources ${SRCSOURCES})
|
||||||
|
extract_make_variable(HB_OT_RAGEL_GENERATED_sources ${SRCSOURCES})
|
||||||
|
#if (IN_HB_DIST)
|
||||||
|
add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_SOURCE_DIR}/src/")
|
||||||
|
add_prefix_to_list(HB_OT_RAGEL_GENERATED_sources "${PROJECT_SOURCE_DIR}/src/")
|
||||||
|
#else ()
|
||||||
|
# add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_BINARY_DIR}/src/")
|
||||||
|
# add_prefix_to_list(HB_OT_RAGEL_GENERATED_sources "${PROJECT_BINARY_DIR}/src/")
|
||||||
|
#endif ()
|
||||||
|
|
||||||
|
extract_make_variable(HB_VIEW_sources ${UTILSOURCES})
|
||||||
|
add_prefix_to_list(HB_VIEW_sources "${PROJECT_SOURCE_DIR}/util/")
|
||||||
|
extract_make_variable(HB_SHAPE_sources ${UTILSOURCES})
|
||||||
|
add_prefix_to_list(HB_SHAPE_sources "${PROJECT_SOURCE_DIR}/util/")
|
||||||
|
extract_make_variable(HB_SUBSET_CLI_sources ${UTILSOURCES})
|
||||||
|
add_prefix_to_list(HB_SUBSET_CLI_sources "${PROJECT_SOURCE_DIR}/util/")
|
||||||
|
extract_make_variable(HB_OT_SHAPE_CLOSURE_sources ${UTILSOURCES})
|
||||||
|
add_prefix_to_list(HB_OT_SHAPE_CLOSURE_sources "${PROJECT_SOURCE_DIR}/util/")
|
||||||
|
|
||||||
|
extract_make_variable(LIBHB_UCDN_sources ${UCDNSOURCES})
|
||||||
|
add_prefix_to_list(LIBHB_UCDN_sources "${PROJECT_SOURCE_DIR}/src/hb-ucdn/")
|
||||||
|
|
||||||
|
|
||||||
|
file(READ configure.ac CONFIGUREAC)
|
||||||
|
string(REGEX MATCH "\\[(([0-9]+)\\.([0-9]+)\\.([0-9]+))\\]" HB_VERSION_MATCH ${CONFIGUREAC})
|
||||||
|
set (HB_VERSION ${CMAKE_MATCH_1})
|
||||||
|
set (HB_VERSION_MAJOR ${CMAKE_MATCH_2})
|
||||||
|
set (HB_VERSION_MINOR ${CMAKE_MATCH_3})
|
||||||
|
set (HB_VERSION_MICRO ${CMAKE_MATCH_4})
|
||||||
|
|
||||||
|
|
||||||
|
## Define ragel tasks
|
||||||
|
if (NOT IN_HB_DIST)
|
||||||
|
find_program(RAGEL "ragel" CMAKE_FIND_ROOT_PATH_BOTH)
|
||||||
|
|
||||||
|
if (RAGEL)
|
||||||
|
message(STATUS "ragel found at: ${RAGEL}")
|
||||||
|
else ()
|
||||||
|
message(FATAL_ERROR "ragel not found, get it here -- http://www.complang.org/ragel/ or, use harfbuzz releases https://github.com/harfbuzz/harfbuzz/releases")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
foreach (ragel_output IN ITEMS ${HB_BASE_RAGEL_GENERATED_sources} ${HB_OT_RAGEL_GENERATED_sources})
|
||||||
|
string(REGEX MATCH "([^/]+)\\.hh" temp ${ragel_output})
|
||||||
|
set (target_name ${CMAKE_MATCH_1})
|
||||||
|
add_custom_command(OUTPUT ${ragel_output}
|
||||||
|
COMMAND ${RAGEL} -G2 -o ${ragel_output} ${PROJECT_SOURCE_DIR}/src/${target_name}.rl -I ${PROJECT_SOURCE_DIR} ${ARGN}
|
||||||
|
DEPENDS ${PROJECT_SOURCE_DIR}/src/${target_name}.rl
|
||||||
|
)
|
||||||
|
add_custom_target(harfbuzz_${target_name} DEPENDS ${PROJECT_BINARY_DIR}/src/${target_name})
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
mark_as_advanced(RAGEL)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## Generate hb-version.h
|
||||||
|
#if (NOT IN_HB_DIST)
|
||||||
|
# set (HB_VERSION_H_IN "${PROJECT_SOURCE_DIR}/src/hb-version.h.in")
|
||||||
|
# set (HB_VERSION_H "${PROJECT_BINARY_DIR}/src/hb-version.h")
|
||||||
|
# set_source_files_properties("${HB_VERSION_H}" PROPERTIES GENERATED true)
|
||||||
|
# configure_file("${HB_VERSION_H_IN}" "${HB_VERSION_H}.tmp" @ONLY)
|
||||||
|
# execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
|
# "${HB_VERSION_H}.tmp"
|
||||||
|
# "${HB_VERSION_H}"
|
||||||
|
# )
|
||||||
|
# file(REMOVE "${HB_VERSION_H}.tmp")
|
||||||
|
#endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## Define sources and headers of the project
|
||||||
|
set (project_sources
|
||||||
|
${HB_BASE_sources}
|
||||||
|
${HB_BASE_RAGEL_GENERATED_sources}
|
||||||
|
|
||||||
|
${HB_FALLBACK_sources}
|
||||||
|
${HB_OT_sources}
|
||||||
|
${HB_OT_RAGEL_GENERATED_sources}
|
||||||
|
)
|
||||||
|
|
||||||
|
set (subset_project_sources
|
||||||
|
${HB_SUBSET_sources}
|
||||||
|
)
|
||||||
|
|
||||||
|
set (project_extra_sources)
|
||||||
|
|
||||||
|
set (project_headers
|
||||||
|
#${HB_VERSION_H}
|
||||||
|
|
||||||
|
${HB_BASE_headers}
|
||||||
|
${HB_OT_headers}
|
||||||
|
)
|
||||||
|
|
||||||
|
set (subset_project_headers
|
||||||
|
${HB_SUBSET_headers}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
## Find and include needed header folders and libraries
|
||||||
|
if (HB_HAVE_FREETYPE)
|
||||||
|
include (FindFreetype)
|
||||||
|
if (NOT FREETYPE_FOUND)
|
||||||
|
message(FATAL_ERROR "HB_HAVE_FREETYPE was set, but we failed to find it. Maybe add a CMAKE_PREFIX_PATH= to your Freetype2 install prefix")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
list(APPEND THIRD_PARTY_LIBS ${FREETYPE_LIBRARIES})
|
||||||
|
include_directories(AFTER ${FREETYPE_INCLUDE_DIRS})
|
||||||
|
add_definitions(-DHAVE_FREETYPE=1)
|
||||||
|
|
||||||
|
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-ft.cc)
|
||||||
|
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-ft.h)
|
||||||
|
|
||||||
|
# So check_funcs can find its headers
|
||||||
|
set (CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${FREETYPE_INCLUDE_DIRS})
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${FREETYPE_LIBRARIES})
|
||||||
|
|
||||||
|
check_funcs(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (HB_HAVE_GRAPHITE2)
|
||||||
|
add_definitions(-DHAVE_GRAPHITE2)
|
||||||
|
|
||||||
|
find_path(GRAPHITE2_INCLUDE_DIR graphite2/Font.h)
|
||||||
|
find_library(GRAPHITE2_LIBRARY graphite2)
|
||||||
|
|
||||||
|
include_directories(${GRAPHITE2_INCLUDE_DIR})
|
||||||
|
|
||||||
|
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-graphite2.cc)
|
||||||
|
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-graphite2.h)
|
||||||
|
|
||||||
|
list(APPEND THIRD_PARTY_LIBS ${GRAPHITE2_LIBRARY})
|
||||||
|
|
||||||
|
mark_as_advanced(GRAPHITE2_INCLUDE_DIR GRAPHITE2_LIBRARY)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (HB_BUILTIN_UCDN)
|
||||||
|
include_directories(src/hb-ucdn)
|
||||||
|
add_definitions(-DHAVE_UCDN)
|
||||||
|
|
||||||
|
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-ucdn.cc)
|
||||||
|
list(APPEND project_extra_sources ${LIBHB_UCDN_sources})
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (HB_HAVE_GLIB)
|
||||||
|
add_definitions(-DHAVE_GLIB)
|
||||||
|
|
||||||
|
# https://github.com/WebKit/webkit/blob/master/Source/cmake/FindGLIB.cmake
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PC_GLIB QUIET glib-2.0)
|
||||||
|
|
||||||
|
find_library(GLIB_LIBRARIES NAMES glib-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS})
|
||||||
|
find_path(GLIBCONFIG_INCLUDE_DIR NAMES glibconfig.h HINTS ${PC_LIBDIR} ${PC_LIBRARY_DIRS} ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0/include)
|
||||||
|
find_path(GLIB_INCLUDE_DIR NAMES glib.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0)
|
||||||
|
|
||||||
|
include_directories(${GLIBCONFIG_INCLUDE_DIR} ${GLIB_INCLUDE_DIR})
|
||||||
|
|
||||||
|
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-glib.cc)
|
||||||
|
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-glib.h)
|
||||||
|
|
||||||
|
list(APPEND THIRD_PARTY_LIBS ${GLIB_LIBRARIES})
|
||||||
|
|
||||||
|
mark_as_advanced(GLIB_LIBRARIES GLIBCONFIG_INCLUDE_DIR GLIB_INCLUDE_DIR)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (HB_HAVE_ICU)
|
||||||
|
add_definitions(-DHAVE_ICU)
|
||||||
|
|
||||||
|
# https://github.com/WebKit/webkit/blob/master/Source/cmake/FindICU.cmake
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PC_ICU QUIET icu-uc)
|
||||||
|
|
||||||
|
find_path(ICU_INCLUDE_DIR NAMES unicode/utypes.h HINTS ${PC_ICU_INCLUDE_DIRS} ${PC_ICU_INCLUDEDIR})
|
||||||
|
find_library(ICU_LIBRARY NAMES libicuuc cygicuuc cygicuuc32 icuuc HINTS ${PC_ICU_LIBRARY_DIRS} ${PC_ICU_LIBDIR})
|
||||||
|
|
||||||
|
include_directories(${ICU_INCLUDE_DIR})
|
||||||
|
|
||||||
|
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-icu.cc)
|
||||||
|
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-icu.h)
|
||||||
|
|
||||||
|
list(APPEND THIRD_PARTY_LIBS ${ICU_LIBRARY})
|
||||||
|
|
||||||
|
mark_as_advanced(ICU_INCLUDE_DIR ICU_LIBRARY)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (APPLE AND HB_HAVE_CORETEXT)
|
||||||
|
# Apple Advanced Typography
|
||||||
|
add_definitions(-DHAVE_CORETEXT)
|
||||||
|
|
||||||
|
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-coretext.cc)
|
||||||
|
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-coretext.h)
|
||||||
|
|
||||||
|
find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices)
|
||||||
|
if (APPLICATION_SERVICES_FRAMEWORK)
|
||||||
|
list(APPEND THIRD_PARTY_LIBS ${APPLICATION_SERVICES_FRAMEWORK})
|
||||||
|
endif (APPLICATION_SERVICES_FRAMEWORK)
|
||||||
|
|
||||||
|
mark_as_advanced(APPLICATION_SERVICES_FRAMEWORK)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (WIN32 AND HB_HAVE_UNISCRIBE)
|
||||||
|
add_definitions(-DHAVE_UNISCRIBE)
|
||||||
|
|
||||||
|
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.cc)
|
||||||
|
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h)
|
||||||
|
|
||||||
|
list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (WIN32 AND HB_HAVE_DIRECTWRITE)
|
||||||
|
add_definitions(-DHAVE_DIRECTWRITE)
|
||||||
|
|
||||||
|
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-directwrite.cc)
|
||||||
|
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-directwrite.h)
|
||||||
|
|
||||||
|
list(APPEND THIRD_PARTY_LIBS dwrite rpcrt4)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (HB_HAVE_GOBJECT)
|
||||||
|
include (FindPythonInterp)
|
||||||
|
include (FindPerl)
|
||||||
|
|
||||||
|
# Use the hints from glib-2.0.pc to find glib-mkenums
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PC_GLIB QUIET glib-2.0)
|
||||||
|
find_program(GLIB_MKENUMS glib-mkenums
|
||||||
|
HINTS ${PC_glib_mkenums}
|
||||||
|
)
|
||||||
|
set (GLIB_MKENUMS_CMD)
|
||||||
|
|
||||||
|
if (WIN32 AND NOT MINGW)
|
||||||
|
# In Visual Studio builds, shebang lines are not supported
|
||||||
|
# in the standard cmd.exe shell that we use, so we need to
|
||||||
|
# first determine whether glib-mkenums is a Python or PERL
|
||||||
|
# script
|
||||||
|
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "${GLIB_MKENUMS}" --version
|
||||||
|
RESULT_VARIABLE GLIB_MKENUMS_PYTHON
|
||||||
|
OUTPUT_QUIET ERROR_QUIET
|
||||||
|
)
|
||||||
|
if (GLIB_MKENUMS_PYTHON EQUAL 0)
|
||||||
|
message("${GLIB_MKENUMS} is a Python script.")
|
||||||
|
set (GLIB_MKENUMS_CMD "${PYTHON_EXECUTABLE}" "${GLIB_MKENUMS}")
|
||||||
|
else ()
|
||||||
|
execute_process(COMMAND "${PERL_EXECUTABLE}" "${GLIB_MKENUMS}" --version
|
||||||
|
RESULT_VARIABLE GLIB_MKENUMS_PERL
|
||||||
|
OUTPUT_QUIET ERROR_QUIET
|
||||||
|
)
|
||||||
|
if (GLIB_MKENUMS_PERL EQUAL 0)
|
||||||
|
message("${GLIB_MKENUMS} is a PERL script.")
|
||||||
|
set (GLIB_MKENUMS_CMD "${PERL_EXECUTABLE}" "${GLIB_MKENUMS}")
|
||||||
|
endif ()
|
||||||
|
if (NOT GLIB_MKENUMS_PERL EQUAL 0 AND NOT GLIB_MKENUMS_PYTHON EQUAL 0)
|
||||||
|
message(FATAL_ERROR "Unable to determine type of glib-mkenums script")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
else ()
|
||||||
|
set (GLIB_MKENUMS_CMD "${GLIB_MKENUMS}")
|
||||||
|
endif ()
|
||||||
|
if (NOT GLIB_MKENUMS_CMD)
|
||||||
|
message(FATAL_ERROR "HB_HAVE_GOBJECT was set, but we failed to find glib-mkenums, which is required")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
pkg_check_modules(PC_GOBJECT QUIET gobject-2.0)
|
||||||
|
|
||||||
|
find_library(GOBJECT_LIBRARIES NAMES gobject-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS})
|
||||||
|
find_path(GOBJECT_INCLUDE_DIR NAMES glib-object.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0)
|
||||||
|
|
||||||
|
include_directories(${GOBJECTCONFIG_INCLUDE_DIR} ${GOBJECT_INCLUDE_DIR})
|
||||||
|
mark_as_advanced(GOBJECT_LIBRARIES GOBJECT_INCLUDE_DIR)
|
||||||
|
|
||||||
|
list(APPEND hb_gobject_sources ${PROJECT_SOURCE_DIR}/src/hb-gobject-structs.cc)
|
||||||
|
list(APPEND hb_gobject_gen_sources
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc
|
||||||
|
)
|
||||||
|
list(APPEND hb_gobject_structs_headers
|
||||||
|
${PROJECT_SOURCE_DIR}/src/hb-gobject-structs.h
|
||||||
|
)
|
||||||
|
list(APPEND hb_gobject_headers
|
||||||
|
${PROJECT_SOURCE_DIR}/src/hb-gobject.h
|
||||||
|
${hb_gobject_structs_headers}
|
||||||
|
)
|
||||||
|
list(APPEND hb_gobject_gen_headers
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
|
||||||
|
COMMAND ${GLIB_MKENUMS_CMD}
|
||||||
|
--template=${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.h.tmpl
|
||||||
|
--identifier-prefix hb_
|
||||||
|
--symbol-prefix hb_gobject
|
||||||
|
${hb_gobject_structs_headers}
|
||||||
|
${project_headers}
|
||||||
|
> ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h.tmp
|
||||||
|
COMMAND "${CMAKE_COMMAND}"
|
||||||
|
"-DENUM_INPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h.tmp"
|
||||||
|
"-DENUM_OUTPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h"
|
||||||
|
-P ${PROJECT_SOURCE_DIR}/replace-enum-strings.cmake
|
||||||
|
DEPENDS ${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.h.tmpl
|
||||||
|
${hb_gobject_header}
|
||||||
|
${project_headers}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc
|
||||||
|
COMMAND ${GLIB_MKENUMS_CMD}
|
||||||
|
--template=${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.cc.tmpl
|
||||||
|
--identifier-prefix hb_
|
||||||
|
--symbol-prefix hb_gobject
|
||||||
|
${hb_gobject_header}
|
||||||
|
${project_headers}
|
||||||
|
> ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc.tmp
|
||||||
|
COMMAND "${CMAKE_COMMAND}"
|
||||||
|
"-DENUM_INPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc.tmp"
|
||||||
|
"-DENUM_OUTPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc"
|
||||||
|
-P ${PROJECT_SOURCE_DIR}/replace-enum-strings.cmake
|
||||||
|
DEPENDS ${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.cc.tmpl
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
|
||||||
|
${hb_gobject_header}
|
||||||
|
${project_headers}
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## Atomic ops availability detection
|
||||||
|
file(WRITE "${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c"
|
||||||
|
" void memory_barrier (void) { __sync_synchronize (); }
|
||||||
|
int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); }
|
||||||
|
int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); }
|
||||||
|
void mutex_unlock (int *m) { __sync_lock_release (m); }
|
||||||
|
int main () { return 0; }
|
||||||
|
")
|
||||||
|
try_compile(HB_HAVE_INTEL_ATOMIC_PRIMITIVES
|
||||||
|
${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives
|
||||||
|
${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c)
|
||||||
|
if (HB_HAVE_INTEL_ATOMIC_PRIMITIVES)
|
||||||
|
add_definitions(-DHAVE_INTEL_ATOMIC_PRIMITIVES)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
file(WRITE "${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops.c"
|
||||||
|
" #include <atomic.h>
|
||||||
|
/* This requires Solaris Studio 12.2 or newer: */
|
||||||
|
#include <mbarrier.h>
|
||||||
|
void memory_barrier (void) { __machine_rw_barrier (); }
|
||||||
|
int atomic_add (volatile unsigned *i) { return atomic_add_int_nv (i, 1); }
|
||||||
|
void *atomic_ptr_cmpxchg (volatile void **target, void *cmp, void *newval) { return atomic_cas_ptr (target, cmp, newval); }
|
||||||
|
int main () { return 0; }
|
||||||
|
")
|
||||||
|
try_compile(HB_HAVE_SOLARIS_ATOMIC_OPS
|
||||||
|
${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops
|
||||||
|
${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops.c)
|
||||||
|
if (HB_HAVE_SOLARIS_ATOMIC_OPS)
|
||||||
|
add_definitions(-DHAVE_SOLARIS_ATOMIC_OPS)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## Define harfbuzz library
|
||||||
|
add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers})
|
||||||
|
target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
|
||||||
|
|
||||||
|
## Define harfbuzz-subset library
|
||||||
|
add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
|
||||||
|
add_dependencies(harfbuzz-subset harfbuzz)
|
||||||
|
target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
|
||||||
|
|
||||||
|
if (UNIX OR MINGW)
|
||||||
|
# Make symbols link locally
|
||||||
|
link_libraries(-Bsymbolic-functions)
|
||||||
|
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
# Make sure we don't link to libstdc++
|
||||||
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
|
||||||
|
set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "m") # libm
|
||||||
|
set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
|
||||||
|
set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C)
|
||||||
|
set_target_properties(harfbuzz-subset PROPERTIES LINKER_LANGUAGE C)
|
||||||
|
|
||||||
|
# No threadsafe statics as we do it ourselves
|
||||||
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-threadsafe-statics")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
## Define harfbuzz-gobject library
|
||||||
|
if (HB_HAVE_GOBJECT)
|
||||||
|
add_library(harfbuzz-gobject
|
||||||
|
${hb_gobject_sources}
|
||||||
|
${hb_gobject_gen_sources}
|
||||||
|
${hb_gobject_headers}
|
||||||
|
${hb_gobject_gen_headers}
|
||||||
|
)
|
||||||
|
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
|
add_dependencies(harfbuzz-gobject harfbuzz)
|
||||||
|
target_link_libraries(harfbuzz-gobject harfbuzz ${GOBJECT_LIBRARIES} ${THIRD_PARTY_LIBS})
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# On Windows, g-ir-scanner requires a DLL build in order for it to work
|
||||||
|
if (WIN32)
|
||||||
|
if (NOT BUILD_SHARED_LIBS)
|
||||||
|
message("Building introspection files on Windows requires BUILD_SHARED_LIBS to be enabled.")
|
||||||
|
set (HB_HAVE_INTROSPECTION OFF)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (HB_HAVE_INTROSPECTION)
|
||||||
|
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PC_GI QUIET gobject-introspection-1.0)
|
||||||
|
|
||||||
|
find_program(G_IR_SCANNER g-ir-scanner
|
||||||
|
HINTS ${PC_g_ir_scanner}
|
||||||
|
)
|
||||||
|
|
||||||
|
find_program(G_IR_COMPILER g-ir-compiler
|
||||||
|
HINTS ${PC_g_ir_compiler}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (WIN32 AND NOT MINGW)
|
||||||
|
# Note that since we already enable HB_HAVE_GOBJECT
|
||||||
|
# we would already have PYTHON_EXECUTABLE handy
|
||||||
|
set (G_IR_SCANNER_CMD "${PYTHON_EXECUTABLE}" "${G_IR_SCANNER}")
|
||||||
|
else ()
|
||||||
|
set (G_IR_SCANNER_CMD "${G_IR_SCANNER}")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# We need to account for the varying output directories
|
||||||
|
# when we build using Visual Studio projects
|
||||||
|
if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
|
||||||
|
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
|
||||||
|
else ()
|
||||||
|
set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Get the CFlags that we used to build HarfBuzz/HarfBuzz-GObject
|
||||||
|
set (hb_defines_cflags "")
|
||||||
|
foreach (hb_cflag ${hb_cflags})
|
||||||
|
list(APPEND hb_defines_cflags "-D${hb_cflag}")
|
||||||
|
endforeach (hb_cflag)
|
||||||
|
|
||||||
|
# Get the other dependent libraries we used to build HarfBuzz/HarfBuzz-GObject
|
||||||
|
set (extra_libs "")
|
||||||
|
foreach (extra_lib ${THIRD_PARTY_LIBS})
|
||||||
|
# We don't want the .lib extension here...
|
||||||
|
string(REPLACE ".lib" "" extra_lib_stripped "${extra_lib}")
|
||||||
|
list(APPEND extra_libs "--extra-library=${extra_lib_stripped}")
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
set (introspected_sources)
|
||||||
|
foreach (f
|
||||||
|
${project_headers}
|
||||||
|
${project_sources}
|
||||||
|
${hb_gobject_gen_sources}
|
||||||
|
${hb_gobject_gen_headers}
|
||||||
|
${hb_gobject_sources}
|
||||||
|
${hb_gobject_headers}
|
||||||
|
)
|
||||||
|
if (WIN32)
|
||||||
|
# Nasty issue: We need to make drive letters lower case,
|
||||||
|
# otherwise g-ir-scanner won't like it and give us a bunch
|
||||||
|
# of invalid items and unresolved types...
|
||||||
|
STRING(SUBSTRING "${f}" 0 1 drive)
|
||||||
|
STRING(SUBSTRING "${f}" 1 -1 path)
|
||||||
|
if (drive MATCHES "[A-Z]")
|
||||||
|
STRING(TOLOWER ${drive} drive_lower)
|
||||||
|
list(APPEND introspected_sources "${drive_lower}${path}")
|
||||||
|
else ()
|
||||||
|
list(APPEND introspected_sources "${f}")
|
||||||
|
endif ()
|
||||||
|
else ()
|
||||||
|
list(APPEND introspected_sources "${f}")
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
# Finally, build the introspection files...
|
||||||
|
add_custom_command(
|
||||||
|
TARGET harfbuzz-gobject
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND ${G_IR_SCANNER_CMD}
|
||||||
|
--warn-all --no-libtool --verbose
|
||||||
|
-n hb
|
||||||
|
--namespace=HarfBuzz
|
||||||
|
--nsversion=0.0
|
||||||
|
--identifier-prefix=hb_
|
||||||
|
--include GObject-2.0
|
||||||
|
--pkg-export=harfbuzz
|
||||||
|
--cflags-begin
|
||||||
|
-I${PROJECT_SOURCE_DIR}/src
|
||||||
|
-I${PROJECT_BINARY_DIR}/src
|
||||||
|
${hb_includedir_cflags}
|
||||||
|
${hb_defines_cflags}
|
||||||
|
-DHB_H
|
||||||
|
-DHB_H_IN
|
||||||
|
-DHB_OT_H
|
||||||
|
-DHB_OT_H_IN
|
||||||
|
-DHB_GOBJECT_H
|
||||||
|
-DHB_GOBJECT_H_IN
|
||||||
|
-DHB_EXTERN=
|
||||||
|
--cflags-end
|
||||||
|
--library=harfbuzz-gobject
|
||||||
|
--library=harfbuzz
|
||||||
|
-L${hb_libpath}
|
||||||
|
${extra_libs}
|
||||||
|
${introspected_sources}
|
||||||
|
-o ${hb_libpath}/HarfBuzz-0.0.gir
|
||||||
|
DEPENDS harfbuzz-gobject harfbuzz
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET harfbuzz-gobject
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND "${G_IR_COMPILER}"
|
||||||
|
--verbose --debug
|
||||||
|
--includedir ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${hb_libpath}/HarfBuzz-0.0.gir
|
||||||
|
-o ${hb_libpath}/HarfBuzz-0.0.typelib
|
||||||
|
DEPENDS ${hb_libpath}/HarfBuzz-0.0.gir harfbuzz-gobject
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## Additional framework build configs
|
||||||
|
if (BUILD_FRAMEWORK)
|
||||||
|
set (CMAKE_MACOSX_RPATH ON)
|
||||||
|
set_target_properties(harfbuzz PROPERTIES
|
||||||
|
FRAMEWORK TRUE
|
||||||
|
PUBLIC_HEADER "${project_headers}"
|
||||||
|
XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
|
||||||
|
)
|
||||||
|
set (MACOSX_FRAMEWORK_IDENTIFIER "harfbuzz")
|
||||||
|
set (MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${HB_VERSION}")
|
||||||
|
set (MACOSX_FRAMEWORK_BUNDLE_VERSION "${HB_VERSION}")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## Additional harfbuzz build artifacts
|
||||||
|
if (HB_BUILD_UTILS)
|
||||||
|
# https://github.com/WebKit/webkit/blob/master/Source/cmake/FindCairo.cmake
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PC_CAIRO QUIET cairo)
|
||||||
|
|
||||||
|
find_path(CAIRO_INCLUDE_DIRS NAMES cairo.h HINTS ${PC_CAIRO_INCLUDEDIR} ${PC_CAIRO_INCLUDE_DIRS} PATH_SUFFIXES cairo)
|
||||||
|
find_library(CAIRO_LIBRARIESNAMES cairo HINTS ${PC_CAIRO_LIBDIR} ${PC_CAIRO_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
add_definitions("-DPACKAGE_NAME=\"HarfBuzz\"")
|
||||||
|
add_definitions("-DPACKAGE_VERSION=\"${HB_VERSION}\"")
|
||||||
|
include_directories(${CAIRO_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
add_executable(hb-view ${HB_VIEW_sources})
|
||||||
|
target_link_libraries(hb-view harfbuzz ${CAIRO_LIBRARIESNAMES})
|
||||||
|
|
||||||
|
add_executable(hb-shape ${HB_SHAPE_sources})
|
||||||
|
target_link_libraries(hb-shape harfbuzz)
|
||||||
|
|
||||||
|
add_executable(hb-subset ${HB_SUBSET_CLI_sources})
|
||||||
|
target_link_libraries(hb-subset harfbuzz harfbuzz-subset)
|
||||||
|
|
||||||
|
add_executable(hb-ot-shape-closure ${HB_OT_SHAPE_CLOSURE_sources})
|
||||||
|
target_link_libraries(hb-ot-shape-closure harfbuzz)
|
||||||
|
|
||||||
|
mark_as_advanced(CAIRO_INCLUDE_DIRS CAIRO_LIBRARIESNAMES)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
include (GNUInstallDirs)
|
||||||
|
|
||||||
|
if (NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL)
|
||||||
|
install(FILES ${project_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz)
|
||||||
|
if (HB_HAVE_GOBJECT)
|
||||||
|
install(FILES ${hb_gobject_headers} ${hb_gobject_gen_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
|
||||||
|
install(TARGETS harfbuzz
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
FRAMEWORK DESTINATION Library/Frameworks
|
||||||
|
)
|
||||||
|
if (HB_BUILD_UTILS)
|
||||||
|
install(TARGETS hb-view
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
install(TARGETS hb-view
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
install(TARGETS hb-shape
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
install(TARGETS hb-ot-shape-closure
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
if (HB_HAVE_GOBJECT)
|
||||||
|
install(TARGETS harfbuzz-gobject
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
if (HB_HAVE_INTROSPECTION)
|
||||||
|
if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
|
||||||
|
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
|
||||||
|
else ()
|
||||||
|
set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
install(FILES "${hb_libpath}/HarfBuzz-0.0.gir"
|
||||||
|
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/gir-1.0
|
||||||
|
)
|
||||||
|
|
||||||
|
install(FILES "${hb_libpath}/HarfBuzz-0.0.typelib"
|
||||||
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/girepository-1.0
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (UNIX AND CMAKE_GENERATOR STREQUAL "Ninja")
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
|
||||||
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcolor-diagnostics")
|
||||||
|
endif ()
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color")
|
||||||
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
## src/ executables
|
||||||
|
if (NOT HB_DISABLE_TEST_PROGS)
|
||||||
|
foreach (prog main test test-would-substitute test-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges)
|
||||||
|
set (prog_name ${prog})
|
||||||
|
if (${prog_name} STREQUAL "test")
|
||||||
|
# test can not be used as a valid executable name on cmake, lets special case it
|
||||||
|
set (prog_name test-test)
|
||||||
|
endif ()
|
||||||
|
add_executable(${prog_name} ${PROJECT_SOURCE_DIR}/src/${prog}.cc)
|
||||||
|
target_link_libraries(${prog_name} harfbuzz ${THIRD_PARTY_LIBS})
|
||||||
|
endforeach ()
|
||||||
|
set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
if (UNIX OR MINGW)
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
# generate harfbuzz.def after build completion
|
||||||
|
string(REPLACE ";" " " space_separated_headers "${project_headers}")
|
||||||
|
add_custom_command(TARGET harfbuzz POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E env "headers=${space_separated_headers}" python ${PROJECT_SOURCE_DIR}/src/gen-def.py ${PROJECT_BINARY_DIR}/harfbuzz.def
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src)
|
||||||
|
|
||||||
|
add_test(NAME check-static-inits.sh
|
||||||
|
COMMAND ${PROJECT_SOURCE_DIR}/src/check-static-inits.sh
|
||||||
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/harfbuzz.dir/src # ugly hack
|
||||||
|
)
|
||||||
|
add_test(NAME check-libstdc++.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-libstdc++.sh)
|
||||||
|
add_test(NAME check-symbols.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-symbols.sh)
|
||||||
|
|
||||||
|
set_tests_properties(
|
||||||
|
check-static-inits.sh check-libstdc++.sh check-symbols.sh
|
||||||
|
PROPERTIES
|
||||||
|
ENVIRONMENT "libs=.;srcdir=${PROJECT_SOURCE_DIR}/src"
|
||||||
|
SKIP_RETURN_CODE 77)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
add_test(NAME check-c-linkage-decls.sh COMMAND ./check-c-linkage-decls.sh)
|
||||||
|
add_test(NAME check-header-guards.sh COMMAND ./check-header-guards.sh)
|
||||||
|
add_test(NAME check-externs.sh COMMAND ./check-externs.sh)
|
||||||
|
add_test(NAME check-includes.sh COMMAND ./check-includes.sh)
|
||||||
|
set_tests_properties(
|
||||||
|
check-c-linkage-decls.sh check-header-guards.sh check-externs.sh check-includes.sh
|
||||||
|
PROPERTIES
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src
|
||||||
|
SKIP_RETURN_CODE 77)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Needs to come last so that variables defined above are passed to
|
||||||
|
# subdirectories.
|
||||||
|
add_subdirectory(test)
|
@ -4,14 +4,16 @@ NULL =
|
|||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
SUBDIRS = src util test docs win32
|
SUBDIRS = src util test docs
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
autogen.sh \
|
autogen.sh \
|
||||||
harfbuzz.doap \
|
harfbuzz.doap \
|
||||||
Android.mk \
|
|
||||||
README.python \
|
README.python \
|
||||||
BUILD.md \
|
BUILD.md \
|
||||||
|
RELEASING.md \
|
||||||
|
CMakeLists.txt \
|
||||||
|
replace-enum-strings.cmake \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = \
|
MAINTAINERCLEANFILES = \
|
||||||
|
393
NEWS
393
NEWS
@ -1,7 +1,376 @@
|
|||||||
Overview of changes leading to 1.2.8
|
=======
|
||||||
Not yet released
|
Overview of changes leading to 1.7.5
|
||||||
|
Tuesday, January 30, 2018
|
||||||
====================================
|
====================================
|
||||||
- Implemented 'CPAL' table in hb-ot-color.
|
|
||||||
|
- Separate Khmer shaper from Indic.
|
||||||
|
- First stab at AAT morx. Not hooked up.
|
||||||
|
- Misc bug fixes.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.7.4
|
||||||
|
Wednesday, December 20, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Fix collect_glyphs() regression caused by hb_set_t changes.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.7.3
|
||||||
|
Monday, December 18, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- hb_set_t performance tuning and optimizations.
|
||||||
|
- Speed up collect_glyphs() and reject garbage data.
|
||||||
|
- In hb_coretext_font_create() set font point-size (ptem).
|
||||||
|
- Misc fixes.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.7.2
|
||||||
|
Monday, December 4, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Optimize hb_set_add_range().
|
||||||
|
- Misc fixes.
|
||||||
|
- New API:
|
||||||
|
hb_coretext_font_create()
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.7.1
|
||||||
|
Tuesday, November 14, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Fix atexit object destruction regression.
|
||||||
|
- Fix minor integer-overflow.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.7.0
|
||||||
|
Monday, November 13, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Minor Indic fixes.
|
||||||
|
- Implement kerning and glyph names in hb-ot-font.
|
||||||
|
- Various DSO optimization re .data and .bss sizes.
|
||||||
|
- Make C++11 optional; build fixes.
|
||||||
|
- Mark all other backends "unsafe-to-break".
|
||||||
|
- Graphite fix.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.6.3
|
||||||
|
Thursday, October 26th, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Fix hb_set_t some more. Should be solid now.
|
||||||
|
- Implement get_glyph_name() for hb-ot-font.
|
||||||
|
- Misc fixes.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.6.2
|
||||||
|
Monday, October 23nd, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Yesterday's release had a bad crasher; don't use it. That's what
|
||||||
|
happens when one works on Sunday...
|
||||||
|
https://github.com/harfbuzz/harfbuzz/issues/578
|
||||||
|
- Build fixes for FreeBSD and Chrome Android.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.6.1
|
||||||
|
Sunday, October 22nd, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Don't skip over COMBINING GRAPHEME JOINER when ligating, etc.
|
||||||
|
To be refined: https://github.com/harfbuzz/harfbuzz/issues/554
|
||||||
|
- Faster hb_set_t implementation.
|
||||||
|
- Don't use deprecated ICU API.
|
||||||
|
- Fix undefined-behavior in Myanmar shaper, introduced in 1.6.0
|
||||||
|
- Deprecated API:
|
||||||
|
hb_set_invert()
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.6.0
|
||||||
|
Friday, October the 13th, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Update to Unicode 10.
|
||||||
|
|
||||||
|
- Various Indic and Universal Shaping Engine fixes as a result of
|
||||||
|
HarfBuzz Hackfest with Jonathan Kew at Web Engines Hackfest at
|
||||||
|
the Igalia offices in A Coruña, Spain. Thanks Igalia for having
|
||||||
|
us!
|
||||||
|
|
||||||
|
- Implement Unicode Arabic Mark Ordering Algorithm UTR#53.
|
||||||
|
|
||||||
|
- Implement optical sizing / tracking in CoreText backend, using
|
||||||
|
new API hb_font_set_ptem().
|
||||||
|
|
||||||
|
- Allow notifying hb_font_t that underlying FT_Face changed sizing,
|
||||||
|
using new API hb_ft_font_changed().
|
||||||
|
|
||||||
|
- More Graphite backend RTL fixes.
|
||||||
|
|
||||||
|
- Fix caching of variable font shaping plans.
|
||||||
|
|
||||||
|
- hb-view / hb-shape now accept following new arguments:
|
||||||
|
|
||||||
|
o --unicodes: takes a list of hex numbers that represent Unicode
|
||||||
|
codepoints.
|
||||||
|
|
||||||
|
New API:
|
||||||
|
+hb_face_get_table_tags()
|
||||||
|
+hb_font_set_ptem()
|
||||||
|
+hb_font_get_ptem()
|
||||||
|
+hb_ft_font_changed()
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.5.1
|
||||||
|
Tuesday, September 5, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Fix "unsafe-to-break" in fallback shaping and other corner cases.
|
||||||
|
All our tests pass with --verify now, meaning unsafe-to-break API
|
||||||
|
works as expected.
|
||||||
|
- Add --unicodes to hb-view / hb-shape.
|
||||||
|
- [indic] Treat Consonant_With_Stacker as consonant. This will need
|
||||||
|
further tweaking.
|
||||||
|
- hb_buffer_diff() tweaks.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.5.0
|
||||||
|
Wednesday, August 23, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Misc new API, for appending a buffer to another, and for comparing
|
||||||
|
contents of two buffers for types of differences.
|
||||||
|
|
||||||
|
- New "unsafe-to-break" API. Can be used to speed up reshaping
|
||||||
|
in line-breaking situations. Essentially, after shaping, it returns
|
||||||
|
positions in the input string (some of the cluster boundaries) that
|
||||||
|
are "safe to break" in that if the text is segmented at that position
|
||||||
|
and two sides reshaped and concatenated, the shaping result is
|
||||||
|
exactly the same as shaping the text in one piece.
|
||||||
|
|
||||||
|
hb-view and hb-shape and hb-shape now take --verify, which verifies
|
||||||
|
the above property.
|
||||||
|
|
||||||
|
Some corner cases of the implementation are still not quite working.
|
||||||
|
Those will be fixed in subsequent releases.
|
||||||
|
|
||||||
|
- New API:
|
||||||
|
|
||||||
|
hb_buffer_append()
|
||||||
|
|
||||||
|
hb_glyph_flags_t
|
||||||
|
HB_GLYPH_FLAG_UNSAFE_TO_BREAK
|
||||||
|
HB_GLYPH_FLAG_DEFINED
|
||||||
|
hb_glyph_info_get_glyph_flags()
|
||||||
|
|
||||||
|
HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS
|
||||||
|
|
||||||
|
hb_buffer_diff_flags_t
|
||||||
|
HB_BUFFER_DIFF_FLAG_EQUAL
|
||||||
|
HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH
|
||||||
|
HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH
|
||||||
|
HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT
|
||||||
|
HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
|
||||||
|
HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH
|
||||||
|
HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH
|
||||||
|
HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH
|
||||||
|
HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH
|
||||||
|
hb_buffer_diff
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.4.8
|
||||||
|
Tuesday, August 8, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Major fix to avar table handling.
|
||||||
|
- Rename hb-shape --show-message to --trace.
|
||||||
|
- Build fixes.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.4.7
|
||||||
|
Tuesday, July 18, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Multiple Indic, Tibetan, and Cham fixes.
|
||||||
|
- CoreText: Allow disabling kerning.
|
||||||
|
- Adjust Arabic feature order again.
|
||||||
|
- Misc build fixes.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.4.6
|
||||||
|
Sunday, April 23, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Graphite2: Fix RTL positioning issue.
|
||||||
|
- Backlist GDEF of more versions of Padauk and Tahoma.
|
||||||
|
- New, experimental, cmake alternative build system.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.4.5
|
||||||
|
Friday, March 10, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Revert "Fix Context lookup application when moving back after a glyph..."
|
||||||
|
This introduced memory access problems. To be fixed properly soon.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.4.4
|
||||||
|
Sunday, March 5, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Fix Context lookup application when moving back after a glyph deletion.
|
||||||
|
- Fix buffer-overrun in Bengali.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.4.3
|
||||||
|
Saturday, February 25, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Route Adlam script to Arabic shaper.
|
||||||
|
- Misc fixes.
|
||||||
|
- New API:
|
||||||
|
hb_font_set_face()
|
||||||
|
- Deprecate API:
|
||||||
|
hb_graphite2_font_get_gr_font()
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.4.2
|
||||||
|
Monday, January 23, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Implement OpenType Font Variation tables avar/fvar/HVAR/VVAR.
|
||||||
|
- hb-shape and hb-view now accept --variations.
|
||||||
|
- New API:
|
||||||
|
|
||||||
|
hb_variation_t
|
||||||
|
hb_variation_from_string()
|
||||||
|
hb_variation_to_string()
|
||||||
|
|
||||||
|
hb_font_set_variations()
|
||||||
|
hb_font_set_var_coords_design()
|
||||||
|
hb_font_get_var_coords_normalized()
|
||||||
|
|
||||||
|
hb-ot-var.h:
|
||||||
|
hb_ot_var_axis_t
|
||||||
|
hb_ot_var_has_data()
|
||||||
|
hb_ot_var_get_axis_count()
|
||||||
|
hb_ot_var_get_axes()
|
||||||
|
hb_ot_var_find_axis()
|
||||||
|
hb_ot_var_normalize_variations()
|
||||||
|
hb_ot_var_normalize_coords()
|
||||||
|
|
||||||
|
- MVAR to be implemented later. Access to named instances to be
|
||||||
|
implemented later as well.
|
||||||
|
|
||||||
|
- Misc fixes.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.4.1
|
||||||
|
Thursday, January 5, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Always build and use UCDN for Unicode data by default.
|
||||||
|
Reduces dependence on version of Unicode data in glib,
|
||||||
|
specially in the Windows bundles we are shipping, which
|
||||||
|
have very old glib.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.4.0
|
||||||
|
Thursday, January 5, 2017
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Merged "OpenType GX" branch which adds core of support for
|
||||||
|
OpenType 1.8 Font Variations. To that extent, the relevant
|
||||||
|
new API is:
|
||||||
|
|
||||||
|
New API:
|
||||||
|
hb_font_set_var_coords_normalized()
|
||||||
|
|
||||||
|
with supporting API:
|
||||||
|
|
||||||
|
New API:
|
||||||
|
HB_OT_LAYOUT_NO_VARIATIONS_INDEX
|
||||||
|
hb_ot_layout_table_find_feature_variations()
|
||||||
|
hb_ot_layout_feature_with_variations_get_lookups()
|
||||||
|
hb_shape_plan_create2()
|
||||||
|
hb_shape_plan_create_cached2()
|
||||||
|
|
||||||
|
Currently variations in GSUB/GPOS/GDEF are fully supported,
|
||||||
|
and no other tables are supported. In particular, fvar/avar
|
||||||
|
are NOT supported, hence the hb_font_set_var_coords_normalized()
|
||||||
|
taking normalized coordinates. API to take design coordinates
|
||||||
|
will be added in the future.
|
||||||
|
|
||||||
|
HVAR/VVAR/MVAR support will also be added to hb-ot-font in the
|
||||||
|
future.
|
||||||
|
|
||||||
|
- Fix regression in GDEF glyph class processing.
|
||||||
|
- Add decompositions for Chakma, Limbu, and Balinese in USE shaper.
|
||||||
|
- Misc fixes.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.3.4
|
||||||
|
Monday, December 5, 2016
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Fix vertical glyph origin in hb-ot-font.
|
||||||
|
- Implement CBDT/CBLC color font glyph extents in hb-ot-font.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.3.3
|
||||||
|
Wednesday, September 28, 2016
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Implement parsing of OpenType MATH table.
|
||||||
|
New API:
|
||||||
|
HB_OT_TAG_MATH
|
||||||
|
HB_OT_MATH_SCRIPT
|
||||||
|
hb_ot_math_constant_t
|
||||||
|
hb_ot_math_kern_t
|
||||||
|
hb_ot_math_glyph_variant_t
|
||||||
|
hb_ot_math_glyph_part_flags_t
|
||||||
|
hb_ot_math_glyph_part_t
|
||||||
|
hb_ot_math_has_data
|
||||||
|
hb_ot_math_get_constant
|
||||||
|
hb_ot_math_get_glyph_italics_correction
|
||||||
|
hb_ot_math_get_glyph_top_accent_attachment
|
||||||
|
hb_ot_math_get_glyph_kerning
|
||||||
|
hb_ot_math_is_glyph_extended_shape
|
||||||
|
hb_ot_math_get_glyph_variants
|
||||||
|
hb_ot_math_get_min_connector_overlap
|
||||||
|
hb_ot_math_get_glyph_assembly
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.3.2
|
||||||
|
Wednesday, September 27, 2016
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Fix build of hb-coretext on older OS X versions.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.3.1
|
||||||
|
Wednesday, September 7, 2016
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Blacklist bad GDEF of more fonts (Padauk).
|
||||||
|
- More CoreText backend crash fixes with OS X 10.9.5.
|
||||||
|
- Misc fixes.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 1.3.0
|
||||||
|
Thursday, July 21, 2016
|
||||||
|
====================================
|
||||||
|
|
||||||
|
- Update to Unicode 9.0.0
|
||||||
|
- Move Javanese from Indic shaper to Universal Shaping Engine.
|
||||||
|
- Allow MultipleSubst to delete a glyph (matching Windows engine).
|
||||||
|
- Update Universal Shaping Engine to latest draft from Microsoft.
|
||||||
|
- DirectWrite backend improvements. Note: this backend is for testing ONLY.
|
||||||
|
- CoreText backend improvements with unreachable fonts.
|
||||||
|
- Implement symbol fonts (cmap 3.0.0) in hb-ft and hb-ot-font.
|
||||||
|
- Blacklist bad GDEF of more fonts (Tahoma & others).
|
||||||
|
- Misc fixes.
|
||||||
|
|
||||||
Overview of changes leading to 1.2.7
|
Overview of changes leading to 1.2.7
|
||||||
Monday, May 2, 2016
|
Monday, May 2, 2016
|
||||||
@ -109,7 +478,7 @@ Tuesday, February 23, 2016
|
|||||||
- CoreText: Drastically speed up font initialization.
|
- CoreText: Drastically speed up font initialization.
|
||||||
- CoreText: Fix tiny leak.
|
- CoreText: Fix tiny leak.
|
||||||
- Group ZWJ/ZWNJ with previous syllable under cluster-level=0.
|
- Group ZWJ/ZWNJ with previous syllable under cluster-level=0.
|
||||||
https://github.com/behdad/harfbuzz/issues/217
|
https://github.com/harfbuzz/harfbuzz/issues/217
|
||||||
- Add test/shaping/README.md about how to add tests to the suite.
|
- Add test/shaping/README.md about how to add tests to the suite.
|
||||||
|
|
||||||
|
|
||||||
@ -125,8 +494,8 @@ Friday, February 19, 2016
|
|||||||
- Allow GPOS cursive connection on marks, and fix the interaction with
|
- Allow GPOS cursive connection on marks, and fix the interaction with
|
||||||
mark attachment. This work resulted in some changes to how mark
|
mark attachment. This work resulted in some changes to how mark
|
||||||
attachments work. See:
|
attachments work. See:
|
||||||
https://github.com/behdad/harfbuzz/issues/211
|
https://github.com/harfbuzz/harfbuzz/issues/211
|
||||||
https://github.com/behdad/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2
|
https://github.com/harfbuzz/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2
|
||||||
- Graphite2 shaper: improved negative advance handling (eg. Nastaliq).
|
- Graphite2 shaper: improved negative advance handling (eg. Nastaliq).
|
||||||
- Add nmake-based build system for Windows.
|
- Add nmake-based build system for Windows.
|
||||||
- Minor speedup.
|
- Minor speedup.
|
||||||
@ -167,7 +536,7 @@ Wednesday, November 26, 2015
|
|||||||
====================================
|
====================================
|
||||||
|
|
||||||
- Fix badly-broken fallback shaper that affected terminology.
|
- Fix badly-broken fallback shaper that affected terminology.
|
||||||
https://github.com/behdad/harfbuzz/issues/187
|
https://github.com/harfbuzz/harfbuzz/issues/187
|
||||||
- Fix y_scaling in Graphite shaper.
|
- Fix y_scaling in Graphite shaper.
|
||||||
- API changes:
|
- API changes:
|
||||||
* An unset glyph_h_origin() function in font-funcs now (sensibly)
|
* An unset glyph_h_origin() function in font-funcs now (sensibly)
|
||||||
@ -189,11 +558,11 @@ Wednesday, November 18, 2015
|
|||||||
====================================
|
====================================
|
||||||
|
|
||||||
- Implement 'stch' stretch feature for Syriac Abbreviation Mark.
|
- Implement 'stch' stretch feature for Syriac Abbreviation Mark.
|
||||||
https://github.com/behdad/harfbuzz/issues/141
|
https://github.com/harfbuzz/harfbuzz/issues/141
|
||||||
- Disable use of decompose_compatibility() callback.
|
- Disable use of decompose_compatibility() callback.
|
||||||
- Implement "shaping" of various Unicode space characters, even
|
- Implement "shaping" of various Unicode space characters, even
|
||||||
if the font does not support them.
|
if the font does not support them.
|
||||||
https://github.com/behdad/harfbuzz/issues/153
|
https://github.com/harfbuzz/harfbuzz/issues/153
|
||||||
- If font does not support U+2011 NO-BREAK HYPHEN, fallback to
|
- If font does not support U+2011 NO-BREAK HYPHEN, fallback to
|
||||||
U+2010 HYPHEN.
|
U+2010 HYPHEN.
|
||||||
- Changes resulting from libFuzzer continuous fuzzing:
|
- Changes resulting from libFuzzer continuous fuzzing:
|
||||||
@ -216,7 +585,7 @@ Thursday, October 15, 2015
|
|||||||
- Revert default load-flags of fonts created using hb_ft_font_create()
|
- Revert default load-flags of fonts created using hb_ft_font_create()
|
||||||
back to FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING. This was changed in
|
back to FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING. This was changed in
|
||||||
last release (1.0.5), but caused major issues, so revert.
|
last release (1.0.5), but caused major issues, so revert.
|
||||||
https://github.com/behdad/harfbuzz/issues/143
|
https://github.com/harfbuzz/harfbuzz/issues/143
|
||||||
|
|
||||||
|
|
||||||
Overview of changes leading to 1.0.5
|
Overview of changes leading to 1.0.5
|
||||||
@ -224,7 +593,7 @@ Tuesday, October 13, 2015
|
|||||||
====================================
|
====================================
|
||||||
|
|
||||||
- Fix multiple memory access bugs discovered using libFuzzer.
|
- Fix multiple memory access bugs discovered using libFuzzer.
|
||||||
https://github.com/behdad/harfbuzz/issues/139
|
https://github.com/harfbuzz/harfbuzz/issues/139
|
||||||
Everyone should upgrade to this version as soon as possible.
|
Everyone should upgrade to this version as soon as possible.
|
||||||
We now have continuous fuzzing set up, to avoid issues like
|
We now have continuous fuzzing set up, to avoid issues like
|
||||||
these creeping in again.
|
these creeping in again.
|
||||||
@ -495,7 +864,7 @@ Wednesday, July 16, 2014
|
|||||||
U+FFFD REPLACEMENT CHARACTER now.
|
U+FFFD REPLACEMENT CHARACTER now.
|
||||||
- With all changes in this release, the buffer will contain fully
|
- With all changes in this release, the buffer will contain fully
|
||||||
valid Unicode after hb_buffer_add_utf8/16/32 no matter how
|
valid Unicode after hb_buffer_add_utf8/16/32 no matter how
|
||||||
broken the input is. This can be overriden though. See below.
|
broken the input is. This can be overridden though. See below.
|
||||||
- Fix Mongolian Variation Selectors for fonts without GDEF.
|
- Fix Mongolian Variation Selectors for fonts without GDEF.
|
||||||
- Fix minor invalid buffer access.
|
- Fix minor invalid buffer access.
|
||||||
- Accept zh-Hant and zh-Hans language tags. hb_ot_tag_to_language()
|
- Accept zh-Hant and zh-Hans language tags. hb_ot_tag_to_language()
|
||||||
|
9
README
9
README
@ -1,5 +1,8 @@
|
|||||||
[![Build Status](https://travis-ci.org/behdad/harfbuzz.svg)](https://travis-ci.org/behdad/harfbuzz)
|
[![Build Status](https://travis-ci.org/harfbuzz/harfbuzz.svg)](https://travis-ci.org/harfbuzz/harfbuzz)
|
||||||
[![Coverage Status](https://img.shields.io/coveralls/behdad/harfbuzz.svg)](https://coveralls.io/r/behdad/harfbuzz)
|
[![Build status](https://ci.appveyor.com/api/projects/status/0t0flrxpstj9lb9w?svg=true)](https://ci.appveyor.com/project/harfbuzz/harfbuzz)
|
||||||
|
[![CircleCI](https://circleci.com/gh/harfbuzz/harfbuzz.svg?style=svg)](https://circleci.com/gh/harfbuzz/harfbuzz)
|
||||||
|
[![Coverity](https://img.shields.io/coverity/scan/5450.svg)](https://scan.coverity.com/projects/behdad-harfbuzz)
|
||||||
|
[![Coverage Status](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz)
|
||||||
[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
|
[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
|
||||||
|
|
||||||
This is HarfBuzz, a text shaping library.
|
This is HarfBuzz, a text shaping library.
|
||||||
@ -9,3 +12,5 @@ For bug reports, mailing list, and other information please visit:
|
|||||||
http://harfbuzz.org/
|
http://harfbuzz.org/
|
||||||
|
|
||||||
For license information, see the file COPYING.
|
For license information, see the file COPYING.
|
||||||
|
|
||||||
|
Documentation: https://harfbuzz.github.io
|
||||||
|
99
RELEASING.md
Normal file
99
RELEASING.md
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
HarfBuzz release walk-through checklist:
|
||||||
|
|
||||||
|
1. Open gitk and review changes since last release.
|
||||||
|
|
||||||
|
* `git diff $(git describe | sed 's/-.*//').. src/*.h` prints all public API
|
||||||
|
changes.
|
||||||
|
|
||||||
|
Document them in NEWS. All API and API semantic changes should be clearly
|
||||||
|
marked as API additions, API changes, or API deletions. Document
|
||||||
|
deprecations.
|
||||||
|
|
||||||
|
If there's a backward-incompatible API change (including deletions for API
|
||||||
|
used anywhere), that's a release blocker. Do NOT release.
|
||||||
|
|
||||||
|
2. Based on severity of changes, decide whether it's a minor or micro release
|
||||||
|
number bump,
|
||||||
|
|
||||||
|
3. Make sure you have correct date and new version at the top of NEWS file,
|
||||||
|
|
||||||
|
4. Bump version in configure.ac line 3,
|
||||||
|
|
||||||
|
5. Do "make distcheck", if it passes, you get a tarball.
|
||||||
|
Otherwise, fix things and commit them separately before making release,
|
||||||
|
|
||||||
|
6. "make release-files". Enter your GPG password. This creates a sha256 hash
|
||||||
|
and signs it.
|
||||||
|
|
||||||
|
7. Now that you have release files built, commit NEWS and configure.ac changes.
|
||||||
|
The commit message is simply the release number. Eg. "1.4.7"
|
||||||
|
|
||||||
|
8. Tag the release and sign it: Eg. "git tag -s 1.4.7 -m 1.4.7". Enter your
|
||||||
|
GPG password again.
|
||||||
|
|
||||||
|
9. Build win32 bundle.
|
||||||
|
|
||||||
|
a. Put contents of [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ) on your `~/.local/i686-w64-mingw32`,
|
||||||
|
|
||||||
|
b. Run `../mingw32.sh --with-uniscribe` script (available below) to configure harfbuzz with mingw in a subdirector (eg. winbuild/),
|
||||||
|
|
||||||
|
c. make
|
||||||
|
|
||||||
|
d. Back in the parent directory, run `./UPDATE.sh` (available below) to build win32 bundle.
|
||||||
|
|
||||||
|
10. Copy all artefacts to users.freedesktop.org and move them into
|
||||||
|
`/srv/www.freedesktop.org/www/software/harfbuzz/release` There should be four
|
||||||
|
files. Eg.:
|
||||||
|
```
|
||||||
|
-rw-r--r-- 1 behdad eng 1592693 Jul 18 11:25 harfbuzz-1.4.7.tar.bz2
|
||||||
|
-rw-r--r-- 1 behdad eng 89 Jul 18 11:34 harfbuzz-1.4.7.tar.bz2.sha256
|
||||||
|
-rw-r--r-- 1 behdad eng 339 Jul 18 11:34 harfbuzz-1.4.7.tar.bz2.sha256.asc
|
||||||
|
-rw-r--r-- 1 behdad eng 2895619 Jul 18 11:34 harfbuzz-1.4.7-win32.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
11. While doing that, quickly double-check the size of the .tar.bz2 and .zip
|
||||||
|
files against their previous releases to make sure nothing bad happened.
|
||||||
|
They should be in the ballpark, perhaps slightly larger. Sometimes they
|
||||||
|
do shrink, that's not by itself a stopper.
|
||||||
|
|
||||||
|
12. Push the commit and tag out: "git push --follow-tags". Make sure it's
|
||||||
|
pushed both to freedesktop repo and github.
|
||||||
|
|
||||||
|
13. Go to GitHub release page [here](https://github.com/harfbuzz/harfbuzz/releases),
|
||||||
|
edit the tag, upload artefacts and NEWS entry and save.
|
||||||
|
|
||||||
|
|
||||||
|
## UPDATE.sh
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
v=$1
|
||||||
|
|
||||||
|
if test "x$v" = x; then
|
||||||
|
echo "usage: UPDATE.sh micro-version"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
dir_prefix=harfbuzz-1.4.
|
||||||
|
dir_suffix=-win32
|
||||||
|
dir=$dir_prefix$v$dir_suffix
|
||||||
|
dir_old=$dir_prefix$((v-1))$dir_suffix
|
||||||
|
if test -d "$dir"; then
|
||||||
|
echo "New dir $dir exists; not overwriting"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! test -d "$dir_old"; then
|
||||||
|
echo "Old dir $dir_old does NOT exist; aborting"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
set -ex
|
||||||
|
cp -a "$dir_old" "$dir.tmp"
|
||||||
|
rm -f "$dir.tmp"/GDX32.dll
|
||||||
|
rm -f "$dir.tmp"/usp10.dll
|
||||||
|
cp ../winbuild/src/.libs/libharfbuzz-0.dll{,.def} $dir.tmp/
|
||||||
|
cp ../winbuild/util/.libs/hb-{shape,view}.exe $dir.tmp/
|
||||||
|
i686-w64-mingw32-strip $dir.tmp/{hb-shape.exe,hb-view.exe,libharfbuzz-0.dll}
|
||||||
|
mv $dir.tmp $dir
|
||||||
|
zip -r $dir.zip $dir
|
||||||
|
echo Bundle $dir.zip ready
|
||||||
|
```
|
29
TODO
29
TODO
@ -1,24 +1,14 @@
|
|||||||
General fixes:
|
General fixes:
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- AAT 'morx' implementation.
|
|
||||||
|
|
||||||
- Return "safe-to-break" bit from shaping.
|
|
||||||
|
|
||||||
- Implement 'rand' feature.
|
- Implement 'rand' feature.
|
||||||
|
|
||||||
- mask propagation? (when ligation, "or" the masks).
|
|
||||||
|
|
||||||
|
|
||||||
API issues:
|
API issues:
|
||||||
===========
|
===========
|
||||||
|
|
||||||
- API to accept a list of languages?
|
- API to accept a list of languages?
|
||||||
|
|
||||||
- Add init_func to font_funcs. Adjust ft.
|
|
||||||
|
|
||||||
- 'const' for getter APIs? (use mutable internally)
|
|
||||||
|
|
||||||
- Remove hb_ot_shape_glyphs_closure()?
|
- Remove hb_ot_shape_glyphs_closure()?
|
||||||
|
|
||||||
|
|
||||||
@ -39,7 +29,7 @@ API additions
|
|||||||
|
|
||||||
- Add query / enumeration API for aalt-like features?
|
- Add query / enumeration API for aalt-like features?
|
||||||
|
|
||||||
- SFNT api? get_num_faces? get_table_tags? (there's something in stash)
|
- SFNT api? get_num_faces?
|
||||||
|
|
||||||
- Add segmentation API
|
- Add segmentation API
|
||||||
|
|
||||||
@ -50,20 +40,3 @@ hb-view / hb-shape enhancements:
|
|||||||
===============================
|
===============================
|
||||||
|
|
||||||
- Add --width, --height, --auto-size, --ink-box, --align, etc?
|
- Add --width, --height, --auto-size, --ink-box, --align, etc?
|
||||||
|
|
||||||
|
|
||||||
Tests to write:
|
|
||||||
==============
|
|
||||||
|
|
||||||
- ot-layout enumeration API (needs font)
|
|
||||||
|
|
||||||
- Finish test-shape.c, grep for TODO
|
|
||||||
|
|
||||||
- Finish test-unicode.c, grep for TODO
|
|
||||||
|
|
||||||
- GObject, FreeType, etc
|
|
||||||
|
|
||||||
- hb_cache_t and relatives
|
|
||||||
|
|
||||||
- hb_feature_to/from_string
|
|
||||||
- hb_buffer_[sg]et_contents
|
|
||||||
|
61
appveyor.yml
Normal file
61
appveyor.yml
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
platform: x64
|
||||||
|
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- compiler: msvc
|
||||||
|
generator: Visual Studio 14
|
||||||
|
platform: Win32
|
||||||
|
configuration: Debug
|
||||||
|
triplet: x86-windows
|
||||||
|
- compiler: msvc
|
||||||
|
generator: Visual Studio 14 Win64
|
||||||
|
platform: x64
|
||||||
|
configuration: Debug
|
||||||
|
triplet: x64-windows
|
||||||
|
|
||||||
|
- compiler: msvc
|
||||||
|
generator: Visual Studio 14 ARM
|
||||||
|
platform: ARM
|
||||||
|
configuration: Debug
|
||||||
|
|
||||||
|
|
||||||
|
- compiler: msys2
|
||||||
|
MINGW_PREFIX: /c/msys2/mingw64/
|
||||||
|
MINGW_CHOST: x86_64-w64-mingw32
|
||||||
|
MSYS2_ARCH: x86_64
|
||||||
|
- compiler: msys2
|
||||||
|
MINGW_PREFIX: /c/msys2/mingw32/
|
||||||
|
MINGW_CHOST: i686-w64-mingw32
|
||||||
|
MSYS2_ARCH: i686
|
||||||
|
|
||||||
|
install:
|
||||||
|
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel"
|
||||||
|
|
||||||
|
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" 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" 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 -S 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 "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 --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make; make check || .ci/fail.sh"'
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- c:\tools\vcpkg\installed\
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
- provider: Email
|
||||||
|
to:
|
||||||
|
- harfbuzz-bots-chatter@googlegroups.com
|
||||||
|
on_build_success: false
|
||||||
|
on_build_failure: true
|
||||||
|
on_build_status_changed: true
|
||||||
|
|
||||||
|
# disable automatic tests
|
||||||
|
test: off
|
16
autogen.sh
16
autogen.sh
@ -7,11 +7,11 @@ test -n "$srcdir" || srcdir=.
|
|||||||
olddir=`pwd`
|
olddir=`pwd`
|
||||||
cd $srcdir
|
cd $srcdir
|
||||||
|
|
||||||
echo -n "checking for ragel... "
|
#echo -n "checking for ragel... "
|
||||||
which ragel || {
|
#which ragel || {
|
||||||
echo "You need to install ragel... See http://www.complang.org/ragel/"
|
# echo "You need to install ragel... See http://www.complang.org/ragel/"
|
||||||
exit 1
|
# exit 1
|
||||||
}
|
#}
|
||||||
|
|
||||||
echo -n "checking for pkg-config... "
|
echo -n "checking for pkg-config... "
|
||||||
which pkg-config || {
|
which pkg-config || {
|
||||||
@ -42,5 +42,7 @@ echo "running autoreconf --force --install --verbose"
|
|||||||
autoreconf --force --install --verbose || exit $?
|
autoreconf --force --install --verbose || exit $?
|
||||||
|
|
||||||
cd $olddir
|
cd $olddir
|
||||||
echo "running configure $@"
|
test -n "$NOCONFIGURE" || {
|
||||||
test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
|
echo "running configure $@"
|
||||||
|
"$srcdir/configure" "$@"
|
||||||
|
}
|
||||||
|
77
configure.ac
77
configure.ac
@ -1,7 +1,7 @@
|
|||||||
AC_PREREQ([2.64])
|
AC_PREREQ([2.64])
|
||||||
AC_INIT([HarfBuzz],
|
AC_INIT([HarfBuzz],
|
||||||
[1.2.7],
|
[1.7.5],
|
||||||
[https://github.com/behdad/harfbuzz/issues/new],
|
[https://github.com/harfbuzz/harfbuzz/issues/new],
|
||||||
[harfbuzz],
|
[harfbuzz],
|
||||||
[http://harfbuzz.org/])
|
[http://harfbuzz.org/])
|
||||||
|
|
||||||
@ -9,8 +9,7 @@ AC_CONFIG_MACRO_DIR([m4])
|
|||||||
AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
|
AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([1.11.1 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
|
AM_INIT_AUTOMAKE([1.13.0 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
|
||||||
AM_CONDITIONAL(AUTOMAKE_OLDER_THAN_1_13, test $am__api_version = 1.11 -o $am__api_version = 1.12)
|
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
|
|
||||||
# Initialize libtool
|
# Initialize libtool
|
||||||
@ -19,9 +18,13 @@ LT_PREREQ([2.2])
|
|||||||
LT_INIT([disable-static])
|
LT_INIT([disable-static])
|
||||||
|
|
||||||
# Check for programs
|
# Check for programs
|
||||||
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
AC_PROG_CC_C99
|
||||||
AM_PROG_CC_C_O
|
AM_PROG_CC_C_O
|
||||||
AC_PROG_CXX
|
AC_PROG_CXX
|
||||||
|
dnl AX_CXX_COMPILE_STDCXX(11, noext, optional)
|
||||||
|
AC_SYS_LARGEFILE
|
||||||
PKG_PROG_PKG_CONFIG([0.20])
|
PKG_PROG_PKG_CONFIG([0.20])
|
||||||
AM_MISSING_PROG([RAGEL], [ragel])
|
AM_MISSING_PROG([RAGEL], [ragel])
|
||||||
AM_MISSING_PROG([GIT], [git])
|
AM_MISSING_PROG([GIT], [git])
|
||||||
@ -55,6 +58,13 @@ m4_define([hb_libtool_current],
|
|||||||
HB_LIBTOOL_VERSION_INFO=hb_libtool_current:hb_libtool_revision:hb_libtool_age
|
HB_LIBTOOL_VERSION_INFO=hb_libtool_current:hb_libtool_revision:hb_libtool_age
|
||||||
AC_SUBST(HB_LIBTOOL_VERSION_INFO)
|
AC_SUBST(HB_LIBTOOL_VERSION_INFO)
|
||||||
|
|
||||||
|
AC_ARG_WITH([libstdc++],
|
||||||
|
[AS_HELP_STRING([--with-libstdc++=@<:@yes/no@:>@],
|
||||||
|
[Allow linking with libstdc++ @<:@default=no@:>@])],
|
||||||
|
[with_libstdcxx=$withval],
|
||||||
|
[with_libstdcxx=no])
|
||||||
|
AM_CONDITIONAL(WITH_LIBSTDCXX, [test "x$with_libstdcxx" = "xyes"])
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
have_gtk_doc=false
|
have_gtk_doc=false
|
||||||
m4_ifdef([GTK_DOC_CHECK], [
|
m4_ifdef([GTK_DOC_CHECK], [
|
||||||
@ -66,9 +76,9 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
|
|||||||
AM_CONDITIONAL([ENABLE_GTK_DOC], false)
|
AM_CONDITIONAL([ENABLE_GTK_DOC], false)
|
||||||
])
|
])
|
||||||
|
|
||||||
# Functions and headers
|
# Functions, and headers
|
||||||
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty)
|
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l setlinebuf)
|
||||||
AC_CHECK_HEADERS(unistd.h sys/mman.h)
|
AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h)
|
||||||
|
|
||||||
# Compiler flags
|
# Compiler flags
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
@ -78,9 +88,6 @@ if test "x$GCC" = "xyes"; then
|
|||||||
# Make symbols link locally
|
# Make symbols link locally
|
||||||
LDFLAGS="$LDFLAGS -Bsymbolic-functions"
|
LDFLAGS="$LDFLAGS -Bsymbolic-functions"
|
||||||
|
|
||||||
# Make sure we don't link to libstdc++
|
|
||||||
CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions"
|
|
||||||
|
|
||||||
# Assorted warnings
|
# Assorted warnings
|
||||||
CXXFLAGS="$CXXFLAGS -Wcast-align"
|
CXXFLAGS="$CXXFLAGS -Wcast-align"
|
||||||
|
|
||||||
@ -145,7 +152,7 @@ AC_ARG_WITH(glib,
|
|||||||
[Use glib @<:@default=auto@:>@])],,
|
[Use glib @<:@default=auto@:>@])],,
|
||||||
[with_glib=auto])
|
[with_glib=auto])
|
||||||
have_glib=false
|
have_glib=false
|
||||||
GLIB_DEPS="glib-2.0 >= 2.16"
|
GLIB_DEPS="glib-2.0 >= 2.19.1"
|
||||||
AC_SUBST(GLIB_DEPS)
|
AC_SUBST(GLIB_DEPS)
|
||||||
if test "x$with_glib" = "xyes" -o "x$with_glib" = "xauto"; then
|
if test "x$with_glib" = "xyes" -o "x$with_glib" = "xauto"; then
|
||||||
PKG_CHECK_MODULES(GLIB, $GLIB_DEPS, have_glib=true, :)
|
PKG_CHECK_MODULES(GLIB, $GLIB_DEPS, have_glib=true, :)
|
||||||
@ -162,7 +169,7 @@ dnl ===========================================================================
|
|||||||
|
|
||||||
AC_ARG_WITH(gobject,
|
AC_ARG_WITH(gobject,
|
||||||
[AS_HELP_STRING([--with-gobject=@<:@yes/no/auto@:>@],
|
[AS_HELP_STRING([--with-gobject=@<:@yes/no/auto@:>@],
|
||||||
[Use gobject @<:@default=auto@:>@])],,
|
[Use gobject @<:@default=no@:>@])],,
|
||||||
[with_gobject=no])
|
[with_gobject=no])
|
||||||
have_gobject=false
|
have_gobject=false
|
||||||
if test "x$with_gobject" = "xyes" -o "x$with_gobject" = "xauto"; then
|
if test "x$with_gobject" = "xyes" -o "x$with_gobject" = "xauto"; then
|
||||||
@ -177,6 +184,7 @@ if $have_gobject; then
|
|||||||
AC_SUBST(GLIB_MKENUMS)
|
AC_SUBST(GLIB_MKENUMS)
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL(HAVE_GOBJECT, $have_gobject)
|
AM_CONDITIONAL(HAVE_GOBJECT, $have_gobject)
|
||||||
|
AC_SUBST(have_gobject)
|
||||||
|
|
||||||
dnl ===========================================================================
|
dnl ===========================================================================
|
||||||
|
|
||||||
@ -287,9 +295,13 @@ AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin")
|
|||||||
|
|
||||||
dnl ===========================================================================
|
dnl ===========================================================================
|
||||||
|
|
||||||
have_ucdn=true
|
AC_ARG_WITH(ucdn,
|
||||||
if $have_glib || $have_icu && test "x$with_icu" = "xbuiltin"; then
|
[AS_HELP_STRING([--with-ucdn=@<:@yes/no@:>@],
|
||||||
have_ucdn=false
|
[Use builtin UCDN library @<:@default=yes@:>@])],,
|
||||||
|
[with_ucdn=yes])
|
||||||
|
have_ucdn=false
|
||||||
|
if test "x$with_ucdn" = "xyes"; then
|
||||||
|
have_ucdn=true
|
||||||
fi
|
fi
|
||||||
if $have_ucdn; then
|
if $have_ucdn; then
|
||||||
AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions])
|
AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions])
|
||||||
@ -307,6 +319,16 @@ GRAPHITE2_DEPS="graphite2"
|
|||||||
AC_SUBST(GRAPHITE2_DEPS)
|
AC_SUBST(GRAPHITE2_DEPS)
|
||||||
if test "x$with_graphite2" = "xyes" -o "x$with_graphite2" = "xauto"; then
|
if test "x$with_graphite2" = "xyes" -o "x$with_graphite2" = "xauto"; then
|
||||||
PKG_CHECK_MODULES(GRAPHITE2, $GRAPHITE2_DEPS, have_graphite2=true, :)
|
PKG_CHECK_MODULES(GRAPHITE2, $GRAPHITE2_DEPS, have_graphite2=true, :)
|
||||||
|
if test "x$have_graphite2" != "xtrue"; then
|
||||||
|
# If pkg-config is not available, graphite2 can still be there
|
||||||
|
ac_save_CFLAGS="$CFLAGS"
|
||||||
|
ac_save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $GRAPHITE2_CFLAGS"
|
||||||
|
CPPFLAGS="$CPPFLAGS $GRAPHITE2_CFLAGS"
|
||||||
|
AC_CHECK_HEADER(graphite2/Segment.h, have_graphite2=true, :)
|
||||||
|
CPPFLAGS="$ac_save_CPPFLAGS"
|
||||||
|
CFLAGS="$ac_save_CFLAGS"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if test "x$with_graphite2" = "xyes" -a "x$have_graphite2" != "xtrue"; then
|
if test "x$with_graphite2" = "xyes" -a "x$have_graphite2" != "xtrue"; then
|
||||||
AC_MSG_ERROR([graphite2 support requested but libgraphite2 not found])
|
AC_MSG_ERROR([graphite2 support requested but libgraphite2 not found])
|
||||||
@ -334,6 +356,10 @@ if test "x$with_freetype" = "xyes" -a "x$have_freetype" != "xtrue"; then
|
|||||||
fi
|
fi
|
||||||
if $have_freetype; then
|
if $have_freetype; then
|
||||||
AC_DEFINE(HAVE_FREETYPE, 1, [Have FreeType 2 library])
|
AC_DEFINE(HAVE_FREETYPE, 1, [Have FreeType 2 library])
|
||||||
|
save_libs=$LIBS
|
||||||
|
LIBS="$LIBS $FREETYPE_LIBS"
|
||||||
|
AC_CHECK_FUNCS(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var)
|
||||||
|
LIBS=$save_libs
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL(HAVE_FREETYPE, $have_freetype)
|
AM_CONDITIONAL(HAVE_FREETYPE, $have_freetype)
|
||||||
|
|
||||||
@ -401,12 +427,13 @@ if test "x$with_coretext" = "xyes" -o "x$with_coretext" = "xauto"; then
|
|||||||
else
|
else
|
||||||
# On iOS CoreText and CoreGraphics are stand-alone frameworks
|
# On iOS CoreText and CoreGraphics are stand-alone frameworks
|
||||||
if test "x$have_coretext" != "xtrue"; then
|
if test "x$have_coretext" != "xtrue"; then
|
||||||
AC_CHECK_TYPE(CTFontRef, have_coretext=true,, [#include <CoreText/CoreText.h>])
|
# Check for a different symbol to avoid getting cached result.
|
||||||
|
AC_CHECK_TYPE(CTRunRef, have_coretext=true,, [#include <CoreText/CoreText.h>])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if $have_coretext; then
|
if $have_coretext; then
|
||||||
CORETEXT_CFLAGS=
|
CORETEXT_CFLAGS=
|
||||||
CORETEXT_LIBS="-framework CoreText -framework CoreGraphics"
|
CORETEXT_LIBS="-framework CoreText -framework CoreGraphics -framework CoreFoundation"
|
||||||
AC_SUBST(CORETEXT_CFLAGS)
|
AC_SUBST(CORETEXT_CFLAGS)
|
||||||
AC_SUBST(CORETEXT_LIBS)
|
AC_SUBST(CORETEXT_LIBS)
|
||||||
fi
|
fi
|
||||||
@ -465,16 +492,20 @@ AC_CONFIG_FILES([
|
|||||||
Makefile
|
Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/hb-version.h
|
src/hb-version.h
|
||||||
|
src/harfbuzz-config.cmake
|
||||||
src/hb-ucdn/Makefile
|
src/hb-ucdn/Makefile
|
||||||
util/Makefile
|
util/Makefile
|
||||||
test/Makefile
|
test/Makefile
|
||||||
test/api/Makefile
|
test/api/Makefile
|
||||||
test/fuzzing/Makefile
|
test/fuzzing/Makefile
|
||||||
test/shaping/Makefile
|
test/shaping/Makefile
|
||||||
|
test/shaping/data/Makefile
|
||||||
|
test/shaping/data/in-house/Makefile
|
||||||
|
test/shaping/data/text-rendering-tests/Makefile
|
||||||
|
test/subset/Makefile
|
||||||
|
test/subset/data/Makefile
|
||||||
docs/Makefile
|
docs/Makefile
|
||||||
docs/version.xml
|
docs/version.xml
|
||||||
win32/Makefile
|
|
||||||
win32/config.h.win32
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
@ -484,18 +515,18 @@ AC_MSG_NOTICE([
|
|||||||
Build configuration:
|
Build configuration:
|
||||||
|
|
||||||
Unicode callbacks (you want at least one):
|
Unicode callbacks (you want at least one):
|
||||||
|
Builtin (UCDN): ${have_ucdn}
|
||||||
Glib: ${have_glib}
|
Glib: ${have_glib}
|
||||||
ICU: ${have_icu}
|
ICU: ${have_icu}
|
||||||
UCDN: ${have_ucdn}
|
|
||||||
|
|
||||||
Font callbacks (the more the better):
|
Font callbacks (the more the merrier):
|
||||||
FreeType: ${have_freetype}
|
FreeType: ${have_freetype}
|
||||||
|
|
||||||
Tools used for command-line utilities:
|
Tools used for command-line utilities:
|
||||||
Cairo: ${have_cairo}
|
Cairo: ${have_cairo}
|
||||||
Fontconfig: ${have_fontconfig}
|
Fontconfig: ${have_fontconfig}
|
||||||
|
|
||||||
Additional shapers (the more the better):
|
Additional shapers (the more the merrier):
|
||||||
Graphite2: ${have_graphite2}
|
Graphite2: ${have_graphite2}
|
||||||
|
|
||||||
Platform shapers (not normally needed):
|
Platform shapers (not normally needed):
|
||||||
@ -504,7 +535,7 @@ Platform shapers (not normally needed):
|
|||||||
DirectWrite: ${have_directwrite}
|
DirectWrite: ${have_directwrite}
|
||||||
|
|
||||||
Other features:
|
Other features:
|
||||||
Documentation: ${have_gtk_doc}
|
Documentation: ${enable_gtk_doc}
|
||||||
GObject bindings: ${have_gobject}
|
GObject bindings: ${have_gobject}
|
||||||
Introspection: ${have_introspection}
|
Introspection: ${have_introspection}
|
||||||
])
|
])
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 8.6 KiB |
277
docs/HarfBuzz.svg
Normal file
277
docs/HarfBuzz.svg
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.1"
|
||||||
|
id="svg2"
|
||||||
|
width="682.66669"
|
||||||
|
height="682.66669"
|
||||||
|
viewBox="0 0 682.66669 682.66669"
|
||||||
|
sodipodi:docname="harfbuzz2.svg"
|
||||||
|
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||||
|
inkscape:export-filename="harfbuzz2.png"
|
||||||
|
inkscape:export-xdpi="72"
|
||||||
|
inkscape:export-ydpi="72">
|
||||||
|
<metadata
|
||||||
|
id="metadata8">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs6">
|
||||||
|
<g
|
||||||
|
id="g50">
|
||||||
|
<symbol
|
||||||
|
id="glyph0-0"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path26"
|
||||||
|
d="M 32,0 V -192 H 224 V 0 Z M 48,-16 H 208 V -176 H 48 Z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-1"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path29"
|
||||||
|
d="m 52.5,-64.875 c -0.08594,2.25 -0.9375,6.335938 -2.5625,12.25 -1.625,5.917969 -3.75,12.375 -6.375,19.375 -2.625,7 -4.9375,12.292969 -6.9375,15.875 -2,3.585938 -4.1875,6.3125 -6.5625,8.1875 -2.375,1.875 -6.210938,3.585938 -11.5,5.125 -5.292969,1.542969 -9.542969,2.585938 -12.75,3.125 -3.210938,0.542969 -5.230469,0.8125 -6.0625,0.8125 -0.832031,-0.082031 -1.332031,-0.414062 -1.5,-1 -0.164062,-0.582031 0.085938,-1.332031 0.75,-2.25 0.9179688,-1.414062 3.226562,-3.269531 6.9375,-5.5625 3.707031,-2.289062 8.019531,-5.164062 12.9375,-8.625 4.914062,-3.457031 8.414062,-6.476562 10.5,-9.0625 2.082031,-2.582031 4.4375,-6.457031 7.0625,-11.625 2.625,-5.164062 5,-10.375 7.125,-15.625 2.125,-5.25 3.644531,-8.832031 4.5625,-10.75 0.914062,-1.914062 1.914062,-2.832031 3,-2.75 0.914062,0.167969 1.375,1 1.375,2.5 z M 41.75,-117.75 c 0,-1.83203 1.5625,-5.8125 4.6875,-11.9375 3.125,-6.125 5.144531,-9.1875 6.0625,-9.1875 1.832031,-0.75 4.5,0.64844 8,4.1875 3.5,3.54297 5.375,6.3125 5.625,8.3125 0,2.66797 -1.460938,6.5 -4.375,11.5 -2.917969,5 -5.042969,7.5 -6.375,7.5 -0.5,-0.25 -2.230469,-1.35156 -5.1875,-3.3125 -2.960938,-1.95703 -5.148438,-3.4375 -6.5625,-4.4375 -1.25,-0.83203 -1.875,-1.70703 -1.875,-2.625 z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-2"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path32"
|
||||||
|
d="m 19.75,-47.125 c -0.167969,3.167969 -0.5,6.023438 -1,8.5625 -0.5,2.542969 -1.167969,4.710938 -2,6.5 -0.835938,1.792969 -1.898438,3.125 -3.1875,4 -1.292969,0.875 -2.855469,1.1875 -4.6875,0.9375 0.082031,-6.5 0.769531,-15.5625 2.0625,-27.1875 1.289062,-11.625 3.226562,-24.476562 5.8125,-38.5625 1.332031,-4.082031 4.039062,-11.28906 8.125,-21.625 0.414062,-1 0.851562,-1.41406 1.3125,-1.25 0.457031,0.16797 0.6875,0.58594 0.6875,1.25 -0.25,5.08594 -1.292969,14.792969 -3.125,29.125 -1.835938,14.335938 -2.960938,24.167969 -3.375,29.5 -0.417969,5.335938 -0.625,8.25 -0.625,8.75 z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-3"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path35"
|
||||||
|
d="m -10.875,-27.25 c 1.667969,-7.164062 3.5625,-12.457031 5.6875,-15.875 2.125,-3.414062 3.855469,-5.289062 5.1875,-5.625 v 5.5 c 0,7 1.875,11.875 5.625,14.625 2.25,1.5 4.5,2 6.75,1.5 2.25,-0.5 3.976562,-1.664062 5.1875,-3.5 1.207031,-1.832031 2.226562,-3.976562 3.0625,-6.4375 0.832031,-2.457031 1.625,-3.6875 2.375,-3.6875 0.914062,0 1.289062,0.875 1.125,2.625 -0.08594,3 -1.023438,7.875 -2.8125,14.625 C 19.519531,-16.75 17.082031,-11.207031 14,-6.875 10.914062,-2.539062 7.164062,-0.25 2.75,0 c -4.5,-0.164062 -8,-2.707031 -10.5,-7.625 -2.25,-4.832031 -3.289062,-11.082031 -3.125,-18.75 z m 6.625,111.5 c 0,-1.835938 1.5625,-5.8125 4.6875,-11.9375 3.125,-6.125 5.144531,-9.1875 6.0625,-9.1875 1.832031,-0.75 4.5,0.644531 8,4.1875 3.5,3.539062 5.375,6.3125 5.625,8.3125 0,2.664062 -1.460938,6.5 -4.375,11.5 -2.917969,5 -5.042969,7.5 -6.375,7.5 C 8.875,94.375 7.144531,93.269531 4.1875,91.3125 1.226562,89.351562 -0.957031,87.875 -2.375,86.875 -3.625,86.039062 -4.25,85.164062 -4.25,84.25 Z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-4"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path38"
|
||||||
|
d=""
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-5"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path41"
|
||||||
|
d="m 118.5,-33 c 15.33203,-3.914062 27.375,-8.289062 36.125,-13.125 7.5,-4.082031 11.25,-7.5 11.25,-10.25 0,-0.832031 -0.5625,-1.894531 -1.6875,-3.1875 -1.125,-1.289062 -1.9375,-1.9375 -2.4375,-1.9375 -0.83594,0 -2.02344,0.148438 -3.5625,0.4375 -1.54297,0.292969 -2.64844,0.4375 -3.3125,0.4375 -2.91797,0 -4.98047,-0.769531 -6.1875,-2.3125 -1.21094,-1.539062 -1.8125,-3.601562 -1.8125,-6.1875 0,-1.5 2.16406,-6.539062 6.5,-15.125 1.66406,-3.414062 3.0625,-5.8125 4.1875,-7.1875 1.125,-1.375 2.76953,-2.0625 4.9375,-2.0625 3.58203,0 6.91406,1.9375 10,5.8125 3.08203,3.875 4.625,8.855469 4.625,14.9375 0,6 -0.8125,11.4375 -2.4375,16.3125 -1.625,4.875 -4.14844,9.605469 -7.5625,14.1875 -3.41797,4.585938 -7.83594,9.042969 -13.25,13.375 -8.08594,6.085938 -17.625,11.230469 -28.625,15.4375 -11,4.210938 -23.83594,7.5 -38.5,9.875 C 72.082031,-1.1875 58.082031,0 44.75,0 37.082031,0 30.082031,-0.375 23.75,-1.125 17.414062,-1.875 12.582031,-3.289062 9.25,-5.375 3.082031,-8.789062 0.25,-14.5 0.75,-22.5 c 0.332031,-4.082031 0.832031,-8.4375 1.5,-13.0625 0.664062,-4.625 1.351562,-8.3125 2.0625,-11.0625 0.707031,-2.75 1.5625,-4.125 2.5625,-4.125 0.832031,0 1.332031,1.75 1.5,5.25 0.164062,3.5 0.6875,6.0625 1.5625,7.6875 0.875,1.625 2.207031,3 4,4.125 1.789062,1.125 4.6875,2.210938 8.6875,3.25 4,1.042969 8.6875,1.855469 14.0625,2.4375 5.375,0.585938 12.519531,0.875 21.4375,0.875 12.414062,0 23.019531,-0.4375 31.8125,-1.3125 C 98.726562,-29.3125 108.25,-30.832031 118.5,-33 Z m -38.75,-86.75 c 0,-1.83203 1.5625,-5.8125 4.6875,-11.9375 3.125,-6.125 5.144531,-9.1875 6.0625,-9.1875 1.832031,-0.75 4.5,0.64844 8,4.1875 3.5,3.54297 5.375,6.3125 5.625,8.3125 0,2.66797 -1.46094,6.5 -4.375,11.5 -2.917969,5 -5.042969,7.5 -6.375,7.5 -0.5,-0.25 -2.230469,-1.35156 -5.1875,-3.3125 -2.960938,-1.95703 -5.148438,-3.4375 -6.5625,-4.4375 -1.25,-0.83203 -1.875,-1.70703 -1.875,-2.625 z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-6"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path44"
|
||||||
|
d="m 78,-56.875 c -1.335938,2.25 -2.25,3.875 -2.75,4.875 -1.417969,2.335938 -2.875,4.210938 -4.375,5.625 -1.75,1.75 -4.042969,3.292969 -6.875,4.625 -6.085938,2.917969 -10.460938,5.75 -13.125,8.5 -1.75,1.75 -3.792969,4.960938 -6.125,9.625 -4.25,8.585938 -8.417969,14.292969 -12.5,17.125 -4.085938,2.917969 -11.417969,5 -22,6.25 C 9.414062,-0.0820312 8.414062,0 7.25,0 H 4.375 c -1.5,0 -2.25,-0.164062 -2.25,-0.5 0,-1.914062 2.539062,-4.5 7.625,-7.75 4,-2.414062 7,-4.207031 9,-5.375 6,-3.414062 10.414062,-6.125 13.25,-8.125 4,-2.914062 6.625,-5.75 7.875,-8.5 4.164062,-8.5 7.625,-14.414062 10.375,-17.75 3.082031,-3.664062 6.625,-6.5 10.625,-8.5 C 67.289062,-60.082031 71,-62.207031 72,-62.875 l 10,2.375 z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-7"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path47"
|
||||||
|
d="m 13,-17.625 c -1,1.75 -2.0625,3.480469 -3.1875,5.1875 C 8.6875,-10.726562 7.539062,-9.082031 6.375,-7.5 5.207031,-5.914062 4.0625,-4.476562 2.9375,-3.1875 1.8125,-1.894531 0.832031,-0.832031 0,0 c -0.5,-2.582031 -0.832031,-5.125 -1,-7.625 -0.164062,-2.5 0.167969,-5.039062 1,-7.625 1.25,-0.75 2.207031,-1.414062 2.875,-2 1.664062,-1.5 5.375,-6.582031 11.125,-15.25 -0.667969,-0.664062 -2.585938,-1.601562 -5.75,-2.8125 -3.167969,-1.207031 -6.167969,-1.894531 -9,-2.0625 -2.582031,-0.164062 -4.726562,0.3125 -6.4375,1.4375 -1.707031,1.125 -3.25,2.710938 -4.625,4.75 -1.375,2.042969 -2.5625,2.980469 -3.5625,2.8125 -0.332031,-0.164062 -0.375,-0.851562 -0.125,-2.0625 0.25,-1.207031 0.625,-2.394531 1.125,-3.5625 2.085938,-4.832031 4.480469,-8.4375 7.1875,-10.8125 2.710938,-2.375 5.9375,-3.5625 9.6875,-3.5625 2.75,0 6.164062,0.667969 10.25,2 2.582031,0.917969 4.789062,1.375 6.625,1.375 3.832031,0 7.625,-1.375 11.375,-4.125 0.832031,0 1.125,0.542969 0.875,1.625 -0.25,1.085938 -0.605469,2.355469 -1.0625,3.8125 -0.460938,1.460938 -0.773438,2.4375 -0.9375,2.9375 -0.835938,2.585938 -1.5,4.085938 -2,4.5 -0.5,0.417969 -1.960938,1.5 -4.375,3.25 -1.335938,1 -2.480469,2.148438 -3.4375,3.4375 -0.960938,1.292969 -1.9375,2.835938 -2.9375,4.625 -1,1.792969 -2.292969,4.230469 -3.875,7.3125 z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g184">
|
||||||
|
<symbol
|
||||||
|
id="glyph0-0-3"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path163"
|
||||||
|
d=""
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-1-6"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path166"
|
||||||
|
d="m 79.625,-103.25 c -3.585938,22 -6.8125,38.417969 -9.6875,49.25 -2.875,10.835938 -5.480469,19.105469 -7.8125,24.8125 -2.335938,5.710938 -4.898438,10.0625 -7.6875,13.0625 -2.792969,3 -7.917969,5.855469 -15.375,8.5625 -7.460938,2.710938 -13.6875,4.605469 -18.6875,5.6875 -5,1.085938 -8.125,1.667969 -9.375,1.75 C 9.75,-0.207031 8.957031,-0.4375 8.625,-0.8125 8.289062,-1.1875 8.582031,-2.082031 9.5,-3.5 c 1.582031,-2.25 4.894531,-5.332031 9.9375,-9.25 5.039062,-3.914062 11,-8.789062 17.875,-14.625 6.875,-5.832031 12.019531,-10.976562 15.4375,-15.4375 3.414062,-4.457031 6.4375,-10.539062 9.0625,-18.25 C 64.4375,-68.769531 67,-76.832031 69.5,-85.25 c 2.5,-8.414062 4.3125,-14.125 5.4375,-17.125 1.125,-3 2.269531,-4.45703 3.4375,-4.375 1.332031,0.25 1.75,1.41797 1.25,3.5 z m 8.875,-68.625 c 0.664062,2.41797 0.644531,4.91797 -0.0625,7.5 -0.710938,2.58594 -2.023438,5.29297 -3.9375,8.125 -1.167969,1.91797 -2.398438,3.64844 -3.6875,5.1875 -1.292969,1.54297 -2.648438,3.02344 -4.0625,4.4375 -0.417969,0.5 -1.085938,1.125 -2,1.875 -0.917969,0.75 -1.875,1.46094 -2.875,2.125 -1,0.66797 -1.960938,1.14844 -2.875,1.4375 -0.917969,0.29297 -1.585938,0.1875 -2,-0.3125 -3,-2.41406 -5.960938,-4.875 -8.875,-7.375 -2.917969,-2.5 -6.125,-4.83203 -9.625,-7 -0.585938,-0.41406 -0.855469,-0.8125 -0.8125,-1.1875 0.03906,-0.375 0.269531,-0.9375 0.6875,-1.6875 l 20,-30.5 c 0.582031,-0.83203 1.164062,-1.22656 1.75,-1.1875 0.582031,0.043 1.207031,0.27344 1.875,0.6875 1.75,1 3.5,2.125 5.25,3.375 1.75,1.25 3.375,2.60547 4.875,4.0625 1.5,1.46094 2.8125,3.04297 3.9375,4.75 1.125,1.71094 1.9375,3.60547 2.4375,5.6875 z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-2-7"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path169"
|
||||||
|
d="m 29.625,-70.625 c -0.667969,8.335938 -2.542969,15.417969 -5.625,21.25 -3.085938,5.835938 -6.585938,8.75 -10.5,8.75 0,-3.164062 1.019531,-13 3.0625,-29.5 2.039062,-16.5 3.582031,-28.3125 4.625,-35.4375 1.039062,-7.125 2.226562,-14.6875 3.5625,-22.6875 1.332031,-8 2.625,-14.45703 3.875,-19.375 1.414062,-4.08203 2.9375,-8.20703 4.5625,-12.375 1.625,-4.16406 3.3125,-8.28906 5.0625,-12.375 1.164062,-1.83203 1.914062,-1.53906 2.25,0.875 -2.085938,13.83594 -4,28.1875 -5.75,43.0625 -1.75,14.875 -2.9375,25.52344 -3.5625,31.9375 -0.625,6.417969 -0.9375,10.167969 -0.9375,11.25 -0.417969,6.835938 -0.625,11.710938 -0.625,14.625 z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-3-5"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path172"
|
||||||
|
d="m -16.125,-40.625 c 1.25,-5.332031 2.625,-10 4.125,-14 1.5,-4 2.960938,-7.3125 4.375,-9.9375 1.417969,-2.625 2.792969,-4.644531 4.125,-6.0625 1.335938,-1.414062 2.5,-2.25 3.5,-2.5 v 8.25 c 0,10.5 2.789062,17.835938 8.375,22 3.414062,2.25 6.8125,3 10.1875,2.25 3.375,-0.75 5.957031,-2.5 7.75,-5.25 1.789062,-2.75 3.3125,-5.976562 4.5625,-9.6875 1.25,-3.707031 2.457031,-5.5625 3.625,-5.5625 1.332031,0 1.875,1.335938 1.625,4 -0.08594,4.5 -1.480469,11.8125 -4.1875,21.9375 -2.710938,10.125 -6.375,18.4375 -11,24.9375 -4.625,6.5 -10.230469,9.917969 -16.8125,10.25 -6.75,-0.25 -12,-4.039062 -15.75,-11.375 -3.414062,-7.25 -4.914062,-16.625 -4.5,-28.125 z M 28.5,82.125 c 0.664062,2.414062 0.644531,4.914062 -0.0625,7.5 -0.710938,2.582031 -2.023438,5.289062 -3.9375,8.125 -1.167969,1.914062 -2.398438,3.64453 -3.6875,5.1875 -1.292969,1.53906 -2.648438,3.01953 -4.0625,4.4375 -0.417969,0.5 -1.085938,1.125 -2,1.875 -0.917969,0.75 -1.875,1.45703 -2.875,2.125 -1,0.66406 -1.960938,1.14453 -2.875,1.4375 C 8.082031,113.10156 7.414062,113 7,112.5 c -3,-2.41797 -5.960938,-4.875 -8.875,-7.375 -2.914062,-2.5 -6.125,-4.83594 -9.625,-7 -0.582031,-0.417969 -0.851562,-0.8125 -0.8125,-1.1875 0.04297,-0.375 0.273438,-0.9375 0.6875,-1.6875 l 20,-30.5 c 0.582031,-0.835938 1.164062,-1.230469 1.75,-1.1875 0.582031,0.03906 1.207031,0.269531 1.875,0.6875 1.75,1 3.5,2.125 5.25,3.375 1.75,1.25 3.375,2.601562 4.875,4.0625 1.5,1.457031 2.8125,3.039062 3.9375,4.75 1.125,1.707031 1.9375,3.601562 2.4375,5.6875 z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-4-3"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path175"
|
||||||
|
d=""
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-5-5"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path178"
|
||||||
|
d="M 72.125,0.125 C 58.039062,0.0390625 47.164062,-0.582031 39.5,-1.75 26.164062,-3.832031 16.664062,-7.832031 11,-13.75 5.914062,-18.332031 3.375,-24.582031 3.375,-32.5 c 0,-3.082031 0.289062,-7.5 0.875,-13.25 0.582031,-5.75 1.375,-11.5 2.375,-17.25 0.414062,-2.414062 0.789062,-4.582031 1.125,-6.5 0.25,-1.332031 0.582031,-2.414062 1,-3.25 0.414062,-0.832031 0.875,-1.3125 1.375,-1.4375 0.5,-0.125 0.976562,0.210938 1.4375,1 0.457031,0.792969 0.894531,2.148438 1.3125,4.0625 0.332031,2.085938 0.789062,4.25 1.375,6.5 1.332031,5.417969 4.957031,9.460938 10.875,12.125 15,6.417969 37.914062,9.75 68.75,10 12.75,-0.164062 24.58203,-0.625 35.5,-1.375 11.16406,-0.832031 23.75,-2.789062 37.75,-5.875 14,-3.082031 25.14453,-6.457031 33.4375,-10.125 8.28906,-3.664062 15.35156,-7.625 21.1875,-11.875 4.58203,-3.332031 6.875,-6.539062 6.875,-9.625 0,-1.25 -1.1875,-2.726562 -3.5625,-4.4375 -2.375,-1.707031 -3.9375,-2.5625 -4.6875,-2.5625 -1.41797,0.667969 -3.08594,1.1875 -5,1.5625 -1.91797,0.375 -3.66797,0.480469 -5.25,0.3125 -4.41797,-0.5 -7.71094,-1.875 -9.875,-4.125 -2.16797,-2.25 -3.25,-5.289062 -3.25,-9.125 0,-2.41406 3.20703,-10 9.625,-22.75 2.58203,-5.16406 4.85156,-8.76953 6.8125,-10.8125 1.95703,-2.03906 4.64453,-3.0625 8.0625,-3.0625 5.41406,0 10.4375,2.91797 15.0625,8.75 4.625,5.83594 6.9375,13.29297 6.9375,22.375 0,9 -1.21094,16.792969 -3.625,23.375 -3,9 -7.08594,17.335938 -12.25,25 -6.5,9.25 -13.625,16.5625 -21.375,21.9375 -7.75,5.375 -15.58594,9.648438 -23.5,12.8125 -7.08594,3.5 -16.23047,6.773438 -27.4375,9.8125 -11.21094,3.042969 -24.8125,5.523438 -40.8125,7.4375 -15.835938,1.917969 -29.960938,2.9140625 -42.375,3 z m 82.375,-172 c 0.66406,2.41797 0.64453,4.91797 -0.0625,7.5 -0.71094,2.58594 -2.02344,5.29297 -3.9375,8.125 -1.16797,1.91797 -2.39844,3.64844 -3.6875,5.1875 -1.29297,1.54297 -2.64844,3.02344 -4.0625,4.4375 -0.41797,0.5 -1.08594,1.125 -2,1.875 -0.91797,0.75 -1.875,1.46094 -2.875,2.125 -1,0.66797 -1.96094,1.14844 -2.875,1.4375 -0.91797,0.29297 -1.58594,0.1875 -2,-0.3125 -3,-2.41406 -5.96094,-4.875 -8.875,-7.375 -2.91797,-2.5 -6.125,-4.83203 -9.625,-7 -0.58594,-0.41406 -0.85547,-0.8125 -0.8125,-1.1875 0.0391,-0.375 0.26953,-0.9375 0.6875,-1.6875 l 20,-30.5 c 0.58203,-0.83203 1.16406,-1.22656 1.75,-1.1875 0.58203,0.043 1.20703,0.27344 1.875,0.6875 1.75,1 3.5,2.125 5.25,3.375 1.75,1.25 3.375,2.60547 4.875,4.0625 1.5,1.46094 2.8125,3.04297 3.9375,4.75 1.125,1.71094 1.9375,3.60547 2.4375,5.6875 z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
<symbol
|
||||||
|
id="glyph0-6-6"
|
||||||
|
overflow="visible"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path181"
|
||||||
|
d="m 115,-102.5 c -1.83594,3.25 -3.75,6.523438 -5.75,9.8125 -2,3.292969 -4.23047,6.398438 -6.6875,9.3125 -2.46094,2.917969 -5.167969,5.5625 -8.125,7.9375 -2.960938,2.375 -6.3125,4.273438 -10.0625,5.6875 -3.085938,1.25 -5.710938,2.648438 -7.875,4.1875 -2.167969,1.542969 -3.960938,3.1875 -5.375,4.9375 -2.167969,2.335938 -4.042969,5.5625 -5.625,9.6875 -1.585938,4.125 -3.230469,8.480469 -4.9375,13.0625 -1.710938,4.585938 -3.585938,9.0625 -5.625,13.4375 -2.042969,4.375 -4.605469,7.980469 -7.6875,10.8125 C 43,-9.125 36.707031,-6.082031 28.375,-4.5 L 5.5,-0.625 C 4.832031,-0.539062 4.019531,-0.476562 3.0625,-0.4375 2.101562,-0.394531 1.414062,-0.414062 1,-0.5 -0.914062,-1.082031 -1.5,-2.351562 -0.75,-4.3125 0,-6.269531 1.957031,-8.25 5.125,-10.25 c 6.414062,-4.25 11.539062,-7.6875 15.375,-10.3125 3.832031,-2.625 6.957031,-4.769531 9.375,-6.4375 2.414062,-1.664062 4.351562,-3.039062 5.8125,-4.125 1.457031,-1.082031 3.019531,-2.289062 4.6875,-3.625 6.75,-5.082031 11.414062,-10.414062 14,-16 1.5,-2.914062 2.875,-5.75 4.125,-8.5 1.25,-2.75 2.5625,-5.457031 3.9375,-8.125 1.375,-2.664062 2.851562,-5.3125 4.4375,-7.9375 1.582031,-2.625 3.414062,-5.269531 5.5,-7.9375 2.164062,-2.664062 5.082031,-5.269531 8.75,-7.8125 3.664062,-2.539062 8.082031,-5.0625 13.25,-7.5625 0.582031,-0.25 1.539062,-0.8125 2.875,-1.6875 1.332031,-0.875 2.95703,-2.26953 4.875,-4.1875 1.91406,-1.91406 4.10156,-4.51953 6.5625,-7.8125 2.45703,-3.28906 5.0625,-7.47656 7.8125,-12.5625 -1,-1 -3.875,-2.375 -8.625,-4.125 -4.75,-1.83203 -9.25,-2.875 -13.5,-3.125 -3.917969,-0.25 -7.148438,0.46094 -9.6875,2.125 -2.542969,1.66797 -4.855469,4.04297 -6.9375,7.125 -2.085938,3.08594 -3.875,4.5 -5.375,4.25 -0.5,-0.25 -0.585938,-1.28906 -0.25,-3.125 0.414062,-1.83203 1,-3.625 1.75,-5.375 3.164062,-7.25 6.75,-12.625 10.75,-16.125 4.082031,-3.58203 8.957031,-5.375 14.625,-5.375 4.08203,0 9.20703,1 15.375,3 3.83203,1.33594 7.125,2 9.875,2 5.75,0 11.45703,-2.03906 17.125,-6.125 1.25,0 1.6875,0.8125 1.3125,2.4375 -0.375,1.625 -0.9375,3.52344 -1.6875,5.6875 -0.66797,2.16797 -1.125,3.625 -1.375,4.375 -1.25,3.91797 -2.25,6.21094 -3,6.875 -0.75,0.58594 -2.91797,2.16797 -6.5,4.75 -2,1.5 -3.73047,3.23047 -5.1875,5.1875 -1.46094,1.96094 -2.9375,4.27344 -4.4375,6.9375 -1.5,2.66797 -3.41797,6.33594 -5.75,11 z m 0,0"
|
||||||
|
style="stroke:none"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</symbol>
|
||||||
|
</g>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1471"
|
||||||
|
id="namedview4"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.59454973"
|
||||||
|
inkscape:cx="-165.7731"
|
||||||
|
inkscape:cy="361.75575"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="55"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg2" />
|
||||||
|
<path
|
||||||
|
id="path871"
|
||||||
|
d="m 205.59223,196.11402 c -5.97657,36.66667 -11.35417,64.02995 -16.14583,82.08333 -4.79167,18.0599 -9.13412,31.84245 -13.02084,41.35417 -3.89323,9.51823 -8.16406,16.77083 -12.8125,21.77083 -4.65495,5 -13.19661,9.75912 -25.625,14.27083 -12.43489,4.51823 -22.8125,7.67579 -31.14583,9.47917 -8.333331,1.8099 -13.541664,2.77995 -15.624997,2.91667 -2.083334,-0.13672 -3.404949,-0.52084 -3.958334,-1.14584 -0.559896,-0.625 -0.07161,-2.11588 1.458334,-4.47916 2.636718,-3.75 8.157551,-8.88672 16.562497,-15.41667 8.39844,-6.52344 18.33333,-14.64844 29.79167,-24.375 11.45833,-9.72005 20.03255,-18.29427 25.72916,-25.72916 5.69011,-7.42839 10.72917,-17.56511 15.10417,-30.41667 4.375,-12.84505 8.64583,-26.28255 12.8125,-40.3125 4.16667,-14.02343 7.1875,-23.54166 9.0625,-28.54166 1.875,-5 3.78255,-7.42839 5.72916,-7.29167 2.22006,0.41667 2.91667,2.36328 2.08334,5.83333 z M 220.38389,81.739028 c 1.10677,4.02995 1.07422,8.196616 -0.10416,12.5 -1.1849,4.309899 -3.3724,8.821612 -6.5625,13.541662 -1.94662,3.19662 -3.9974,6.08074 -6.14584,8.64584 -2.15494,2.57161 -4.41406,5.03906 -6.77083,7.39583 -0.69661,0.83333 -1.8099,1.875 -3.33333,3.125 -1.52995,1.25 -3.125,2.4349 -4.79167,3.54167 -1.66666,1.11328 -3.26823,1.91406 -4.79166,2.39583 -1.52995,0.48828 -2.64323,0.3125 -3.33334,-0.52083 -5,-4.02344 -9.93489,-8.125 -14.79166,-12.29167 -4.86329,-4.16667 -10.20834,-8.05338 -16.04167,-11.66667 -0.97656,-0.6901 -1.42578,-1.35416 -1.35417,-1.97916 0.0651,-0.625 0.44922,-1.5625 1.14584,-2.8125 l 33.33333,-50.833334 c 0.97005,-1.386717 1.9401,-2.044267 2.91667,-1.979167 0.97005,0.07167 2.01171,0.455734 3.125,1.145834 2.91666,1.666666 5.83333,3.541666 8.74999,5.624999 2.91667,2.083334 5.625,4.34245 8.125,6.770833 2.5,2.4349 4.6875,5.071617 6.5625,7.916667 1.875,2.851566 3.22917,6.009116 4.0625,9.479166 z m 0,0"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.66666663"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.66666663"
|
||||||
|
d="m 256.21722,250.48902 c -1.11328,13.89323 -4.23828,25.69662 -9.375,35.41667 -5.14323,9.72656 -10.97656,14.58333 -17.5,14.58333 0,-5.27344 1.69922,-21.66667 5.10417,-49.16667 3.39843,-27.49999 5.97005,-47.18749 7.70833,-59.06249 1.73177,-11.875 3.71094,-24.47917 5.9375,-37.8125 2.22005,-13.33333 4.375,-24.09505 6.45833,-32.29167 2.35677,-6.80338 4.89583,-13.67838 7.60417,-20.625 2.70833,-6.940096 5.52083,-13.815095 8.4375,-20.624995 1.9401,-3.053383 3.1901,-2.5651 3.75,1.458333 -3.47657,23.059902 -6.66667,46.979162 -9.58334,71.770832 -2.91666,24.79166 -4.89583,42.53906 -5.9375,53.22916 -1.04166,10.69662 -1.5625,16.94662 -1.5625,18.75 -0.69661,11.39323 -1.04166,19.51823 -1.04166,24.375 z m 0,0"
|
||||||
|
id="path875" />
|
||||||
|
<path
|
||||||
|
id="path945"
|
||||||
|
d="m 229.34222,300.48902 c 2.08333,-8.88672 4.375,-16.66667 6.875,-23.33333 2.5,-6.66667 4.9349,-12.1875 7.29167,-16.5625 2.36328,-4.375 4.65495,-7.74089 6.875,-10.10417 2.22656,-2.35677 4.16666,-3.75 5.83333,-4.16667 v 13.75 c 0,17.5 4.64844,29.72657 13.95833,36.66667 5.69011,3.75 11.35417,5 16.97917,3.75 5.625,-1.25 9.92838,-4.16667 12.91666,-8.75 2.98177,-4.58333 5.52084,-9.96094 7.60417,-16.14583 2.08333,-6.17839 4.09505,-9.27084 6.04167,-9.27084 2.22005,0 3.125,2.22657 2.70833,6.66667 -0.14323,7.5 -2.46745,19.6875 -6.97917,36.5625 -4.51823,16.875 -10.625,30.72916 -18.33333,41.5625 -7.70833,10.83333 -17.05078,16.52995 -28.02083,17.08333 -11.25,-0.41667 -20,-6.73177 -26.25,-18.95833 -5.6901,-12.08334 -8.1901,-27.70833 -7.5,-46.875 z"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.66666663"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
id="path943"
|
||||||
|
d="m 286.78334,583.03989 c 1.10677,4.02343 1.07422,8.1901 -0.10416,12.5 -1.1849,4.30338 -3.3724,8.8151 -6.5625,13.54167 -1.94662,3.1901 -3.9974,6.07421 -6.14584,8.64583 -2.15495,2.5651 -4.41406,5.03255 -6.77083,7.39583 -0.69662,0.83334 -1.8099,1.875 -3.33333,3.125 -1.52995,1.25 -3.125,2.42839 -4.79167,3.54167 -1.66667,1.10677 -3.26823,1.90755 -4.79167,2.39583 -1.52994,0.48177 -2.64323,0.3125 -3.33333,-0.52083 -5,-4.02995 -9.9349,-8.125 -14.79167,-12.29167 -4.85677,-4.16666 -10.20833,-8.0599 -16.04166,-11.66666 -0.97005,-0.69662 -1.41927,-1.35417 -1.35417,-1.97917 0.0716,-0.625 0.45573,-1.5625 1.14583,-2.8125 l 33.33334,-50.83333 c 0.97005,-1.39323 1.9401,-2.05078 2.91666,-1.97917 0.97006,0.0652 2.01172,0.44922 3.125,1.14584 2.91667,1.66666 5.83334,3.54166 8.75,5.625 2.91667,2.08333 5.625,4.33593 8.125,6.77083 2.5,2.42838 4.6875,5.0651 6.5625,7.91667 1.875,2.84505 3.22917,6.00259 4.0625,9.47916 z"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.66666663"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
id="path879"
|
||||||
|
d="M 303.71722,505.07234"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.66666663"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path925"
|
||||||
|
d="m 168.42167,500.82557 c -23.47656,-0.14323 -41.60156,-1.17838 -54.375,-3.125 -22.226562,-3.47005 -38.059894,-10.13671 -47.499997,-20 -8.476563,-7.63671 -12.708333,-18.05338 -12.708333,-31.24999 0,-5.13672 0.48177,-12.5 1.458333,-22.08334 0.970052,-9.58333 2.291667,-19.16666 3.958333,-28.75 0.690104,-4.02343 1.315104,-7.63671 1.875,-10.83333 0.416667,-2.22005 0.970052,-4.02344 1.666667,-5.41667 0.690103,-1.38671 1.458333,-2.1875 2.291666,-2.39583 0.833334,-0.20833 1.627604,0.35156 2.395834,1.66667 0.761718,1.32161 1.490885,3.58073 2.187499,6.77083 0.553385,3.47656 1.315104,7.08333 2.291667,10.83333 2.220052,9.02995 8.261718,15.76823 18.124999,20.20834 25.000002,10.69661 63.190102,16.25 114.583332,16.66666 21.25,-0.27343 40.97005,-1.04166 59.16666,-2.29166 18.60677,-1.38672 39.58333,-4.64844 62.91667,-9.79167 23.33333,-5.13672 41.90754,-10.76172 55.72916,-16.875 13.8151,-6.10677 25.58593,-12.70833 35.3125,-19.79167 7.63671,-5.55338 11.45833,-10.89843 11.45833,-16.04166 0,-2.08333 -1.97917,-4.54427 -5.9375,-7.39583 -3.95833,-2.84506 -6.5625,-4.27084 -7.8125,-4.27084 -2.36328,1.11328 -5.14323,1.97917 -8.33333,2.60417 -3.19662,0.625 -6.11328,0.80078 -8.75,0.52083 -7.36328,-0.83333 -12.85157,-3.125 -16.45833,-6.875 -3.61329,-3.75 -5.41667,-8.8151 -5.41667,-15.20833 0,-4.02343 5.34505,-16.66667 16.04167,-37.91667 4.30338,-8.60676 8.08593,-14.61588 11.35416,-18.02083 3.26172,-3.39843 7.74089,-5.10416 13.4375,-5.10416 9.02343,0 17.39583,4.86328 25.10417,14.58333 7.70833,9.72656 11.5625,22.15495 11.5625,37.29166 0,15 -2.01824,27.98828 -6.04167,38.95834 -5,14.99999 -11.8099,28.89322 -20.41667,41.66666 -10.83333,15.41667 -22.70833,27.60417 -35.62499,36.5625 -12.91667,8.95833 -25.97657,16.08073 -39.16667,21.35416 -11.8099,5.83334 -27.05078,11.28907 -45.72916,16.35417 -18.6849,5.07162 -41.35417,9.20573 -68.02083,12.39583 -26.39323,3.19662 -49.9349,4.85677 -70.625,5 z"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.66666663" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path923"
|
||||||
|
d="m 430.22191,133.16177 c 1.10676,4.02995 1.07421,8.19662 -0.10417,12.5 -1.1849,4.3099 -3.3724,8.82162 -6.5625,13.54167 -1.94661,3.19661 -3.9974,6.08073 -6.14583,8.64583 -2.15495,2.57162 -4.41407,5.03907 -6.77083,7.39583 -0.69662,0.83334 -1.8099,1.875 -3.33334,3.125 -1.52995,1.25 -3.125,2.4349 -4.79166,3.54167 -1.66667,1.11328 -3.26824,1.91407 -4.79167,2.39583 -1.52995,0.48829 -2.64323,0.3125 -3.33333,-0.52083 -5,-4.02343 -9.9349,-8.125 -14.79167,-12.29167 -4.86328,-4.16666 -10.20833,-8.05338 -16.04167,-11.66666 -0.97656,-0.6901 -1.42578,-1.35417 -1.35416,-1.97917 0.0652,-0.625 0.44921,-1.5625 1.14583,-2.8125 l 33.33333,-50.83333 c 0.97005,-1.38672 1.9401,-2.04427 2.91667,-1.97917 0.97005,0.0717 2.01172,0.45574 3.125,1.14584 2.91667,1.66666 5.83333,3.54166 8.75,5.625 2.91667,2.08333 5.625,4.34245 8.125,6.77083 2.5,2.4349 4.6875,5.07162 6.5625,7.91667 1.875,2.85156 3.22916,6.00911 4.0625,9.47916 z"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.66666663" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path883"
|
||||||
|
d="M 305.71333,214.15892"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.66666663" />
|
||||||
|
<path
|
||||||
|
id="path887"
|
||||||
|
d="m 599.12998,319.78391 c -3.0599,5.41667 -6.25,10.8724 -9.58333,16.35417 -3.33334,5.48828 -7.05079,10.66406 -11.14584,15.52083 -4.10156,4.86328 -8.61328,9.27084 -13.54166,13.22917 -4.9349,3.95833 -10.52084,7.12239 -16.77084,9.47916 -5.14323,2.08334 -9.51823,4.41407 -13.125,6.97917 -3.61328,2.57162 -6.60156,5.3125 -8.95833,8.22917 -3.61328,3.89323 -6.73828,9.27083 -9.375,16.14583 -2.64323,6.875 -5.38411,14.13411 -8.22916,21.77083 -2.85157,7.64323 -5.97657,15.10417 -9.375,22.39583 -3.40495,7.29167 -7.67579,13.30079 -12.8125,18.02084 -7.08334,7.5 -17.57162,12.57161 -31.45834,15.20833 l -38.12499,6.45833 c -1.11329,0.14323 -2.46745,0.2474 -4.0625,0.3125 -1.60157,0.0716 -2.7474,0.0391 -3.4375,-0.10416 -3.19011,-0.97005 -4.16667,-3.08594 -2.91667,-6.35417 1.25,-3.26172 4.51172,-6.5625 9.79167,-9.89583 10.6901,-7.08334 19.23177,-12.8125 25.625,-17.1875 6.38671,-4.375 11.59505,-7.94922 15.62499,-10.72917 4.02344,-2.77343 7.25261,-5.0651 9.6875,-6.875 2.42839,-1.80338 5.03256,-3.8151 7.8125,-6.04166 11.25,-8.47006 19.02344,-17.35677 23.33334,-26.66667 2.5,-4.85677 4.79166,-9.58333 6.875,-14.16667 2.08333,-4.58333 4.27083,-9.09505 6.5625,-13.54166 2.29166,-4.44011 4.7526,-8.85417 7.39583,-13.22917 2.63672,-4.375 5.6901,-8.78255 9.16667,-13.22916 3.60677,-4.44011 8.47005,-8.78256 14.58333,-13.02084 6.10677,-4.23177 13.47005,-8.4375 22.08333,-12.60416 0.97005,-0.41667 2.5651,-1.35417 4.79167,-2.8125 2.22005,-1.45834 4.92838,-3.78255 8.125,-6.97917 3.1901,-3.1901 6.83593,-7.53255 10.9375,-13.02083 4.09505,-5.48177 8.4375,-12.46094 13.02083,-20.9375 -1.66667,-1.66667 -6.45833,-3.95833 -14.375,-6.875 -7.91667,-3.05338 -15.41667,-4.79167 -22.5,-5.20833 -6.52995,-0.41667 -11.91406,0.76823 -16.14583,3.54166 -4.23828,2.77995 -8.09245,6.73829 -11.5625,11.875 -3.47657,5.14323 -6.45833,7.5 -8.95833,7.08333 -0.83334,-0.41666 -0.97657,-2.14843 -0.41667,-5.20833 0.6901,-3.05338 1.66667,-6.04166 2.91667,-8.95833 5.27343,-12.08333 11.24999,-21.04167 17.91666,-26.875 6.80339,-5.97005 14.92839,-8.95833 24.375,-8.95833 6.80338,0 15.34505,1.66666 25.625,5 6.38672,2.22656 11.875,3.33333 16.45833,3.33333 9.58333,0 19.09505,-3.39843 28.54167,-10.20833 2.08333,0 2.8125,1.35416 2.1875,4.0625 -0.625,2.70833 -1.5625,5.8724 -2.8125,9.47916 -1.11329,3.61329 -1.875,6.04167 -2.29167,7.29167 -2.08333,6.52995 -3.75,10.35157 -5,11.45833 -1.25,0.97657 -4.86328,3.61329 -10.83333,7.91667 -3.33334,2.5 -6.21745,5.38411 -8.64584,8.64583 -2.43489,3.26823 -4.89583,7.1224 -7.39583,11.5625 -2.5,4.44662 -5.69661,10.5599 -9.58333,18.33333 z m 0,0"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.66666663"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<use
|
||||||
|
style="fill:#000000;fill-opacity:1"
|
||||||
|
id="use62"
|
||||||
|
y="291"
|
||||||
|
x="119.25"
|
||||||
|
xlink:href="#glyph0-4"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
transform="matrix(1.3333333,0,0,1.3333333,72.589732,-189.32751)" />
|
||||||
|
<use
|
||||||
|
style="fill:#000000;fill-opacity:1"
|
||||||
|
id="use196"
|
||||||
|
y="391"
|
||||||
|
x="168.375"
|
||||||
|
xlink:href="#glyph0-4-3"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
transform="matrix(1.3333333,0,0,1.3333333,-861.41828,-631.73483)" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 31 KiB |
@ -67,7 +67,8 @@ EXTRA_HFILES=$(top_builddir)/src/hb-version.h
|
|||||||
# Images to copy into HTML directory.
|
# Images to copy into HTML directory.
|
||||||
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
|
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
|
||||||
HTML_IMAGES= \
|
HTML_IMAGES= \
|
||||||
HarfBuzz.png
|
HarfBuzz.png \
|
||||||
|
HarfBuzz.svg
|
||||||
|
|
||||||
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
|
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
|
||||||
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
|
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
|
||||||
@ -110,7 +111,7 @@ EXTRA_DIST += version.xml.in
|
|||||||
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
|
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
|
||||||
#DISTCLEANFILES +=
|
#DISTCLEANFILES +=
|
||||||
|
|
||||||
# Comment this out if you want 'make check' to test you doc status
|
# Comment this out if you don't want 'make check' to test you doc status
|
||||||
# and run some sanity checks
|
# and run some sanity checks
|
||||||
if ENABLE_GTK_DOC
|
if ENABLE_GTK_DOC
|
||||||
TESTS_ENVIRONMENT = cd $(srcdir) && \
|
TESTS_ENVIRONMENT = cd $(srcdir) && \
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
source tree is available
|
source tree is available
|
||||||
<ulink url="http://cgit.freedesktop.org/harfbuzz/">here</ulink>.
|
<ulink url="http://cgit.freedesktop.org/harfbuzz/">here</ulink>.
|
||||||
Also available on
|
Also available on
|
||||||
<ulink url="https://github.com/behdad/harfbuzz">github</ulink>.
|
<ulink url="https://github.com/harfbuzz/harfbuzz">github</ulink>.
|
||||||
See <xref linkend="download" endterm="download.title"/> for release tarballs.
|
See <xref linkend="download" endterm="download.title"/> for release tarballs.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
@ -60,7 +60,7 @@
|
|||||||
</partinfo>
|
</partinfo>
|
||||||
<title>Reference manual</title>
|
<title>Reference manual</title>
|
||||||
<chapter>
|
<chapter>
|
||||||
<title>Harfbuzz API</title>
|
<title>HarfBuzz API</title>
|
||||||
<xi:include href="xml/hb.xml"/>
|
<xi:include href="xml/hb.xml"/>
|
||||||
<xi:include href="xml/hb-common.xml"/>
|
<xi:include href="xml/hb-common.xml"/>
|
||||||
<xi:include href="xml/hb-unicode.xml"/>
|
<xi:include href="xml/hb-unicode.xml"/>
|
||||||
@ -80,6 +80,7 @@
|
|||||||
<xi:include href="xml/hb-ot-tag.xml"/>
|
<xi:include href="xml/hb-ot-tag.xml"/>
|
||||||
<xi:include href="xml/hb-ot-font.xml"/>
|
<xi:include href="xml/hb-ot-font.xml"/>
|
||||||
<xi:include href="xml/hb-ot-shape.xml"/>
|
<xi:include href="xml/hb-ot-shape.xml"/>
|
||||||
|
<xi:include href="xml/hb-ot-math.xml"/>
|
||||||
|
|
||||||
<xi:include href="xml/hb-shape-plan.xml"/>
|
<xi:include href="xml/hb-shape-plan.xml"/>
|
||||||
|
|
||||||
@ -175,6 +176,30 @@
|
|||||||
<title>Index of new symbols in 1.1.3</title>
|
<title>Index of new symbols in 1.1.3</title>
|
||||||
<xi:include href="xml/api-index-1.1.3.xml"><xi:fallback /></xi:include>
|
<xi:include href="xml/api-index-1.1.3.xml"><xi:fallback /></xi:include>
|
||||||
</index>
|
</index>
|
||||||
|
<index id="api-index-1-2-3" role="1.2.3">
|
||||||
|
<title>Index of new symbols in 1.2.3</title>
|
||||||
|
<xi:include href="xml/api-index-1.2.3.xml"><xi:fallback /></xi:include>
|
||||||
|
</index>
|
||||||
|
<index id="api-index-1-3-3" role="1.3.3">
|
||||||
|
<title>Index of new symbols in 1.3.3</title>
|
||||||
|
<xi:include href="xml/api-index-1.3.3.xml"><xi:fallback /></xi:include>
|
||||||
|
</index>
|
||||||
|
<index id="api-index-1-4-2" role="1.4.2">
|
||||||
|
<title>Index of new symbols in 1.4.2</title>
|
||||||
|
<xi:include href="xml/api-index-1.4.2.xml"><xi:fallback /></xi:include>
|
||||||
|
</index>
|
||||||
|
<index id="api-index-1-4-3" role="1.4.3">
|
||||||
|
<title>Index of new symbols in 1.4.3</title>
|
||||||
|
<xi:include href="xml/api-index-1.4.3.xml"><xi:fallback /></xi:include>
|
||||||
|
</index>
|
||||||
|
<index id="api-index-1-5-0" role="1.5.0">
|
||||||
|
<title>Index of new symbols in 1.5.0</title>
|
||||||
|
<xi:include href="xml/api-index-1.5.0.xml"><xi:fallback /></xi:include>
|
||||||
|
</index>
|
||||||
|
<index id="api-index-1-6-0" role="1.6.0">
|
||||||
|
<title>Index of new symbols in 1.6.0</title>
|
||||||
|
<xi:include href="xml/api-index-1.6.0.xml"><xi:fallback /></xi:include>
|
||||||
|
</index>
|
||||||
<index id="deprecated-api-index" role="deprecated">
|
<index id="deprecated-api-index" role="deprecated">
|
||||||
<title>Index of deprecated API</title>
|
<title>Index of deprecated API</title>
|
||||||
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
|
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
|
||||||
|
@ -9,6 +9,7 @@ HB_EXTERN
|
|||||||
<FILE>hb-blob</FILE>
|
<FILE>hb-blob</FILE>
|
||||||
hb_blob_create
|
hb_blob_create
|
||||||
hb_blob_create_sub_blob
|
hb_blob_create_sub_blob
|
||||||
|
hb_blob_copy_writable_or_fail
|
||||||
hb_blob_destroy
|
hb_blob_destroy
|
||||||
hb_blob_get_data
|
hb_blob_get_data
|
||||||
hb_blob_get_data_writable
|
hb_blob_get_data_writable
|
||||||
@ -41,6 +42,7 @@ hb_buffer_add_utf32
|
|||||||
hb_buffer_add_utf16
|
hb_buffer_add_utf16
|
||||||
hb_buffer_add_utf8
|
hb_buffer_add_utf8
|
||||||
hb_buffer_add_latin1
|
hb_buffer_add_latin1
|
||||||
|
hb_buffer_append
|
||||||
hb_buffer_set_content_type
|
hb_buffer_set_content_type
|
||||||
hb_buffer_get_content_type
|
hb_buffer_get_content_type
|
||||||
hb_buffer_set_direction
|
hb_buffer_set_direction
|
||||||
@ -77,9 +79,12 @@ hb_buffer_serialize_format_to_string
|
|||||||
hb_buffer_serialize_list_formats
|
hb_buffer_serialize_list_formats
|
||||||
hb_segment_properties_equal
|
hb_segment_properties_equal
|
||||||
hb_segment_properties_hash
|
hb_segment_properties_hash
|
||||||
|
hb_buffer_diff
|
||||||
hb_buffer_set_message_func
|
hb_buffer_set_message_func
|
||||||
hb_buffer_t
|
hb_buffer_t
|
||||||
|
hb_glyph_info_get_glyph_flags
|
||||||
hb_glyph_info_t
|
hb_glyph_info_t
|
||||||
|
hb_glyph_flags_t
|
||||||
hb_glyph_position_t
|
hb_glyph_position_t
|
||||||
hb_buffer_content_type_t
|
hb_buffer_content_type_t
|
||||||
hb_buffer_flags_t
|
hb_buffer_flags_t
|
||||||
@ -87,6 +92,7 @@ hb_buffer_cluster_level_t
|
|||||||
hb_segment_properties_t
|
hb_segment_properties_t
|
||||||
hb_buffer_serialize_format_t
|
hb_buffer_serialize_format_t
|
||||||
hb_buffer_serialize_flags_t
|
hb_buffer_serialize_flags_t
|
||||||
|
hb_buffer_diff_flags_t
|
||||||
hb_buffer_message_func_t
|
hb_buffer_message_func_t
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
@ -144,13 +150,18 @@ uint8_t
|
|||||||
HB_BUFFER_FLAGS_DEFAULT
|
HB_BUFFER_FLAGS_DEFAULT
|
||||||
HB_BUFFER_SERIALIZE_FLAGS_DEFAULT
|
HB_BUFFER_SERIALIZE_FLAGS_DEFAULT
|
||||||
HB_SCRIPT_CANADIAN_ABORIGINAL
|
HB_SCRIPT_CANADIAN_ABORIGINAL
|
||||||
|
hb_font_funcs_set_glyph_func
|
||||||
|
hb_font_get_glyph_func_t
|
||||||
|
hb_set_invert
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-coretext</FILE>
|
<FILE>hb-coretext</FILE>
|
||||||
|
HB_CORETEXT_TAG_KERX
|
||||||
HB_CORETEXT_TAG_MORT
|
HB_CORETEXT_TAG_MORT
|
||||||
HB_CORETEXT_TAG_MORX
|
HB_CORETEXT_TAG_MORX
|
||||||
hb_coretext_face_create
|
hb_coretext_face_create
|
||||||
|
hb_coretext_font_create
|
||||||
hb_coretext_face_get_cg_font
|
hb_coretext_face_get_cg_font
|
||||||
hb_coretext_font_get_ct_font
|
hb_coretext_font_get_ct_font
|
||||||
</SECTION>
|
</SECTION>
|
||||||
@ -161,6 +172,7 @@ hb_face_create
|
|||||||
hb_face_create_for_tables
|
hb_face_create_for_tables
|
||||||
hb_face_destroy
|
hb_face_destroy
|
||||||
hb_face_get_empty
|
hb_face_get_empty
|
||||||
|
hb_face_get_table_tags
|
||||||
hb_face_get_glyph_count
|
hb_face_get_glyph_count
|
||||||
hb_face_get_index
|
hb_face_get_index
|
||||||
hb_face_get_upem
|
hb_face_get_upem
|
||||||
@ -193,7 +205,6 @@ hb_font_funcs_reference
|
|||||||
hb_font_funcs_set_glyph_contour_point_func
|
hb_font_funcs_set_glyph_contour_point_func
|
||||||
hb_font_funcs_set_glyph_extents_func
|
hb_font_funcs_set_glyph_extents_func
|
||||||
hb_font_funcs_set_glyph_from_name_func
|
hb_font_funcs_set_glyph_from_name_func
|
||||||
hb_font_funcs_set_glyph_func
|
|
||||||
hb_font_funcs_set_glyph_h_advance_func
|
hb_font_funcs_set_glyph_h_advance_func
|
||||||
hb_font_funcs_set_glyph_h_kerning_func
|
hb_font_funcs_set_glyph_h_kerning_func
|
||||||
hb_font_funcs_set_glyph_h_origin_func
|
hb_font_funcs_set_glyph_h_origin_func
|
||||||
@ -201,7 +212,9 @@ hb_font_funcs_set_glyph_name_func
|
|||||||
hb_font_funcs_set_glyph_v_advance_func
|
hb_font_funcs_set_glyph_v_advance_func
|
||||||
hb_font_funcs_set_glyph_v_kerning_func
|
hb_font_funcs_set_glyph_v_kerning_func
|
||||||
hb_font_funcs_set_glyph_v_origin_func
|
hb_font_funcs_set_glyph_v_origin_func
|
||||||
|
hb_font_funcs_set_nominal_glyph_func
|
||||||
hb_font_funcs_set_user_data
|
hb_font_funcs_set_user_data
|
||||||
|
hb_font_funcs_set_variation_glyph_func
|
||||||
hb_font_funcs_t
|
hb_font_funcs_t
|
||||||
hb_font_get_empty
|
hb_font_get_empty
|
||||||
hb_font_get_face
|
hb_font_get_face
|
||||||
@ -216,7 +229,6 @@ hb_font_get_glyph_extents_for_origin
|
|||||||
hb_font_get_glyph_extents_func_t
|
hb_font_get_glyph_extents_func_t
|
||||||
hb_font_get_glyph_from_name
|
hb_font_get_glyph_from_name
|
||||||
hb_font_get_glyph_from_name_func_t
|
hb_font_get_glyph_from_name_func_t
|
||||||
hb_font_get_glyph_func_t
|
|
||||||
hb_font_get_glyph_h_advance
|
hb_font_get_glyph_h_advance
|
||||||
hb_font_get_glyph_h_advance_func_t
|
hb_font_get_glyph_h_advance_func_t
|
||||||
hb_font_get_glyph_h_kerning
|
hb_font_get_glyph_h_kerning
|
||||||
@ -235,20 +247,35 @@ hb_font_get_glyph_v_kerning
|
|||||||
hb_font_get_glyph_v_kerning_func_t
|
hb_font_get_glyph_v_kerning_func_t
|
||||||
hb_font_get_glyph_v_origin
|
hb_font_get_glyph_v_origin
|
||||||
hb_font_get_glyph_v_origin_func_t
|
hb_font_get_glyph_v_origin_func_t
|
||||||
|
hb_font_get_nominal_glyph
|
||||||
|
hb_font_get_nominal_glyph_func_t
|
||||||
hb_font_get_parent
|
hb_font_get_parent
|
||||||
hb_font_get_ppem
|
hb_font_get_ppem
|
||||||
|
hb_font_get_ptem
|
||||||
hb_font_get_scale
|
hb_font_get_scale
|
||||||
hb_font_get_user_data
|
hb_font_get_user_data
|
||||||
|
hb_font_get_variation_glyph
|
||||||
|
hb_font_get_variation_glyph_func_t
|
||||||
|
hb_font_get_var_coords_normalized
|
||||||
hb_font_glyph_from_string
|
hb_font_glyph_from_string
|
||||||
hb_font_glyph_to_string
|
hb_font_glyph_to_string
|
||||||
hb_font_is_immutable
|
hb_font_is_immutable
|
||||||
hb_font_make_immutable
|
hb_font_make_immutable
|
||||||
hb_font_reference
|
hb_font_reference
|
||||||
|
hb_font_set_face
|
||||||
hb_font_set_funcs
|
hb_font_set_funcs
|
||||||
hb_font_set_funcs_data
|
hb_font_set_funcs_data
|
||||||
|
hb_font_set_parent
|
||||||
hb_font_set_ppem
|
hb_font_set_ppem
|
||||||
|
hb_font_set_ptem
|
||||||
hb_font_set_scale
|
hb_font_set_scale
|
||||||
hb_font_set_user_data
|
hb_font_set_user_data
|
||||||
|
hb_variation_t
|
||||||
|
hb_variation_from_string
|
||||||
|
hb_variation_to_string
|
||||||
|
hb_font_set_variations
|
||||||
|
hb_font_set_var_coords_design
|
||||||
|
hb_font_set_var_coords_normalized
|
||||||
hb_font_subtract_glyph_origin_for_direction
|
hb_font_subtract_glyph_origin_for_direction
|
||||||
hb_font_t
|
hb_font_t
|
||||||
hb_reference_table_func_t
|
hb_reference_table_func_t
|
||||||
@ -260,7 +287,6 @@ hb_font_get_font_h_extents_func_t
|
|||||||
hb_font_get_font_v_extents_func_t
|
hb_font_get_font_v_extents_func_t
|
||||||
hb_font_get_h_extents
|
hb_font_get_h_extents
|
||||||
hb_font_get_v_extents
|
hb_font_get_v_extents
|
||||||
hb_font_set_parent
|
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
@ -270,6 +296,7 @@ hb_ft_face_create_cached
|
|||||||
hb_ft_face_create_referenced
|
hb_ft_face_create_referenced
|
||||||
hb_ft_font_create
|
hb_ft_font_create
|
||||||
hb_ft_font_create_referenced
|
hb_ft_font_create_referenced
|
||||||
|
hb_ft_font_changed
|
||||||
hb_ft_font_get_face
|
hb_ft_font_get_face
|
||||||
hb_ft_font_set_load_flags
|
hb_ft_font_set_load_flags
|
||||||
hb_ft_font_get_load_flags
|
hb_ft_font_get_load_flags
|
||||||
@ -289,6 +316,7 @@ hb_glib_blob_create
|
|||||||
HB_GOBJECT_TYPE_BLOB
|
HB_GOBJECT_TYPE_BLOB
|
||||||
HB_GOBJECT_TYPE_BUFFER
|
HB_GOBJECT_TYPE_BUFFER
|
||||||
HB_GOBJECT_TYPE_BUFFER_CONTENT_TYPE
|
HB_GOBJECT_TYPE_BUFFER_CONTENT_TYPE
|
||||||
|
HB_GOBJECT_TYPE_BUFFER_DIFF_FLAGS
|
||||||
HB_GOBJECT_TYPE_BUFFER_FLAGS
|
HB_GOBJECT_TYPE_BUFFER_FLAGS
|
||||||
HB_GOBJECT_TYPE_BUFFER_SERIALIZE_FLAGS
|
HB_GOBJECT_TYPE_BUFFER_SERIALIZE_FLAGS
|
||||||
HB_GOBJECT_TYPE_BUFFER_SERIALIZE_FORMAT
|
HB_GOBJECT_TYPE_BUFFER_SERIALIZE_FORMAT
|
||||||
@ -296,8 +324,14 @@ HB_GOBJECT_TYPE_DIRECTION
|
|||||||
HB_GOBJECT_TYPE_FACE
|
HB_GOBJECT_TYPE_FACE
|
||||||
HB_GOBJECT_TYPE_FONT
|
HB_GOBJECT_TYPE_FONT
|
||||||
HB_GOBJECT_TYPE_FONT_FUNCS
|
HB_GOBJECT_TYPE_FONT_FUNCS
|
||||||
|
HB_GOBJECT_TYPE_GLYPH_FLAGS
|
||||||
HB_GOBJECT_TYPE_MEMORY_MODE
|
HB_GOBJECT_TYPE_MEMORY_MODE
|
||||||
HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS
|
HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS
|
||||||
|
HB_GOBJECT_TYPE_OT_MATH_CONSTANT
|
||||||
|
HB_GOBJECT_TYPE_OT_MATH_GLYPH_PART
|
||||||
|
HB_GOBJECT_TYPE_OT_MATH_GLYPH_PART_FLAGS
|
||||||
|
HB_GOBJECT_TYPE_OT_MATH_GLYPH_VARIANT
|
||||||
|
HB_GOBJECT_TYPE_OT_MATH_KERN
|
||||||
HB_GOBJECT_TYPE_SCRIPT
|
HB_GOBJECT_TYPE_SCRIPT
|
||||||
HB_GOBJECT_TYPE_SHAPE_PLAN
|
HB_GOBJECT_TYPE_SHAPE_PLAN
|
||||||
HB_GOBJECT_TYPE_UNICODE_COMBINING_CLASS
|
HB_GOBJECT_TYPE_UNICODE_COMBINING_CLASS
|
||||||
@ -312,6 +346,7 @@ HB_GOBJECT_TYPE_SET
|
|||||||
HB_GOBJECT_TYPE_USER_DATA_KEY
|
HB_GOBJECT_TYPE_USER_DATA_KEY
|
||||||
hb_gobject_blob_get_type
|
hb_gobject_blob_get_type
|
||||||
hb_gobject_buffer_content_type_get_type
|
hb_gobject_buffer_content_type_get_type
|
||||||
|
hb_gobject_buffer_diff_flags_get_type
|
||||||
hb_gobject_buffer_flags_get_type
|
hb_gobject_buffer_flags_get_type
|
||||||
hb_gobject_buffer_get_type
|
hb_gobject_buffer_get_type
|
||||||
hb_gobject_buffer_serialize_flags_get_type
|
hb_gobject_buffer_serialize_flags_get_type
|
||||||
@ -320,8 +355,14 @@ hb_gobject_direction_get_type
|
|||||||
hb_gobject_face_get_type
|
hb_gobject_face_get_type
|
||||||
hb_gobject_font_funcs_get_type
|
hb_gobject_font_funcs_get_type
|
||||||
hb_gobject_font_get_type
|
hb_gobject_font_get_type
|
||||||
|
hb_gobject_glyph_flags_get_type
|
||||||
hb_gobject_memory_mode_get_type
|
hb_gobject_memory_mode_get_type
|
||||||
hb_gobject_ot_layout_glyph_class_get_type
|
hb_gobject_ot_layout_glyph_class_get_type
|
||||||
|
hb_gobject_ot_math_constant_get_type
|
||||||
|
hb_gobject_ot_math_glyph_part_get_type
|
||||||
|
hb_gobject_ot_math_glyph_part_flags_get_type
|
||||||
|
hb_gobject_ot_math_glyph_variant_get_type
|
||||||
|
hb_gobject_ot_math_kern_get_type
|
||||||
hb_gobject_script_get_type
|
hb_gobject_script_get_type
|
||||||
hb_gobject_shape_plan_get_type
|
hb_gobject_shape_plan_get_type
|
||||||
hb_gobject_unicode_combining_class_get_type
|
hb_gobject_unicode_combining_class_get_type
|
||||||
@ -378,12 +419,14 @@ hb_ot_shape_glyphs_closure
|
|||||||
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX
|
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX
|
||||||
HB_OT_LAYOUT_NO_FEATURE_INDEX
|
HB_OT_LAYOUT_NO_FEATURE_INDEX
|
||||||
HB_OT_LAYOUT_NO_SCRIPT_INDEX
|
HB_OT_LAYOUT_NO_SCRIPT_INDEX
|
||||||
|
HB_OT_LAYOUT_NO_VARIATIONS_INDEX
|
||||||
HB_OT_TAG_GDEF
|
HB_OT_TAG_GDEF
|
||||||
HB_OT_TAG_GPOS
|
HB_OT_TAG_GPOS
|
||||||
HB_OT_TAG_GSUB
|
HB_OT_TAG_GSUB
|
||||||
HB_OT_TAG_JSTF
|
HB_OT_TAG_JSTF
|
||||||
hb_ot_layout_collect_lookups
|
hb_ot_layout_collect_lookups
|
||||||
hb_ot_layout_feature_get_lookups
|
hb_ot_layout_feature_get_lookups
|
||||||
|
hb_ot_layout_feature_with_variations_get_lookups
|
||||||
hb_ot_layout_get_attach_points
|
hb_ot_layout_get_attach_points
|
||||||
hb_ot_layout_get_glyph_class
|
hb_ot_layout_get_glyph_class
|
||||||
hb_ot_layout_get_glyphs_in_class
|
hb_ot_layout_get_glyphs_in_class
|
||||||
@ -404,6 +447,7 @@ hb_ot_layout_lookup_would_substitute
|
|||||||
hb_ot_layout_script_find_language
|
hb_ot_layout_script_find_language
|
||||||
hb_ot_layout_script_get_language_tags
|
hb_ot_layout_script_get_language_tags
|
||||||
hb_ot_layout_table_choose_script
|
hb_ot_layout_table_choose_script
|
||||||
|
hb_ot_layout_table_find_feature_variations
|
||||||
hb_ot_layout_table_find_script
|
hb_ot_layout_table_find_script
|
||||||
hb_ot_layout_table_get_feature_tags
|
hb_ot_layout_table_get_feature_tags
|
||||||
hb_ot_layout_table_get_script_tags
|
hb_ot_layout_table_get_script_tags
|
||||||
@ -416,6 +460,43 @@ Xhb_ot_layout_lookup_position
|
|||||||
Xhb_ot_layout_lookup_substitute
|
Xhb_ot_layout_lookup_substitute
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>hb-ot-var</FILE>
|
||||||
|
HB_OT_TAG_VAR_AXIS_ITALIC
|
||||||
|
HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
|
||||||
|
HB_OT_TAG_VAR_AXIS_SLANT
|
||||||
|
HB_OT_TAG_VAR_AXIS_WEIGHT
|
||||||
|
HB_OT_TAG_VAR_AXIS_WIDTH
|
||||||
|
HB_OT_VAR_NO_AXIS_INDEX
|
||||||
|
hb_ot_var_axis_t
|
||||||
|
hb_ot_var_has_data
|
||||||
|
hb_ot_var_find_axis
|
||||||
|
hb_ot_var_get_axis_count
|
||||||
|
hb_ot_var_get_axes
|
||||||
|
hb_ot_var_normalize_variations
|
||||||
|
hb_ot_var_normalize_coords
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>hb-ot-math</FILE>
|
||||||
|
HB_OT_TAG_MATH
|
||||||
|
HB_OT_MATH_SCRIPT
|
||||||
|
hb_ot_math_constant_t
|
||||||
|
hb_ot_math_kern_t
|
||||||
|
hb_ot_math_glyph_variant_t
|
||||||
|
hb_ot_math_glyph_part_flags_t
|
||||||
|
hb_ot_math_glyph_part_t
|
||||||
|
hb_ot_math_has_data
|
||||||
|
hb_ot_math_get_constant
|
||||||
|
hb_ot_math_get_glyph_italics_correction
|
||||||
|
hb_ot_math_get_glyph_top_accent_attachment
|
||||||
|
hb_ot_math_get_glyph_kerning
|
||||||
|
hb_ot_math_is_glyph_extended_shape
|
||||||
|
hb_ot_math_get_glyph_variants
|
||||||
|
hb_ot_math_get_min_connector_overlap
|
||||||
|
hb_ot_math_get_glyph_assembly
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-ot-tag</FILE>
|
<FILE>hb-ot-tag</FILE>
|
||||||
HB_OT_TAG_DEFAULT_LANGUAGE
|
HB_OT_TAG_DEFAULT_LANGUAGE
|
||||||
@ -444,11 +525,12 @@ hb_set_get_population
|
|||||||
hb_set_get_user_data
|
hb_set_get_user_data
|
||||||
hb_set_has
|
hb_set_has
|
||||||
hb_set_intersect
|
hb_set_intersect
|
||||||
hb_set_invert
|
|
||||||
hb_set_is_empty
|
hb_set_is_empty
|
||||||
hb_set_is_equal
|
hb_set_is_equal
|
||||||
hb_set_next
|
hb_set_next
|
||||||
|
hb_set_previous
|
||||||
hb_set_next_range
|
hb_set_next_range
|
||||||
|
hb_set_previous_range
|
||||||
hb_set_reference
|
hb_set_reference
|
||||||
hb_set_set
|
hb_set_set
|
||||||
hb_set_set_user_data
|
hb_set_set_user_data
|
||||||
@ -460,8 +542,8 @@ hb_set_union
|
|||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-shape</FILE>
|
<FILE>hb-shape</FILE>
|
||||||
hb_feature_from_string
|
|
||||||
hb_feature_t
|
hb_feature_t
|
||||||
|
hb_feature_from_string
|
||||||
hb_feature_to_string
|
hb_feature_to_string
|
||||||
hb_shape
|
hb_shape
|
||||||
hb_shape_full
|
hb_shape_full
|
||||||
@ -472,6 +554,8 @@ hb_shape_list_shapers
|
|||||||
<FILE>hb-shape-plan</FILE>
|
<FILE>hb-shape-plan</FILE>
|
||||||
hb_shape_plan_create
|
hb_shape_plan_create
|
||||||
hb_shape_plan_create_cached
|
hb_shape_plan_create_cached
|
||||||
|
hb_shape_plan_create2
|
||||||
|
hb_shape_plan_create_cached2
|
||||||
hb_shape_plan_destroy
|
hb_shape_plan_destroy
|
||||||
hb_shape_plan_execute
|
hb_shape_plan_execute
|
||||||
hb_shape_plan_get_empty
|
hb_shape_plan_get_empty
|
||||||
@ -526,6 +610,8 @@ hb_unicode_script_func_t
|
|||||||
<FILE>hb-uniscribe</FILE>
|
<FILE>hb-uniscribe</FILE>
|
||||||
hb_uniscribe_font_get_hfont
|
hb_uniscribe_font_get_hfont
|
||||||
hb_uniscribe_font_get_logfontw
|
hb_uniscribe_font_get_logfontw
|
||||||
|
<SUBSECTION Private>
|
||||||
|
hb_directwrite_shape_experimental_width
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<chapter id="buffers-language-script-and-direction">
|
<chapter id="buffers-language-script-and-direction">
|
||||||
<title>Buffers, language, script and direction</title>
|
<title>Buffers, language, script and direction</title>
|
||||||
<para>
|
<para>
|
||||||
The input to Harfbuzz is a series of Unicode characters, stored in a
|
The input to HarfBuzz is a series of Unicode characters, stored in a
|
||||||
buffer. In this chapter, we'll look at how to set up a buffer with
|
buffer. In this chapter, we'll look at how to set up a buffer with
|
||||||
the text that we want and then customize the properties of the
|
the text that we want and then customize the properties of the
|
||||||
buffer.
|
buffer.
|
||||||
@ -15,7 +15,7 @@
|
|||||||
default values and ready to accept your Unicode strings.
|
default values and ready to accept your Unicode strings.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Harfbuzz manages the memory of objects that it creates (such as
|
HarfBuzz manages the memory of objects that it creates (such as
|
||||||
buffers), so you don't have to. When you have finished working on
|
buffers), so you don't have to. When you have finished working on
|
||||||
a buffer, you can call <literal>hb_buffer_destroy()</literal>:
|
a buffer, you can call <literal>hb_buffer_destroy()</literal>:
|
||||||
</para>
|
</para>
|
||||||
@ -27,7 +27,7 @@
|
|||||||
<para>
|
<para>
|
||||||
This will destroy the object and free its associated memory -
|
This will destroy the object and free its associated memory -
|
||||||
unless some other part of the program holds a reference to this
|
unless some other part of the program holds a reference to this
|
||||||
buffer. If you acquire a Harfbuzz buffer from another subsystem
|
buffer. If you acquire a HarfBuzz buffer from another subsystem
|
||||||
and want to ensure that it is not garbage collected by someone
|
and want to ensure that it is not garbage collected by someone
|
||||||
else destroying it, you should increase its reference count:
|
else destroying it, you should increase its reference count:
|
||||||
</para>
|
</para>
|
||||||
@ -53,8 +53,8 @@ void somefunc(hb_buffer_t *buffer) {
|
|||||||
<section id="adding-text-to-the-buffer">
|
<section id="adding-text-to-the-buffer">
|
||||||
<title>Adding text to the buffer</title>
|
<title>Adding text to the buffer</title>
|
||||||
<para>
|
<para>
|
||||||
Now we have a brand new Harfbuzz buffer. Let's start filling it
|
Now we have a brand new HarfBuzz buffer. Let's start filling it
|
||||||
with text! From Harfbuzz's perspective, a buffer is just a stream
|
with text! From HarfBuzz's perspective, a buffer is just a stream
|
||||||
of Unicode codepoints, but your input string is probably in one of
|
of Unicode codepoints, but your input string is probably in one of
|
||||||
the standard Unicode character encodings (UTF-8, UTF-16, UTF-32)
|
the standard Unicode character encodings (UTF-8, UTF-16, UTF-32)
|
||||||
</para>
|
</para>
|
||||||
|
@ -290,11 +290,11 @@
|
|||||||
0 ,3,2,4
|
0 ,3,2,4
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
There's no way to differentitate between these two scenarios based
|
There's no way to differentiate between these two scenarios based
|
||||||
on the cluster numbers alone.
|
on the cluster numbers alone.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Another problem appens with ligatures under level 2 if the
|
Another problem happens with ligatures under level 2 if the
|
||||||
direction of the text is forced to opposite of its natural
|
direction of the text is forced to opposite of its natural
|
||||||
direction (e.g. left-to-right Arabic). But that's too much of a
|
direction (e.g. left-to-right Arabic). But that's too much of a
|
||||||
corner case to worry about.
|
corner case to worry about.
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section id="using-harfbuzzs-native-opentype-implementation">
|
<section id="using-harfbuzzs-native-opentype-implementation">
|
||||||
<title>Using Harfbuzz's native OpenType implementation</title>
|
<title>Using HarfBuzz's native OpenType implementation</title>
|
||||||
<para>
|
<para>
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<chapter id="hello-harfbuzz">
|
<chapter id="hello-harfbuzz">
|
||||||
<title>Hello, Harfbuzz</title>
|
<title>Hello, HarfBuzz</title>
|
||||||
<para>
|
<para>
|
||||||
Here's the simplest Harfbuzz that can possibly work. We will improve
|
Here's the simplest HarfBuzz that can possibly work. We will improve
|
||||||
it later.
|
it later.
|
||||||
</para>
|
</para>
|
||||||
<orderedlist numeration="arabic">
|
<orderedlist numeration="arabic">
|
||||||
@ -91,23 +91,23 @@
|
|||||||
hb_font_destroy(hb_ft_font);
|
hb_font_destroy(hb_ft_font);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<section id="what-harfbuzz-doesnt-do">
|
<section id="what-harfbuzz-doesnt-do">
|
||||||
<title>What Harfbuzz doesn't do</title>
|
<title>What HarfBuzz doesn't do</title>
|
||||||
<para>
|
<para>
|
||||||
The code above will take a UTF8 string, shape it, and give you the
|
The code above will take a UTF8 string, shape it, and give you the
|
||||||
information required to lay it out correctly on a single
|
information required to lay it out correctly on a single
|
||||||
horizontal (or vertical) line using the font provided. That is the
|
horizontal (or vertical) line using the font provided. That is the
|
||||||
extent of Harfbuzz's responsibility.
|
extent of HarfBuzz's responsibility.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If you are implementing a text layout engine you may have other
|
If you are implementing a text layout engine you may have other
|
||||||
responsibilities, that Harfbuzz will not help you with:
|
responsibilities, that HarfBuzz will not help you with:
|
||||||
</para>
|
</para>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Harfbuzz won't help you with bidirectionality. If you want to
|
HarfBuzz won't help you with bidirectionality. If you want to
|
||||||
lay out text with mixed Hebrew and English, you will need to
|
lay out text with mixed Hebrew and English, you will need to
|
||||||
ensure that the buffer provided to Harfbuzz has those
|
ensure that the buffer provided to HarfBuzz has those
|
||||||
characters in the correct layout order. This will be different
|
characters in the correct layout order. This will be different
|
||||||
from the logical order in which the Unicode text is stored. In
|
from the logical order in which the Unicode text is stored. In
|
||||||
other words, the user will hit the keys in the following
|
other words, the user will hit the keys in the following
|
||||||
@ -127,30 +127,30 @@ ABC אבג DEF
|
|||||||
("bidi" is short for bidirectional), and there's an
|
("bidi" is short for bidirectional), and there's an
|
||||||
algorithm as an annex to the Unicode Standard which tells you how
|
algorithm as an annex to the Unicode Standard which tells you how
|
||||||
to reorder a string from logical order into presentation order.
|
to reorder a string from logical order into presentation order.
|
||||||
Before sending your string to Harfbuzz, you may need to apply the
|
Before sending your string to HarfBuzz, you may need to apply the
|
||||||
bidi algorithm to it. Libraries such as ICU and fribidi can do
|
bidi algorithm to it. Libraries such as ICU and fribidi can do
|
||||||
this for you.
|
this for you.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Harfbuzz won't help you with text that contains different font
|
HarfBuzz won't help you with text that contains different font
|
||||||
properties. For instance, if you have the string "a
|
properties. For instance, if you have the string "a
|
||||||
<emphasis>huge</emphasis> breakfast", and you expect
|
<emphasis>huge</emphasis> breakfast", and you expect
|
||||||
"huge" to be italic, you will need to send three
|
"huge" to be italic, you will need to send three
|
||||||
strings to Harfbuzz: <literal>a</literal>, in your Roman font;
|
strings to HarfBuzz: <literal>a</literal>, in your Roman font;
|
||||||
<literal>huge</literal> using your italic font; and
|
<literal>huge</literal> using your italic font; and
|
||||||
<literal>breakfast</literal> using your Roman font again.
|
<literal>breakfast</literal> using your Roman font again.
|
||||||
Similarly if you change font, font size, script, language or
|
Similarly if you change font, font size, script, language or
|
||||||
direction within your string, you will need to shape each run
|
direction within your string, you will need to shape each run
|
||||||
independently and then output them independently. Harfbuzz
|
independently and then output them independently. HarfBuzz
|
||||||
expects to shape a run of characters sharing the same
|
expects to shape a run of characters sharing the same
|
||||||
properties.
|
properties.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Harfbuzz won't help you with line breaking, hyphenation or
|
HarfBuzz won't help you with line breaking, hyphenation or
|
||||||
justification. As mentioned above, it lays out the string
|
justification. As mentioned above, it lays out the string
|
||||||
along a <emphasis>single line</emphasis> of, notionally,
|
along a <emphasis>single line</emphasis> of, notionally,
|
||||||
infinite length. If you want to find out where the potential
|
infinite length. If you want to find out where the potential
|
||||||
@ -158,12 +158,12 @@ ABC אבג DEF
|
|||||||
could use the ICU library's break iterator functions.
|
could use the ICU library's break iterator functions.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Harfbuzz can tell you how wide a shaped piece of text is, which is
|
HarfBuzz can tell you how wide a shaped piece of text is, which is
|
||||||
useful input to a justification algorithm, but it knows nothing
|
useful input to a justification algorithm, but it knows nothing
|
||||||
about paragraphs, lines or line lengths. Nor will it adjust the
|
about paragraphs, lines or line lengths. Nor will it adjust the
|
||||||
space between words to fit them proportionally into a line. If you
|
space between words to fit them proportionally into a line. If you
|
||||||
want to layout text in paragraphs, you will probably want to send
|
want to layout text in paragraphs, you will probably want to send
|
||||||
each word of your text to Harfbuzz to determine its shaped width
|
each word of your text to HarfBuzz to determine its shaped width
|
||||||
after glyph substitutions, then work out how many words will fit
|
after glyph substitutions, then work out how many words will fit
|
||||||
on a line, and then finally output each word of the line separated
|
on a line, and then finally output each word of the line separated
|
||||||
by a space of the correct size to fully justify the paragraph.
|
by a space of the correct size to fully justify the paragraph.
|
||||||
@ -171,12 +171,12 @@ ABC אבג DEF
|
|||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
<para>
|
<para>
|
||||||
As a layout engine implementor, Harfbuzz will help you with the
|
As a layout engine implementor, HarfBuzz will help you with the
|
||||||
interface between your text and your font, and that's something
|
interface between your text and your font, and that's something
|
||||||
that you'll need - what you then do with the glyphs that your font
|
that you'll need - what you then do with the glyphs that your font
|
||||||
returns is up to you. The example we saw above enough to get us
|
returns is up to you. The example we saw above enough to get us
|
||||||
started using Harfbuzz. Now we are going to use the remainder of
|
started using HarfBuzz. Now we are going to use the remainder of
|
||||||
Harfbuzz's API to refine that example and improve our text shaping
|
HarfBuzz's API to refine that example and improve our text shaping
|
||||||
capabilities.
|
capabilities.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<chapter id="install-harfbuzz">
|
<chapter id="install-harfbuzz">
|
||||||
<title>Install Harfbuzz</title>
|
<title>Install HarfBuzz</title>
|
||||||
<section id="download">
|
<section id="download">
|
||||||
<title id="download.title">Download</title>
|
<title id="download.title">Download</title>
|
||||||
<para>
|
<para>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<para>
|
<para>
|
||||||
The canonical source tree is available
|
The canonical source tree is available
|
||||||
<ulink url="http://cgit.freedesktop.org/harfbuzz/">here</ulink>.
|
<ulink url="http://cgit.freedesktop.org/harfbuzz/">here</ulink>.
|
||||||
Also available on <ulink url="https://github.com/behdad/harfbuzz">github</ulink>.
|
Also available on <ulink url="https://github.com/harfbuzz/harfbuzz">github</ulink>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The API that comes with <filename class='headerfile'>hb.h</filename> will
|
The API that comes with <filename class='headerfile'>hb.h</filename> will
|
||||||
@ -50,7 +50,7 @@
|
|||||||
and hb-shape under <filename>util/</filename>.
|
and hb-shape under <filename>util/</filename>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If you are bootstraping from git, you need a few more tools before you
|
If you are bootstrapping from git, you need a few more tools before you
|
||||||
can run <filename>autogen.sh</filename> for the first time. Namely,
|
can run <filename>autogen.sh</filename> for the first time. Namely,
|
||||||
pkg-config and <ulink url="http://www.complang.org/ragel/">ragel</ulink>.
|
pkg-config and <ulink url="http://www.complang.org/ragel/">ragel</ulink>.
|
||||||
Again, on Ubuntu / Debian:
|
Again, on Ubuntu / Debian:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<chapter id="what-is-harfbuzz">
|
<chapter id="what-is-harfbuzz">
|
||||||
<title>What is Harfbuzz?</title>
|
<title>What is HarfBuzz?</title>
|
||||||
<para>
|
<para>
|
||||||
Harfbuzz is a <emphasis>text shaping engine</emphasis>. It solves
|
HarfBuzz is a <emphasis>text shaping engine</emphasis>. It solves
|
||||||
the problem of selecting and positioning glyphs from a font given a
|
the problem of selecting and positioning glyphs from a font given a
|
||||||
Unicode string.
|
Unicode string.
|
||||||
</para>
|
</para>
|
||||||
@ -9,17 +9,17 @@
|
|||||||
<title>Why do I need it?</title>
|
<title>Why do I need it?</title>
|
||||||
<para>
|
<para>
|
||||||
Text shaping is an integral part of preparing text for display. It
|
Text shaping is an integral part of preparing text for display. It
|
||||||
is a fairly low level operation; Harfbuzz is used directly by
|
is a fairly low level operation; HarfBuzz is used directly by
|
||||||
graphic rendering libraries such as Pango, and the layout engines
|
graphic rendering libraries such as Pango, and the layout engines
|
||||||
in Firefox, LibreOffice and Chromium. Unless you are
|
in Firefox, LibreOffice and Chromium. Unless you are
|
||||||
<emphasis>writing</emphasis> one of these layout engines yourself,
|
<emphasis>writing</emphasis> one of these layout engines yourself,
|
||||||
you will probably not need to use Harfbuzz - normally higher level
|
you will probably not need to use HarfBuzz - normally higher level
|
||||||
libraries will turn text into glyphs for you.
|
libraries will turn text into glyphs for you.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
However, if you <emphasis>are</emphasis> writing a layout engine
|
However, if you <emphasis>are</emphasis> writing a layout engine
|
||||||
or graphics library yourself, you will need to perform text
|
or graphics library yourself, you will need to perform text
|
||||||
shaping, and this is where Harfbuzz can help you. Here are some
|
shaping, and this is where HarfBuzz can help you. Here are some
|
||||||
reasons why you need it:
|
reasons why you need it:
|
||||||
</para>
|
</para>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
@ -95,20 +95,20 @@
|
|||||||
<para>
|
<para>
|
||||||
If this is something that you need to do, then you need a text
|
If this is something that you need to do, then you need a text
|
||||||
shaping engine: you could use Uniscribe if you are using Windows;
|
shaping engine: you could use Uniscribe if you are using Windows;
|
||||||
you could use CoreText on OS X; or you could use Harfbuzz. In the
|
you could use CoreText on OS X; or you could use HarfBuzz. In the
|
||||||
rest of this manual, we are going to assume that you are the
|
rest of this manual, we are going to assume that you are the
|
||||||
implementor of a text layout engine.
|
implementor of a text layout engine.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section id="why-is-it-called-harfbuzz">
|
<section id="why-is-it-called-harfbuzz">
|
||||||
<title>Why is it called Harfbuzz?</title>
|
<title>Why is it called HarfBuzz?</title>
|
||||||
<para>
|
<para>
|
||||||
Harfbuzz began its life as text shaping code within the FreeType
|
HarfBuzz began its life as text shaping code within the FreeType
|
||||||
project, (and you will see references to the FreeType authors
|
project, (and you will see references to the FreeType authors
|
||||||
within the source code copyright declarations) but was then
|
within the source code copyright declarations) but was then
|
||||||
abstracted out to its own project. This project is maintained by
|
abstracted out to its own project. This project is maintained by
|
||||||
Behdad Esfahbod, and named Harfbuzz. Originally, it was a shaping
|
Behdad Esfahbod, and named HarfBuzz. Originally, it was a shaping
|
||||||
engine for OpenType fonts - "Harfbuzz" is the Persian
|
engine for OpenType fonts - "HarfBuzz" is the Persian
|
||||||
for "open type".
|
for "open type".
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
57
git.mk
57
git.mk
@ -48,7 +48,7 @@ GIT_MK_URL = https://raw.githubusercontent.com/behdad/git.mk/master/git.mk
|
|||||||
#
|
#
|
||||||
# This file knows how to handle autoconf, automake, libtool, gtk-doc,
|
# This file knows how to handle autoconf, automake, libtool, gtk-doc,
|
||||||
# gnome-doc-utils, yelp.m4, mallard, intltool, gsettings, dejagnu, appdata,
|
# gnome-doc-utils, yelp.m4, mallard, intltool, gsettings, dejagnu, appdata,
|
||||||
# appstream.
|
# appstream, hotdoc.
|
||||||
#
|
#
|
||||||
# This makefile provides the following targets:
|
# This makefile provides the following targets:
|
||||||
#
|
#
|
||||||
@ -86,6 +86,7 @@ GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL = \
|
|||||||
ar-lib \
|
ar-lib \
|
||||||
compile \
|
compile \
|
||||||
config.guess \
|
config.guess \
|
||||||
|
config.rpath \
|
||||||
config.sub \
|
config.sub \
|
||||||
depcomp \
|
depcomp \
|
||||||
install-sh \
|
install-sh \
|
||||||
@ -120,6 +121,47 @@ GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL = \
|
|||||||
lt~obsolete.m4 \
|
lt~obsolete.m4 \
|
||||||
; do echo "$$MACRO_DIR/$$x"; done; \
|
; do echo "$$MACRO_DIR/$$x"; done; \
|
||||||
fi`
|
fi`
|
||||||
|
#
|
||||||
|
# Modules that use gettext and use AC_CONFIG_MACRO_DIR() may also include this,
|
||||||
|
# though it's harmless to include regardless.
|
||||||
|
GITIGNORE_MAINTAINERCLEANFILES_M4_GETTEXT = \
|
||||||
|
`MACRO_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_MACRO_DIR:$$1' ./configure.ac); \
|
||||||
|
if test "x$$MACRO_DIR" != "x$(srcdir)/"; then \
|
||||||
|
for x in \
|
||||||
|
codeset.m4 \
|
||||||
|
extern-inline.m4 \
|
||||||
|
fcntl-o.m4 \
|
||||||
|
gettext.m4 \
|
||||||
|
glibc2.m4 \
|
||||||
|
glibc21.m4 \
|
||||||
|
iconv.m4 \
|
||||||
|
intdiv0.m4 \
|
||||||
|
intl.m4 \
|
||||||
|
intldir.m4 \
|
||||||
|
intlmacosx.m4 \
|
||||||
|
intmax.m4 \
|
||||||
|
inttypes-pri.m4 \
|
||||||
|
inttypes_h.m4 \
|
||||||
|
lcmessage.m4 \
|
||||||
|
lib-ld.m4 \
|
||||||
|
lib-link.m4 \
|
||||||
|
lib-prefix.m4 \
|
||||||
|
lock.m4 \
|
||||||
|
longlong.m4 \
|
||||||
|
nls.m4 \
|
||||||
|
po.m4 \
|
||||||
|
printf-posix.m4 \
|
||||||
|
progtest.m4 \
|
||||||
|
size_max.m4 \
|
||||||
|
stdint_h.m4 \
|
||||||
|
threadlib.m4 \
|
||||||
|
uintmax_t.m4 \
|
||||||
|
visibility.m4 \
|
||||||
|
wchar_t.m4 \
|
||||||
|
wint_t.m4 \
|
||||||
|
xsize.m4 \
|
||||||
|
; do echo "$$MACRO_DIR/$$x"; done; \
|
||||||
|
fi`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -208,6 +250,15 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
|
|||||||
"*/*.omf.out" \
|
"*/*.omf.out" \
|
||||||
; do echo /$$x; done; \
|
; do echo /$$x; done; \
|
||||||
fi; \
|
fi; \
|
||||||
|
if test "x$(HOTDOC)" = x; then :; else \
|
||||||
|
$(foreach project, $(HOTDOC_PROJECTS),echo "/$(call HOTDOC_TARGET,$(project))"; \
|
||||||
|
echo "/$(shell $(call HOTDOC_PROJECT_COMMAND,$(project)) --get-conf-path output)" ; \
|
||||||
|
echo "/$(shell $(call HOTDOC_PROJECT_COMMAND,$(project)) --get-private-folder)" ; \
|
||||||
|
) \
|
||||||
|
for x in \
|
||||||
|
.hotdoc.d \
|
||||||
|
; do echo "/$$x"; done; \
|
||||||
|
fi; \
|
||||||
if test "x$(HELP_ID)" = x -o "x$(HELP_LINGUAS)" = x; then :; else \
|
if test "x$(HELP_ID)" = x -o "x$(HELP_LINGUAS)" = x; then :; else \
|
||||||
for lc in $(HELP_LINGUAS); do \
|
for lc in $(HELP_LINGUAS); do \
|
||||||
for x in \
|
for x in \
|
||||||
@ -235,6 +286,7 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
|
|||||||
fi; \
|
fi; \
|
||||||
if test -f $(srcdir)/po/Makefile.in.in; then \
|
if test -f $(srcdir)/po/Makefile.in.in; then \
|
||||||
for x in \
|
for x in \
|
||||||
|
ABOUT-NLS \
|
||||||
po/Makefile.in.in \
|
po/Makefile.in.in \
|
||||||
po/Makefile.in.in~ \
|
po/Makefile.in.in~ \
|
||||||
po/Makefile.in \
|
po/Makefile.in \
|
||||||
@ -243,6 +295,7 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
|
|||||||
po/POTFILES \
|
po/POTFILES \
|
||||||
po/Rules-quot \
|
po/Rules-quot \
|
||||||
po/stamp-it \
|
po/stamp-it \
|
||||||
|
po/stamp-po \
|
||||||
po/.intltool-merge-cache \
|
po/.intltool-merge-cache \
|
||||||
"po/*.gmo" \
|
"po/*.gmo" \
|
||||||
"po/*.header" \
|
"po/*.header" \
|
||||||
@ -274,7 +327,7 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
|
|||||||
if test "x$(am__dirstamp)" = x; then :; else \
|
if test "x$(am__dirstamp)" = x; then :; else \
|
||||||
echo "$(am__dirstamp)"; \
|
echo "$(am__dirstamp)"; \
|
||||||
fi; \
|
fi; \
|
||||||
if test "x$(LTCOMPILE)" = x -a "x$(LTCXXCOMPILE)" = x -a "x$(GTKDOC_RUN)" = x; then :; else \
|
if test "x$(findstring libtool,$(LTCOMPILE))" = x -a "x$(findstring libtool,$(LTCXXCOMPILE))" = x -a "x$(GTKDOC_RUN)" = x; then :; else \
|
||||||
for x in \
|
for x in \
|
||||||
"*.lo" \
|
"*.lo" \
|
||||||
".libs" "_libs" \
|
".libs" "_libs" \
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<!--download-page
|
<!--download-page
|
||||||
rdf:resource=""/-->
|
rdf:resource=""/-->
|
||||||
<bug-database
|
<bug-database
|
||||||
rdf:resource="http://bugs.freedesktop.org/enter_bug.cgi?product=harfbuzz"/>
|
rdf:resource="https://github.com/harfbuzz/harfbuzz/issues" />
|
||||||
|
|
||||||
<maintainer>
|
<maintainer>
|
||||||
<foaf:Person>
|
<foaf:Person>
|
||||||
|
982
m4/ax_cxx_compile_stdcxx.m4
Normal file
982
m4/ax_cxx_compile_stdcxx.m4
Normal file
@ -0,0 +1,982 @@
|
|||||||
|
# ===========================================================================
|
||||||
|
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
|
||||||
|
# ===========================================================================
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# Check for baseline language coverage in the compiler for the specified
|
||||||
|
# version of the C++ standard. If necessary, add switches to CXX and
|
||||||
|
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
|
||||||
|
# or '14' (for the C++14 standard).
|
||||||
|
#
|
||||||
|
# The second argument, if specified, indicates whether you insist on an
|
||||||
|
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
||||||
|
# -std=c++11). If neither is specified, you get whatever works, with
|
||||||
|
# preference for an extended mode.
|
||||||
|
#
|
||||||
|
# The third argument, if specified 'mandatory' or if left unspecified,
|
||||||
|
# indicates that baseline support for the specified C++ standard is
|
||||||
|
# required and that the macro should error out if no mode with that
|
||||||
|
# support is found. If specified 'optional', then configuration proceeds
|
||||||
|
# regardless, after defining HAVE_CXX${VERSION} if and only if a
|
||||||
|
# supporting mode is found.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||||
|
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
|
||||||
|
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
||||||
|
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
|
||||||
|
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
|
||||||
|
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||||
|
# Copyright (c) 2016 Krzesimir Nowak <qdlacz@gmail.com>
|
||||||
|
#
|
||||||
|
# Copying and distribution of this file, with or without modification, are
|
||||||
|
# permitted in any medium without royalty provided the copyright notice
|
||||||
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
|
# warranty.
|
||||||
|
|
||||||
|
#serial 7
|
||||||
|
|
||||||
|
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
||||||
|
dnl (serial version number 13).
|
||||||
|
|
||||||
|
AX_REQUIRE_DEFINED([AC_MSG_WARN])
|
||||||
|
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
||||||
|
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
|
||||||
|
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
|
||||||
|
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
|
||||||
|
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$2], [], [],
|
||||||
|
[$2], [ext], [],
|
||||||
|
[$2], [noext], [],
|
||||||
|
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
|
||||||
|
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
|
||||||
|
AC_LANG_PUSH([C++])dnl
|
||||||
|
ac_success=no
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
|
||||||
|
ax_cv_cxx_compile_cxx$1,
|
||||||
|
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[ax_cv_cxx_compile_cxx$1=yes],
|
||||||
|
[ax_cv_cxx_compile_cxx$1=no])])
|
||||||
|
if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
|
||||||
|
ac_success=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
m4_if([$2], [noext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
|
switch="-std=gnu++${alternative}"
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
|
||||||
|
m4_if([$2], [ext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
dnl HP's aCC needs +std=c++11 according to:
|
||||||
|
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
|
||||||
|
dnl Cray's crayCC needs "-h std=c++11"
|
||||||
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
|
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test x$ac_success = xyes; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
AC_LANG_POP([C++])
|
||||||
|
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
HAVE_CXX$1=0
|
||||||
|
AC_MSG_NOTICE([No compiler with C++$1 support was found])
|
||||||
|
else
|
||||||
|
HAVE_CXX$1=1
|
||||||
|
AC_DEFINE(HAVE_CXX$1,1,
|
||||||
|
[define if the compiler supports basic C++$1 syntax])
|
||||||
|
fi
|
||||||
|
AC_SUBST(HAVE_CXX$1)
|
||||||
|
m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])])
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++11 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++14 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
)
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
|
||||||
|
)
|
||||||
|
|
||||||
|
dnl Tests for new features in C++11
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++11, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201103L
|
||||||
|
|
||||||
|
#error "This is not a C++11 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx11
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_static_assert
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct check
|
||||||
|
{
|
||||||
|
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_final_override
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Base
|
||||||
|
{
|
||||||
|
virtual void f() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derived : public Base
|
||||||
|
{
|
||||||
|
virtual void f() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_double_right_angle_brackets
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct check {};
|
||||||
|
|
||||||
|
typedef check<void> single_type;
|
||||||
|
typedef check<check<void>> double_type;
|
||||||
|
typedef check<check<check<void>>> triple_type;
|
||||||
|
typedef check<check<check<check<void>>>> quadruple_type;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_decltype
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
f()
|
||||||
|
{
|
||||||
|
int a = 1;
|
||||||
|
decltype(a) b = 2;
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static const bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
auto
|
||||||
|
add(T1 a1, T2 a2) -> decltype(a1 + a2)
|
||||||
|
{
|
||||||
|
return a1 + a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test(const int c, volatile int v)
|
||||||
|
{
|
||||||
|
static_assert(is_same<int, decltype(0)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(c)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(v)>::value == false, "");
|
||||||
|
auto ac = c;
|
||||||
|
auto av = v;
|
||||||
|
auto sumi = ac + av + 'x';
|
||||||
|
auto sumf = ac + av + 1.0;
|
||||||
|
static_assert(is_same<int, decltype(ac)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(av)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumi)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumf)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
|
||||||
|
return (sumf > 0.0) ? sumi : add(c, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
int f() { return 0; }
|
||||||
|
int g() noexcept { return 0; }
|
||||||
|
|
||||||
|
static_assert(noexcept(f()) == false, "");
|
||||||
|
static_assert(noexcept(g()) == true, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
|
||||||
|
{
|
||||||
|
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
return strlen_c_r(s, 0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("1") == 1UL, "");
|
||||||
|
static_assert(strlen_c("example") == 7UL, "");
|
||||||
|
static_assert(strlen_c("another\0example") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_rvalue_references
|
||||||
|
{
|
||||||
|
|
||||||
|
template < int N >
|
||||||
|
struct answer
|
||||||
|
{
|
||||||
|
static constexpr int value = N;
|
||||||
|
};
|
||||||
|
|
||||||
|
answer<1> f(int&) { return answer<1>(); }
|
||||||
|
answer<2> f(const int&) { return answer<2>(); }
|
||||||
|
answer<3> f(int&&) { return answer<3>(); }
|
||||||
|
|
||||||
|
void
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
const int c = 0;
|
||||||
|
static_assert(decltype(f(i))::value == 1, "");
|
||||||
|
static_assert(decltype(f(c))::value == 2, "");
|
||||||
|
static_assert(decltype(f(0))::value == 3, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_uniform_initialization
|
||||||
|
{
|
||||||
|
|
||||||
|
struct test
|
||||||
|
{
|
||||||
|
static const int zero {};
|
||||||
|
static const int one {1};
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(test::zero == 0, "");
|
||||||
|
static_assert(test::one == 1, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
void
|
||||||
|
test1()
|
||||||
|
{
|
||||||
|
auto lambda1 = [](){};
|
||||||
|
auto lambda2 = lambda1;
|
||||||
|
lambda1();
|
||||||
|
lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test2()
|
||||||
|
{
|
||||||
|
auto a = [](int i, int j){ return i + j; }(1, 2);
|
||||||
|
auto b = []() -> int { return '0'; }();
|
||||||
|
auto c = [=](){ return a + b; }();
|
||||||
|
auto d = [&](){ return c; }();
|
||||||
|
auto e = [a, &b](int x) mutable {
|
||||||
|
const auto identity = [](int y){ return y; };
|
||||||
|
for (auto i = 0; i < a; ++i)
|
||||||
|
a += b--;
|
||||||
|
return x + identity(a + b);
|
||||||
|
}(0);
|
||||||
|
return a + b + c + d + e;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test3()
|
||||||
|
{
|
||||||
|
const auto nullary = [](){ return 0; };
|
||||||
|
const auto unary = [](int x){ return x; };
|
||||||
|
using nullary_t = decltype(nullary);
|
||||||
|
using unary_t = decltype(unary);
|
||||||
|
const auto higher1st = [](nullary_t f){ return f(); };
|
||||||
|
const auto higher2nd = [unary](nullary_t f1){
|
||||||
|
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
|
||||||
|
};
|
||||||
|
return higher1st(nullary) + higher2nd(nullary)(unary);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_variadic_templates
|
||||||
|
{
|
||||||
|
|
||||||
|
template <int...>
|
||||||
|
struct sum;
|
||||||
|
|
||||||
|
template <int N0, int... N1toN>
|
||||||
|
struct sum<N0, N1toN...>
|
||||||
|
{
|
||||||
|
static constexpr auto value = N0 + sum<N1toN...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct sum<>
|
||||||
|
{
|
||||||
|
static constexpr auto value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sum<>::value == 0, "");
|
||||||
|
static_assert(sum<1>::value == 1, "");
|
||||||
|
static_assert(sum<23>::value == 23, "");
|
||||||
|
static_assert(sum<1, 2>::value == 3, "");
|
||||||
|
static_assert(sum<5, 5, 11>::value == 21, "");
|
||||||
|
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
|
||||||
|
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
|
||||||
|
// because of this.
|
||||||
|
namespace test_template_alias_sfinae
|
||||||
|
{
|
||||||
|
|
||||||
|
struct foo {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using member = typename T::member_type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(...) {}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(member<T>*) {}
|
||||||
|
|
||||||
|
void test();
|
||||||
|
|
||||||
|
void test() { func<foo>(0); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx11
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201103L
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++14
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++14, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201402L
|
||||||
|
|
||||||
|
#error "This is not a C++14 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx14
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_polymorphic_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
const auto lambda = [](auto&&... args){
|
||||||
|
const auto istiny = [](auto x){
|
||||||
|
return (sizeof(x) == 1UL) ? 1 : 0;
|
||||||
|
};
|
||||||
|
const int aretiny[] = { istiny(args)... };
|
||||||
|
return aretiny[0];
|
||||||
|
};
|
||||||
|
return lambda(1, 1L, 1.0f, '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_binary_literals
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ivii = 0b0000000000101010;
|
||||||
|
static_assert(ivii == 42, "wrong value");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_generalized_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
constexpr unsigned long
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
auto length = 0UL;
|
||||||
|
for (auto p = s; *p; ++p)
|
||||||
|
++length;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("x") == 1UL, "");
|
||||||
|
static_assert(strlen_c("test") == 4UL, "");
|
||||||
|
static_assert(strlen_c("another\0test") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambda_init_capture
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
const auto lambda1 = [a = x](int b){ return a + b; };
|
||||||
|
const auto lambda2 = [a = lambda1(x)](){ return a; };
|
||||||
|
return lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_digit_separators
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ten_million = 100'000'000;
|
||||||
|
static_assert(ten_million == 100000000, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_return_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
auto f(int& x) { return x; }
|
||||||
|
decltype(auto) g(int& x) { return x; }
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static constexpr auto value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static constexpr auto value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
static_assert(is_same<int, decltype(f(x))>::value, "");
|
||||||
|
static_assert(is_same<int&, decltype(g(x))>::value, "");
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx14
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201402L
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++17
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++17, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus <= 201402L
|
||||||
|
|
||||||
|
#error "This is not a C++17 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define REALLY_CLANG
|
||||||
|
#else
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define REALLY_GCC
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <utility>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace cxx17
|
||||||
|
{
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_constexpr_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
constexpr int foo = [](){return 42;}();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
namespace test::nested_namespace::definitions
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_fold_expression
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
int multiply(Args... args)
|
||||||
|
{
|
||||||
|
return (args * ... * 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
bool all(Args... args)
|
||||||
|
{
|
||||||
|
return (args && ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_extended_static_assert
|
||||||
|
{
|
||||||
|
|
||||||
|
static_assert (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_auto_brace_init_list
|
||||||
|
{
|
||||||
|
|
||||||
|
auto foo = {5};
|
||||||
|
auto bar {5};
|
||||||
|
|
||||||
|
static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
|
||||||
|
static_assert(std::is_same<int, decltype(bar)>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_typename_in_template_template_parameter
|
||||||
|
{
|
||||||
|
|
||||||
|
template<template<typename> typename X> struct D;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_fallthrough_nodiscard_maybe_unused_attributes
|
||||||
|
{
|
||||||
|
|
||||||
|
int f1()
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int f2()
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto unused = f1();
|
||||||
|
|
||||||
|
switch (f1())
|
||||||
|
{
|
||||||
|
case 17:
|
||||||
|
f1();
|
||||||
|
[[fallthrough]];
|
||||||
|
case 42:
|
||||||
|
f1();
|
||||||
|
}
|
||||||
|
return f1();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_extended_aggregate_initialization
|
||||||
|
{
|
||||||
|
|
||||||
|
struct base1
|
||||||
|
{
|
||||||
|
int b1, b2 = 42;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct base2
|
||||||
|
{
|
||||||
|
base2() {
|
||||||
|
b3 = 42;
|
||||||
|
}
|
||||||
|
int b3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct derived : base1, base2
|
||||||
|
{
|
||||||
|
int d;
|
||||||
|
};
|
||||||
|
|
||||||
|
derived d1 {{1, 2}, {}, 4}; // full initialization
|
||||||
|
derived d2 {{}, {}, 4}; // value-initialized bases
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_general_range_based_for_loop
|
||||||
|
{
|
||||||
|
|
||||||
|
struct iter
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
int& operator* ()
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int& operator* () const
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter& operator++()
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sentinel
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator== (const iter& i, const sentinel& s)
|
||||||
|
{
|
||||||
|
return i.i == s.i;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!= (const iter& i, const sentinel& s)
|
||||||
|
{
|
||||||
|
return !(i == s);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct range
|
||||||
|
{
|
||||||
|
iter begin() const
|
||||||
|
{
|
||||||
|
return {0};
|
||||||
|
}
|
||||||
|
|
||||||
|
sentinel end() const
|
||||||
|
{
|
||||||
|
return {5};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
range r {};
|
||||||
|
|
||||||
|
for (auto i : r)
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto v = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambda_capture_asterisk_this_by_value
|
||||||
|
{
|
||||||
|
|
||||||
|
struct t
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int foo()
|
||||||
|
{
|
||||||
|
return [*this]()
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_enum_class_construction
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class byte : unsigned char
|
||||||
|
{};
|
||||||
|
|
||||||
|
byte foo {42};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_constexpr_if
|
||||||
|
{
|
||||||
|
|
||||||
|
template <bool cond>
|
||||||
|
int f ()
|
||||||
|
{
|
||||||
|
if constexpr(cond)
|
||||||
|
{
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_selection_statement_with_initializer
|
||||||
|
{
|
||||||
|
|
||||||
|
int f()
|
||||||
|
{
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
int f2()
|
||||||
|
{
|
||||||
|
if (auto i = f(); i > 0)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (auto i = f(); i + 4)
|
||||||
|
{
|
||||||
|
case 17:
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_template_argument_deduction_for_class_templates
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
struct pair
|
||||||
|
{
|
||||||
|
pair (T1 p1, T2 p2)
|
||||||
|
: m1 {p1},
|
||||||
|
m2 {p2}
|
||||||
|
{}
|
||||||
|
|
||||||
|
T1 m1;
|
||||||
|
T2 m2;
|
||||||
|
};
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto p = pair{13, 42u};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
namespace test_non_type_auto_template_parameters
|
||||||
|
{
|
||||||
|
|
||||||
|
template <auto n>
|
||||||
|
struct B
|
||||||
|
{};
|
||||||
|
|
||||||
|
B<5> b1;
|
||||||
|
B<'a'> b2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_structured_bindings
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
int arr[2] = { 1, 2 };
|
||||||
|
std::pair<int, int> pr = { 1, 2 };
|
||||||
|
|
||||||
|
auto f1() -> int(&)[2]
|
||||||
|
{
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto f2() -> std::pair<int, int>&
|
||||||
|
{
|
||||||
|
return pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
int x1 : 2;
|
||||||
|
volatile double y1;
|
||||||
|
};
|
||||||
|
|
||||||
|
S f3()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [ x1, y1 ] = f1();
|
||||||
|
auto& [ xr1, yr1 ] = f1();
|
||||||
|
auto [ x2, y2 ] = f2();
|
||||||
|
auto& [ xr2, yr2 ] = f2();
|
||||||
|
const auto [ x3, y3 ] = f3();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_exception_spec_type_system
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
struct Good {};
|
||||||
|
struct Bad {};
|
||||||
|
|
||||||
|
void g1() noexcept;
|
||||||
|
void g2();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Bad
|
||||||
|
f(T*, T*);
|
||||||
|
|
||||||
|
template<typename T1, typename T2>
|
||||||
|
Good
|
||||||
|
f(T1*, T2*);
|
||||||
|
|
||||||
|
static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
namespace test_inline_variables
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> void f(T)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<class T> inline T g(T)
|
||||||
|
{
|
||||||
|
return T{};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> inline void f<>(int)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<> int g<>(int)
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx17
|
||||||
|
|
||||||
|
#endif // __cplusplus <= 201402L
|
||||||
|
|
||||||
|
]])
|
402
m4/ax_pthread.m4
402
m4/ax_pthread.m4
@ -1,5 +1,5 @@
|
|||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
@ -19,10 +19,10 @@
|
|||||||
# is necessary on AIX to use the special cc_r compiler alias.)
|
# is necessary on AIX to use the special cc_r compiler alias.)
|
||||||
#
|
#
|
||||||
# NOTE: You are assumed to not only compile your program with these flags,
|
# NOTE: You are assumed to not only compile your program with these flags,
|
||||||
# but also link it with them as well. e.g. you should link with
|
# but also to link with them as well. For example, you might link with
|
||||||
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
||||||
#
|
#
|
||||||
# If you are only building threads programs, you may wish to use these
|
# If you are only building threaded programs, you may wish to use these
|
||||||
# variables in your default LIBS, CFLAGS, and CC:
|
# variables in your default LIBS, CFLAGS, and CC:
|
||||||
#
|
#
|
||||||
# LIBS="$PTHREAD_LIBS $LIBS"
|
# LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
@ -30,8 +30,8 @@
|
|||||||
# CC="$PTHREAD_CC"
|
# CC="$PTHREAD_CC"
|
||||||
#
|
#
|
||||||
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
||||||
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
|
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
|
||||||
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||||
#
|
#
|
||||||
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
||||||
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
||||||
@ -67,7 +67,7 @@
|
|||||||
# Public License for more details.
|
# Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License along
|
# You should have received a copy of the GNU General Public License along
|
||||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
# gives unlimited permission to copy, distribute and modify the configure
|
||||||
@ -82,35 +82,40 @@
|
|||||||
# modified version of the Autoconf Macro, you may extend this special
|
# modified version of the Autoconf Macro, you may extend this special
|
||||||
# exception to the GPL to apply to your modified version as well.
|
# exception to the GPL to apply to your modified version as well.
|
||||||
|
|
||||||
#serial 18
|
#serial 24
|
||||||
|
|
||||||
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
||||||
AC_DEFUN([AX_PTHREAD], [
|
AC_DEFUN([AX_PTHREAD], [
|
||||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||||
|
AC_REQUIRE([AC_PROG_CC])
|
||||||
|
AC_REQUIRE([AC_PROG_SED])
|
||||||
AC_LANG_PUSH([C])
|
AC_LANG_PUSH([C])
|
||||||
ax_pthread_ok=no
|
ax_pthread_ok=no
|
||||||
|
|
||||||
# We used to check for pthread.h first, but this fails if pthread.h
|
# We used to check for pthread.h first, but this fails if pthread.h
|
||||||
# requires special compiler flags (e.g. on True64 or Sequent).
|
# requires special compiler flags (e.g. on Tru64 or Sequent).
|
||||||
# It gets checked for in the link test anyway.
|
# It gets checked for in the link test anyway.
|
||||||
|
|
||||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||||
# etcetera environment variables, and if threads linking works using
|
# etcetera environment variables, and if threads linking works using
|
||||||
# them:
|
# them:
|
||||||
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
|
||||||
save_CFLAGS="$CFLAGS"
|
ax_pthread_save_CC="$CC"
|
||||||
|
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||||
|
ax_pthread_save_LIBS="$LIBS"
|
||||||
|
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
save_LIBS="$LIBS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
|
||||||
AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
|
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
|
||||||
AC_MSG_RESULT($ax_pthread_ok)
|
AC_MSG_RESULT([$ax_pthread_ok])
|
||||||
if test x"$ax_pthread_ok" = xno; then
|
if test "x$ax_pthread_ok" = "xno"; then
|
||||||
PTHREAD_LIBS=""
|
PTHREAD_LIBS=""
|
||||||
PTHREAD_CFLAGS=""
|
PTHREAD_CFLAGS=""
|
||||||
fi
|
fi
|
||||||
LIBS="$save_LIBS"
|
CC="$ax_pthread_save_CC"
|
||||||
CFLAGS="$save_CFLAGS"
|
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||||
|
LIBS="$ax_pthread_save_LIBS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# We must check for the threads library under a number of different
|
# We must check for the threads library under a number of different
|
||||||
@ -123,7 +128,7 @@ fi
|
|||||||
# which indicates that we try without any flags at all, and "pthread-config"
|
# which indicates that we try without any flags at all, and "pthread-config"
|
||||||
# which is a program returning the flags for the Pth emulation library.
|
# which is a program returning the flags for the Pth emulation library.
|
||||||
|
|
||||||
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||||
|
|
||||||
# The ordering *is* (sometimes) important. Some notes on the
|
# The ordering *is* (sometimes) important. Some notes on the
|
||||||
# individual items follow:
|
# individual items follow:
|
||||||
@ -132,68 +137,225 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt
|
|||||||
# none: in case threads are in libc; should be tried before -Kthread and
|
# none: in case threads are in libc; should be tried before -Kthread and
|
||||||
# other compiler flags to prevent continual compiler warnings
|
# other compiler flags to prevent continual compiler warnings
|
||||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
|
||||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
# (Note: HP C rejects this with "bad form for `-t' option")
|
||||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
# -pthreads: Solaris/gcc (Note: HP C also rejects)
|
||||||
# -pthreads: Solaris/gcc
|
|
||||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
|
||||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||||
# doesn't hurt to check since this sometimes defines pthreads too;
|
# doesn't hurt to check since this sometimes defines pthreads and
|
||||||
# also defines -D_REENTRANT)
|
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
|
||||||
# ... -mt is also the pthreads flag for HP/aCC
|
# is present but should not be used directly; and before -mthreads,
|
||||||
|
# because the compiler interprets this as "-mt" + "-hreads")
|
||||||
|
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||||
# pthread: Linux, etcetera
|
# pthread: Linux, etcetera
|
||||||
# --thread-safe: KAI C++
|
# --thread-safe: KAI C++
|
||||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||||
|
|
||||||
case ${host_os} in
|
case $host_os in
|
||||||
|
|
||||||
|
freebsd*)
|
||||||
|
|
||||||
|
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||||
|
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||||
|
|
||||||
|
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
|
||||||
|
;;
|
||||||
|
|
||||||
|
hpux*)
|
||||||
|
|
||||||
|
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
|
||||||
|
# multi-threading and also sets -lpthread."
|
||||||
|
|
||||||
|
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
|
||||||
|
;;
|
||||||
|
|
||||||
|
openedition*)
|
||||||
|
|
||||||
|
# IBM z/OS requires a feature-test macro to be defined in order to
|
||||||
|
# enable POSIX threads at all, so give the user a hint if this is
|
||||||
|
# not set. (We don't define these ourselves, as they can affect
|
||||||
|
# other portions of the system API in unpredictable ways.)
|
||||||
|
|
||||||
|
AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
|
||||||
|
[
|
||||||
|
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
|
||||||
|
AX_PTHREAD_ZOS_MISSING
|
||||||
|
# endif
|
||||||
|
],
|
||||||
|
[AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
|
||||||
|
;;
|
||||||
|
|
||||||
solaris*)
|
solaris*)
|
||||||
|
|
||||||
# On Solaris (at least, for some versions), libc contains stubbed
|
# On Solaris (at least, for some versions), libc contains stubbed
|
||||||
# (non-functional) versions of the pthreads routines, so link-based
|
# (non-functional) versions of the pthreads routines, so link-based
|
||||||
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
# tests will erroneously succeed. (N.B.: The stubs are missing
|
||||||
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
# pthread_cleanup_push, or rather a function called by this macro,
|
||||||
# a function called by this macro, so we could check for that, but
|
# so we could check for that, but who knows whether they'll stub
|
||||||
# who knows whether they'll stub that too in a future libc.) So,
|
# that too in a future libc.) So we'll check first for the
|
||||||
# we'll just look for -pthreads and -lpthread first:
|
# standard Solaris way of linking pthreads (-mt -lpthread).
|
||||||
|
|
||||||
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
|
ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
|
||||||
;;
|
|
||||||
|
|
||||||
darwin*)
|
|
||||||
ax_pthread_flags="-pthread $ax_pthread_flags"
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if test x"$ax_pthread_ok" = xno; then
|
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
|
||||||
for flag in $ax_pthread_flags; do
|
|
||||||
|
|
||||||
case $flag in
|
AS_IF([test "x$GCC" = "xyes"],
|
||||||
|
[ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"])
|
||||||
|
|
||||||
|
# The presence of a feature test macro requesting re-entrant function
|
||||||
|
# definitions is, on some systems, a strong hint that pthreads support is
|
||||||
|
# correctly enabled
|
||||||
|
|
||||||
|
case $host_os in
|
||||||
|
darwin* | hpux* | linux* | osf* | solaris*)
|
||||||
|
ax_pthread_check_macro="_REENTRANT"
|
||||||
|
;;
|
||||||
|
|
||||||
|
aix*)
|
||||||
|
ax_pthread_check_macro="_THREAD_SAFE"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
ax_pthread_check_macro="--"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
AS_IF([test "x$ax_pthread_check_macro" = "x--"],
|
||||||
|
[ax_pthread_check_cond=0],
|
||||||
|
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
|
||||||
|
|
||||||
|
# Are we compiling with Clang?
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([whether $CC is Clang],
|
||||||
|
[ax_cv_PTHREAD_CLANG],
|
||||||
|
[ax_cv_PTHREAD_CLANG=no
|
||||||
|
# Note that Autoconf sets GCC=yes for Clang as well as GCC
|
||||||
|
if test "x$GCC" = "xyes"; then
|
||||||
|
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
|
||||||
|
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
|
||||||
|
# if defined(__clang__) && defined(__llvm__)
|
||||||
|
AX_PTHREAD_CC_IS_CLANG
|
||||||
|
# endif
|
||||||
|
],
|
||||||
|
[ax_cv_PTHREAD_CLANG=yes])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
|
||||||
|
|
||||||
|
ax_pthread_clang_warning=no
|
||||||
|
|
||||||
|
# Clang needs special handling, because older versions handle the -pthread
|
||||||
|
# option in a rather... idiosyncratic way
|
||||||
|
|
||||||
|
if test "x$ax_pthread_clang" = "xyes"; then
|
||||||
|
|
||||||
|
# Clang takes -pthread; it has never supported any other flag
|
||||||
|
|
||||||
|
# (Note 1: This will need to be revisited if a system that Clang
|
||||||
|
# supports has POSIX threads in a separate library. This tends not
|
||||||
|
# to be the way of modern systems, but it's conceivable.)
|
||||||
|
|
||||||
|
# (Note 2: On some systems, notably Darwin, -pthread is not needed
|
||||||
|
# to get POSIX threads support; the API is always present and
|
||||||
|
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
|
||||||
|
# -pthread does define _REENTRANT, and while the Darwin headers
|
||||||
|
# ignore this macro, third-party headers might not.)
|
||||||
|
|
||||||
|
PTHREAD_CFLAGS="-pthread"
|
||||||
|
PTHREAD_LIBS=
|
||||||
|
|
||||||
|
ax_pthread_ok=yes
|
||||||
|
|
||||||
|
# However, older versions of Clang make a point of warning the user
|
||||||
|
# that, in an invocation where only linking and no compilation is
|
||||||
|
# taking place, the -pthread option has no effect ("argument unused
|
||||||
|
# during compilation"). They expect -pthread to be passed in only
|
||||||
|
# when source code is being compiled.
|
||||||
|
#
|
||||||
|
# Problem is, this is at odds with the way Automake and most other
|
||||||
|
# C build frameworks function, which is that the same flags used in
|
||||||
|
# compilation (CFLAGS) are also used in linking. Many systems
|
||||||
|
# supported by AX_PTHREAD require exactly this for POSIX threads
|
||||||
|
# support, and in fact it is often not straightforward to specify a
|
||||||
|
# flag that is used only in the compilation phase and not in
|
||||||
|
# linking. Such a scenario is extremely rare in practice.
|
||||||
|
#
|
||||||
|
# Even though use of the -pthread flag in linking would only print
|
||||||
|
# a warning, this can be a nuisance for well-run software projects
|
||||||
|
# that build with -Werror. So if the active version of Clang has
|
||||||
|
# this misfeature, we search for an option to squash it.
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
|
||||||
|
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
|
||||||
|
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
|
||||||
|
# Create an alternate version of $ac_link that compiles and
|
||||||
|
# links in two steps (.c -> .o, .o -> exe) instead of one
|
||||||
|
# (.c -> exe), because the warning occurs only in the second
|
||||||
|
# step
|
||||||
|
ax_pthread_save_ac_link="$ac_link"
|
||||||
|
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
|
||||||
|
ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
|
||||||
|
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
|
||||||
|
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||||
|
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
|
||||||
|
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
|
||||||
|
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
|
||||||
|
ac_link="$ax_pthread_save_ac_link"
|
||||||
|
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
||||||
|
[ac_link="$ax_pthread_2step_ac_link"
|
||||||
|
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
||||||
|
[break])
|
||||||
|
])
|
||||||
|
done
|
||||||
|
ac_link="$ax_pthread_save_ac_link"
|
||||||
|
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||||
|
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
|
||||||
|
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
|
||||||
|
])
|
||||||
|
|
||||||
|
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
|
||||||
|
no | unknown) ;;
|
||||||
|
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
fi # $ax_pthread_clang = yes
|
||||||
|
|
||||||
|
if test "x$ax_pthread_ok" = "xno"; then
|
||||||
|
for ax_pthread_try_flag in $ax_pthread_flags; do
|
||||||
|
|
||||||
|
case $ax_pthread_try_flag in
|
||||||
none)
|
none)
|
||||||
AC_MSG_CHECKING([whether pthreads work without any flags])
|
AC_MSG_CHECKING([whether pthreads work without any flags])
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
-mt,pthread)
|
||||||
|
AC_MSG_CHECKING([whether pthreads work with -mt -lpthread])
|
||||||
|
PTHREAD_CFLAGS="-mt"
|
||||||
|
PTHREAD_LIBS="-lpthread"
|
||||||
|
;;
|
||||||
|
|
||||||
-*)
|
-*)
|
||||||
AC_MSG_CHECKING([whether pthreads work with $flag])
|
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
|
||||||
PTHREAD_CFLAGS="$flag"
|
PTHREAD_CFLAGS="$ax_pthread_try_flag"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
pthread-config)
|
pthread-config)
|
||||||
AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
|
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
|
||||||
if test x"$ax_pthread_config" = xno; then continue; fi
|
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
|
||||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
|
||||||
PTHREAD_LIBS="-l$flag"
|
PTHREAD_LIBS="-l$ax_pthread_try_flag"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
save_LIBS="$LIBS"
|
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||||
save_CFLAGS="$CFLAGS"
|
ax_pthread_save_LIBS="$LIBS"
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
|
||||||
# Check for various functions. We must include pthread.h,
|
# Check for various functions. We must include pthread.h,
|
||||||
# since some functions may be macros. (On the Sequent, we
|
# since some functions may be macros. (On the Sequent, we
|
||||||
@ -204,7 +366,11 @@ for flag in $ax_pthread_flags; do
|
|||||||
# pthread_cleanup_push because it is one of the few pthread
|
# pthread_cleanup_push because it is one of the few pthread
|
||||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||||
# We try pthread_create on general principles.
|
# We try pthread_create on general principles.
|
||||||
|
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
|
||||||
|
# if $ax_pthread_check_cond
|
||||||
|
# error "$ax_pthread_check_macro must be defined"
|
||||||
|
# endif
|
||||||
static void routine(void *a) { a = 0; }
|
static void routine(void *a) { a = 0; }
|
||||||
static void *start_routine(void *a) { return a; }],
|
static void *start_routine(void *a) { return a; }],
|
||||||
[pthread_t th; pthread_attr_t attr;
|
[pthread_t th; pthread_attr_t attr;
|
||||||
@ -213,16 +379,14 @@ for flag in $ax_pthread_flags; do
|
|||||||
pthread_attr_init(&attr);
|
pthread_attr_init(&attr);
|
||||||
pthread_cleanup_push(routine, 0);
|
pthread_cleanup_push(routine, 0);
|
||||||
pthread_cleanup_pop(0) /* ; */])],
|
pthread_cleanup_pop(0) /* ; */])],
|
||||||
[ax_pthread_ok=yes],
|
[ax_pthread_ok=yes],
|
||||||
[])
|
[])
|
||||||
|
|
||||||
LIBS="$save_LIBS"
|
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||||
CFLAGS="$save_CFLAGS"
|
LIBS="$ax_pthread_save_LIBS"
|
||||||
|
|
||||||
AC_MSG_RESULT($ax_pthread_ok)
|
AC_MSG_RESULT([$ax_pthread_ok])
|
||||||
if test "x$ax_pthread_ok" = xyes; then
|
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
|
||||||
break;
|
|
||||||
fi
|
|
||||||
|
|
||||||
PTHREAD_LIBS=""
|
PTHREAD_LIBS=""
|
||||||
PTHREAD_CFLAGS=""
|
PTHREAD_CFLAGS=""
|
||||||
@ -230,76 +394,88 @@ done
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Various other checks:
|
# Various other checks:
|
||||||
if test "x$ax_pthread_ok" = xyes; then
|
if test "x$ax_pthread_ok" = "xyes"; then
|
||||||
save_LIBS="$LIBS"
|
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
ax_pthread_save_LIBS="$LIBS"
|
||||||
save_CFLAGS="$CFLAGS"
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
|
||||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||||
AC_MSG_CHECKING([for joinable pthread attribute])
|
AC_CACHE_CHECK([for joinable pthread attribute],
|
||||||
attr_name=unknown
|
[ax_cv_PTHREAD_JOINABLE_ATTR],
|
||||||
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||||
[int attr = $attr; return attr /* ; */])],
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||||
[attr_name=$attr; break],
|
[int attr = $ax_pthread_attr; return attr /* ; */])],
|
||||||
[])
|
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
|
||||||
done
|
[])
|
||||||
AC_MSG_RESULT($attr_name)
|
done
|
||||||
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
])
|
||||||
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
|
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
|
||||||
[Define to necessary symbol if this constant
|
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
|
||||||
uses a non-standard name on your system.])
|
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
|
||||||
fi
|
[AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
|
||||||
|
[$ax_cv_PTHREAD_JOINABLE_ATTR],
|
||||||
|
[Define to necessary symbol if this constant
|
||||||
|
uses a non-standard name on your system.])
|
||||||
|
ax_pthread_joinable_attr_defined=yes
|
||||||
|
])
|
||||||
|
|
||||||
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
AC_CACHE_CHECK([whether more special flags are required for pthreads],
|
||||||
flag=no
|
[ax_cv_PTHREAD_SPECIAL_FLAGS],
|
||||||
case ${host_os} in
|
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
|
||||||
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
|
case $host_os in
|
||||||
osf* | hpux*) flag="-D_REENTRANT";;
|
solaris*)
|
||||||
solaris*)
|
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
|
||||||
if test "$GCC" = "yes"; then
|
;;
|
||||||
flag="-D_REENTRANT"
|
esac
|
||||||
else
|
])
|
||||||
flag="-mt -D_REENTRANT"
|
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
|
||||||
fi
|
test "x$ax_pthread_special_flags_added" != "xyes"],
|
||||||
;;
|
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
|
||||||
esac
|
ax_pthread_special_flags_added=yes])
|
||||||
AC_MSG_RESULT(${flag})
|
|
||||||
if test "x$flag" != xno; then
|
|
||||||
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
||||||
ax_cv_PTHREAD_PRIO_INHERIT, [
|
[ax_cv_PTHREAD_PRIO_INHERIT],
|
||||||
AC_LINK_IFELSE([
|
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
||||||
AC_LANG_PROGRAM([[#include <pthread.h>]], [[int i = PTHREAD_PRIO_INHERIT;]])],
|
[[int i = PTHREAD_PRIO_INHERIT;]])],
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||||
])
|
])
|
||||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
|
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
|
||||||
AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
|
test "x$ax_pthread_prio_inherit_defined" != "xyes"],
|
||||||
|
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
|
||||||
|
ax_pthread_prio_inherit_defined=yes
|
||||||
|
])
|
||||||
|
|
||||||
LIBS="$save_LIBS"
|
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||||
CFLAGS="$save_CFLAGS"
|
LIBS="$ax_pthread_save_LIBS"
|
||||||
|
|
||||||
# More AIX lossage: must compile with xlc_r or cc_r
|
# More AIX lossage: compile with *_r variant
|
||||||
if test x"$GCC" != xyes; then
|
if test "x$GCC" != "xyes"; then
|
||||||
AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
|
case $host_os in
|
||||||
else
|
aix*)
|
||||||
PTHREAD_CC=$CC
|
AS_CASE(["x/$CC"],
|
||||||
|
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
|
||||||
|
[#handle absolute path differently from PATH based program lookup
|
||||||
|
AS_CASE(["x$CC"],
|
||||||
|
[x/*],
|
||||||
|
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
|
||||||
|
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
PTHREAD_CC="$CC"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_SUBST(PTHREAD_LIBS)
|
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
||||||
AC_SUBST(PTHREAD_CFLAGS)
|
|
||||||
AC_SUBST(PTHREAD_CC)
|
AC_SUBST([PTHREAD_LIBS])
|
||||||
|
AC_SUBST([PTHREAD_CFLAGS])
|
||||||
|
AC_SUBST([PTHREAD_CC])
|
||||||
|
|
||||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||||
if test x"$ax_pthread_ok" = xyes; then
|
if test "x$ax_pthread_ok" = "xyes"; then
|
||||||
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
|
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
ax_pthread_ok=no
|
ax_pthread_ok=no
|
||||||
|
22
mingw32.sh
Executable file
22
mingw32.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
target=i686-w64-mingw32
|
||||||
|
|
||||||
|
unset CC
|
||||||
|
unset CXX
|
||||||
|
unset CPP
|
||||||
|
unset LD
|
||||||
|
unset LDFLAGS
|
||||||
|
unset CFLAGS
|
||||||
|
unset CXXFLAGS
|
||||||
|
unset PKG_CONFIG_PATH
|
||||||
|
|
||||||
|
# Removed -static from the following
|
||||||
|
export CFLAGS="-static-libgcc"
|
||||||
|
export CXXFLAGS="-static-libgcc -static-libstdc++"
|
||||||
|
export CPPFLAGS="-I$HOME/.local/$target/include -O2"
|
||||||
|
export LDFLAGS=-L$HOME/.local/$target/lib
|
||||||
|
export PKG_CONFIG_LIBDIR=$HOME/.local/$target/lib/pkgconfig
|
||||||
|
export PATH=$HOME/.local/$target/bin:$PATH
|
||||||
|
|
||||||
|
../configure --build=`../config.guess` --host=$target --prefix=$HOME/.local/$target "$@"
|
22
mingw64.sh
Executable file
22
mingw64.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
target=x86_64-w64-mingw32
|
||||||
|
|
||||||
|
unset CC
|
||||||
|
unset CXX
|
||||||
|
unset CPP
|
||||||
|
unset LD
|
||||||
|
unset LDFLAGS
|
||||||
|
unset CFLAGS
|
||||||
|
unset CXXFLAGS
|
||||||
|
unset PKG_CONFIG_PATH
|
||||||
|
|
||||||
|
# Removed -static from the following
|
||||||
|
export CFLAGS="-static-libgcc"
|
||||||
|
export CXXFLAGS="-static-libgcc -static-libstdc++"
|
||||||
|
export CPPFLAGS="-I$HOME/.local/$target/include -O2"
|
||||||
|
export LDFLAGS=-L$HOME/.local/$target/lib
|
||||||
|
export PKG_CONFIG_LIBDIR=$HOME/.local/$target/lib/pkgconfig
|
||||||
|
export PATH=$HOME/.local/$target/bin:$PATH
|
||||||
|
|
||||||
|
../configure --build=`../config.guess` --host=$target --prefix=$HOME/.local/$target "$@"
|
21
replace-enum-strings.cmake
Normal file
21
replace-enum-strings.cmake
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# CMake script to replace items
|
||||||
|
# in sources generated by glib-mkenums
|
||||||
|
|
||||||
|
FILE(READ ${ENUM_INPUT_SRC} enum_in)
|
||||||
|
|
||||||
|
STRING(REPLACE
|
||||||
|
"_t_get_type"
|
||||||
|
"_get_type"
|
||||||
|
enum_out_tmp
|
||||||
|
"${enum_in}"
|
||||||
|
)
|
||||||
|
|
||||||
|
STRING(REPLACE
|
||||||
|
"_T ("
|
||||||
|
" ("
|
||||||
|
enum_out
|
||||||
|
"${enum_out_tmp}"
|
||||||
|
)
|
||||||
|
|
||||||
|
FILE(WRITE ${ENUM_OUTPUT_SRC} "${enum_out}")
|
||||||
|
FILE(REMOVE ${ENUM_INPUT_SRC})
|
185
src/Makefile.am
185
src/Makefile.am
@ -1,5 +1,6 @@
|
|||||||
# Process this file with automake to produce Makefile.in
|
# Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
NULL =
|
||||||
SUBDIRS =
|
SUBDIRS =
|
||||||
DIST_SUBDIRS =
|
DIST_SUBDIRS =
|
||||||
BUILT_SOURCES =
|
BUILT_SOURCES =
|
||||||
@ -8,12 +9,14 @@ CLEANFILES =
|
|||||||
DISTCLEANFILES =
|
DISTCLEANFILES =
|
||||||
MAINTAINERCLEANFILES =
|
MAINTAINERCLEANFILES =
|
||||||
DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
|
DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
|
||||||
|
TESTS =
|
||||||
|
check_PROGRAMS =
|
||||||
|
|
||||||
# The following warning options are useful for debugging: -Wpadded
|
# The following warning options are useful for debugging: -Wpadded
|
||||||
#AM_CXXFLAGS =
|
#AM_CXXFLAGS =
|
||||||
|
|
||||||
# Convenience targets:
|
# Convenience targets:
|
||||||
lib: $(BUILT_SOURCES) libharfbuzz.la
|
lib: $(BUILT_SOURCES) libharfbuzz.la libharfbuzz-subset.la
|
||||||
fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la
|
fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la
|
||||||
|
|
||||||
lib_LTLIBRARIES = libharfbuzz.la
|
lib_LTLIBRARIES = libharfbuzz.la
|
||||||
@ -25,11 +28,21 @@ HBLIBS =
|
|||||||
HBNONPCLIBS =
|
HBNONPCLIBS =
|
||||||
HBDEPS =
|
HBDEPS =
|
||||||
HBSOURCES = $(HB_BASE_sources)
|
HBSOURCES = $(HB_BASE_sources)
|
||||||
|
HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
|
||||||
HBHEADERS = $(HB_BASE_headers)
|
HBHEADERS = $(HB_BASE_headers)
|
||||||
HBNODISTHEADERS = $(HB_NODIST_headers)
|
|
||||||
|
if WITH_LIBSTDCXX
|
||||||
|
HBNOLIBCXXCFLAGS =
|
||||||
|
else
|
||||||
|
# Make sure we don't link to libstdc++
|
||||||
|
# No threadsafe statics in C++ as we do it ourselves
|
||||||
|
HBCFLAGS += -fno-exceptions
|
||||||
|
HBNOLIBCXXFLAGS = -fno-threadsafe-statics -fno-rtti
|
||||||
|
endif
|
||||||
|
|
||||||
if HAVE_OT
|
if HAVE_OT
|
||||||
HBSOURCES += $(HB_OT_sources)
|
HBSOURCES += $(HB_OT_sources)
|
||||||
|
HBSOURCES += $(HB_OT_RAGEL_GENERATED_sources)
|
||||||
HBHEADERS += $(HB_OT_headers)
|
HBHEADERS += $(HB_OT_headers)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -97,6 +110,9 @@ SUBDIRS += hb-ucdn
|
|||||||
HBCFLAGS += -I$(srcdir)/hb-ucdn
|
HBCFLAGS += -I$(srcdir)/hb-ucdn
|
||||||
HBLIBS += hb-ucdn/libhb-ucdn.la
|
HBLIBS += hb-ucdn/libhb-ucdn.la
|
||||||
HBSOURCES += $(HB_UCDN_sources)
|
HBSOURCES += $(HB_UCDN_sources)
|
||||||
|
hb-ucdn/libhb-ucdn.la: ucdn
|
||||||
|
ucdn:
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) -C hb-ucdn
|
||||||
endif
|
endif
|
||||||
DIST_SUBDIRS += hb-ucdn
|
DIST_SUBDIRS += hb-ucdn
|
||||||
|
|
||||||
@ -108,40 +124,69 @@ HBLIBS += $(HBNONPCLIBS)
|
|||||||
if OS_WIN32
|
if OS_WIN32
|
||||||
export_symbols = -export-symbols harfbuzz.def
|
export_symbols = -export-symbols harfbuzz.def
|
||||||
harfbuzz_def_dependency = harfbuzz.def
|
harfbuzz_def_dependency = harfbuzz.def
|
||||||
libharfbuzz_la_LINK = $(CXXLINK) $(libharfbuzz_la_LDFLAGS)
|
export_symbols_subset = -export-symbols harfbuzz-subset.def
|
||||||
|
harfbuzz_subset_def_dependency = harfbuzz-subset.def
|
||||||
|
export_symbols_icu = -export-symbols harfbuzz-icu.def
|
||||||
|
harfbuzz_icu_def_dependency = harfbuzz-icu.def
|
||||||
|
export_symbols_gobject = -export-symbols harfbuzz-gobject.def
|
||||||
|
harfbuzz_gobject_def_dependency = harfbuzz-gobject.def
|
||||||
|
chosen_linker = $(CXXLINK)
|
||||||
|
else
|
||||||
|
if WITH_LIBSTDCXX
|
||||||
|
chosen_linker = $(CXXLINK)
|
||||||
else
|
else
|
||||||
# Use a C linker for GCC, not C++; Don't link to libstdc++
|
|
||||||
if HAVE_GCC
|
if HAVE_GCC
|
||||||
libharfbuzz_la_LINK = $(LINK) $(libharfbuzz_la_LDFLAGS)
|
# Use a C linker for GCC, not C++; Don't link to libstdc++
|
||||||
|
chosen_linker = $(LINK)
|
||||||
else
|
else
|
||||||
libharfbuzz_la_LINK = $(CXXLINK) $(libharfbuzz_la_LDFLAGS)
|
chosen_linker = $(CXXLINK)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS) $(HBNODISTHEADERS)
|
base_link_flags = $(AM_LDFLAGS) -lm -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
|
||||||
libharfbuzz_la_CPPFLAGS = $(HBCFLAGS)
|
libharfbuzz_la_LINK = $(chosen_linker) $(libharfbuzz_la_LDFLAGS)
|
||||||
libharfbuzz_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) $(export_symbols) -no-undefined
|
libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS)
|
||||||
|
libharfbuzz_la_CPPFLAGS = $(HBCFLAGS) $(HBNOLIBCXXFLAGS)
|
||||||
|
libharfbuzz_la_LDFLAGS = $(base_link_flags) $(export_symbols)
|
||||||
libharfbuzz_la_LIBADD = $(HBLIBS)
|
libharfbuzz_la_LIBADD = $(HBLIBS)
|
||||||
EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency)
|
EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency)
|
||||||
pkginclude_HEADERS = $(HBHEADERS)
|
pkginclude_HEADERS = $(HBHEADERS)
|
||||||
nodist_pkginclude_HEADERS = $(HBNODISTHEADERS)
|
nodist_pkginclude_HEADERS =
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
pkgconfig_DATA = harfbuzz.pc
|
pkgconfig_DATA = harfbuzz.pc
|
||||||
EXTRA_DIST += harfbuzz.pc.in
|
cmakedir = $(libdir)/cmake/harfbuzz
|
||||||
|
cmake_DATA = harfbuzz-config.cmake
|
||||||
|
EXTRA_DIST += harfbuzz.pc.in harfbuzz-config.cmake.in
|
||||||
|
|
||||||
FUZZING_CPPFLAGS= \
|
lib_LTLIBRARIES += libharfbuzz-subset.la
|
||||||
|
libharfbuzz_subset_la_SOURCES = $(HB_SUBSET_sources)
|
||||||
|
libharfbuzz_subset_la_CPPFLAGS = $(HBCFLAGS)
|
||||||
|
libharfbuzz_subset_la_LDFLAGS = $(base_link_flags) $(export_symbols_subset)
|
||||||
|
libharfbuzz_subset_la_LIBADD = libharfbuzz.la
|
||||||
|
EXTRA_libharfbuzz_subset_la_DEPENDENCIES = $(harfbuzz_subset_def_dependency)
|
||||||
|
pkginclude_HEADERS += $(HB_SUBSET_headers)
|
||||||
|
pkgconfig_DATA += harfbuzz-subset.pc
|
||||||
|
EXTRA_DIST += harfbuzz-subset.pc.in
|
||||||
|
|
||||||
|
FUZZING_CPPFLAGS = \
|
||||||
-DHB_NDEBUG \
|
-DHB_NDEBUG \
|
||||||
-DHB_MAX_NESTING_LEVEL=3 \
|
-DHB_MAX_NESTING_LEVEL=3 \
|
||||||
-DHB_SANITIZE_MAX_EDITS=3 \
|
-DHB_SANITIZE_MAX_EDITS=3 \
|
||||||
-DHB_BUFFER_MAX_EXPANSION_FACTOR=3 \
|
-DHB_SANITIZE_MAX_OPS_FACTOR=3 \
|
||||||
|
-DHB_SANITIZE_MAX_OPS_MIN=128 \
|
||||||
|
-DHB_BUFFER_MAX_LEN_FACTOR=3 \
|
||||||
-DHB_BUFFER_MAX_LEN_MIN=8 \
|
-DHB_BUFFER_MAX_LEN_MIN=8 \
|
||||||
-DHB_BUFFER_MAX_LEN_DEFAULT=128 \
|
-DHB_BUFFER_MAX_LEN_DEFAULT=128 \
|
||||||
|
-DHB_BUFFER_MAX_OPS_FACTOR=8 \
|
||||||
|
-DHB_BUFFER_MAX_OPS_MIN=64 \
|
||||||
|
-DHB_BUFFER_MAX_OPS_DEFAULT=1024 \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
EXTRA_LTLIBRARIES = libharfbuzz-fuzzing.la
|
EXTRA_LTLIBRARIES = libharfbuzz-fuzzing.la
|
||||||
libharfbuzz_fuzzing_la_LINK = $(libharfbuzz_la_LINK)
|
libharfbuzz_fuzzing_la_LINK = $(chosen_linker) $(libharfbuzz_fuzzing_la_LDFLAGS)
|
||||||
libharfbuzz_fuzzing_la_SOURCES = $(libharfbuzz_la_SOURCES)
|
libharfbuzz_fuzzing_la_SOURCES = $(libharfbuzz_la_SOURCES)
|
||||||
libharfbuzz_fuzzing_la_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS) $(FUZZING_CPPFLAGS)
|
libharfbuzz_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(FUZZING_CPPFLAGS)
|
||||||
libharfbuzz_fuzzing_la_LDFLAGS = $(libharfbuzz_la_LDFLAGS)
|
libharfbuzz_fuzzing_la_LDFLAGS = $(AM_LDFLAGS)
|
||||||
libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD)
|
libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD)
|
||||||
EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES)
|
EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES)
|
||||||
CLEANFILES += libharfbuzz-fuzzing.la
|
CLEANFILES += libharfbuzz-fuzzing.la
|
||||||
@ -155,9 +200,10 @@ HBHEADERS += $(HB_ICU_headers)
|
|||||||
else
|
else
|
||||||
lib_LTLIBRARIES += libharfbuzz-icu.la
|
lib_LTLIBRARIES += libharfbuzz-icu.la
|
||||||
libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
|
libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
|
||||||
libharfbuzz_icu_la_CPPFLAGS = $(ICU_CFLAGS)
|
libharfbuzz_icu_la_CPPFLAGS = $(HBCFLAGS) $(ICU_CFLAGS)
|
||||||
libharfbuzz_icu_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
|
libharfbuzz_icu_la_LDFLAGS = $(base_link_flags) $(export_symbols_icu)
|
||||||
libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la
|
libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la
|
||||||
|
EXTRA_libharfbuzz_icu_la_DEPENDENCIES = $(harfbuzz_icu_def_dependency)
|
||||||
pkginclude_HEADERS += $(HB_ICU_headers)
|
pkginclude_HEADERS += $(HB_ICU_headers)
|
||||||
pkgconfig_DATA += harfbuzz-icu.pc
|
pkgconfig_DATA += harfbuzz-icu.pc
|
||||||
endif
|
endif
|
||||||
@ -166,13 +212,15 @@ EXTRA_DIST += harfbuzz-icu.pc.in
|
|||||||
|
|
||||||
if HAVE_GOBJECT
|
if HAVE_GOBJECT
|
||||||
lib_LTLIBRARIES += libharfbuzz-gobject.la
|
lib_LTLIBRARIES += libharfbuzz-gobject.la
|
||||||
libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_sources)
|
libharfbuzz_gobject_la_LINK = $(chosen_linker) $(libharfbuzz_gobject_la_LDFLAGS)
|
||||||
nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_ENUM_sources)
|
libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_DIST_sources)
|
||||||
libharfbuzz_gobject_la_CPPFLAGS = $(GOBJECT_CFLAGS)
|
nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_NODIST_sources)
|
||||||
libharfbuzz_gobject_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
|
libharfbuzz_gobject_la_CPPFLAGS = $(HBCFLAGS) $(HBNOLIBCXXFLAGS) $(GOBJECT_CFLAGS)
|
||||||
|
libharfbuzz_gobject_la_LDFLAGS = $(base_link_flags)
|
||||||
libharfbuzz_gobject_la_LIBADD = $(GOBJECT_LIBS) libharfbuzz.la
|
libharfbuzz_gobject_la_LIBADD = $(GOBJECT_LIBS) libharfbuzz.la
|
||||||
pkginclude_HEADERS += $(HB_GOBJECT_headers)
|
EXTRA_libharfbuzz_gobject_la_DEPENDENCIES = $(harfbuzz_gobject_def_dependency)
|
||||||
nodist_pkginclude_HEADERS += $(HB_GOBJECT_ENUM_headers)
|
pkginclude_HEADERS += $(HB_GOBJECT_DIST_headers)
|
||||||
|
nodist_pkginclude_HEADERS += $(HB_GOBJECT_NODIST_headers)
|
||||||
pkgconfig_DATA += harfbuzz-gobject.pc
|
pkgconfig_DATA += harfbuzz-gobject.pc
|
||||||
|
|
||||||
BUILT_SOURCES += \
|
BUILT_SOURCES += \
|
||||||
@ -212,23 +260,27 @@ EXTRA_DIST += \
|
|||||||
CLEANFILES += $(pkgconfig_DATA)
|
CLEANFILES += $(pkgconfig_DATA)
|
||||||
|
|
||||||
|
|
||||||
CLEANFILES += harfbuzz.def
|
DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def
|
||||||
|
if HAVE_GOBJECT
|
||||||
|
DEF_FILES += harfbuzz-gobject.def
|
||||||
|
endif
|
||||||
|
check: $(DEF_FILES) # For check-symbols.sh
|
||||||
|
CLEANFILES += $(DEF_FILES)
|
||||||
harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS)
|
harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS)
|
||||||
$(AM_V_GEN) (echo EXPORTS; \
|
$(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@
|
||||||
(cat $^ || echo 'hb_ERROR ()' ) | \
|
harfbuzz-subset.def: $(HB_SUBSET_headers)
|
||||||
$(EGREP) '^hb_.* \(' | \
|
$(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@
|
||||||
sed -e 's/ (.*//' | \
|
harfbuzz-icu.def: $(HB_ICU_headers)
|
||||||
LANG=C sort; \
|
$(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@
|
||||||
echo LIBRARY libharfbuzz-0.dll; \
|
harfbuzz-gobject.def: $(HB_GOBJECT_headers)
|
||||||
) >"$@"
|
$(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@
|
||||||
@ ! grep -q hb_ERROR "$@" \
|
|
||||||
|| ($(RM) "$@"; false)
|
|
||||||
|
|
||||||
|
|
||||||
GENERATORS = \
|
GENERATORS = \
|
||||||
gen-arabic-table.py \
|
gen-arabic-table.py \
|
||||||
gen-indic-table.py \
|
gen-indic-table.py \
|
||||||
gen-use-table.py \
|
gen-use-table.py \
|
||||||
|
gen-def.py \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
EXTRA_DIST += $(GENERATORS)
|
EXTRA_DIST += $(GENERATORS)
|
||||||
|
|
||||||
@ -251,21 +303,16 @@ built-sources: $(BUILT_SOURCES)
|
|||||||
.PHONY: unicode-tables arabic-table indic-table use-table built-sources
|
.PHONY: unicode-tables arabic-table indic-table use-table built-sources
|
||||||
|
|
||||||
RAGEL_GENERATED = \
|
RAGEL_GENERATED = \
|
||||||
$(srcdir)/hb-buffer-deserialize-json.hh \
|
$(patsubst %,$(srcdir)/%,$(HB_BASE_RAGEL_GENERATED_sources)) \
|
||||||
$(srcdir)/hb-buffer-deserialize-text.hh \
|
$(patsubst %,$(srcdir)/%,$(HB_OT_RAGEL_GENERATED_sources)) \
|
||||||
$(srcdir)/hb-ot-shape-complex-indic-machine.hh \
|
|
||||||
$(srcdir)/hb-ot-shape-complex-myanmar-machine.hh \
|
|
||||||
$(srcdir)/hb-ot-shape-complex-use-machine.hh \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
BUILT_SOURCES += $(RAGEL_GENERATED)
|
BUILT_SOURCES += $(RAGEL_GENERATED)
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
hb-buffer-deserialize-json.rl \
|
$(HB_BASE_RAGEL_sources) \
|
||||||
hb-buffer-deserialize-text.rl \
|
$(HB_OT_RAGEL_sources) \
|
||||||
hb-ot-shape-complex-indic-machine.rl \
|
|
||||||
hb-ot-shape-complex-myanmar-machine.rl \
|
|
||||||
hb-ot-shape-complex-use-machine.rl \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
MAINTAINERCLEANFILES += $(RAGEL_GENERATED)
|
# We decided to add ragel-generated files to git...
|
||||||
|
#MAINTAINERCLEANFILES += $(RAGEL_GENERATED)
|
||||||
$(srcdir)/%.hh: $(srcdir)/%.rl
|
$(srcdir)/%.hh: $(srcdir)/%.rl
|
||||||
$(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \
|
$(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \
|
||||||
|| ($(RM) "$@"; false)
|
|| ($(RM) "$@"; false)
|
||||||
@ -301,30 +348,55 @@ test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
|
|||||||
|
|
||||||
dist_check_SCRIPTS = \
|
dist_check_SCRIPTS = \
|
||||||
check-c-linkage-decls.sh \
|
check-c-linkage-decls.sh \
|
||||||
check-defs.sh \
|
check-externs.sh \
|
||||||
check-header-guards.sh \
|
check-header-guards.sh \
|
||||||
check-includes.sh \
|
check-includes.sh \
|
||||||
check-libstdc++.sh \
|
|
||||||
check-static-inits.sh \
|
check-static-inits.sh \
|
||||||
check-symbols.sh \
|
check-symbols.sh \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
TESTS += $(dist_check_SCRIPTS)
|
||||||
|
|
||||||
check_PROGRAMS = \
|
if !WITH_LIBSTDCXX
|
||||||
test-ot-tag \
|
dist_check_SCRIPTS += \
|
||||||
|
check-libstdc++.sh \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
test_ot_color_SOURCES = hb-ot-color.cc
|
endif
|
||||||
test_ot_color_CPPFLAGS = $(HBCFLAGS) -DMAIN
|
|
||||||
test_ot_color_LDADD = libharfbuzz.la $(HBLIBS)
|
check_PROGRAMS += \
|
||||||
|
dump-indic-data \
|
||||||
|
dump-khmer-data \
|
||||||
|
dump-myanmar-data \
|
||||||
|
dump-use-data \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
dump_indic_data_SOURCES = dump-indic-data.cc hb-ot-shape-complex-indic-table.cc
|
||||||
|
dump_indic_data_CPPFLAGS = $(HBCFLAGS)
|
||||||
|
dump_indic_data_LDADD = libharfbuzz.la $(HBLIBS)
|
||||||
|
dump_khmer_data_SOURCES = dump-khmer-data.cc hb-ot-shape-complex-indic-table.cc
|
||||||
|
dump_khmer_data_CPPFLAGS = $(HBCFLAGS)
|
||||||
|
dump_khmer_data_LDADD = libharfbuzz.la $(HBLIBS)
|
||||||
|
dump_myanmar_data_SOURCES = dump-myanmar-data.cc hb-ot-shape-complex-indic-table.cc
|
||||||
|
dump_myanmar_data_CPPFLAGS = $(HBCFLAGS)
|
||||||
|
dump_myanmar_data_LDADD = libharfbuzz.la $(HBLIBS)
|
||||||
|
dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc
|
||||||
|
dump_use_data_CPPFLAGS = $(HBCFLAGS)
|
||||||
|
dump_use_data_LDADD = libharfbuzz.la $(HBLIBS)
|
||||||
|
|
||||||
|
check_PROGRAMS += test-ot-tag test-unicode-ranges
|
||||||
|
TESTS += test-ot-tag test-unicode-ranges
|
||||||
|
|
||||||
test_ot_tag_SOURCES = hb-ot-tag.cc
|
test_ot_tag_SOURCES = hb-ot-tag.cc
|
||||||
test_ot_tag_CPPFLAGS = $(HBCFLAGS) -DMAIN
|
test_ot_tag_CPPFLAGS = $(HBCFLAGS) -DMAIN
|
||||||
test_ot_tag_LDADD = libharfbuzz.la $(HBLIBS)
|
test_ot_tag_LDADD = libharfbuzz.la $(HBLIBS)
|
||||||
|
|
||||||
TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS)
|
test_unicode_ranges_SOURCES = test-unicode-ranges.cc
|
||||||
|
test_unicode_ranges_LDADD = libharfbuzz.la $(HBLIBS)
|
||||||
|
|
||||||
TESTS_ENVIRONMENT = \
|
TESTS_ENVIRONMENT = \
|
||||||
srcdir="$(srcdir)" \
|
srcdir="$(srcdir)" \
|
||||||
MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
|
MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
|
||||||
HBSOURCES="$(HBSOURCES)" \
|
HBSOURCES="$(HBSOURCES)" \
|
||||||
HBHEADERS="$(HBHEADERS) $(HBNODISTHEADERS)" \
|
HBHEADERS="$(HBHEADERS)" \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
if HAVE_INTROSPECTION
|
if HAVE_INTROSPECTION
|
||||||
@ -354,12 +426,9 @@ HarfBuzz_0_0_gir_LIBS = \
|
|||||||
$(NULL)
|
$(NULL)
|
||||||
HarfBuzz_0_0_gir_FILES = \
|
HarfBuzz_0_0_gir_FILES = \
|
||||||
$(HBHEADERS) \
|
$(HBHEADERS) \
|
||||||
$(HBNODISTHEADERS) \
|
|
||||||
$(HBSOURCES) \
|
$(HBSOURCES) \
|
||||||
$(HB_GOBJECT_ENUM_sources) \
|
|
||||||
$(HB_GOBJECT_ENUM_headers) \
|
|
||||||
$(HB_GOBJECT_sources) \
|
$(HB_GOBJECT_sources) \
|
||||||
$(HB_GOBJECT_STRUCTS_headers) \
|
$(HB_GOBJECT_headers) \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
girdir = $(datadir)/gir-1.0
|
girdir = $(datadir)/gir-1.0
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
NULL =
|
|
||||||
|
|
||||||
# Base and default-included sources and headers
|
# Base and default-included sources and headers
|
||||||
|
|
||||||
HB_BASE_sources = \
|
HB_BASE_sources = \
|
||||||
hb-atomic-private.hh \
|
hb-atomic-private.hh \
|
||||||
hb-blob.cc \
|
hb-blob.cc \
|
||||||
hb-buffer-deserialize-json.hh \
|
|
||||||
hb-buffer-deserialize-text.hh \
|
|
||||||
hb-buffer-private.hh \
|
hb-buffer-private.hh \
|
||||||
hb-buffer-serialize.cc \
|
hb-buffer-serialize.cc \
|
||||||
hb-buffer.cc \
|
hb-buffer.cc \
|
||||||
hb-cache-private.hh \
|
|
||||||
hb-common.cc \
|
hb-common.cc \
|
||||||
|
hb-debug.hh \
|
||||||
|
hb-dsalgs.hh \
|
||||||
hb-face-private.hh \
|
hb-face-private.hh \
|
||||||
hb-face.cc \
|
hb-face.cc \
|
||||||
hb-font-private.hh \
|
hb-font-private.hh \
|
||||||
@ -20,17 +17,23 @@ HB_BASE_sources = \
|
|||||||
hb-object-private.hh \
|
hb-object-private.hh \
|
||||||
hb-open-file-private.hh \
|
hb-open-file-private.hh \
|
||||||
hb-open-type-private.hh \
|
hb-open-type-private.hh \
|
||||||
|
hb-ot-cbdt-table.hh \
|
||||||
hb-ot-cmap-table.hh \
|
hb-ot-cmap-table.hh \
|
||||||
hb-ot-glyf-table.hh \
|
hb-ot-glyf-table.hh \
|
||||||
|
hb-ot-hdmx-table.hh \
|
||||||
hb-ot-head-table.hh \
|
hb-ot-head-table.hh \
|
||||||
hb-ot-hhea-table.hh \
|
hb-ot-hhea-table.hh \
|
||||||
hb-ot-hmtx-table.hh \
|
hb-ot-hmtx-table.hh \
|
||||||
|
hb-ot-kern-table.hh \
|
||||||
hb-ot-maxp-table.hh \
|
hb-ot-maxp-table.hh \
|
||||||
hb-ot-name-table.hh \
|
hb-ot-name-table.hh \
|
||||||
hb-ot-os2-table.hh \
|
hb-ot-os2-table.hh \
|
||||||
|
hb-ot-os2-unicode-ranges.hh \
|
||||||
|
hb-ot-post-macroman.hh \
|
||||||
hb-ot-post-table.hh \
|
hb-ot-post-table.hh \
|
||||||
hb-ot-tag.cc \
|
hb-ot-tag.cc \
|
||||||
hb-private.hh \
|
hb-private.hh \
|
||||||
|
hb-set-digest-private.hh \
|
||||||
hb-set-private.hh \
|
hb-set-private.hh \
|
||||||
hb-set.cc \
|
hb-set.cc \
|
||||||
hb-shape.cc \
|
hb-shape.cc \
|
||||||
@ -40,12 +43,22 @@ HB_BASE_sources = \
|
|||||||
hb-shaper-impl-private.hh \
|
hb-shaper-impl-private.hh \
|
||||||
hb-shaper-private.hh \
|
hb-shaper-private.hh \
|
||||||
hb-shaper.cc \
|
hb-shaper.cc \
|
||||||
|
hb-string-array.hh \
|
||||||
hb-unicode-private.hh \
|
hb-unicode-private.hh \
|
||||||
hb-unicode.cc \
|
hb-unicode.cc \
|
||||||
hb-utf-private.hh \
|
hb-utf-private.hh \
|
||||||
hb-warning.cc \
|
hb-warning.cc \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
HB_BASE_RAGEL_GENERATED_sources = \
|
||||||
|
hb-buffer-deserialize-json.hh \
|
||||||
|
hb-buffer-deserialize-text.hh \
|
||||||
|
$(NULL)
|
||||||
|
HB_BASE_RAGEL_sources = \
|
||||||
|
hb-buffer-deserialize-json.rl \
|
||||||
|
hb-buffer-deserialize-text.rl \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
HB_BASE_headers = \
|
HB_BASE_headers = \
|
||||||
hb.h \
|
hb.h \
|
||||||
hb-blob.h \
|
hb-blob.h \
|
||||||
@ -58,19 +71,24 @@ HB_BASE_headers = \
|
|||||||
hb-shape.h \
|
hb-shape.h \
|
||||||
hb-shape-plan.h \
|
hb-shape-plan.h \
|
||||||
hb-unicode.h \
|
hb-unicode.h \
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
HB_NODIST_headers = \
|
|
||||||
hb-version.h \
|
hb-version.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
HB_FALLBACK_sources = hb-fallback-shape.cc
|
HB_FALLBACK_sources = \
|
||||||
|
hb-fallback-shape.cc \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
HB_OT_sources = \
|
HB_OT_sources = \
|
||||||
hb-ot-color.cc \
|
hb-aat-layout.cc \
|
||||||
hb-ot-cpal-table.hh \
|
hb-aat-layout-common-private.hh \
|
||||||
|
hb-aat-layout-ankr-table.hh \
|
||||||
|
hb-aat-layout-kerx-table.hh \
|
||||||
|
hb-aat-layout-morx-table.hh \
|
||||||
|
hb-aat-layout-trak-table.hh \
|
||||||
|
hb-aat-layout-private.hh \
|
||||||
hb-ot-font.cc \
|
hb-ot-font.cc \
|
||||||
hb-ot-layout.cc \
|
hb-ot-layout.cc \
|
||||||
|
hb-ot-layout-base-table.hh \
|
||||||
hb-ot-layout-common-private.hh \
|
hb-ot-layout-common-private.hh \
|
||||||
hb-ot-layout-gdef-table.hh \
|
hb-ot-layout-gdef-table.hh \
|
||||||
hb-ot-layout-gpos-table.hh \
|
hb-ot-layout-gpos-table.hh \
|
||||||
@ -78,8 +96,12 @@ HB_OT_sources = \
|
|||||||
hb-ot-layout-gsub-table.hh \
|
hb-ot-layout-gsub-table.hh \
|
||||||
hb-ot-layout-jstf-table.hh \
|
hb-ot-layout-jstf-table.hh \
|
||||||
hb-ot-layout-private.hh \
|
hb-ot-layout-private.hh \
|
||||||
|
hb-ot-color.cc \
|
||||||
|
hb-ot-cpal-table.hh \
|
||||||
hb-ot-map.cc \
|
hb-ot-map.cc \
|
||||||
hb-ot-map-private.hh \
|
hb-ot-map-private.hh \
|
||||||
|
hb-ot-math.cc \
|
||||||
|
hb-ot-math-table.hh \
|
||||||
hb-ot-shape.cc \
|
hb-ot-shape.cc \
|
||||||
hb-ot-shape-complex-arabic.cc \
|
hb-ot-shape-complex-arabic.cc \
|
||||||
hb-ot-shape-complex-arabic-fallback.hh \
|
hb-ot-shape-complex-arabic-fallback.hh \
|
||||||
@ -90,15 +112,15 @@ HB_OT_sources = \
|
|||||||
hb-ot-shape-complex-hangul.cc \
|
hb-ot-shape-complex-hangul.cc \
|
||||||
hb-ot-shape-complex-hebrew.cc \
|
hb-ot-shape-complex-hebrew.cc \
|
||||||
hb-ot-shape-complex-indic.cc \
|
hb-ot-shape-complex-indic.cc \
|
||||||
hb-ot-shape-complex-indic-machine.hh \
|
|
||||||
hb-ot-shape-complex-indic-private.hh \
|
hb-ot-shape-complex-indic-private.hh \
|
||||||
hb-ot-shape-complex-indic-table.cc \
|
hb-ot-shape-complex-indic-table.cc \
|
||||||
|
hb-ot-shape-complex-khmer-private.hh \
|
||||||
|
hb-ot-shape-complex-khmer.cc \
|
||||||
|
hb-ot-shape-complex-myanmar-private.hh \
|
||||||
hb-ot-shape-complex-myanmar.cc \
|
hb-ot-shape-complex-myanmar.cc \
|
||||||
hb-ot-shape-complex-myanmar-machine.hh \
|
|
||||||
hb-ot-shape-complex-thai.cc \
|
hb-ot-shape-complex-thai.cc \
|
||||||
hb-ot-shape-complex-tibetan.cc \
|
hb-ot-shape-complex-tibetan.cc \
|
||||||
hb-ot-shape-complex-use.cc \
|
hb-ot-shape-complex-use.cc \
|
||||||
hb-ot-shape-complex-use-machine.hh \
|
|
||||||
hb-ot-shape-complex-use-private.hh \
|
hb-ot-shape-complex-use-private.hh \
|
||||||
hb-ot-shape-complex-use-table.cc \
|
hb-ot-shape-complex-use-table.cc \
|
||||||
hb-ot-shape-complex-private.hh \
|
hb-ot-shape-complex-private.hh \
|
||||||
@ -107,6 +129,24 @@ HB_OT_sources = \
|
|||||||
hb-ot-shape-fallback-private.hh \
|
hb-ot-shape-fallback-private.hh \
|
||||||
hb-ot-shape-fallback.cc \
|
hb-ot-shape-fallback.cc \
|
||||||
hb-ot-shape-private.hh \
|
hb-ot-shape-private.hh \
|
||||||
|
hb-ot-var.cc \
|
||||||
|
hb-ot-var-avar-table.hh \
|
||||||
|
hb-ot-var-fvar-table.hh \
|
||||||
|
hb-ot-var-hvar-table.hh \
|
||||||
|
hb-ot-var-mvar-table.hh \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
HB_OT_RAGEL_GENERATED_sources = \
|
||||||
|
hb-ot-shape-complex-indic-machine.hh \
|
||||||
|
hb-ot-shape-complex-khmer-machine.hh \
|
||||||
|
hb-ot-shape-complex-myanmar-machine.hh \
|
||||||
|
hb-ot-shape-complex-use-machine.hh \
|
||||||
|
$(NULL)
|
||||||
|
HB_OT_RAGEL_sources = \
|
||||||
|
hb-ot-shape-complex-indic-machine.rl \
|
||||||
|
hb-ot-shape-complex-khmer-machine.rl \
|
||||||
|
hb-ot-shape-complex-myanmar-machine.rl \
|
||||||
|
hb-ot-shape-complex-use-machine.rl \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
HB_OT_headers = \
|
HB_OT_headers = \
|
||||||
@ -114,8 +154,11 @@ HB_OT_headers = \
|
|||||||
hb-ot-color.h \
|
hb-ot-color.h \
|
||||||
hb-ot-font.h \
|
hb-ot-font.h \
|
||||||
hb-ot-layout.h \
|
hb-ot-layout.h \
|
||||||
|
hb-ot-math.h \
|
||||||
|
hb-ot-base.h \
|
||||||
hb-ot-shape.h \
|
hb-ot-shape.h \
|
||||||
hb-ot-tag.h \
|
hb-ot-tag.h \
|
||||||
|
hb-ot-var.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# Optional Sources and Headers with external deps
|
# Optional Sources and Headers with external deps
|
||||||
@ -147,8 +190,26 @@ HB_UCDN_sources = hb-ucdn.cc
|
|||||||
HB_ICU_sources = hb-icu.cc
|
HB_ICU_sources = hb-icu.cc
|
||||||
HB_ICU_headers = hb-icu.h
|
HB_ICU_headers = hb-icu.h
|
||||||
|
|
||||||
HB_GOBJECT_sources = hb-gobject-structs.cc
|
# Sources for libharfbuzz-subset
|
||||||
HB_GOBJECT_STRUCTS_headers = hb-gobject-structs.h
|
HB_SUBSET_sources = \
|
||||||
HB_GOBJECT_headers = hb-gobject.h $(HB_GOBJECT_STRUCTS_headers)
|
hb-subset.cc \
|
||||||
|
hb-subset-glyf.cc \
|
||||||
|
hb-subset-input.cc \
|
||||||
|
hb-subset-plan.cc \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
HB_SUBSET_headers = \
|
||||||
|
hb-subset.h \
|
||||||
|
hb-subset-glyf.hh \
|
||||||
|
hb-subset-plan.hh \
|
||||||
|
hb-subset-private.hh \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
HB_GOBJECT_DIST_sources = hb-gobject-structs.cc
|
||||||
|
HB_GOBJECT_DIST_headers = hb-gobject.h hb-gobject-structs.h
|
||||||
HB_GOBJECT_ENUM_sources = hb-gobject-enums.cc
|
HB_GOBJECT_ENUM_sources = hb-gobject-enums.cc
|
||||||
HB_GOBJECT_ENUM_headers = hb-gobject-enums.h
|
HB_GOBJECT_ENUM_headers = hb-gobject-enums.h
|
||||||
|
HB_GOBJECT_NODIST_sources = $(HB_GOBJECT_ENUM_sources)
|
||||||
|
HB_GOBJECT_NODIST_headers = $(HB_GOBJECT_ENUM_headers)
|
||||||
|
HB_GOBJECT_sources = $(HB_GOBJECT_DIST_sources) $(HB_GOBJECT_NODIST_sources)
|
||||||
|
HB_GOBJECT_headers = $(HB_GOBJECT_DIST_headers) $(HB_GOBJECT_NODIST_headers)
|
||||||
|
@ -7,18 +7,17 @@ test -z "$srcdir" && srcdir=.
|
|||||||
stat=0
|
stat=0
|
||||||
|
|
||||||
test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'`
|
test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'`
|
||||||
test "x$HBSOURCES" = x && HBSOURCES=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'`
|
test "x$HBSOURCES" = x && HBSOURCES=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.cc'`
|
||||||
|
|
||||||
|
|
||||||
for x in $HBHEADERS; do
|
for x in $HBHEADERS; do
|
||||||
test -f $srcdir/$x && x=$srcdir/$x
|
test -f "$srcdir/$x" -a ! -f "$x" && x="$srcdir/$x"
|
||||||
if ! grep -q HB_BEGIN_DECLS "$x" || ! grep -q HB_END_DECLS "$x"; then
|
if ! grep -q HB_BEGIN_DECLS "$x" || ! grep -q HB_END_DECLS "$x"; then
|
||||||
echo "Ouch, file $x does not have HB_BEGIN_DECLS / HB_END_DECLS, but it should"
|
echo "Ouch, file $x does not have HB_BEGIN_DECLS / HB_END_DECLS, but it should"
|
||||||
stat=1
|
stat=1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
for x in $HBSOURCES; do
|
for x in $HBSOURCES; do
|
||||||
test -f $srcdir/$x && x=$srcdir/$x
|
test -f "$srcdir/$x" -a ! -f "$x" && x="$srcdir/$x"
|
||||||
if grep -q HB_BEGIN_DECLS "$x" || grep -q HB_END_DECLS "$x"; then
|
if grep -q HB_BEGIN_DECLS "$x" || grep -q HB_END_DECLS "$x"; then
|
||||||
echo "Ouch, file $x has HB_BEGIN_DECLS / HB_END_DECLS, but it shouldn't"
|
echo "Ouch, file $x has HB_BEGIN_DECLS / HB_END_DECLS, but it shouldn't"
|
||||||
stat=1
|
stat=1
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
LC_ALL=C
|
|
||||||
export LC_ALL
|
|
||||||
|
|
||||||
test -z "$srcdir" && srcdir=.
|
|
||||||
test -z "$MAKE" && MAKE=make
|
|
||||||
stat=0
|
|
||||||
|
|
||||||
if which nm 2>/dev/null >/dev/null; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
echo "check-defs.sh: 'nm' not found; skipping test"
|
|
||||||
exit 77
|
|
||||||
fi
|
|
||||||
|
|
||||||
defs="harfbuzz.def"
|
|
||||||
$MAKE $defs > /dev/null
|
|
||||||
tested=false
|
|
||||||
for def in $defs; do
|
|
||||||
lib=`echo "$def" | sed 's/[.]def$//;s@.*/@@'`
|
|
||||||
so=.libs/lib${lib}.so
|
|
||||||
|
|
||||||
EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`"
|
|
||||||
|
|
||||||
if test -f "$so"; then
|
|
||||||
|
|
||||||
echo "Checking that $so has the same symbol list as $def"
|
|
||||||
{
|
|
||||||
echo EXPORTS
|
|
||||||
echo "$EXPORTED_SYMBOLS"
|
|
||||||
# cheat: copy the last line from the def file!
|
|
||||||
tail -n1 "$def"
|
|
||||||
} | diff "$def" - >&2 || stat=1
|
|
||||||
|
|
||||||
tested=true
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if ! $tested; then
|
|
||||||
echo "check-defs.sh: libharfbuzz shared library not found; skipping test"
|
|
||||||
exit 77
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit $stat
|
|
22
src/check-externs.sh
Executable file
22
src/check-externs.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
LC_ALL=C
|
||||||
|
export LC_ALL
|
||||||
|
|
||||||
|
test -z "$srcdir" && srcdir=.
|
||||||
|
stat=0
|
||||||
|
|
||||||
|
test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'`
|
||||||
|
test "x$EGREP" = x && EGREP='grep -E'
|
||||||
|
|
||||||
|
|
||||||
|
echo 'Checking that all public symbols are exported with HB_EXTERN'
|
||||||
|
|
||||||
|
for x in $HBHEADERS; do
|
||||||
|
test -f "$srcdir/$x" -a ! -f "$x" && x="$srcdir/$x"
|
||||||
|
$EGREP -B1 -n '^hb_' /dev/null "$x" |
|
||||||
|
$EGREP -v '(^--|:hb_|-HB_EXTERN )' -A1
|
||||||
|
done |
|
||||||
|
grep . >&2 && stat=1
|
||||||
|
|
||||||
|
exit $stat
|
@ -6,11 +6,11 @@ export LC_ALL
|
|||||||
test -z "$srcdir" && srcdir=.
|
test -z "$srcdir" && srcdir=.
|
||||||
stat=0
|
stat=0
|
||||||
|
|
||||||
test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'`
|
test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h' ! -name 'hb-gobject-structs.h'`
|
||||||
test "x$HBSOURCES" = x && HBSOURCES=`cd "$srcdir"; find . -maxdepth 1 -name 'hb-*.cc' -or -name 'hb-*.hh'`
|
test "x$HBSOURCES" = x && HBSOURCES=`cd "$srcdir"; find . -maxdepth 1 -name 'hb-*.cc' -or -name 'hb-*.hh'`
|
||||||
|
|
||||||
for x in $HBHEADERS $HBSOURCES; do
|
for x in $HBHEADERS $HBSOURCES; do
|
||||||
test -f "$srcdir/$x" && x="$srcdir/$x"
|
test -f "$srcdir/$x" -a ! -f "$x" && x="$srcdir/$x"
|
||||||
echo "$x" | grep -q '[^h]$' && continue;
|
echo "$x" | grep -q '[^h]$' && continue;
|
||||||
xx=`echo "$x" | sed 's@.*/@@'`
|
xx=`echo "$x" | sed 's@.*/@@'`
|
||||||
tag=`echo "$xx" | tr 'a-z.-' 'A-Z_'`
|
tag=`echo "$xx" | tr 'a-z.-' 'A-Z_'`
|
||||||
|
@ -13,7 +13,7 @@ test "x$HBSOURCES" = x && HBSOURCES=`cd "$srcdir"; find . -maxdepth 1 -name 'hb-
|
|||||||
echo 'Checking that public header files #include "hb-common.h" or "hb.h" first (or none)'
|
echo 'Checking that public header files #include "hb-common.h" or "hb.h" first (or none)'
|
||||||
|
|
||||||
for x in $HBHEADERS; do
|
for x in $HBHEADERS; do
|
||||||
test -f "$srcdir/$x" && x="$srcdir/$x"
|
test -f "$srcdir/$x" -a ! -f "$x" && x="$srcdir/$x"
|
||||||
grep '#.*\<include\>' "$x" /dev/null | head -n 1
|
grep '#.*\<include\>' "$x" /dev/null | head -n 1
|
||||||
done |
|
done |
|
||||||
grep -v '"hb-common[.]h"' |
|
grep -v '"hb-common[.]h"' |
|
||||||
@ -26,7 +26,7 @@ grep . >&2 && stat=1
|
|||||||
echo 'Checking that source files #include "hb-*private.hh" first (or none)'
|
echo 'Checking that source files #include "hb-*private.hh" first (or none)'
|
||||||
|
|
||||||
for x in $HBSOURCES; do
|
for x in $HBSOURCES; do
|
||||||
test -f "$srcdir/$x" && x="$srcdir/$x"
|
test -f "$srcdir/$x" -a ! -f "$x" && x="$srcdir/$x"
|
||||||
grep '#.*\<include\>' "$x" /dev/null | grep -v 'include _' | head -n 1
|
grep '#.*\<include\>' "$x" /dev/null | grep -v 'include _' | head -n 1
|
||||||
done |
|
done |
|
||||||
grep -v '"hb-.*private[.]hh"' |
|
grep -v '"hb-.*private[.]hh"' |
|
||||||
@ -34,7 +34,7 @@ grep -v 'hb-private[.]hh:' |
|
|||||||
grep . >&2 && stat=1
|
grep . >&2 && stat=1
|
||||||
|
|
||||||
|
|
||||||
echo 'Checking that there is no #include <hb.*.h>'
|
echo 'Checking that there is no #include <hb-*.h>'
|
||||||
for x in $HBHEADERS $HBSOURCES; do
|
for x in $HBHEADERS $HBSOURCES; do
|
||||||
test -f "$srcdir/$x" && x="$srcdir/$x"
|
test -f "$srcdir/$x" && x="$srcdir/$x"
|
||||||
grep '#.*\<include\>.*<.*hb' "$x" /dev/null >&2 && stat=1
|
grep '#.*\<include\>.*<.*hb' "$x" /dev/null >&2 && stat=1
|
||||||
|
@ -4,27 +4,37 @@ LC_ALL=C
|
|||||||
export LC_ALL
|
export LC_ALL
|
||||||
|
|
||||||
test -z "$srcdir" && srcdir=.
|
test -z "$srcdir" && srcdir=.
|
||||||
|
test -z "$libs" && libs=.libs
|
||||||
stat=0
|
stat=0
|
||||||
|
|
||||||
|
|
||||||
if which ldd 2>/dev/null >/dev/null; then
|
if which ldd 2>/dev/null >/dev/null; then
|
||||||
:
|
LDD=ldd
|
||||||
else
|
else
|
||||||
echo "check-libstdc++.sh: 'ldd' not found; skipping test"
|
# macOS specific tool
|
||||||
exit 77
|
if which otool 2>/dev/null >/dev/null; then
|
||||||
|
LDD="otool -L"
|
||||||
|
else
|
||||||
|
echo "check-libstdc++.sh: 'ldd' not found; skipping test"
|
||||||
|
exit 77
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tested=false
|
tested=false
|
||||||
for suffix in so dylib; do
|
# harfbuzz-icu links to libstdc++ because icu does.
|
||||||
so=.libs/libharfbuzz.$suffix
|
# harfbuzz-subset uses libstdc++.
|
||||||
if ! test -f "$so"; then continue; fi
|
for soname in harfbuzz harfbuzz-gobject; do
|
||||||
|
for suffix in so dylib; do
|
||||||
|
so=$libs/lib$soname.$suffix
|
||||||
|
if ! test -f "$so"; then continue; fi
|
||||||
|
|
||||||
echo "Checking that we are not linking to libstdc++ or libc++"
|
echo "Checking that we are not linking to libstdc++ or libc++ in $so"
|
||||||
if ldd $so | grep 'libstdc[+][+]\|libc[+][+]'; then
|
if $LDD $so | grep 'libstdc[+][+]\|libc[+][+]'; then
|
||||||
echo "Ouch, linked to libstdc++ or libc++"
|
echo "Ouch, linked to libstdc++ or libc++"
|
||||||
stat=1
|
stat=1
|
||||||
fi
|
fi
|
||||||
tested=true
|
tested=true
|
||||||
|
done
|
||||||
done
|
done
|
||||||
if ! $tested; then
|
if ! $tested; then
|
||||||
echo "check-libstdc++.sh: libharfbuzz shared library not found; skipping test"
|
echo "check-libstdc++.sh: libharfbuzz shared library not found; skipping test"
|
||||||
|
@ -4,6 +4,7 @@ LC_ALL=C
|
|||||||
export LC_ALL
|
export LC_ALL
|
||||||
|
|
||||||
test -z "$srcdir" && srcdir=.
|
test -z "$srcdir" && srcdir=.
|
||||||
|
test -z "$libs" && libs=.libs
|
||||||
stat=0
|
stat=0
|
||||||
|
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ else
|
|||||||
exit 77
|
exit 77
|
||||||
fi
|
fi
|
||||||
|
|
||||||
OBJS=.libs/*.o
|
OBJS=$libs/*.o
|
||||||
if test "x`echo $OBJS`" = "x$OBJS" 2>/dev/null >/dev/null; then
|
if test "x`echo $OBJS`" = "x$OBJS" 2>/dev/null >/dev/null; then
|
||||||
echo "check-static-inits.sh: object files not found; skipping test"
|
echo "check-static-inits.sh: object files not found; skipping test"
|
||||||
exit 77
|
exit 77
|
||||||
|
@ -4,8 +4,10 @@ LC_ALL=C
|
|||||||
export LC_ALL
|
export LC_ALL
|
||||||
|
|
||||||
test -z "$srcdir" && srcdir=.
|
test -z "$srcdir" && srcdir=.
|
||||||
|
test -z "$libs" && libs=.libs
|
||||||
stat=0
|
stat=0
|
||||||
|
|
||||||
|
IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_flush\|llvm_.*'
|
||||||
|
|
||||||
if which nm 2>/dev/null >/dev/null; then
|
if which nm 2>/dev/null >/dev/null; then
|
||||||
:
|
:
|
||||||
@ -14,29 +16,46 @@ else
|
|||||||
exit 77
|
exit 77
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Checking that we are not exposing internal symbols"
|
|
||||||
tested=false
|
tested=false
|
||||||
for suffix in so dylib; do
|
for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do
|
||||||
so=.libs/libharfbuzz.$suffix
|
for suffix in so dylib; do
|
||||||
if ! test -f "$so"; then continue; fi
|
so=$libs/lib$soname.$suffix
|
||||||
|
if ! test -f "$so"; then continue; fi
|
||||||
EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`"
|
|
||||||
|
|
||||||
prefix=`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'`
|
# On macOS, C symbols are prefixed with _
|
||||||
|
symprefix=
|
||||||
|
if test $suffix = dylib; then symprefix=_; fi
|
||||||
|
|
||||||
# On mac, C symbols are prefixed with _
|
EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`"
|
||||||
if test $suffix = dylib; then prefix="_$prefix"; fi
|
|
||||||
|
|
||||||
echo "Processing $so"
|
prefix=$symprefix`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'`
|
||||||
if echo "$EXPORTED_SYMBOLS" | grep -v "^${prefix}_"; then
|
|
||||||
echo "Ouch, internal symbols exposed"
|
|
||||||
stat=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
tested=true
|
echo
|
||||||
|
echo "Checking that $so does not expose internal symbols"
|
||||||
|
if echo "$EXPORTED_SYMBOLS" | grep -v "^${prefix}\(_\|$\)"; then
|
||||||
|
echo "Ouch, internal symbols exposed"
|
||||||
|
stat=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
def=$soname.def
|
||||||
|
if ! test -f "$def"; then
|
||||||
|
echo "'$def' not found; skipping"
|
||||||
|
else
|
||||||
|
echo
|
||||||
|
echo "Checking that $so has the same symbol list as $def"
|
||||||
|
{
|
||||||
|
echo EXPORTS
|
||||||
|
echo "$EXPORTED_SYMBOLS" | sed -e "s/^${symprefix}hb/hb/g"
|
||||||
|
# cheat: copy the last line from the def file!
|
||||||
|
tail -n1 "$def"
|
||||||
|
} | c++filt | diff "$def" - >&2 || stat=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
tested=true
|
||||||
|
done
|
||||||
done
|
done
|
||||||
if ! $tested; then
|
if ! $tested; then
|
||||||
echo "check-symbols.sh: no shared library found; skipping test"
|
echo "check-symbols.sh: no shared libraries found; skipping test"
|
||||||
exit 77
|
exit 77
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
84
src/dev-run.sh
Executable file
84
src/dev-run.sh
Executable file
@ -0,0 +1,84 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Suggested setup to use the script:
|
||||||
|
# (on the root of the project)
|
||||||
|
# $ NOCONFIGURE=1 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo
|
||||||
|
# $ mkdir build && cd build && ../configure && make -j5 && cd ..
|
||||||
|
# $ src/dev-run.sh [FONT-FILE] [TEXT]
|
||||||
|
#
|
||||||
|
# Or, using cmake:
|
||||||
|
# $ cmake -DHB_CHECK=ON -Bbuild -H. -GNinja && ninja -Cbuild
|
||||||
|
# $ src/dev-run.sh [FONT-FILE] [TEXT]
|
||||||
|
#
|
||||||
|
# If you are using iTerm2, issue the script like this:
|
||||||
|
# $ src/dev-run.sh img [FONT-FILE] [TEXT]
|
||||||
|
#
|
||||||
|
|
||||||
|
[ $# = 0 ] && echo Usage: "src/dev-run.sh [FONT-FILE] [TEXT]" && exit
|
||||||
|
command -v entr >/dev/null 2>&1 || { echo >&2 "This script needs `entr` be installed"; exit 1; }
|
||||||
|
|
||||||
|
|
||||||
|
GDB=gdb
|
||||||
|
# if gdb doesn't exist, hopefully lldb exist
|
||||||
|
command -v $GDB >/dev/null 2>&1 || export GDB="lldb"
|
||||||
|
|
||||||
|
|
||||||
|
[ $1 = "img" ] && img=1 && shift
|
||||||
|
# http://iterm2.com/documentation-images.html
|
||||||
|
osc="\033]"
|
||||||
|
if [[ $TERM == screen* ]]; then osc="\033Ptmux;\033\033]"; fi
|
||||||
|
st="\a"
|
||||||
|
if [[ $TERM == screen* ]]; then st="\a"; fi
|
||||||
|
|
||||||
|
|
||||||
|
tmp=$(mktemp)
|
||||||
|
[ -f 'build/build.ninja' ] && CMAKENINJA=TRUE
|
||||||
|
# or "fswatch -0 . -e build/ -e .git"
|
||||||
|
find src/ | entr printf '\0' | while read -d ""; do
|
||||||
|
clear
|
||||||
|
echo '===================================================='
|
||||||
|
if [[ $CMAKENINJA ]]; then
|
||||||
|
ninja -Cbuild hb-shape hb-view && {
|
||||||
|
build/hb-shape $@
|
||||||
|
if [ $img ]; then
|
||||||
|
build/hb-view $@ -O png -o $tmp
|
||||||
|
printf "\n${osc}1337;File=;inline=1:`cat $tmp | base64`${st}\n"
|
||||||
|
else
|
||||||
|
build/hb-view $@
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
else
|
||||||
|
make -Cbuild/src -j5 -s lib && {
|
||||||
|
build/util/hb-shape $@
|
||||||
|
if [ $img ]; then
|
||||||
|
build/util/hb-view $@ -O png -o $tmp
|
||||||
|
printf "\n${osc}1337;File=;inline=1:`cat $tmp | base64`${st}\n"
|
||||||
|
else
|
||||||
|
build/util/hb-view $@
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
read -n 1 -p "[C]heck, [D]ebug, [R]estart, [Q]uit? " answer
|
||||||
|
case "$answer" in
|
||||||
|
c|C )
|
||||||
|
if [[ $CMAKENINJA ]]; then
|
||||||
|
CTEST_OUTPUT_ON_FAILURE=1 CTEST_PARALLEL_LEVEL=5 ninja -Cbuild test
|
||||||
|
else
|
||||||
|
make -Cbuild -j5 check && .ci/fail.sh
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
d|D )
|
||||||
|
if [[ $CMAKENINJA ]]; then
|
||||||
|
echo "Not supported on cmake builds yet"
|
||||||
|
else
|
||||||
|
build/libtool --mode=execute $GDB -- build/util/hb-shape $@
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
r|R )
|
||||||
|
src/dev-run.sh $@
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
esac
|
43
src/dump-indic-data.cc
Normal file
43
src/dump-indic-data.cc
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hb-ot-shape-complex-indic-private.hh"
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
|
||||||
|
{
|
||||||
|
hb_glyph_info_t info;
|
||||||
|
info.codepoint = u;
|
||||||
|
set_indic_properties (info);
|
||||||
|
if (info.indic_category() != INDIC_SYLLABIC_CATEGORY_OTHER ||
|
||||||
|
info.indic_position() != INDIC_MATRA_CATEGORY_NOT_APPLICABLE)
|
||||||
|
printf("U+%04X %u %u\n", u,
|
||||||
|
info.indic_category(),
|
||||||
|
info.indic_position());
|
||||||
|
}
|
||||||
|
}
|
43
src/dump-khmer-data.cc
Normal file
43
src/dump-khmer-data.cc
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hb-ot-shape-complex-khmer-private.hh"
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
|
||||||
|
{
|
||||||
|
hb_glyph_info_t info;
|
||||||
|
info.codepoint = u;
|
||||||
|
set_khmer_properties (info);
|
||||||
|
if (info.khmer_category() != INDIC_SYLLABIC_CATEGORY_OTHER ||
|
||||||
|
info.khmer_position() != INDIC_MATRA_CATEGORY_NOT_APPLICABLE)
|
||||||
|
printf("U+%04X %u %u\n", u,
|
||||||
|
info.khmer_category(),
|
||||||
|
info.khmer_position());
|
||||||
|
}
|
||||||
|
}
|
43
src/dump-myanmar-data.cc
Normal file
43
src/dump-myanmar-data.cc
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hb-ot-shape-complex-myanmar-private.hh"
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
|
||||||
|
{
|
||||||
|
hb_glyph_info_t info;
|
||||||
|
info.codepoint = u;
|
||||||
|
set_myanmar_properties (info);
|
||||||
|
if (info.myanmar_category() != INDIC_SYLLABIC_CATEGORY_OTHER ||
|
||||||
|
info.myanmar_position() != INDIC_MATRA_CATEGORY_NOT_APPLICABLE)
|
||||||
|
printf("U+%04X %u %u\n", u,
|
||||||
|
info.myanmar_category(),
|
||||||
|
info.myanmar_position());
|
||||||
|
}
|
||||||
|
}
|
38
src/dump-use-data.cc
Normal file
38
src/dump-use-data.cc
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hb-ot-shape-complex-use-private.hh"
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
|
||||||
|
{
|
||||||
|
unsigned int category = hb_use_get_category (u);
|
||||||
|
if (category != USE_O)
|
||||||
|
printf("U+%04X %u\n", u, category);
|
||||||
|
}
|
||||||
|
}
|
@ -134,7 +134,7 @@ def print_joining_table(f):
|
|||||||
for (start,end) in ranges:
|
for (start,end) in ranges:
|
||||||
if p not in [start>>page_bits, end>>page_bits]: continue
|
if p not in [start>>page_bits, end>>page_bits]: continue
|
||||||
offset = "joining_offset_0x%04xu" % start
|
offset = "joining_offset_0x%04xu" % start
|
||||||
print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return joining_table[u - 0x%04Xu + %s];" % (start, end, start, offset)
|
print " if (hb_in_range<hb_codepoint_t> (u, 0x%04Xu, 0x%04Xu)) return joining_table[u - 0x%04Xu + %s];" % (start, end, start, offset)
|
||||||
print " break;"
|
print " break;"
|
||||||
print ""
|
print ""
|
||||||
print " default:"
|
print " default:"
|
||||||
|
19
src/gen-def.py
Executable file
19
src/gen-def.py
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import io, os, re, sys
|
||||||
|
|
||||||
|
headers_content = []
|
||||||
|
for h in os.environ["headers"].split (' '):
|
||||||
|
if h.endswith (".h"):
|
||||||
|
with io.open(h, encoding='utf8') as f: headers_content.append (f.read ())
|
||||||
|
|
||||||
|
result = """EXPORTS
|
||||||
|
%s
|
||||||
|
LIBRARY lib%s-0.dll""" % (
|
||||||
|
"\n".join (sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M))),
|
||||||
|
sys.argv[1].replace ('.def', '')
|
||||||
|
)
|
||||||
|
|
||||||
|
with open (sys.argv[1], "w") as f: f.write (result)
|
@ -229,13 +229,13 @@ print " {"
|
|||||||
pages = set([u>>page_bits for u in starts+ends+singles.keys()])
|
pages = set([u>>page_bits for u in starts+ends+singles.keys()])
|
||||||
for p in sorted(pages):
|
for p in sorted(pages):
|
||||||
print " case 0x%0Xu:" % p
|
print " case 0x%0Xu:" % p
|
||||||
for (start,end) in zip (starts, ends):
|
|
||||||
if p not in [start>>page_bits, end>>page_bits]: continue
|
|
||||||
offset = "indic_offset_0x%04xu" % start
|
|
||||||
print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset)
|
|
||||||
for u,d in singles.items ():
|
for u,d in singles.items ():
|
||||||
if p != u>>page_bits: continue
|
if p != u>>page_bits: continue
|
||||||
print " if (unlikely (u == 0x%04Xu)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]])
|
print " if (unlikely (u == 0x%04Xu)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]])
|
||||||
|
for (start,end) in zip (starts, ends):
|
||||||
|
if p not in [start>>page_bits, end>>page_bits]: continue
|
||||||
|
offset = "indic_offset_0x%04xu" % start
|
||||||
|
print " if (hb_in_range<hb_codepoint_t> (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset)
|
||||||
print " break;"
|
print " break;"
|
||||||
print ""
|
print ""
|
||||||
print " default:"
|
print " default:"
|
||||||
|
52
src/gen-unicode-ranges.py
Normal file
52
src/gen-unicode-ranges.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Generates the code for a sorted unicode range array as used in hb-ot-os2-unicode-ranges.hh
|
||||||
|
# Input is a tab seperated list of unicode ranges from the otspec
|
||||||
|
# (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ulunicoderange1).
|
||||||
|
|
||||||
|
import io
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
reload(sys)
|
||||||
|
sys.setdefaultencoding('utf-8')
|
||||||
|
|
||||||
|
print (u"""static Range os2UnicodeRangesSorted[] =
|
||||||
|
{""")
|
||||||
|
|
||||||
|
args = sys.argv[1:]
|
||||||
|
input_file = args[0]
|
||||||
|
|
||||||
|
with io.open(input_file, mode="r", encoding="utf-8") as f:
|
||||||
|
|
||||||
|
all_ranges = [];
|
||||||
|
current_bit = 0
|
||||||
|
while True:
|
||||||
|
line = f.readline().strip()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
fields = re.split(r'\t+', line)
|
||||||
|
if len(fields) == 3:
|
||||||
|
current_bit = fields[0]
|
||||||
|
fields = fields[1:]
|
||||||
|
elif len(fields) > 3:
|
||||||
|
raise Error("bad input :(.")
|
||||||
|
|
||||||
|
name = fields[0]
|
||||||
|
ranges = re.split("-", fields[1])
|
||||||
|
if len(ranges) != 2:
|
||||||
|
raise Error("bad input :(.")
|
||||||
|
|
||||||
|
v = tuple((int(ranges[0], 16), int(ranges[1], 16), int(current_bit), name))
|
||||||
|
all_ranges.append(v)
|
||||||
|
|
||||||
|
all_ranges = sorted(all_ranges, key=lambda t: t[0])
|
||||||
|
|
||||||
|
for ranges in all_ranges:
|
||||||
|
start = ("0x%X" % ranges[0]).rjust(8)
|
||||||
|
end = ("0x%X" % ranges[1]).rjust(8)
|
||||||
|
bit = ("%s" % ranges[2]).rjust(3)
|
||||||
|
|
||||||
|
print " {%s, %s, %s}, // %s" % (start, end, bit, ranges[3])
|
||||||
|
|
||||||
|
print (u"""};""");
|
@ -44,6 +44,7 @@ defaults = ('Other', 'Not_Applicable', 'Cn', 'No_Block')
|
|||||||
# TODO Characters that are not in Unicode Indic files, but used in USE
|
# TODO Characters that are not in Unicode Indic files, but used in USE
|
||||||
data[0][0x034F] = defaults[0]
|
data[0][0x034F] = defaults[0]
|
||||||
data[0][0x2060] = defaults[0]
|
data[0][0x2060] = defaults[0]
|
||||||
|
data[0][0x20F0] = defaults[0]
|
||||||
for u in range (0xFE00, 0xFE0F + 1):
|
for u in range (0xFE00, 0xFE0F + 1):
|
||||||
data[0][u] = defaults[0]
|
data[0][u] = defaults[0]
|
||||||
|
|
||||||
@ -117,6 +118,7 @@ property_names = [
|
|||||||
'Top_And_Right',
|
'Top_And_Right',
|
||||||
'Top_And_Left',
|
'Top_And_Left',
|
||||||
'Top_And_Left_And_Right',
|
'Top_And_Left_And_Right',
|
||||||
|
'Bottom_And_Left',
|
||||||
'Bottom_And_Right',
|
'Bottom_And_Right',
|
||||||
'Top_And_Bottom_And_Right',
|
'Top_And_Bottom_And_Right',
|
||||||
'Overstruck',
|
'Overstruck',
|
||||||
@ -153,7 +155,7 @@ def is_BASE(U, UISC, UGC):
|
|||||||
def is_BASE_IND(U, UISC, UGC):
|
def is_BASE_IND(U, UISC, UGC):
|
||||||
#SPEC-DRAFT return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po)
|
#SPEC-DRAFT return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po)
|
||||||
return (UISC in [Consonant_Dead, Modifying_Letter] or
|
return (UISC in [Consonant_Dead, Modifying_Letter] or
|
||||||
(UGC == Po and not U in [0x104E, 0x2022]) or
|
(UGC == Po and not U in [0x104E, 0x2022, 0x11A3F, 0x11A45]) or
|
||||||
False # SPEC-DRAFT-OUTDATED! U == 0x002D
|
False # SPEC-DRAFT-OUTDATED! U == 0x002D
|
||||||
)
|
)
|
||||||
def is_BASE_NUM(U, UISC, UGC):
|
def is_BASE_NUM(U, UISC, UGC):
|
||||||
@ -177,6 +179,8 @@ def is_CONS_MOD(U, UISC, UGC):
|
|||||||
def is_CONS_SUB(U, UISC, UGC):
|
def is_CONS_SUB(U, UISC, UGC):
|
||||||
#SPEC-DRAFT return UISC == Consonant_Subjoined
|
#SPEC-DRAFT return UISC == Consonant_Subjoined
|
||||||
return UISC == Consonant_Subjoined and UGC != Lo
|
return UISC == Consonant_Subjoined and UGC != Lo
|
||||||
|
def is_CONS_WITH_STACKER(U, UISC, UGC):
|
||||||
|
return UISC == Consonant_With_Stacker
|
||||||
def is_HALANT(U, UISC, UGC):
|
def is_HALANT(U, UISC, UGC):
|
||||||
return UISC in [Virama, Invisible_Stacker]
|
return UISC in [Virama, Invisible_Stacker]
|
||||||
def is_HALANT_NUM(U, UISC, UGC):
|
def is_HALANT_NUM(U, UISC, UGC):
|
||||||
@ -198,9 +202,7 @@ def is_OTHER(U, UISC, UGC):
|
|||||||
def is_Reserved(U, UISC, UGC):
|
def is_Reserved(U, UISC, UGC):
|
||||||
return UGC == 'Cn'
|
return UGC == 'Cn'
|
||||||
def is_REPHA(U, UISC, UGC):
|
def is_REPHA(U, UISC, UGC):
|
||||||
#return UISC == Consonant_Preceding_Repha
|
return UISC in [Consonant_Preceding_Repha, Consonant_Prefixed]
|
||||||
#SPEC-OUTDATED hack to categorize Consonant_With_Stacker and Consonant_Prefixed
|
|
||||||
return UISC in [Consonant_Preceding_Repha, Consonant_With_Stacker, Consonant_Prefixed]
|
|
||||||
def is_SYM(U, UISC, UGC):
|
def is_SYM(U, UISC, UGC):
|
||||||
if U == 0x25CC: return False #SPEC-DRAFT
|
if U == 0x25CC: return False #SPEC-DRAFT
|
||||||
#SPEC-DRAFT return UGC in [So, Sc] or UISC == Symbol_Letter
|
#SPEC-DRAFT return UGC in [So, Sc] or UISC == Symbol_Letter
|
||||||
@ -210,11 +212,13 @@ def is_SYM_MOD(U, UISC, UGC):
|
|||||||
def is_VARIATION_SELECTOR(U, UISC, UGC):
|
def is_VARIATION_SELECTOR(U, UISC, UGC):
|
||||||
return 0xFE00 <= U <= 0xFE0F
|
return 0xFE00 <= U <= 0xFE0F
|
||||||
def is_VOWEL(U, UISC, UGC):
|
def is_VOWEL(U, UISC, UGC):
|
||||||
|
# https://github.com/roozbehp/unicode-data/issues/6
|
||||||
return (UISC == Pure_Killer or
|
return (UISC == Pure_Killer or
|
||||||
(UGC != Lo and UISC in [Vowel, Vowel_Dependent]))
|
(UGC != Lo and UISC in [Vowel, Vowel_Dependent] and U not in [0xAA29]))
|
||||||
def is_VOWEL_MOD(U, UISC, UGC):
|
def is_VOWEL_MOD(U, UISC, UGC):
|
||||||
|
# https://github.com/roozbehp/unicode-data/issues/6
|
||||||
return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or
|
return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or
|
||||||
(UGC != Lo and UISC == Bindu))
|
(UGC != Lo and (UISC == Bindu or U in [0xAA29])))
|
||||||
|
|
||||||
use_mapping = {
|
use_mapping = {
|
||||||
'B': is_BASE,
|
'B': is_BASE,
|
||||||
@ -227,6 +231,7 @@ use_mapping = {
|
|||||||
'M': is_CONS_MED,
|
'M': is_CONS_MED,
|
||||||
'CM': is_CONS_MOD,
|
'CM': is_CONS_MOD,
|
||||||
'SUB': is_CONS_SUB,
|
'SUB': is_CONS_SUB,
|
||||||
|
'CS': is_CONS_WITH_STACKER,
|
||||||
'H': is_HALANT,
|
'H': is_HALANT,
|
||||||
'HN': is_HALANT_NUM,
|
'HN': is_HALANT_NUM,
|
||||||
'ZWNJ': is_ZWNJ,
|
'ZWNJ': is_ZWNJ,
|
||||||
@ -250,7 +255,7 @@ use_positions = {
|
|||||||
},
|
},
|
||||||
'M': {
|
'M': {
|
||||||
'Abv': [Top],
|
'Abv': [Top],
|
||||||
'Blw': [Bottom],
|
'Blw': [Bottom, Bottom_And_Left],
|
||||||
'Pst': [Right],
|
'Pst': [Right],
|
||||||
'Pre': [Left],
|
'Pre': [Left],
|
||||||
},
|
},
|
||||||
@ -292,12 +297,23 @@ def map_to_use(data):
|
|||||||
if U == 0x17DD: UISC = Vowel_Dependent
|
if U == 0x17DD: UISC = Vowel_Dependent
|
||||||
if 0x1CE2 <= U <= 0x1CE8: UISC = Cantillation_Mark
|
if 0x1CE2 <= U <= 0x1CE8: UISC = Cantillation_Mark
|
||||||
|
|
||||||
|
# TODO: https://github.com/harfbuzz/harfbuzz/pull/627
|
||||||
|
if 0x1BF2 <= U <= 0x1BF3: UISC = Nukta; UIPC = Bottom
|
||||||
|
|
||||||
# TODO: U+1CED should only be allowed after some of
|
# TODO: U+1CED should only be allowed after some of
|
||||||
# the nasalization marks, maybe only for U+1CE9..U+1CF1.
|
# the nasalization marks, maybe only for U+1CE9..U+1CF1.
|
||||||
if U == 0x1CED: UISC = Tone_Mark
|
if U == 0x1CED: UISC = Tone_Mark
|
||||||
|
|
||||||
evals = [(k, v(U,UISC,UGC)) for k,v in items]
|
# TODO: https://github.com/harfbuzz/harfbuzz/issues/525
|
||||||
values = [k for k,v in evals if v]
|
if U == 0x1A7F: UISC = Consonant_Final; UIPC = Bottom
|
||||||
|
|
||||||
|
# TODO: https://github.com/harfbuzz/harfbuzz/pull/609
|
||||||
|
if U == 0x20F0: UISC = Cantillation_Mark; UIPC = Top
|
||||||
|
|
||||||
|
# TODO: https://github.com/harfbuzz/harfbuzz/pull/626
|
||||||
|
if U == 0xA8B4: UISC = Consonant_Medial
|
||||||
|
|
||||||
|
values = [k for k,v in items if v(U,UISC,UGC)]
|
||||||
assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values)
|
assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values)
|
||||||
USE = values[0]
|
USE = values[0]
|
||||||
|
|
||||||
@ -336,12 +352,6 @@ def map_to_use(data):
|
|||||||
defaults = ('O', 'No_Block')
|
defaults = ('O', 'No_Block')
|
||||||
data = map_to_use(data)
|
data = map_to_use(data)
|
||||||
|
|
||||||
# Remove the outliers
|
|
||||||
singles = {}
|
|
||||||
for u in [0x034F, 0x25CC, 0x1107F]:
|
|
||||||
singles[u] = data[u]
|
|
||||||
del data[u]
|
|
||||||
|
|
||||||
print "/* == Start of generated table == */"
|
print "/* == Start of generated table == */"
|
||||||
print "/*"
|
print "/*"
|
||||||
print " * The following table is generated by running:"
|
print " * The following table is generated by running:"
|
||||||
@ -439,20 +449,17 @@ page_bits = 12
|
|||||||
print "}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy)
|
print "}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy)
|
||||||
print
|
print
|
||||||
print "USE_TABLE_ELEMENT_TYPE"
|
print "USE_TABLE_ELEMENT_TYPE"
|
||||||
print "hb_use_get_categories (hb_codepoint_t u)"
|
print "hb_use_get_category (hb_codepoint_t u)"
|
||||||
print "{"
|
print "{"
|
||||||
print " switch (u >> %d)" % page_bits
|
print " switch (u >> %d)" % page_bits
|
||||||
print " {"
|
print " {"
|
||||||
pages = set([u>>page_bits for u in starts+ends+singles.keys()])
|
pages = set([u>>page_bits for u in starts+ends])
|
||||||
for p in sorted(pages):
|
for p in sorted(pages):
|
||||||
print " case 0x%0Xu:" % p
|
print " case 0x%0Xu:" % p
|
||||||
for (start,end) in zip (starts, ends):
|
for (start,end) in zip (starts, ends):
|
||||||
if p not in [start>>page_bits, end>>page_bits]: continue
|
if p not in [start>>page_bits, end>>page_bits]: continue
|
||||||
offset = "use_offset_0x%04xu" % start
|
offset = "use_offset_0x%04xu" % start
|
||||||
print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return use_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset)
|
print " if (hb_in_range<hb_codepoint_t> (u, 0x%04Xu, 0x%04Xu)) return use_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset)
|
||||||
for u,d in singles.items ():
|
|
||||||
if p != u>>page_bits: continue
|
|
||||||
print " if (unlikely (u == 0x%04Xu)) return %s;" % (u, d[0])
|
|
||||||
print " break;"
|
print " break;"
|
||||||
print ""
|
print ""
|
||||||
print " default:"
|
print " default:"
|
||||||
|
82
src/harfbuzz-config.cmake.in
Normal file
82
src/harfbuzz-config.cmake.in
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# Set these variables so that the `${prefix}/lib` expands to something we can
|
||||||
|
# remove.
|
||||||
|
set(_harfbuzz_remove_string "REMOVE_ME")
|
||||||
|
set(exec_prefix "${_harfbuzz_remove_string}")
|
||||||
|
set(prefix "${_harfbuzz_remove_string}")
|
||||||
|
|
||||||
|
# Compute the installation prefix by stripping components from our current
|
||||||
|
# location.
|
||||||
|
get_filename_component(_harfbuzz_prefix "${CMAKE_CURRENT_LIST_DIR}" DIRECTORY)
|
||||||
|
get_filename_component(_harfbuzz_prefix "${_harfbuzz_prefix}" DIRECTORY)
|
||||||
|
set(_harfbuzz_libdir "@libdir@")
|
||||||
|
string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_libdir "${_harfbuzz_libdir}")
|
||||||
|
set(_harfbuzz_libdir_iter "${_harfbuzz_libdir}")
|
||||||
|
while (_harfbuzz_libdir_iter)
|
||||||
|
get_filename_component(_harfbuzz_libdir_iter "${_harfbuzz_libdir_iter}" DIRECTORY)
|
||||||
|
get_filename_component(_harfbuzz_prefix "${_harfbuzz_prefix}" DIRECTORY)
|
||||||
|
endwhile ()
|
||||||
|
unset(_harfbuzz_libdir_iter)
|
||||||
|
|
||||||
|
# Get the include subdir.
|
||||||
|
set(_harfbuzz_includedir "@includedir@")
|
||||||
|
string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_includedir "${_harfbuzz_includedir}")
|
||||||
|
|
||||||
|
# Extract version information from libtool.
|
||||||
|
set(_harfbuzz_version_info "@HB_LIBTOOL_VERSION_INFO@")
|
||||||
|
string(REPLACE ":" ";" _harfbuzz_version_info "${_harfbuzz_version_info}")
|
||||||
|
list(GET _harfbuzz_version_info 0
|
||||||
|
_harfbuzz_current)
|
||||||
|
list(GET _harfbuzz_version_info 1
|
||||||
|
_harfbuzz_revision)
|
||||||
|
list(GET _harfbuzz_version_info 2
|
||||||
|
_harfbuzz_age)
|
||||||
|
unset(_harfbuzz_version_info)
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
set(_harfbuzz_lib_suffix ".0${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||||
|
elseif (UNIX)
|
||||||
|
set(_harfbuzz_lib_suffix "${CMAKE_SHARED_LIBRARY_SUFFIX}.0.${_harfbuzz_current}.${_harfbuzz_revision}")
|
||||||
|
else ()
|
||||||
|
# Unsupported.
|
||||||
|
set(harfbuzz_FOUND 0)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Add the libraries.
|
||||||
|
add_library(harfbuzz::harfbuzz SHARED IMPORTED)
|
||||||
|
set_target_properties(harfbuzz::harfbuzz PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||||
|
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}")
|
||||||
|
|
||||||
|
add_library(harfbuzz::icu SHARED IMPORTED)
|
||||||
|
set_target_properties(harfbuzz::icu PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||||
|
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
||||||
|
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-icu${_harfbuzz_lib_suffix}")
|
||||||
|
|
||||||
|
add_library(harfbuzz::subset SHARED IMPORTED)
|
||||||
|
set_target_properties(harfbuzz::subset PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||||
|
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
||||||
|
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-subset${_harfbuzz_lib_suffix}")
|
||||||
|
|
||||||
|
# Only add the gobject library if it was built.
|
||||||
|
set(_harfbuzz_have_gobject "@have_gobject@")
|
||||||
|
if (_harfbuzz_have_gobject)
|
||||||
|
add_library(harfbuzz::gobject SHARED IMPORTED)
|
||||||
|
set_target_properties(harfbuzz::gobject PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||||
|
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
||||||
|
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-gobject${_harfbuzz_lib_suffix}")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Clean out variables we used in our scope.
|
||||||
|
unset(_harfbuzz_lib_suffix)
|
||||||
|
unset(_harfbuzz_current)
|
||||||
|
unset(_harfbuzz_revision)
|
||||||
|
unset(_harfbuzz_age)
|
||||||
|
unset(_harfbuzz_includedir)
|
||||||
|
unset(_harfbuzz_libdir)
|
||||||
|
unset(_harfbuzz_prefix)
|
||||||
|
unset(exec_prefix)
|
||||||
|
unset(prefix)
|
||||||
|
unset(_harfbuzz_remove_string)
|
12
src/harfbuzz-subset.pc.in
Normal file
12
src/harfbuzz-subset.pc.in
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
prefix=%prefix%
|
||||||
|
exec_prefix=%exec_prefix%
|
||||||
|
libdir=%libdir%
|
||||||
|
includedir=%includedir%
|
||||||
|
|
||||||
|
Name: harfbuzz
|
||||||
|
Description: HarfBuzz font subsetter
|
||||||
|
Version: %VERSION%
|
||||||
|
|
||||||
|
Requires: harfbuzz
|
||||||
|
Libs: -L${libdir} -lharfbuzz-subset
|
||||||
|
Cflags: -I${includedir}/harfbuzz
|
@ -8,6 +8,6 @@ Description: HarfBuzz text shaping library
|
|||||||
Version: %VERSION%
|
Version: %VERSION%
|
||||||
|
|
||||||
Libs: -L${libdir} -lharfbuzz
|
Libs: -L${libdir} -lharfbuzz
|
||||||
Libs.private: %libs_private%
|
Libs.private: -lm %libs_private%
|
||||||
Requires.private: %requires_private%
|
Requires.private: %requires_private%
|
||||||
Cflags: -I${includedir}/harfbuzz
|
Cflags: -I${includedir}/harfbuzz
|
||||||
|
80
src/hb-aat-layout-ankr-table.hh
Normal file
80
src/hb-aat-layout-ankr-table.hh
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2018 Ebrahim Byagowi
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_AAT_LAYOUT_ANKR_TABLE_HH
|
||||||
|
#define HB_AAT_LAYOUT_ANKR_TABLE_HH
|
||||||
|
|
||||||
|
#include "hb-aat-layout-common-private.hh"
|
||||||
|
|
||||||
|
#define HB_AAT_TAG_ankr HB_TAG('a','n','k','r')
|
||||||
|
|
||||||
|
|
||||||
|
namespace AAT {
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ankr -- Anchor point
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Anchor
|
||||||
|
{
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this));
|
||||||
|
}
|
||||||
|
|
||||||
|
FWORD xCoordinate;
|
||||||
|
FWORD yCoordinate;
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (4);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ankr
|
||||||
|
{
|
||||||
|
static const hb_tag_t tableTag = HB_AAT_TAG_ankr;
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this) && version == 0 &&
|
||||||
|
lookupTable.sanitize (c, this) &&
|
||||||
|
anchors.sanitize (c, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT16 version; /* Version number (set to zero) */
|
||||||
|
HBUINT16 flags; /* Flags (currently unused; set to zero) */
|
||||||
|
LOffsetTo<Lookup<HBUINT16> > lookupTable; /* Offset to the table's lookup table */
|
||||||
|
LOffsetTo<ArrayOf<Anchor, HBUINT32> >
|
||||||
|
anchors; /* Offset to the glyph data table */
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (12);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace AAT */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HB_AAT_LAYOUT_ANKR_TABLE_HH */
|
728
src/hb-aat-layout-common-private.hh
Normal file
728
src/hb-aat-layout-common-private.hh
Normal file
@ -0,0 +1,728 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2017 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_LAYOUT_COMMON_PRIVATE_HH
|
||||||
|
#define HB_AAT_LAYOUT_COMMON_PRIVATE_HH
|
||||||
|
|
||||||
|
#include "hb-aat-layout-private.hh"
|
||||||
|
|
||||||
|
|
||||||
|
namespace AAT {
|
||||||
|
|
||||||
|
using namespace OT;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Binary Searching Tables
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct BinSearchHeader
|
||||||
|
{
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this));
|
||||||
|
}
|
||||||
|
|
||||||
|
HBUINT16 unitSize; /* Size of a lookup unit for this search in bytes. */
|
||||||
|
HBUINT16 nUnits; /* Number of units of the preceding size to be searched. */
|
||||||
|
HBUINT16 searchRange; /* The value of unitSize times the largest power of 2
|
||||||
|
* that is less than or equal to the value of nUnits. */
|
||||||
|
HBUINT16 entrySelector; /* The log base 2 of the largest power of 2 less than
|
||||||
|
* or equal to the value of nUnits. */
|
||||||
|
HBUINT16 rangeShift; /* The value of unitSize times the difference of the
|
||||||
|
* value of nUnits minus the largest power of 2 less
|
||||||
|
* than or equal to the value of nUnits. */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (10);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
struct BinSearchArrayOf
|
||||||
|
{
|
||||||
|
inline const Type& operator [] (unsigned int i) const
|
||||||
|
{
|
||||||
|
if (unlikely (i >= header.nUnits)) return Null(Type);
|
||||||
|
return StructAtOffset<Type> (bytes, i * header.unitSize);
|
||||||
|
}
|
||||||
|
inline Type& operator [] (unsigned int i)
|
||||||
|
{
|
||||||
|
return StructAtOffset<Type> (bytes, i * header.unitSize);
|
||||||
|
}
|
||||||
|
inline unsigned int get_size (void) const
|
||||||
|
{ return header.static_size + header.nUnits * header.unitSize; }
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (unlikely (!sanitize_shallow (c))) return_trace (false);
|
||||||
|
|
||||||
|
/* Note: for structs that do not reference other structs,
|
||||||
|
* we do not need to call their sanitize() as we already did
|
||||||
|
* a bound check on the aggregate array size. We just include
|
||||||
|
* a small unreachable expression to make sure the structs
|
||||||
|
* pointed to do have a simple sanitize(), ie. they do not
|
||||||
|
* reference other structs via offsets.
|
||||||
|
*/
|
||||||
|
(void) (false && StructAtOffset<Type> (bytes, 0).sanitize (c));
|
||||||
|
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (unlikely (!sanitize_shallow (c))) return_trace (false);
|
||||||
|
unsigned int count = header.nUnits;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
if (unlikely (!(*this)[i].sanitize (c, base)))
|
||||||
|
return_trace (false);
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline const Type *bsearch (const T &key) const
|
||||||
|
{
|
||||||
|
unsigned int size = header.unitSize;
|
||||||
|
int min = 0, max = (int) header.nUnits - 1;
|
||||||
|
while (min <= max)
|
||||||
|
{
|
||||||
|
int mid = (min + max) / 2;
|
||||||
|
const Type *p = (const Type *) (((const char *) bytes) + (mid * size));
|
||||||
|
int c = p->cmp (key);
|
||||||
|
if (c < 0)
|
||||||
|
max = mid - 1;
|
||||||
|
else if (c > 0)
|
||||||
|
min = mid + 1;
|
||||||
|
else
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (header.sanitize (c) &&
|
||||||
|
Type::static_size >= header.unitSize &&
|
||||||
|
c->check_array (bytes, header.unitSize, header.nUnits));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BinSearchHeader header;
|
||||||
|
HBUINT8 bytes[VAR];
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_ARRAY (10, bytes);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO Move this to hb-open-type-private.hh and use it in ArrayOf, HeadlessArrayOf,
|
||||||
|
* and other places around the code base?? */
|
||||||
|
template <typename Type>
|
||||||
|
struct UnsizedArrayOf
|
||||||
|
{
|
||||||
|
inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; }
|
||||||
|
inline Type& operator [] (unsigned int i) { return arrayZ[i]; }
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
|
||||||
|
|
||||||
|
/* Note: for structs that do not reference other structs,
|
||||||
|
* we do not need to call their sanitize() as we already did
|
||||||
|
* a bound check on the aggregate array size. We just include
|
||||||
|
* a small unreachable expression to make sure the structs
|
||||||
|
* pointed to do have a simple sanitize(), ie. they do not
|
||||||
|
* reference other structs via offsets.
|
||||||
|
*/
|
||||||
|
(void) (false && arrayZ[0].sanitize (c));
|
||||||
|
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
if (unlikely (!arrayZ[i].sanitize (c, base)))
|
||||||
|
return_trace (false);
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
|
||||||
|
return_trace (false);
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Type arrayZ[VAR];
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_ARRAY (0, arrayZ);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Unsized array of offset's */
|
||||||
|
template <typename Type, typename OffsetType>
|
||||||
|
struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType> > {};
|
||||||
|
|
||||||
|
/* Unsized array of offsets relative to the beginning of the array itself. */
|
||||||
|
template <typename Type, typename OffsetType>
|
||||||
|
struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType>
|
||||||
|
{
|
||||||
|
inline const Type& operator [] (unsigned int i) const
|
||||||
|
{
|
||||||
|
return this+this->arrayZ[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this)));
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this, user_data)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup Table
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename T> struct Lookup;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct LookupFormat0
|
||||||
|
{
|
||||||
|
friend struct Lookup<T>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
|
||||||
|
{
|
||||||
|
if (unlikely (glyph_id >= num_glyphs)) return nullptr;
|
||||||
|
return &arrayZ[glyph_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (arrayZ.sanitize (c, c->num_glyphs));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT16 format; /* Format identifier--format = 0 */
|
||||||
|
UnsizedArrayOf<T>
|
||||||
|
arrayZ; /* Array of lookup values, indexed by glyph index. */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_ARRAY (2, arrayZ);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct LookupSegmentSingle
|
||||||
|
{
|
||||||
|
inline int cmp (hb_codepoint_t g) const {
|
||||||
|
return g < first ? -1 : g <= last ? 0 : +1 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this) && value.sanitize (c));
|
||||||
|
}
|
||||||
|
|
||||||
|
GlyphID last; /* Last GlyphID in this segment */
|
||||||
|
GlyphID first; /* First GlyphID in this segment */
|
||||||
|
T value; /* The lookup value (only one) */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (4 + T::static_size);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct LookupFormat2
|
||||||
|
{
|
||||||
|
friend struct Lookup<T>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline const T* get_value (hb_codepoint_t glyph_id) const
|
||||||
|
{
|
||||||
|
const LookupSegmentSingle<T> *v = segments.bsearch (glyph_id);
|
||||||
|
return v ? &v->value : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (segments.sanitize (c));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT16 format; /* Format identifier--format = 2 */
|
||||||
|
BinSearchArrayOf<LookupSegmentSingle<T> >
|
||||||
|
segments; /* The actual segments. These must already be sorted,
|
||||||
|
* according to the first word in each one (the last
|
||||||
|
* glyph in each segment). */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_ARRAY (8, segments);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct LookupSegmentArray
|
||||||
|
{
|
||||||
|
inline const T* get_value (hb_codepoint_t glyph_id, const void *base) const
|
||||||
|
{
|
||||||
|
return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int cmp (hb_codepoint_t g) const {
|
||||||
|
return g < first ? -1 : g <= last ? 0 : +1 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this) &&
|
||||||
|
first <= last &&
|
||||||
|
valuesZ.sanitize (c, base, last - first + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
GlyphID last; /* Last GlyphID in this segment */
|
||||||
|
GlyphID first; /* First GlyphID in this segment */
|
||||||
|
OffsetTo<UnsizedArrayOf<T> >
|
||||||
|
valuesZ; /* A 16-bit offset from the start of
|
||||||
|
* the table to the data. */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (6);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct LookupFormat4
|
||||||
|
{
|
||||||
|
friend struct Lookup<T>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline const T* get_value (hb_codepoint_t glyph_id) const
|
||||||
|
{
|
||||||
|
const LookupSegmentArray<T> *v = segments.bsearch (glyph_id);
|
||||||
|
return v ? v->get_value (glyph_id, this) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (segments.sanitize (c, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT16 format; /* Format identifier--format = 2 */
|
||||||
|
BinSearchArrayOf<LookupSegmentArray<T> >
|
||||||
|
segments; /* The actual segments. These must already be sorted,
|
||||||
|
* according to the first word in each one (the last
|
||||||
|
* glyph in each segment). */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_ARRAY (8, segments);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct LookupSingle
|
||||||
|
{
|
||||||
|
inline int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this) && value.sanitize (c));
|
||||||
|
}
|
||||||
|
|
||||||
|
GlyphID glyph; /* Last GlyphID */
|
||||||
|
T value; /* The lookup value (only one) */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (4 + T::static_size);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct LookupFormat6
|
||||||
|
{
|
||||||
|
friend struct Lookup<T>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline const T* get_value (hb_codepoint_t glyph_id) const
|
||||||
|
{
|
||||||
|
const LookupSingle<T> *v = entries.bsearch (glyph_id);
|
||||||
|
return v ? &v->value : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (entries.sanitize (c));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT16 format; /* Format identifier--format = 6 */
|
||||||
|
BinSearchArrayOf<LookupSingle<T> >
|
||||||
|
entries; /* The actual entries, sorted by glyph index. */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_ARRAY (8, entries);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct LookupFormat8
|
||||||
|
{
|
||||||
|
friend struct Lookup<T>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline const T* get_value (hb_codepoint_t glyph_id) const
|
||||||
|
{
|
||||||
|
return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ? &valueArrayZ[glyph_id - firstGlyph] : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT16 format; /* Format identifier--format = 6 */
|
||||||
|
GlyphID firstGlyph; /* First glyph index included in the trimmed array. */
|
||||||
|
HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
|
||||||
|
* glyph minus the value of firstGlyph plus 1). */
|
||||||
|
UnsizedArrayOf<T>
|
||||||
|
valueArrayZ; /* The lookup values (indexed by the glyph index
|
||||||
|
* minus the value of firstGlyph). */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_ARRAY (6, valueArrayZ);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Lookup
|
||||||
|
{
|
||||||
|
inline const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
|
||||||
|
{
|
||||||
|
switch (u.format) {
|
||||||
|
case 0: return u.format0.get_value (glyph_id, num_glyphs);
|
||||||
|
case 2: return u.format2.get_value (glyph_id);
|
||||||
|
case 4: return u.format4.get_value (glyph_id);
|
||||||
|
case 6: return u.format6.get_value (glyph_id);
|
||||||
|
case 8: return u.format8.get_value (glyph_id);
|
||||||
|
default:return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (!u.format.sanitize (c)) return_trace (false);
|
||||||
|
switch (u.format) {
|
||||||
|
case 0: return_trace (u.format0.sanitize (c));
|
||||||
|
case 2: return_trace (u.format2.sanitize (c));
|
||||||
|
case 4: return_trace (u.format4.sanitize (c));
|
||||||
|
case 6: return_trace (u.format6.sanitize (c));
|
||||||
|
case 8: return_trace (u.format8.sanitize (c));
|
||||||
|
default:return_trace (true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
union {
|
||||||
|
HBUINT16 format; /* Format identifier */
|
||||||
|
LookupFormat0<T> format0;
|
||||||
|
LookupFormat2<T> format2;
|
||||||
|
LookupFormat4<T> format4;
|
||||||
|
LookupFormat6<T> format6;
|
||||||
|
LookupFormat8<T> format8;
|
||||||
|
} u;
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_UNION (2, format);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extended State Table
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
/* Note, we don't recurse-sanitize data because we don't access it.
|
||||||
|
* That said, in our DEFINE_SIZE_STATIC we access T::static_size,
|
||||||
|
* which ensures that data has a simple sanitize(). To be determined
|
||||||
|
* if I need to remove that as well. */
|
||||||
|
return_trace (c->check_struct (this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
HBUINT16 newState; /* Byte offset from beginning of state table
|
||||||
|
* to the new state. Really?!?! Or just state
|
||||||
|
* number? The latter in morx for sure. */
|
||||||
|
HBUINT16 flags; /* Table specific. */
|
||||||
|
T data; /* Optional offsets to per-glyph tables. */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (4 + T::static_size);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Entry<void>
|
||||||
|
{
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
HBUINT16 newState; /* Byte offset from beginning of state table to the new state. */
|
||||||
|
HBUINT16 flags; /* Table specific. */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (4);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Extra>
|
||||||
|
struct StateTable
|
||||||
|
{
|
||||||
|
inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
|
||||||
|
{
|
||||||
|
const HBUINT16 *v = (this+classTable).get_value (glyph_id, num_glyphs);
|
||||||
|
return v ? *v : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Entry<Extra> *get_entries () const
|
||||||
|
{
|
||||||
|
return (this+entryTable).arrayZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Entry<Extra> *get_entryZ (unsigned int state, unsigned int klass) const
|
||||||
|
{
|
||||||
|
if (unlikely (klass >= nClasses)) return nullptr;
|
||||||
|
|
||||||
|
const HBUINT16 *states = (this+stateArrayTable).arrayZ;
|
||||||
|
const Entry<Extra> *entries = (this+entryTable).arrayZ;
|
||||||
|
|
||||||
|
unsigned int entry = states[state * nClasses + klass];
|
||||||
|
|
||||||
|
return &entries[entry];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c,
|
||||||
|
unsigned int *num_entries_out = nullptr) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (unlikely (!(c->check_struct (this) &&
|
||||||
|
classTable.sanitize (c, this)))) return_trace (false);
|
||||||
|
|
||||||
|
const HBUINT16 *states = (this+stateArrayTable).arrayZ;
|
||||||
|
const Entry<Extra> *entries = (this+entryTable).arrayZ;
|
||||||
|
|
||||||
|
unsigned int num_states = 1;
|
||||||
|
unsigned int num_entries = 0;
|
||||||
|
|
||||||
|
unsigned int state = 0;
|
||||||
|
unsigned int entry = 0;
|
||||||
|
while (state < num_states)
|
||||||
|
{
|
||||||
|
if (unlikely (!c->check_array (states,
|
||||||
|
states[0].static_size * nClasses,
|
||||||
|
num_states)))
|
||||||
|
return_trace (false);
|
||||||
|
{ /* Sweep new states. */
|
||||||
|
const HBUINT16 *stop = &states[num_states * nClasses];
|
||||||
|
for (const HBUINT16 *p = &states[state * nClasses]; p < stop; p++)
|
||||||
|
num_entries = MAX<unsigned int> (num_entries, *p + 1);
|
||||||
|
state = num_states;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely (!c->check_array (entries,
|
||||||
|
entries[0].static_size,
|
||||||
|
num_entries)))
|
||||||
|
return_trace (false);
|
||||||
|
{ /* Sweep new entries. */
|
||||||
|
const Entry<Extra> *stop = &entries[num_entries];
|
||||||
|
for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
|
||||||
|
num_states = MAX<unsigned int> (num_states, p->newState + 1);
|
||||||
|
entry = num_entries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_entries_out)
|
||||||
|
*num_entries_out = num_entries;
|
||||||
|
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT32 nClasses; /* Number of classes, which is the number of indices
|
||||||
|
* in a single line in the state array. */
|
||||||
|
OffsetTo<Lookup<HBUINT16>, HBUINT32>
|
||||||
|
classTable; /* Offset to the class table. */
|
||||||
|
OffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT32>
|
||||||
|
stateArrayTable;/* Offset to the state array. */
|
||||||
|
OffsetTo<UnsizedArrayOf<Entry<Extra> >, HBUINT32>
|
||||||
|
entryTable; /* Offset to the entry array. */
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (16);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename EntryData>
|
||||||
|
struct StateTableDriver
|
||||||
|
{
|
||||||
|
inline StateTableDriver (const StateTable<EntryData> &machine_,
|
||||||
|
hb_buffer_t *buffer_,
|
||||||
|
hb_face_t *face_) :
|
||||||
|
machine (machine_),
|
||||||
|
buffer (buffer_),
|
||||||
|
num_glyphs (face_->get_num_glyphs ()) {}
|
||||||
|
|
||||||
|
template <typename context_t>
|
||||||
|
inline void drive (context_t *c)
|
||||||
|
{
|
||||||
|
hb_glyph_info_t *info = buffer->info;
|
||||||
|
|
||||||
|
if (!c->in_place)
|
||||||
|
buffer->clear_output ();
|
||||||
|
|
||||||
|
unsigned int state = 0;
|
||||||
|
bool last_was_dont_advance = false;
|
||||||
|
for (buffer->idx = 0;;)
|
||||||
|
{
|
||||||
|
unsigned int klass = buffer->idx < buffer->len ?
|
||||||
|
machine.get_class (info[buffer->idx].codepoint, num_glyphs) :
|
||||||
|
0 /* End of text */;
|
||||||
|
const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
|
||||||
|
if (unlikely (!entry))
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/* If there's no action and we're just epsilon-transitioning to state 0,
|
||||||
|
* safe to break. */
|
||||||
|
if (c->is_actionable (this, entry) ||
|
||||||
|
!(entry->newState == 0 && entry->flags == context_t::DontAdvance))
|
||||||
|
buffer->unsafe_to_break (buffer->idx - 1, buffer->idx + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unsafe-to-break if end-of-text would kick in here. */
|
||||||
|
if (buffer->idx + 2 <= buffer->len)
|
||||||
|
{
|
||||||
|
const Entry<EntryData> *end_entry = machine.get_entryZ (state, 0);
|
||||||
|
if (c->is_actionable (this, end_entry))
|
||||||
|
buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely (!c->transition (this, entry)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
last_was_dont_advance = (entry->flags & context_t::DontAdvance) && buffer->max_ops-- > 0;
|
||||||
|
|
||||||
|
state = entry->newState;
|
||||||
|
|
||||||
|
if (buffer->idx == buffer->len)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!last_was_dont_advance)
|
||||||
|
buffer->next_glyph ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c->in_place)
|
||||||
|
{
|
||||||
|
for (; buffer->idx < buffer->len;)
|
||||||
|
buffer->next_glyph ();
|
||||||
|
buffer->swap_buffers ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
const StateTable<EntryData> &machine;
|
||||||
|
hb_buffer_t *buffer;
|
||||||
|
unsigned int num_glyphs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct hb_aat_apply_context_t :
|
||||||
|
hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
|
||||||
|
{
|
||||||
|
inline const char *get_name (void) { return "APPLY"; }
|
||||||
|
template <typename T>
|
||||||
|
inline return_t dispatch (const T &obj) { return obj.apply (this); }
|
||||||
|
static return_t default_return_value (void) { return false; }
|
||||||
|
bool stop_sublookup_iteration (return_t r) const { return r; }
|
||||||
|
|
||||||
|
hb_font_t *font;
|
||||||
|
hb_face_t *face;
|
||||||
|
hb_buffer_t *buffer;
|
||||||
|
hb_sanitize_context_t sanitizer;
|
||||||
|
|
||||||
|
/* Unused. For debug tracing only. */
|
||||||
|
unsigned int lookup_index;
|
||||||
|
unsigned int debug_depth;
|
||||||
|
|
||||||
|
inline hb_aat_apply_context_t (hb_font_t *font_,
|
||||||
|
hb_buffer_t *buffer_,
|
||||||
|
hb_blob_t *table) :
|
||||||
|
font (font_), face (font->face), buffer (buffer_),
|
||||||
|
sanitizer (), lookup_index (0), debug_depth (0)
|
||||||
|
{
|
||||||
|
sanitizer.init (table);
|
||||||
|
sanitizer.num_glyphs = face->get_num_glyphs ();
|
||||||
|
sanitizer.start_processing ();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set_lookup_index (unsigned int i) { lookup_index = i; }
|
||||||
|
|
||||||
|
inline ~hb_aat_apply_context_t (void)
|
||||||
|
{
|
||||||
|
sanitizer.end_processing ();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace AAT */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HB_AAT_LAYOUT_COMMON_PRIVATE_HH */
|
384
src/hb-aat-layout-kerx-table.hh
Normal file
384
src/hb-aat-layout-kerx-table.hh
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2018 Google, Inc.
|
||||||
|
* Copyright © 2018 Ebrahim Byagowi
|
||||||
|
*
|
||||||
|
* 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_LAYOUT_KERX_TABLE_HH
|
||||||
|
#define HB_AAT_LAYOUT_KERX_TABLE_HH
|
||||||
|
|
||||||
|
#include "hb-aat-layout-common-private.hh"
|
||||||
|
|
||||||
|
namespace AAT {
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* kerx -- Kerning
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HB_AAT_TAG_kerx HB_TAG('k','e','r','x')
|
||||||
|
|
||||||
|
struct hb_glyph_pair_t
|
||||||
|
{
|
||||||
|
hb_codepoint_t left;
|
||||||
|
hb_codepoint_t right;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KerxPair
|
||||||
|
{
|
||||||
|
inline int get_kerning (void) const
|
||||||
|
{ return value; }
|
||||||
|
|
||||||
|
inline int cmp (const hb_glyph_pair_t &o) const
|
||||||
|
{
|
||||||
|
int ret = left.cmp (o.left);
|
||||||
|
if (ret) return ret;
|
||||||
|
return right.cmp (o.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GlyphID left;
|
||||||
|
GlyphID right;
|
||||||
|
FWORD value;
|
||||||
|
HBUINT16 pad;
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (8);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KerxSubTableFormat0
|
||||||
|
{
|
||||||
|
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
|
||||||
|
{
|
||||||
|
//hb_glyph_pair_t pair = {left, right};
|
||||||
|
//int i = pairs.bsearch (pair);
|
||||||
|
//if (i == -1)
|
||||||
|
return 0;
|
||||||
|
//return pairs[i].get_kerning ();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (pairs.sanitize (c));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BinSearchArrayOf<KerxPair> pairs; /* Array of kerning pairs. */
|
||||||
|
//FIXME: BinSearchArrayOf and its BinSearchHeader should be
|
||||||
|
//modified in a way to accept uint32s
|
||||||
|
public:
|
||||||
|
//DEFINE_SIZE_ARRAY (16, pairs);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KerxAction
|
||||||
|
{
|
||||||
|
HBUINT16 index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KerxSubTableFormat1
|
||||||
|
{
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
//TRACE_SANITIZE (this);
|
||||||
|
//return_trace (stateHeader.sanitize (c));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
StateTable<KerxAction> stateHeader;
|
||||||
|
OffsetTo<ArrayOf<HBUINT16>, HBUINT32> valueTable;
|
||||||
|
|
||||||
|
public:
|
||||||
|
//DEFINE_SIZE_MIN (4);
|
||||||
|
};
|
||||||
|
|
||||||
|
//FIXME: Maybe this can be replaced with Lookup<HBUINT16>?
|
||||||
|
struct KerxClassTable
|
||||||
|
{
|
||||||
|
inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; }
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (firstGlyph.sanitize (c) && classes.sanitize (c));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT16 firstGlyph; /* First glyph in class range. */
|
||||||
|
ArrayOf<HBUINT16> classes; /* Glyph classes. */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_ARRAY (4, classes);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KerxSubTableFormat2
|
||||||
|
{
|
||||||
|
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
|
||||||
|
{
|
||||||
|
unsigned int l = (this+leftClassTable).get_class (left);
|
||||||
|
unsigned int r = (this+leftClassTable).get_class (left);
|
||||||
|
unsigned int offset = l * rowWidth + r * sizeof (FWORD);
|
||||||
|
const FWORD *arr = &(this+array);
|
||||||
|
if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end))
|
||||||
|
return 0;
|
||||||
|
const FWORD *v = &StructAtOffset<FWORD> (arr, offset);
|
||||||
|
if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end))
|
||||||
|
return 0;
|
||||||
|
return *v;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (rowWidth.sanitize (c) &&
|
||||||
|
leftClassTable.sanitize (c, this) &&
|
||||||
|
rightClassTable.sanitize (c, this) &&
|
||||||
|
array.sanitize (c, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT32 rowWidth; /* The width, in bytes, of a row in the table. */
|
||||||
|
LOffsetTo<KerxClassTable>
|
||||||
|
leftClassTable; /* Offset from beginning of this subtable to
|
||||||
|
* left-hand class table. */
|
||||||
|
LOffsetTo<KerxClassTable>
|
||||||
|
rightClassTable;/* Offset from beginning of this subtable to
|
||||||
|
* right-hand class table. */
|
||||||
|
LOffsetTo<FWORD>
|
||||||
|
array; /* Offset from beginning of this subtable to
|
||||||
|
* the start of the kerning array. */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_MIN (16);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KerxSubTableFormat4
|
||||||
|
{
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (rowWidth.sanitize (c) &&
|
||||||
|
leftClassTable.sanitize (c, this) &&
|
||||||
|
rightClassTable.sanitize (c, this) &&
|
||||||
|
array.sanitize (c, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT32 rowWidth; /* The width, in bytes, of a row in the table. */
|
||||||
|
LOffsetTo<KerxClassTable>
|
||||||
|
leftClassTable; /* Offset from beginning of this subtable to
|
||||||
|
* left-hand class table. */
|
||||||
|
LOffsetTo<KerxClassTable>
|
||||||
|
rightClassTable;/* Offset from beginning of this subtable to
|
||||||
|
* right-hand class table. */
|
||||||
|
LOffsetTo<FWORD>
|
||||||
|
array; /* Offset from beginning of this subtable to
|
||||||
|
* the start of the kerning array. */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_MIN (16);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KerxSubTableFormat6
|
||||||
|
{
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
//TRACE_SANITIZE (this);
|
||||||
|
//return_trace ;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT32 flags;
|
||||||
|
HBUINT16 rowCount;
|
||||||
|
HBUINT16 columnCount;
|
||||||
|
HBUINT32 rowIndexTableOffset;
|
||||||
|
HBUINT32 columnIndexTableOffset;
|
||||||
|
HBUINT32 kerningArrayOffset;
|
||||||
|
HBUINT32 kerningVectorOffset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_MIN (24);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KerxSubTable
|
||||||
|
{
|
||||||
|
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case 0: return u.format0.get_kerning (left, right);
|
||||||
|
case 2: return u.format2.get_kerning (left, right, end);
|
||||||
|
default:return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
switch (format) {
|
||||||
|
case 0: return_trace (u.format0.sanitize (c));
|
||||||
|
case 2: return_trace (u.format2.sanitize (c));
|
||||||
|
default:return_trace (true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
union {
|
||||||
|
KerxSubTableFormat0 format0;
|
||||||
|
KerxSubTableFormat2 format2;
|
||||||
|
KerxSubTableFormat4 format4;
|
||||||
|
KerxSubTableFormat6 format6;
|
||||||
|
} u;
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_MIN (0);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
TRACE_APPLY (this);
|
||||||
|
/* TODO */
|
||||||
|
return_trace (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SubTableWrapper
|
||||||
|
{
|
||||||
|
enum coverage_flags_t {
|
||||||
|
COVERAGE_VERTICAL_FLAG = 0x8000u,
|
||||||
|
COVERAGE_CROSSSTREAM_FLAG = 0x4000u,
|
||||||
|
COVERAGE_VARIATION_FLAG = 0x2000u,
|
||||||
|
|
||||||
|
COVERAGE_OVERRIDE_FLAG = 0x0000u, /* Not supported. */
|
||||||
|
|
||||||
|
COVERAGE_CHECK_FLAGS = 0x0700u, //FIXME: Where these two come from?
|
||||||
|
COVERAGE_CHECK_HORIZONTAL = 0x0100u
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT32 length; /* Length of the subtable (including this header). */
|
||||||
|
HBUINT16 coverage; /* Coverage bits. */
|
||||||
|
HBUINT16 format; /* Subtable format. */
|
||||||
|
HBUINT32 tupleIndex; /* The tuple index (used for variations fonts).
|
||||||
|
* This value specifies which tuple this subtable covers. */
|
||||||
|
KerxSubTable subtable; /* Subtable data. */
|
||||||
|
public:
|
||||||
|
inline bool is_horizontal (void) const
|
||||||
|
{ return (coverage & COVERAGE_CHECK_FLAGS) == COVERAGE_CHECK_HORIZONTAL; }
|
||||||
|
|
||||||
|
inline bool is_override (void) const
|
||||||
|
{ return bool (coverage & COVERAGE_OVERRIDE_FLAG); }
|
||||||
|
|
||||||
|
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
|
||||||
|
{ return subtable.get_kerning (left, right, end, format); }
|
||||||
|
|
||||||
|
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
|
||||||
|
{ return is_horizontal () ? get_kerning (left, right, end) : 0; }
|
||||||
|
|
||||||
|
inline unsigned int get_size (void) const { return length; }
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this) &&
|
||||||
|
length >= min_size &&
|
||||||
|
c->check_array (this, 1, length) &&
|
||||||
|
subtable.sanitize (c, format));
|
||||||
|
}
|
||||||
|
DEFINE_SIZE_MIN (12);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
|
||||||
|
{
|
||||||
|
int v = 0;
|
||||||
|
const SubTableWrapper *st = (SubTableWrapper *) data;
|
||||||
|
unsigned int count = nTables;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (st->is_override ())
|
||||||
|
v = 0;
|
||||||
|
v += st->get_h_kerning (left, right, table_length + (const char *) this);
|
||||||
|
st = (SubTableWrapper *) st;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
const SubTableWrapper *st = (SubTableWrapper *) data;
|
||||||
|
unsigned int count = nTables;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (unlikely (!st->sanitize (c)))
|
||||||
|
return_trace (false);
|
||||||
|
st = (SubTableWrapper *) st;
|
||||||
|
}
|
||||||
|
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct accelerator_t
|
||||||
|
{
|
||||||
|
inline void init (hb_face_t *face)
|
||||||
|
{
|
||||||
|
blob = Sanitizer<kerx>().sanitize (face->reference_table (HB_AAT_TAG_kerx));
|
||||||
|
table = Sanitizer<kerx>::lock_instance (blob);
|
||||||
|
table_length = hb_blob_get_length (blob);
|
||||||
|
}
|
||||||
|
inline void fini (void)
|
||||||
|
{
|
||||||
|
hb_blob_destroy (blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
|
||||||
|
{ return table->get_h_kerning (left, right, table_length); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
hb_blob_t *blob;
|
||||||
|
const kerx *table;
|
||||||
|
unsigned int table_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT16 version;
|
||||||
|
HBUINT16 padding;
|
||||||
|
HBUINT32 nTables; /* Number of subtables in the kerning table. */
|
||||||
|
HBUINT8 data[VAR];
|
||||||
|
//ArrayOf<GlyphCoverageArray> subtableGlyphCoverageArray;
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_ARRAY (8, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace AAT */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HB_AAT_LAYOUT_KERX_TABLE_HH */
|
728
src/hb-aat-layout-morx-table.hh
Normal file
728
src/hb-aat-layout-morx-table.hh
Normal file
@ -0,0 +1,728 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2017 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_LAYOUT_MORX_TABLE_HH
|
||||||
|
#define HB_AAT_LAYOUT_MORX_TABLE_HH
|
||||||
|
|
||||||
|
#include "hb-open-type-private.hh"
|
||||||
|
#include "hb-aat-layout-common-private.hh"
|
||||||
|
|
||||||
|
#define HB_AAT_TAG_MORX HB_TAG('m','o','r','x')
|
||||||
|
|
||||||
|
|
||||||
|
namespace AAT {
|
||||||
|
|
||||||
|
using namespace OT;
|
||||||
|
|
||||||
|
|
||||||
|
struct RearrangementSubtable
|
||||||
|
{
|
||||||
|
typedef void EntryData;
|
||||||
|
|
||||||
|
struct driver_context_t
|
||||||
|
{
|
||||||
|
static const bool in_place = true;
|
||||||
|
enum Flags {
|
||||||
|
MarkFirst = 0x8000, /* If set, make the current glyph the first
|
||||||
|
* glyph to be rearranged. */
|
||||||
|
DontAdvance = 0x4000, /* If set, don't advance to the next glyph
|
||||||
|
* before going to the new state. This means
|
||||||
|
* that the glyph index doesn't change, even
|
||||||
|
* if the glyph at that index has changed. */
|
||||||
|
MarkLast = 0x2000, /* If set, make the current glyph the last
|
||||||
|
* glyph to be rearranged. */
|
||||||
|
Reserved = 0x1FF0, /* These bits are reserved and should be set to 0. */
|
||||||
|
Verb = 0x000F, /* The type of rearrangement specified. */
|
||||||
|
};
|
||||||
|
|
||||||
|
inline driver_context_t (const RearrangementSubtable *table) :
|
||||||
|
ret (false),
|
||||||
|
start (0), end (0) {}
|
||||||
|
|
||||||
|
inline bool is_actionable (StateTableDriver<EntryData> *driver,
|
||||||
|
const Entry<EntryData> *entry)
|
||||||
|
{
|
||||||
|
return (entry->flags & Verb) && start < end;
|
||||||
|
}
|
||||||
|
inline bool transition (StateTableDriver<EntryData> *driver,
|
||||||
|
const Entry<EntryData> *entry)
|
||||||
|
{
|
||||||
|
hb_buffer_t *buffer = driver->buffer;
|
||||||
|
unsigned int flags = entry->flags;
|
||||||
|
|
||||||
|
if (flags & MarkFirst)
|
||||||
|
start = buffer->idx;
|
||||||
|
|
||||||
|
if (flags & MarkLast)
|
||||||
|
end = MIN (buffer->idx + 1, buffer->len);
|
||||||
|
|
||||||
|
if ((flags & Verb) && start < end)
|
||||||
|
{
|
||||||
|
/* The following map has two nibbles, for start-side
|
||||||
|
* and end-side. Values of 0,1,2 mean move that many
|
||||||
|
* to the other side. Value of 3 means move 2 and
|
||||||
|
* flip them. */
|
||||||
|
const unsigned char map[16] =
|
||||||
|
{
|
||||||
|
0x00, /* 0 no change */
|
||||||
|
0x10, /* 1 Ax => xA */
|
||||||
|
0x01, /* 2 xD => Dx */
|
||||||
|
0x11, /* 3 AxD => DxA */
|
||||||
|
0x20, /* 4 ABx => xAB */
|
||||||
|
0x30, /* 5 ABx => xBA */
|
||||||
|
0x02, /* 6 xCD => CDx */
|
||||||
|
0x03, /* 7 xCD => DCx */
|
||||||
|
0x12, /* 8 AxCD => CDxA */
|
||||||
|
0x13, /* 9 AxCD => DCxA */
|
||||||
|
0x21, /* 10 ABxD => DxAB */
|
||||||
|
0x31, /* 11 ABxD => DxBA */
|
||||||
|
0x22, /* 12 ABxCD => CDxAB */
|
||||||
|
0x32, /* 13 ABxCD => CDxBA */
|
||||||
|
0x23, /* 14 ABxCD => DCxAB */
|
||||||
|
0x33, /* 15 ABxCD => DCxBA */
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int m = map[flags & Verb];
|
||||||
|
unsigned int l = MIN<unsigned int> (2, m >> 4);
|
||||||
|
unsigned int r = MIN<unsigned int> (2, m & 0x0F);
|
||||||
|
bool reverse_l = 3 == (m >> 4);
|
||||||
|
bool reverse_r = 3 == (m & 0x0F);
|
||||||
|
|
||||||
|
if (end - start >= l + r)
|
||||||
|
{
|
||||||
|
buffer->merge_clusters (start, MIN (buffer->idx + 1, buffer->len));
|
||||||
|
buffer->merge_clusters (start, end);
|
||||||
|
|
||||||
|
hb_glyph_info_t *info = buffer->info;
|
||||||
|
hb_glyph_info_t buf[4];
|
||||||
|
|
||||||
|
memcpy (buf, info + start, l * sizeof (buf[0]));
|
||||||
|
memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
|
||||||
|
|
||||||
|
if (l != r)
|
||||||
|
memmove (info + start + r, info + start + l, (end - start - l - r) * sizeof (buf[0]));
|
||||||
|
|
||||||
|
memcpy (info + start, buf + 2, r * sizeof (buf[0]));
|
||||||
|
memcpy (info + end - l, buf, l * sizeof (buf[0]));
|
||||||
|
if (reverse_l)
|
||||||
|
{
|
||||||
|
buf[0] = info[end - 1];
|
||||||
|
info[end - 1] = info[end - 2];
|
||||||
|
info[end - 2] = buf[0];
|
||||||
|
}
|
||||||
|
if (reverse_r)
|
||||||
|
{
|
||||||
|
buf[0] = info[start];
|
||||||
|
info[start] = info[start + 1];
|
||||||
|
info[start + 1] = buf[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool ret;
|
||||||
|
private:
|
||||||
|
unsigned int start;
|
||||||
|
unsigned int end;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool apply (hb_aat_apply_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_APPLY (this);
|
||||||
|
|
||||||
|
driver_context_t dc (this);
|
||||||
|
|
||||||
|
StateTableDriver<void> driver (machine, c->buffer, c->face);
|
||||||
|
driver.drive (&dc);
|
||||||
|
|
||||||
|
return_trace (dc.ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (machine.sanitize (c));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
StateTable<EntryData> machine;
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (16);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContextualSubtable
|
||||||
|
{
|
||||||
|
struct EntryData
|
||||||
|
{
|
||||||
|
HBUINT16 markIndex; /* Index of the substitution table for the
|
||||||
|
* marked glyph (use 0xFFFF for none). */
|
||||||
|
HBUINT16 currentIndex; /* Index of the substitution table for the
|
||||||
|
* current glyph (use 0xFFFF for none). */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (4);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct driver_context_t
|
||||||
|
{
|
||||||
|
static const bool in_place = true;
|
||||||
|
enum Flags {
|
||||||
|
SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */
|
||||||
|
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
|
||||||
|
* going to the new state. */
|
||||||
|
Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */
|
||||||
|
};
|
||||||
|
|
||||||
|
inline driver_context_t (const ContextualSubtable *table) :
|
||||||
|
ret (false),
|
||||||
|
mark_set (false),
|
||||||
|
mark (0),
|
||||||
|
subs (table+table->substitutionTables) {}
|
||||||
|
|
||||||
|
inline bool is_actionable (StateTableDriver<EntryData> *driver,
|
||||||
|
const Entry<EntryData> *entry)
|
||||||
|
{
|
||||||
|
hb_buffer_t *buffer = driver->buffer;
|
||||||
|
|
||||||
|
if (buffer->idx == buffer->len && !mark_set)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return entry->data.markIndex != 0xFFFF || entry->data.currentIndex != 0xFFFF;
|
||||||
|
}
|
||||||
|
inline bool transition (StateTableDriver<EntryData> *driver,
|
||||||
|
const Entry<EntryData> *entry)
|
||||||
|
{
|
||||||
|
hb_buffer_t *buffer = driver->buffer;
|
||||||
|
|
||||||
|
/* Looks like CoreText applies neither mark nor current substitution for
|
||||||
|
* end-of-text if mark was not explicitly set. */
|
||||||
|
if (buffer->idx == buffer->len && !mark_set)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (entry->data.markIndex != 0xFFFF)
|
||||||
|
{
|
||||||
|
const Lookup<GlyphID> &lookup = subs[entry->data.markIndex];
|
||||||
|
hb_glyph_info_t *info = buffer->info;
|
||||||
|
const GlyphID *replacement = lookup.get_value (info[mark].codepoint, driver->num_glyphs);
|
||||||
|
if (replacement)
|
||||||
|
{
|
||||||
|
buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
|
||||||
|
info[mark].codepoint = *replacement;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (entry->data.currentIndex != 0xFFFF)
|
||||||
|
{
|
||||||
|
unsigned int idx = MIN (buffer->idx, buffer->len - 1);
|
||||||
|
const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex];
|
||||||
|
hb_glyph_info_t *info = buffer->info;
|
||||||
|
const GlyphID *replacement = lookup.get_value (info[idx].codepoint, driver->num_glyphs);
|
||||||
|
if (replacement)
|
||||||
|
{
|
||||||
|
info[idx].codepoint = *replacement;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->flags & SetMark)
|
||||||
|
{
|
||||||
|
mark_set = true;
|
||||||
|
mark = buffer->idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool ret;
|
||||||
|
private:
|
||||||
|
bool mark_set;
|
||||||
|
unsigned int mark;
|
||||||
|
const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32> &subs;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool apply (hb_aat_apply_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_APPLY (this);
|
||||||
|
|
||||||
|
driver_context_t dc (this);
|
||||||
|
|
||||||
|
StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
|
||||||
|
driver.drive (&dc);
|
||||||
|
|
||||||
|
return_trace (dc.ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
|
||||||
|
unsigned int num_entries = 0;
|
||||||
|
if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false);
|
||||||
|
|
||||||
|
unsigned int num_lookups = 0;
|
||||||
|
|
||||||
|
const Entry<EntryData> *entries = machine.get_entries ();
|
||||||
|
for (unsigned int i = 0; i < num_entries; i++)
|
||||||
|
{
|
||||||
|
const EntryData &data = entries[i].data;
|
||||||
|
|
||||||
|
if (data.markIndex != 0xFFFF)
|
||||||
|
num_lookups = MAX<unsigned int> (num_lookups, 1 + data.markIndex);
|
||||||
|
if (data.currentIndex != 0xFFFF)
|
||||||
|
num_lookups = MAX<unsigned int> (num_lookups, 1 + data.currentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return_trace (substitutionTables.sanitize (c, this, num_lookups));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
StateTable<EntryData> machine;
|
||||||
|
OffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32>, HBUINT32>
|
||||||
|
substitutionTables;
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (20);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LigatureSubtable
|
||||||
|
{
|
||||||
|
struct EntryData
|
||||||
|
{
|
||||||
|
HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry
|
||||||
|
* for processing this group, if indicated
|
||||||
|
* by the flags. */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (2);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct driver_context_t
|
||||||
|
{
|
||||||
|
static const bool in_place = false;
|
||||||
|
enum Flags {
|
||||||
|
SetComponent = 0x8000, /* Push this glyph onto the component stack for
|
||||||
|
* eventual processing. */
|
||||||
|
DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the
|
||||||
|
next iteration. */
|
||||||
|
PerformAction = 0x2000, /* Use the ligActionIndex to process a ligature
|
||||||
|
* group. */
|
||||||
|
Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */
|
||||||
|
};
|
||||||
|
enum LigActionFlags {
|
||||||
|
LigActionLast = 0x80000000, /* This is the last action in the list. This also
|
||||||
|
* implies storage. */
|
||||||
|
LigActionStore = 0x40000000, /* Store the ligature at the current cumulated index
|
||||||
|
* in the ligature table in place of the marked
|
||||||
|
* (i.e. currently-popped) glyph. */
|
||||||
|
LigActionOffset = 0x3FFFFFFF, /* A 30-bit value which is sign-extended to 32-bits
|
||||||
|
* and added to the glyph ID, resulting in an index
|
||||||
|
* into the component table. */
|
||||||
|
};
|
||||||
|
|
||||||
|
inline driver_context_t (const LigatureSubtable *table,
|
||||||
|
hb_aat_apply_context_t *c_) :
|
||||||
|
ret (false),
|
||||||
|
c (c_),
|
||||||
|
ligAction (table+table->ligAction),
|
||||||
|
component (table+table->component),
|
||||||
|
ligature (table+table->ligature),
|
||||||
|
match_length (0) {}
|
||||||
|
|
||||||
|
inline bool is_actionable (StateTableDriver<EntryData> *driver,
|
||||||
|
const Entry<EntryData> *entry)
|
||||||
|
{
|
||||||
|
return !!(entry->flags & PerformAction);
|
||||||
|
}
|
||||||
|
inline bool transition (StateTableDriver<EntryData> *driver,
|
||||||
|
const Entry<EntryData> *entry)
|
||||||
|
{
|
||||||
|
hb_buffer_t *buffer = driver->buffer;
|
||||||
|
unsigned int flags = entry->flags;
|
||||||
|
|
||||||
|
if (flags & SetComponent)
|
||||||
|
{
|
||||||
|
if (unlikely (match_length >= ARRAY_LENGTH (match_positions)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Never mark same index twice, in case DontAdvance was used... */
|
||||||
|
if (match_length && match_positions[match_length - 1] == buffer->out_len)
|
||||||
|
match_length--;
|
||||||
|
|
||||||
|
match_positions[match_length++] = buffer->out_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & PerformAction)
|
||||||
|
{
|
||||||
|
unsigned int end = buffer->out_len;
|
||||||
|
unsigned int action_idx = entry->data.ligActionIndex;
|
||||||
|
unsigned int action;
|
||||||
|
unsigned int ligature_idx = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (unlikely (!match_length))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
buffer->move_to (match_positions[--match_length]);
|
||||||
|
|
||||||
|
const HBUINT32 &actionData = ligAction[action_idx];
|
||||||
|
if (unlikely (!actionData.sanitize (&c->sanitizer))) return false;
|
||||||
|
action = actionData;
|
||||||
|
|
||||||
|
uint32_t uoffset = action & LigActionOffset;
|
||||||
|
if (uoffset & 0x20000000)
|
||||||
|
uoffset += 0xC0000000;
|
||||||
|
int32_t offset = (int32_t) uoffset;
|
||||||
|
unsigned int component_idx = buffer->cur().codepoint + offset;
|
||||||
|
|
||||||
|
const HBUINT16 &componentData = component[component_idx];
|
||||||
|
if (unlikely (!componentData.sanitize (&c->sanitizer))) return false;
|
||||||
|
ligature_idx += componentData;
|
||||||
|
|
||||||
|
if (action & (LigActionStore | LigActionLast))
|
||||||
|
{
|
||||||
|
const GlyphID &ligatureData = ligature[ligature_idx];
|
||||||
|
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false;
|
||||||
|
hb_codepoint_t lig = ligatureData;
|
||||||
|
|
||||||
|
match_positions[match_length++] = buffer->out_len;
|
||||||
|
buffer->replace_glyph (lig);
|
||||||
|
|
||||||
|
//ligature_idx = 0; // XXX Yes or no?
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer->skip_glyph ();
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
/* TODO merge_clusters / unsafe_to_break */
|
||||||
|
|
||||||
|
action_idx++;
|
||||||
|
}
|
||||||
|
while (!(action & LigActionLast));
|
||||||
|
buffer->move_to (end);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool ret;
|
||||||
|
private:
|
||||||
|
hb_aat_apply_context_t *c;
|
||||||
|
const UnsizedArrayOf<HBUINT32> &ligAction;
|
||||||
|
const UnsizedArrayOf<HBUINT16> &component;
|
||||||
|
const UnsizedArrayOf<GlyphID> &ligature;
|
||||||
|
unsigned int match_length;
|
||||||
|
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool apply (hb_aat_apply_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_APPLY (this);
|
||||||
|
|
||||||
|
driver_context_t dc (this, c);
|
||||||
|
|
||||||
|
StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
|
||||||
|
driver.drive (&dc);
|
||||||
|
|
||||||
|
return_trace (dc.ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
/* The rest of array sanitizations are done at run-time. */
|
||||||
|
return_trace (c->check_struct (this) && machine.sanitize (c) &&
|
||||||
|
ligAction && component && ligature);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
StateTable<EntryData> machine;
|
||||||
|
OffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT32>
|
||||||
|
ligAction; /* Offset to the ligature action table. */
|
||||||
|
OffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT32>
|
||||||
|
component; /* Offset to the component table. */
|
||||||
|
OffsetTo<UnsizedArrayOf<GlyphID>, HBUINT32>
|
||||||
|
ligature; /* Offset to the actual ligature lists. */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (28);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NoncontextualSubtable
|
||||||
|
{
|
||||||
|
inline bool apply (hb_aat_apply_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_APPLY (this);
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
unsigned int num_glyphs = c->face->get_num_glyphs ();
|
||||||
|
|
||||||
|
hb_glyph_info_t *info = c->buffer->info;
|
||||||
|
unsigned int count = c->buffer->len;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
const GlyphID *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
|
||||||
|
if (replacement)
|
||||||
|
{
|
||||||
|
info[i].codepoint = *replacement;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return_trace (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (substitute.sanitize (c));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Lookup<GlyphID> substitute;
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_MIN (2);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InsertionSubtable
|
||||||
|
{
|
||||||
|
inline bool apply (hb_aat_apply_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_APPLY (this);
|
||||||
|
/* TODO */
|
||||||
|
return_trace (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
/* TODO */
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Feature
|
||||||
|
{
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
HBUINT16 featureType; /* The type of feature. */
|
||||||
|
HBUINT16 featureSetting; /* The feature's setting (aka selector). */
|
||||||
|
HBUINT32 enableFlags; /* Flags for the settings that this feature
|
||||||
|
* and setting enables. */
|
||||||
|
HBUINT32 disableFlags; /* Complement of flags for the settings that this
|
||||||
|
* feature and setting disable. */
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (12);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ChainSubtable
|
||||||
|
{
|
||||||
|
friend struct Chain;
|
||||||
|
|
||||||
|
inline unsigned int get_size (void) const { return length; }
|
||||||
|
inline unsigned int get_type (void) const { return coverage & 0xFF; }
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
Rearrangement = 0,
|
||||||
|
Contextual = 1,
|
||||||
|
Ligature = 2,
|
||||||
|
Noncontextual = 4,
|
||||||
|
Insertion = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void apply (hb_aat_apply_context_t *c) const
|
||||||
|
{
|
||||||
|
dispatch (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename context_t>
|
||||||
|
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 Rearrangement: return_trace (c->dispatch (u.rearrangement));
|
||||||
|
case Contextual: return_trace (c->dispatch (u.contextual));
|
||||||
|
case Ligature: return_trace (c->dispatch (u.ligature));
|
||||||
|
case Noncontextual: return_trace (c->dispatch (u.noncontextual));
|
||||||
|
case Insertion: return_trace (c->dispatch (u.insertion));
|
||||||
|
default: return_trace (c->default_return_value ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (!length.sanitize (c) ||
|
||||||
|
length < min_size ||
|
||||||
|
!c->check_range (this, length))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
|
return_trace (dispatch (c));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT32 length; /* Total subtable length, including this header. */
|
||||||
|
HBUINT32 coverage; /* Coverage flags and subtable type. */
|
||||||
|
HBUINT32 subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */
|
||||||
|
union {
|
||||||
|
RearrangementSubtable rearrangement;
|
||||||
|
ContextualSubtable contextual;
|
||||||
|
LigatureSubtable ligature;
|
||||||
|
NoncontextualSubtable noncontextual;
|
||||||
|
InsertionSubtable insertion;
|
||||||
|
} u;
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_MIN (12);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Chain
|
||||||
|
{
|
||||||
|
inline void apply (hb_aat_apply_context_t *c) const
|
||||||
|
{
|
||||||
|
const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (featureZ, featureZ[0].static_size * featureCount);
|
||||||
|
unsigned int count = subtableCount;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index))
|
||||||
|
{
|
||||||
|
c->set_lookup_index (c->lookup_index + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
subtable->apply (c);
|
||||||
|
subtable = &StructAfter<ChainSubtable> (*subtable);
|
||||||
|
|
||||||
|
(void) c->buffer->message (c->font, "end chain subtable %d", c->lookup_index);
|
||||||
|
|
||||||
|
c->set_lookup_index (c->lookup_index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int get_size (void) const { return length; }
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int major) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (!length.sanitize (c) ||
|
||||||
|
length < min_size ||
|
||||||
|
!c->check_range (this, length))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
|
if (!c->check_array (featureZ, featureZ[0].static_size, featureCount))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
|
const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (featureZ, featureZ[0].static_size * featureCount);
|
||||||
|
unsigned int count = subtableCount;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (!subtable->sanitize (c))
|
||||||
|
return_trace (false);
|
||||||
|
subtable = &StructAfter<ChainSubtable> (*subtable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT32 defaultFlags; /* The default specification for subtables. */
|
||||||
|
HBUINT32 length; /* Total byte count, including this header. */
|
||||||
|
HBUINT32 featureCount; /* Number of feature subtable entries. */
|
||||||
|
HBUINT32 subtableCount; /* The number of subtables in the chain. */
|
||||||
|
|
||||||
|
Feature featureZ[VAR]; /* Features. */
|
||||||
|
ChainSubtable subtableX[VAR]; /* Subtables. */
|
||||||
|
// subtableGlyphCoverageArray if major == 3
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_MIN (16);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The 'mort'/'morx' Tables
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct morx
|
||||||
|
{
|
||||||
|
static const hb_tag_t tableTag = HB_AAT_TAG_MORX;
|
||||||
|
|
||||||
|
inline void apply (hb_aat_apply_context_t *c) const
|
||||||
|
{
|
||||||
|
c->set_lookup_index (0);
|
||||||
|
const Chain *chain = chains;
|
||||||
|
unsigned int count = chainCount;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
chain->apply (c);
|
||||||
|
chain = &StructAfter<Chain> (*chain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
if (!version.sanitize (c) ||
|
||||||
|
(version.major >> (sizeof (HBUINT32) == 4 ? 1 : 0)) != 1 ||
|
||||||
|
!chainCount.sanitize (c))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
|
const Chain *chain = chains;
|
||||||
|
unsigned int count = chainCount;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (!chain->sanitize (c, version.major))
|
||||||
|
return_trace (false);
|
||||||
|
chain = &StructAfter<Chain> (*chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FixedVersion<>version; /* Version number of the glyph metamorphosis table.
|
||||||
|
* 1 for mort, 2 or 3 for morx. */
|
||||||
|
HBUINT32 chainCount; /* Number of metamorphosis chains contained in this
|
||||||
|
* table. */
|
||||||
|
Chain chains[VAR]; /* Chains. */
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_MIN (8);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace AAT */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HB_AAT_LAYOUT_MORX_TABLE_HH */
|
43
src/hb-aat-layout-private.hh
Normal file
43
src/hb-aat-layout-private.hh
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2017 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_LAYOUT_PRIVATE_HH
|
||||||
|
#define HB_AAT_LAYOUT_PRIVATE_HH
|
||||||
|
|
||||||
|
#include "hb-private.hh"
|
||||||
|
|
||||||
|
#include "hb-font-private.hh"
|
||||||
|
#include "hb-buffer-private.hh"
|
||||||
|
#include "hb-open-type-private.hh"
|
||||||
|
|
||||||
|
|
||||||
|
HB_INTERNAL void
|
||||||
|
hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer);
|
||||||
|
|
||||||
|
HB_INTERNAL void
|
||||||
|
hb_aat_layout_position (hb_font_t *font, hb_buffer_t *buffer);
|
||||||
|
|
||||||
|
#endif /* HB_AAT_LAYOUT_PRIVATE_HH */
|
201
src/hb-aat-layout-trak-table.hh
Normal file
201
src/hb-aat-layout-trak-table.hh
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2018 Ebrahim Byagowi
|
||||||
|
* 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_LAYOUT_TRAK_TABLE_HH
|
||||||
|
#define HB_AAT_LAYOUT_TRAK_TABLE_HH
|
||||||
|
|
||||||
|
#include "hb-aat-layout-common-private.hh"
|
||||||
|
#include "hb-open-type-private.hh"
|
||||||
|
|
||||||
|
#define HB_AAT_TAG_trak HB_TAG('t','r','a','k')
|
||||||
|
|
||||||
|
|
||||||
|
namespace AAT {
|
||||||
|
|
||||||
|
|
||||||
|
struct TrackTableEntry
|
||||||
|
{
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, const void *base, unsigned int size) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this) && (values.sanitize (c, base, size)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float get_track_value () const
|
||||||
|
{
|
||||||
|
return track.to_float ();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int get_value (const void *base, unsigned int index) const
|
||||||
|
{
|
||||||
|
return (base+values)[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Fixed track; /* Track value for this record. */
|
||||||
|
HBUINT16 trackNameID; /* The 'name' table index for this track */
|
||||||
|
OffsetTo<UnsizedArrayOf<FWORD> >
|
||||||
|
values; /* Offset from start of tracking table to
|
||||||
|
* per-size tracking values for this track. */
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (8);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TrackData
|
||||||
|
{
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (c->check_struct (this) &&
|
||||||
|
sizeTable.sanitize (c, base, nSizes) &&
|
||||||
|
trackTable.sanitize (c, nTracks, base, nSizes));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float get_tracking (const void *base, float ptem) const
|
||||||
|
{
|
||||||
|
/* CoreText points are CSS pixels (96 per inch),
|
||||||
|
* NOT typographic points (72 per inch).
|
||||||
|
*
|
||||||
|
* https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
|
||||||
|
*/
|
||||||
|
float csspx = ptem * 96.f / 72.f;
|
||||||
|
Fixed fixed_size;
|
||||||
|
fixed_size.set_float (csspx);
|
||||||
|
|
||||||
|
/* XXX Clean this up. Make it work with nSizes==1 and 0. */
|
||||||
|
|
||||||
|
unsigned int sizes = nSizes;
|
||||||
|
|
||||||
|
const TrackTableEntry *trackTableEntry = nullptr;
|
||||||
|
for (unsigned int i = 0; i < sizes; ++i)
|
||||||
|
// For now we only seek for track entries with zero tracking value
|
||||||
|
if (trackTable[i].get_track_value () == 0.)
|
||||||
|
trackTableEntry = &trackTable[0];
|
||||||
|
|
||||||
|
// We couldn't match any, exit
|
||||||
|
if (!trackTableEntry) return 0.;
|
||||||
|
|
||||||
|
/* TODO bfind() */
|
||||||
|
unsigned int size_index;
|
||||||
|
UnsizedArrayOf<Fixed> size_table = base+sizeTable;
|
||||||
|
for (size_index = 0; size_index < sizes; ++size_index)
|
||||||
|
if (size_table[size_index] >= fixed_size)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// TODO(ebraminio): We don't attempt to extrapolate to larger or
|
||||||
|
// smaller values for now but we should do, per spec
|
||||||
|
if (size_index == sizes)
|
||||||
|
return trackTableEntry->get_value (base, sizes - 1);
|
||||||
|
if (size_index == 0 || size_table[size_index] == fixed_size)
|
||||||
|
return trackTableEntry->get_value (base, size_index);
|
||||||
|
|
||||||
|
float s0 = size_table[size_index - 1].to_float ();
|
||||||
|
float s1 = size_table[size_index].to_float ();
|
||||||
|
float t = (csspx - s0) / (s1 - s0);
|
||||||
|
return t * trackTableEntry->get_value (base, size_index) +
|
||||||
|
(1.0 - t) * trackTableEntry->get_value (base, size_index - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT16 nTracks; /* Number of separate tracks included in this table. */
|
||||||
|
HBUINT16 nSizes; /* Number of point sizes included in this table. */
|
||||||
|
LOffsetTo<UnsizedArrayOf<Fixed> > /* Offset to array[nSizes] of size values. */
|
||||||
|
sizeTable;
|
||||||
|
UnsizedArrayOf<TrackTableEntry>
|
||||||
|
trackTable; /* Array[nTracks] of TrackTableEntry records. */
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_ARRAY (8, trackTable);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct trak
|
||||||
|
{
|
||||||
|
static const hb_tag_t tableTag = HB_AAT_TAG_trak;
|
||||||
|
|
||||||
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
|
||||||
|
return_trace (c->check_struct (this) &&
|
||||||
|
horizData.sanitize (c, this, this) &&
|
||||||
|
vertData.sanitize (c, this, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool apply (hb_aat_apply_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_APPLY (this);
|
||||||
|
|
||||||
|
const float ptem = c->font->ptem;
|
||||||
|
if (ptem <= 0.f)
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
|
hb_buffer_t *buffer = c->buffer;
|
||||||
|
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
|
||||||
|
{
|
||||||
|
const TrackData &trackData = this+horizData;
|
||||||
|
float tracking = trackData.get_tracking (this, ptem);
|
||||||
|
hb_position_t advance_to_add = c->font->em_scalef_x (tracking / 2);
|
||||||
|
foreach_grapheme (buffer, start, end)
|
||||||
|
{
|
||||||
|
/* TODO This is wrong. */
|
||||||
|
buffer->pos[start].x_advance += advance_to_add;
|
||||||
|
buffer->pos[end].x_advance += advance_to_add;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const TrackData &trackData = this+vertData;
|
||||||
|
float tracking = trackData.get_tracking (this, ptem);
|
||||||
|
hb_position_t advance_to_add = c->font->em_scalef_y (tracking / 2);
|
||||||
|
foreach_grapheme (buffer, start, end)
|
||||||
|
{
|
||||||
|
/* TODO This is wrong. */
|
||||||
|
buffer->pos[start].y_advance += advance_to_add;
|
||||||
|
buffer->pos[end].y_advance += advance_to_add;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FixedVersion<> version; /* Version of the tracking table--currently
|
||||||
|
* 0x00010000u for version 1.0. */
|
||||||
|
HBUINT16 format; /* Format of the tracking table */
|
||||||
|
OffsetTo<TrackData> horizData; /* TrackData for horizontal text */
|
||||||
|
OffsetTo<TrackData> vertData; /* TrackData for vertical text */
|
||||||
|
HBUINT16 reserved; /* Reserved. Set to 0. */
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_MIN (12);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace AAT */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HB_AAT_LAYOUT_TRAK_TABLE_HH */
|
143
src/hb-aat-layout.cc
Normal file
143
src/hb-aat-layout.cc
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2017 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hb-open-type-private.hh"
|
||||||
|
|
||||||
|
#include "hb-ot-layout-private.hh"
|
||||||
|
#include "hb-ot-layout-gsubgpos-private.hh"
|
||||||
|
|
||||||
|
#include "hb-aat-layout-private.hh"
|
||||||
|
#include "hb-aat-layout-ankr-table.hh"
|
||||||
|
#include "hb-aat-layout-kerx-table.hh"
|
||||||
|
#include "hb-aat-layout-morx-table.hh"
|
||||||
|
#include "hb-aat-layout-trak-table.hh"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* morx/kerx/trak
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline const AAT::ankr&
|
||||||
|
_get_ankr (hb_face_t *face, hb_blob_t **blob = nullptr)
|
||||||
|
{
|
||||||
|
if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
|
||||||
|
{
|
||||||
|
if (blob)
|
||||||
|
*blob = hb_blob_get_empty ();
|
||||||
|
return OT::Null(AAT::ankr);
|
||||||
|
}
|
||||||
|
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
|
||||||
|
const AAT::ankr& ankr = *(layout->ankr.get ());
|
||||||
|
if (blob)
|
||||||
|
*blob = layout->ankr.blob;
|
||||||
|
return ankr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const AAT::kerx&
|
||||||
|
_get_kerx (hb_face_t *face, hb_blob_t **blob = nullptr)
|
||||||
|
{
|
||||||
|
if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
|
||||||
|
{
|
||||||
|
if (blob)
|
||||||
|
*blob = hb_blob_get_empty ();
|
||||||
|
return OT::Null(AAT::kerx);
|
||||||
|
}
|
||||||
|
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
|
||||||
|
/* XXX this doesn't call set_num_glyphs on sanitizer. */
|
||||||
|
const AAT::kerx& kerx = *(layout->kerx.get ());
|
||||||
|
if (blob)
|
||||||
|
*blob = layout->kerx.blob;
|
||||||
|
return kerx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const AAT::morx&
|
||||||
|
_get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
|
||||||
|
{
|
||||||
|
if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
|
||||||
|
{
|
||||||
|
if (blob)
|
||||||
|
*blob = hb_blob_get_empty ();
|
||||||
|
return OT::Null(AAT::morx);
|
||||||
|
}
|
||||||
|
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
|
||||||
|
/* XXX this doesn't call set_num_glyphs on sanitizer. */
|
||||||
|
const AAT::morx& morx = *(layout->morx.get ());
|
||||||
|
if (blob)
|
||||||
|
*blob = layout->morx.blob;
|
||||||
|
return morx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const AAT::trak&
|
||||||
|
_get_trak (hb_face_t *face, hb_blob_t **blob = nullptr)
|
||||||
|
{
|
||||||
|
if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
|
||||||
|
{
|
||||||
|
if (blob)
|
||||||
|
*blob = hb_blob_get_empty ();
|
||||||
|
return OT::Null(AAT::trak);
|
||||||
|
}
|
||||||
|
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
|
||||||
|
const AAT::trak& trak = *(layout->trak.get ());
|
||||||
|
if (blob)
|
||||||
|
*blob = layout->trak.blob;
|
||||||
|
return trak;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static inline void
|
||||||
|
// _hb_aat_layout_create (hb_face_t *face)
|
||||||
|
// {
|
||||||
|
// OT::Sanitizer<AAT::morx> sanitizer;
|
||||||
|
// sanitizer.set_num_glyphs (face->get_num_glyphs ());
|
||||||
|
// hb_blob_t *morx_blob = sanitizer.sanitize (face->reference_table (HB_AAT_TAG_MORX));
|
||||||
|
// OT::Sanitizer<AAT::morx>::lock_instance (morx_blob);
|
||||||
|
|
||||||
|
// if (0)
|
||||||
|
// {
|
||||||
|
// OT::Sanitizer<AAT::Lookup<OT::GlyphID> >::lock_instance (morx_blob)->get_value (1, face->get_num_glyphs ());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer)
|
||||||
|
{
|
||||||
|
hb_blob_t *blob;
|
||||||
|
const AAT::morx& morx = _get_morx (font->face, &blob);
|
||||||
|
|
||||||
|
AAT::hb_aat_apply_context_t c (font, buffer, blob);
|
||||||
|
morx.apply (&c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_aat_layout_position (hb_font_t *font, hb_buffer_t *buffer)
|
||||||
|
{
|
||||||
|
hb_blob_t *blob;
|
||||||
|
const AAT::ankr& ankr = _get_ankr (font->face, &blob);
|
||||||
|
const AAT::kerx& kerx = _get_kerx (font->face, &blob);
|
||||||
|
const AAT::trak& trak = _get_trak (font->face, &blob);
|
||||||
|
|
||||||
|
AAT::hb_aat_apply_context_t c (font, buffer, blob);
|
||||||
|
kerx.apply (&c, &ankr);
|
||||||
|
trak.apply (&c);
|
||||||
|
}
|
@ -70,32 +70,6 @@ typedef LONG hb_atomic_int_impl_t;
|
|||||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
|
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
|
||||||
|
|
||||||
|
|
||||||
#elif !defined(HB_NO_MT) && defined(__APPLE__)
|
|
||||||
|
|
||||||
#include <libkern/OSAtomic.h>
|
|
||||||
#ifdef __MAC_OS_X_MIN_REQUIRED
|
|
||||||
#include <AvailabilityMacros.h>
|
|
||||||
#elif defined(__IPHONE_OS_MIN_REQUIRED)
|
|
||||||
#include <Availability.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
typedef int32_t hb_atomic_int_impl_t;
|
|
||||||
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
|
|
||||||
#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
|
|
||||||
|
|
||||||
#define hb_atomic_ptr_impl_get(P) (OSMemoryBarrier (), (void *) *(P))
|
|
||||||
#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
|
|
||||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
|
|
||||||
#else
|
|
||||||
#if __ppc64__ || __x86_64__ || __aarch64__
|
|
||||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
|
|
||||||
#else
|
|
||||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
|
#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
|
||||||
|
|
||||||
typedef int hb_atomic_int_impl_t;
|
typedef int hb_atomic_int_impl_t;
|
||||||
@ -119,18 +93,44 @@ typedef unsigned int hb_atomic_int_impl_t;
|
|||||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
|
#define hb_atomic_ptr_impl_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
|
||||||
|
|
||||||
|
|
||||||
|
#elif !defined(HB_NO_MT) && defined(__APPLE__)
|
||||||
|
|
||||||
|
#include <libkern/OSAtomic.h>
|
||||||
|
#ifdef __MAC_OS_X_MIN_REQUIRED
|
||||||
|
#include <AvailabilityMacros.h>
|
||||||
|
#elif defined(__IPHONE_OS_MIN_REQUIRED)
|
||||||
|
#include <Availability.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef int32_t hb_atomic_int_impl_t;
|
||||||
|
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
|
||||||
|
#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
|
||||||
|
|
||||||
|
#define hb_atomic_ptr_impl_get(P) (OSMemoryBarrier (), (void *) *(P))
|
||||||
|
#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
|
||||||
|
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
|
||||||
|
#else
|
||||||
|
#if __ppc64__ || __x86_64__ || __aarch64__
|
||||||
|
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (void *) (O), (int64_t) (void *) (N), (int64_t*) (P))
|
||||||
|
#else
|
||||||
|
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (void *) (O), (int32_t) (void *) (N), (int32_t*) (P))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__)
|
#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__)
|
||||||
|
|
||||||
#include <builtins.h>
|
#include <builtins.h>
|
||||||
|
|
||||||
|
|
||||||
static inline int hb_fetch_and_add(volatile int* AI, unsigned int V) {
|
static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) {
|
||||||
__lwsync();
|
__lwsync();
|
||||||
int result = __fetch_and_add(AI, V);
|
int result = __fetch_and_add(AI, V);
|
||||||
__isync();
|
__isync();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
static inline int hb_compare_and_swaplp(volatile long* P, long O, long N) {
|
static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) {
|
||||||
__sync();
|
__sync();
|
||||||
int result = __compare_and_swaplp (P, &O, N);
|
int result = __compare_and_swaplp (P, &O, N);
|
||||||
__sync();
|
__sync();
|
||||||
@ -139,10 +139,10 @@ static inline int hb_compare_and_swaplp(volatile long* P, long O, long N) {
|
|||||||
|
|
||||||
typedef int hb_atomic_int_impl_t;
|
typedef int hb_atomic_int_impl_t;
|
||||||
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
|
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
|
||||||
#define hb_atomic_int_impl_add(AI, V) hb_fetch_and_add (&(AI), (V))
|
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add (&(AI), (V))
|
||||||
|
|
||||||
#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P))
|
#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P))
|
||||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
|
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
|
||||||
|
|
||||||
#elif !defined(HB_NO_MT)
|
#elif !defined(HB_NO_MT)
|
||||||
|
|
||||||
|
@ -26,10 +26,11 @@
|
|||||||
|
|
||||||
/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */
|
/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */
|
||||||
#ifndef _POSIX_C_SOURCE
|
#ifndef _POSIX_C_SOURCE
|
||||||
#define _POSIX_C_SOURCE 199309L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "hb-private.hh"
|
#include "hb-private.hh"
|
||||||
|
#include "hb-debug.hh"
|
||||||
|
|
||||||
#include "hb-object-private.hh"
|
#include "hb-object-private.hh"
|
||||||
|
|
||||||
@ -44,12 +45,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HB_DEBUG_BLOB
|
|
||||||
#define HB_DEBUG_BLOB (HB_DEBUG+0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
struct hb_blob_t {
|
struct hb_blob_t {
|
||||||
hb_object_header_t header;
|
hb_object_header_t header;
|
||||||
ASSERT_POD ();
|
ASSERT_POD ();
|
||||||
@ -72,8 +67,8 @@ _hb_blob_destroy_user_data (hb_blob_t *blob)
|
|||||||
{
|
{
|
||||||
if (blob->destroy) {
|
if (blob->destroy) {
|
||||||
blob->destroy (blob->user_data);
|
blob->destroy (blob->user_data);
|
||||||
blob->user_data = NULL;
|
blob->user_data = nullptr;
|
||||||
blob->destroy = NULL;
|
blob->destroy = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +123,12 @@ hb_blob_create (const char *data,
|
|||||||
return blob;
|
return blob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_hb_blob_destroy (void *data)
|
||||||
|
{
|
||||||
|
hb_blob_destroy ((hb_blob_t *) data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_blob_create_sub_blob:
|
* hb_blob_create_sub_blob:
|
||||||
* @parent: Parent blob.
|
* @parent: Parent blob.
|
||||||
@ -164,7 +165,32 @@ hb_blob_create_sub_blob (hb_blob_t *parent,
|
|||||||
MIN (length, parent->length - offset),
|
MIN (length, parent->length - offset),
|
||||||
HB_MEMORY_MODE_READONLY,
|
HB_MEMORY_MODE_READONLY,
|
||||||
hb_blob_reference (parent),
|
hb_blob_reference (parent),
|
||||||
(hb_destroy_func_t) hb_blob_destroy);
|
_hb_blob_destroy);
|
||||||
|
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_blob_copy_writable_or_fail:
|
||||||
|
* @blob: A blob.
|
||||||
|
*
|
||||||
|
* Makes a writable copy of @blob.
|
||||||
|
*
|
||||||
|
* Return value: New blob, or nullptr if allocation failed.
|
||||||
|
*
|
||||||
|
* Since: 1.8.0
|
||||||
|
**/
|
||||||
|
hb_blob_t *
|
||||||
|
hb_blob_copy_writable_or_fail (hb_blob_t *blob)
|
||||||
|
{
|
||||||
|
blob = hb_blob_create (blob->data,
|
||||||
|
blob->length,
|
||||||
|
HB_MEMORY_MODE_DUPLICATE,
|
||||||
|
nullptr,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
if (unlikely (blob == hb_blob_get_empty ()))
|
||||||
|
blob = nullptr;
|
||||||
|
|
||||||
return blob;
|
return blob;
|
||||||
}
|
}
|
||||||
@ -188,12 +214,12 @@ hb_blob_get_empty (void)
|
|||||||
|
|
||||||
true, /* immutable */
|
true, /* immutable */
|
||||||
|
|
||||||
NULL, /* data */
|
nullptr, /* data */
|
||||||
0, /* length */
|
0, /* length */
|
||||||
HB_MEMORY_MODE_READONLY, /* mode */
|
HB_MEMORY_MODE_READONLY, /* mode */
|
||||||
|
|
||||||
NULL, /* user_data */
|
nullptr, /* user_data */
|
||||||
NULL /* destroy */
|
nullptr /* destroy */
|
||||||
};
|
};
|
||||||
|
|
||||||
return const_cast<hb_blob_t *> (&_hb_blob_nil);
|
return const_cast<hb_blob_t *> (&_hb_blob_nil);
|
||||||
@ -221,7 +247,7 @@ hb_blob_reference (hb_blob_t *blob)
|
|||||||
* hb_blob_destroy: (skip)
|
* hb_blob_destroy: (skip)
|
||||||
* @blob: a blob.
|
* @blob: a blob.
|
||||||
*
|
*
|
||||||
* Descreases the reference count on @blob, and if it reaches zero, destroys
|
* Decreases the reference count on @blob, and if it reaches zero, destroys
|
||||||
* @blob, freeing all memory, possibly calling the destroy-callback the blob
|
* @blob, freeing all memory, possibly calling the destroy-callback the blob
|
||||||
* was created for if it has not been called already.
|
* was created for if it has not been called already.
|
||||||
*
|
*
|
||||||
@ -373,7 +399,7 @@ hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length)
|
|||||||
if (length)
|
if (length)
|
||||||
*length = 0;
|
*length = 0;
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length)
|
if (length)
|
||||||
|
@ -44,7 +44,7 @@ HB_BEGIN_DECLS
|
|||||||
* any such possibility, MODE_DUPLICATE should be used
|
* any such possibility, MODE_DUPLICATE should be used
|
||||||
* such that HarfBuzz makes a copy immediately,
|
* such that HarfBuzz makes a copy immediately,
|
||||||
*
|
*
|
||||||
* - Use MODE_READONLY otherse, unless you really really
|
* - Use MODE_READONLY otherwise, unless you really really
|
||||||
* really know what you are doing,
|
* really know what you are doing,
|
||||||
*
|
*
|
||||||
* - MODE_WRITABLE is appropriate if you really made a
|
* - MODE_WRITABLE is appropriate if you really made a
|
||||||
@ -82,6 +82,9 @@ hb_blob_create_sub_blob (hb_blob_t *parent,
|
|||||||
unsigned int offset,
|
unsigned int offset,
|
||||||
unsigned int length);
|
unsigned int length);
|
||||||
|
|
||||||
|
HB_EXTERN hb_blob_t *
|
||||||
|
hb_blob_copy_writable_or_fail (hb_blob_t *blob);
|
||||||
|
|
||||||
HB_EXTERN hb_blob_t *
|
HB_EXTERN hb_blob_t *
|
||||||
hb_blob_get_empty (void);
|
hb_blob_get_empty (void);
|
||||||
|
|
||||||
|
643
src/hb-buffer-deserialize-json.hh
Normal file
643
src/hb-buffer-deserialize-json.hh
Normal file
@ -0,0 +1,643 @@
|
|||||||
|
|
||||||
|
#line 1 "hb-buffer-deserialize-json.rl"
|
||||||
|
/*
|
||||||
|
* Copyright © 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.
|
||||||
|
*
|
||||||
|
* Google Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_BUFFER_DESERIALIZE_JSON_HH
|
||||||
|
#define HB_BUFFER_DESERIALIZE_JSON_HH
|
||||||
|
|
||||||
|
#include "hb-private.hh"
|
||||||
|
|
||||||
|
|
||||||
|
#line 36 "hb-buffer-deserialize-json.hh"
|
||||||
|
static const unsigned char _deserialize_json_trans_keys[] = {
|
||||||
|
0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
|
||||||
|
48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
|
||||||
|
9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u,
|
||||||
|
120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u,
|
||||||
|
9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
|
||||||
|
65u, 122u, 34u, 122u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char _deserialize_json_key_spans[] = {
|
||||||
|
0, 115, 26, 7, 2, 1, 50, 49,
|
||||||
|
10, 117, 117, 117, 1, 50, 49, 10,
|
||||||
|
117, 117, 1, 1, 50, 49, 117, 117,
|
||||||
|
2, 1, 50, 49, 10, 117, 117, 1,
|
||||||
|
50, 49, 10, 117, 117, 1, 50, 49,
|
||||||
|
58, 89, 117, 117, 85, 115, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const short _deserialize_json_index_offsets[] = {
|
||||||
|
0, 0, 116, 143, 151, 154, 156, 207,
|
||||||
|
257, 268, 386, 504, 622, 624, 675, 725,
|
||||||
|
736, 854, 972, 974, 976, 1027, 1077, 1195,
|
||||||
|
1313, 1316, 1318, 1369, 1419, 1430, 1548, 1666,
|
||||||
|
1668, 1719, 1769, 1780, 1898, 2016, 2018, 2069,
|
||||||
|
2119, 2178, 2268, 2386, 2504, 2590, 2706
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char _deserialize_json_indicies[] = {
|
||||||
|
0, 0, 0, 0, 0, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
0, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 2, 1, 3, 3, 3,
|
||||||
|
3, 3, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 3, 1, 4, 1,
|
||||||
|
5, 1, 6, 7, 1, 1, 8, 1,
|
||||||
|
9, 10, 1, 11, 1, 11, 11, 11,
|
||||||
|
11, 11, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 11, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 12, 1,
|
||||||
|
12, 12, 12, 12, 12, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 12,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 13, 1, 1, 14,
|
||||||
|
15, 15, 15, 15, 15, 15, 15, 15,
|
||||||
|
15, 1, 16, 17, 17, 17, 17, 17,
|
||||||
|
17, 17, 17, 17, 1, 18, 18, 18,
|
||||||
|
18, 18, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 18, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
19, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 20, 1, 21, 21, 21, 21, 21,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 21, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 3, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 22,
|
||||||
|
1, 18, 18, 18, 18, 18, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
18, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 19, 1, 1, 1,
|
||||||
|
17, 17, 17, 17, 17, 17, 17, 17,
|
||||||
|
17, 17, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 20, 1, 23,
|
||||||
|
1, 23, 23, 23, 23, 23, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
23, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 24, 1, 24, 24, 24, 24,
|
||||||
|
24, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 24, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
25, 1, 1, 26, 27, 27, 27, 27,
|
||||||
|
27, 27, 27, 27, 27, 1, 28, 29,
|
||||||
|
29, 29, 29, 29, 29, 29, 29, 29,
|
||||||
|
1, 30, 30, 30, 30, 30, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
30, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 31, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 32, 1, 30,
|
||||||
|
30, 30, 30, 30, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 30, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 31, 1, 1, 1, 29, 29,
|
||||||
|
29, 29, 29, 29, 29, 29, 29, 29,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 32, 1, 33, 1, 34,
|
||||||
|
1, 34, 34, 34, 34, 34, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
34, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 35, 1, 35, 35, 35, 35,
|
||||||
|
35, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 35, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 36, 37, 37, 37, 37,
|
||||||
|
37, 37, 37, 37, 37, 1, 38, 38,
|
||||||
|
38, 38, 38, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 38, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 39, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 40, 1, 38, 38, 38, 38,
|
||||||
|
38, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 38, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 39,
|
||||||
|
1, 1, 1, 41, 41, 41, 41, 41,
|
||||||
|
41, 41, 41, 41, 41, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
40, 1, 42, 43, 1, 44, 1, 44,
|
||||||
|
44, 44, 44, 44, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 44, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
45, 1, 45, 45, 45, 45, 45, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 45, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 46, 1,
|
||||||
|
1, 47, 48, 48, 48, 48, 48, 48,
|
||||||
|
48, 48, 48, 1, 49, 50, 50, 50,
|
||||||
|
50, 50, 50, 50, 50, 50, 1, 51,
|
||||||
|
51, 51, 51, 51, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 51, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 52, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 53, 1, 51, 51, 51,
|
||||||
|
51, 51, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 51, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
52, 1, 1, 1, 50, 50, 50, 50,
|
||||||
|
50, 50, 50, 50, 50, 50, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 53, 1, 54, 1, 54, 54, 54,
|
||||||
|
54, 54, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 54, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 55, 1,
|
||||||
|
55, 55, 55, 55, 55, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 55,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 56, 1, 1, 57,
|
||||||
|
58, 58, 58, 58, 58, 58, 58, 58,
|
||||||
|
58, 1, 59, 60, 60, 60, 60, 60,
|
||||||
|
60, 60, 60, 60, 1, 61, 61, 61,
|
||||||
|
61, 61, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 61, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
62, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 63, 1, 61, 61, 61, 61, 61,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 61, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 62, 1,
|
||||||
|
1, 1, 60, 60, 60, 60, 60, 60,
|
||||||
|
60, 60, 60, 60, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 63,
|
||||||
|
1, 64, 1, 64, 64, 64, 64, 64,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 64, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 65, 1, 65, 65,
|
||||||
|
65, 65, 65, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 65, 1, 66,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 67, 68, 68,
|
||||||
|
68, 68, 68, 68, 68, 68, 68, 1,
|
||||||
|
69, 69, 69, 69, 69, 69, 69, 69,
|
||||||
|
69, 69, 69, 69, 69, 69, 69, 69,
|
||||||
|
69, 69, 69, 69, 69, 69, 69, 69,
|
||||||
|
69, 69, 1, 1, 1, 1, 1, 1,
|
||||||
|
69, 69, 69, 69, 69, 69, 69, 69,
|
||||||
|
69, 69, 69, 69, 69, 69, 69, 69,
|
||||||
|
69, 69, 69, 69, 69, 69, 69, 69,
|
||||||
|
69, 69, 1, 70, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 71, 71,
|
||||||
|
1, 71, 71, 71, 71, 71, 71, 71,
|
||||||
|
71, 71, 71, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 71, 71, 71, 71, 71, 71,
|
||||||
|
71, 71, 71, 71, 71, 71, 71, 71,
|
||||||
|
71, 71, 71, 71, 71, 71, 71, 71,
|
||||||
|
71, 71, 71, 71, 1, 1, 1, 1,
|
||||||
|
71, 1, 71, 71, 71, 71, 71, 71,
|
||||||
|
71, 71, 71, 71, 71, 71, 71, 71,
|
||||||
|
71, 71, 71, 71, 71, 71, 71, 71,
|
||||||
|
71, 71, 71, 71, 1, 72, 72, 72,
|
||||||
|
72, 72, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 72, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
73, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 74, 1, 72, 72, 72, 72, 72,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 72, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 73, 1,
|
||||||
|
1, 1, 75, 75, 75, 75, 75, 75,
|
||||||
|
75, 75, 75, 75, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 74,
|
||||||
|
1, 76, 76, 76, 76, 76, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
76, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 77, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 78, 1, 0,
|
||||||
|
0, 0, 0, 0, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 0, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 2, 1, 1, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char _deserialize_json_trans_targs[] = {
|
||||||
|
1, 0, 2, 2, 3, 4, 18, 24,
|
||||||
|
37, 5, 12, 6, 7, 8, 9, 11,
|
||||||
|
9, 11, 10, 2, 44, 10, 44, 13,
|
||||||
|
14, 15, 16, 17, 16, 17, 10, 2,
|
||||||
|
44, 19, 20, 21, 22, 23, 10, 2,
|
||||||
|
44, 23, 25, 31, 26, 27, 28, 29,
|
||||||
|
30, 29, 30, 10, 2, 44, 32, 33,
|
||||||
|
34, 35, 36, 35, 36, 10, 2, 44,
|
||||||
|
38, 39, 40, 42, 43, 41, 10, 41,
|
||||||
|
10, 2, 44, 43, 44, 45, 46
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char _deserialize_json_trans_actions[] = {
|
||||||
|
0, 0, 1, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 2, 2, 2,
|
||||||
|
0, 0, 3, 3, 4, 0, 5, 0,
|
||||||
|
0, 2, 2, 2, 0, 0, 6, 6,
|
||||||
|
7, 0, 0, 0, 2, 2, 8, 8,
|
||||||
|
9, 0, 0, 0, 0, 0, 2, 2,
|
||||||
|
2, 0, 0, 10, 10, 11, 0, 0,
|
||||||
|
2, 2, 2, 0, 0, 12, 12, 13,
|
||||||
|
0, 0, 0, 2, 2, 2, 14, 0,
|
||||||
|
15, 15, 16, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int deserialize_json_start = 1;
|
||||||
|
static const int deserialize_json_first_final = 44;
|
||||||
|
static const int deserialize_json_error = 0;
|
||||||
|
|
||||||
|
static const int deserialize_json_en_main = 1;
|
||||||
|
|
||||||
|
|
||||||
|
#line 97 "hb-buffer-deserialize-json.rl"
|
||||||
|
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
_hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer,
|
||||||
|
const char *buf,
|
||||||
|
unsigned int buf_len,
|
||||||
|
const char **end_ptr,
|
||||||
|
hb_font_t *font)
|
||||||
|
{
|
||||||
|
const char *p = buf, *pe = buf + buf_len;
|
||||||
|
|
||||||
|
/* Ensure we have positions. */
|
||||||
|
(void) hb_buffer_get_glyph_positions (buffer, nullptr);
|
||||||
|
|
||||||
|
while (p < pe && ISSPACE (*p))
|
||||||
|
p++;
|
||||||
|
if (p < pe && *p == (buffer->len ? ',' : '['))
|
||||||
|
{
|
||||||
|
*end_ptr = ++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *tok = nullptr;
|
||||||
|
int cs;
|
||||||
|
hb_glyph_info_t info = {0};
|
||||||
|
hb_glyph_position_t pos = {0};
|
||||||
|
|
||||||
|
#line 466 "hb-buffer-deserialize-json.hh"
|
||||||
|
{
|
||||||
|
cs = deserialize_json_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#line 471 "hb-buffer-deserialize-json.hh"
|
||||||
|
{
|
||||||
|
int _slen;
|
||||||
|
int _trans;
|
||||||
|
const unsigned char *_keys;
|
||||||
|
const char *_inds;
|
||||||
|
if ( p == pe )
|
||||||
|
goto _test_eof;
|
||||||
|
if ( cs == 0 )
|
||||||
|
goto _out;
|
||||||
|
_resume:
|
||||||
|
_keys = _deserialize_json_trans_keys + (cs<<1);
|
||||||
|
_inds = _deserialize_json_indicies + _deserialize_json_index_offsets[cs];
|
||||||
|
|
||||||
|
_slen = _deserialize_json_key_spans[cs];
|
||||||
|
_trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
|
||||||
|
(*p) <= _keys[1] ?
|
||||||
|
(*p) - _keys[0] : _slen ];
|
||||||
|
|
||||||
|
cs = _deserialize_json_trans_targs[_trans];
|
||||||
|
|
||||||
|
if ( _deserialize_json_trans_actions[_trans] == 0 )
|
||||||
|
goto _again;
|
||||||
|
|
||||||
|
switch ( _deserialize_json_trans_actions[_trans] ) {
|
||||||
|
case 1:
|
||||||
|
#line 38 "hb-buffer-deserialize-json.rl"
|
||||||
|
{
|
||||||
|
memset (&info, 0, sizeof (info));
|
||||||
|
memset (&pos , 0, sizeof (pos ));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
#line 43 "hb-buffer-deserialize-json.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
#line 51 "hb-buffer-deserialize-json.rl"
|
||||||
|
{
|
||||||
|
tok = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
#line 55 "hb-buffer-deserialize-json.rl"
|
||||||
|
{
|
||||||
|
if (!hb_font_glyph_from_string (font,
|
||||||
|
tok, p - tok,
|
||||||
|
&info.codepoint))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
#line 62 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
#line 63 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
#line 64 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.x_offset )) return false; }
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
#line 65 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
#line 66 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
#line 67 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
#line 62 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-json.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
#line 63 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-json.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
#line 64 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.x_offset )) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-json.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
#line 65 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-json.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
#line 66 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-json.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
#line 67 "hb-buffer-deserialize-json.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-json.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#line 624 "hb-buffer-deserialize-json.hh"
|
||||||
|
}
|
||||||
|
|
||||||
|
_again:
|
||||||
|
if ( cs == 0 )
|
||||||
|
goto _out;
|
||||||
|
if ( ++p != pe )
|
||||||
|
goto _resume;
|
||||||
|
_test_eof: {}
|
||||||
|
_out: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#line 125 "hb-buffer-deserialize-json.rl"
|
||||||
|
|
||||||
|
|
||||||
|
*end_ptr = p;
|
||||||
|
|
||||||
|
return p == pe && *(p-1) != ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HB_BUFFER_DESERIALIZE_JSON_HH */
|
@ -106,7 +106,7 @@ _hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer,
|
|||||||
const char *p = buf, *pe = buf + buf_len;
|
const char *p = buf, *pe = buf + buf_len;
|
||||||
|
|
||||||
/* Ensure we have positions. */
|
/* Ensure we have positions. */
|
||||||
(void) hb_buffer_get_glyph_positions (buffer, NULL);
|
(void) hb_buffer_get_glyph_positions (buffer, nullptr);
|
||||||
|
|
||||||
while (p < pe && ISSPACE (*p))
|
while (p < pe && ISSPACE (*p))
|
||||||
p++;
|
p++;
|
||||||
@ -115,7 +115,7 @@ _hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer,
|
|||||||
*end_ptr = ++p;
|
*end_ptr = ++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *tok = NULL;
|
const char *tok = nullptr;
|
||||||
int cs;
|
int cs;
|
||||||
hb_glyph_info_t info = {0};
|
hb_glyph_info_t info = {0};
|
||||||
hb_glyph_position_t pos = {0};
|
hb_glyph_position_t pos = {0};
|
||||||
|
571
src/hb-buffer-deserialize-text.hh
Normal file
571
src/hb-buffer-deserialize-text.hh
Normal file
@ -0,0 +1,571 @@
|
|||||||
|
|
||||||
|
#line 1 "hb-buffer-deserialize-text.rl"
|
||||||
|
/*
|
||||||
|
* Copyright © 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.
|
||||||
|
*
|
||||||
|
* Google Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_BUFFER_DESERIALIZE_TEXT_HH
|
||||||
|
#define HB_BUFFER_DESERIALIZE_TEXT_HH
|
||||||
|
|
||||||
|
#include "hb-private.hh"
|
||||||
|
|
||||||
|
|
||||||
|
#line 36 "hb-buffer-deserialize-text.hh"
|
||||||
|
static const unsigned char _deserialize_text_trans_keys[] = {
|
||||||
|
0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u,
|
||||||
|
48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u,
|
||||||
|
9u, 122u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
|
||||||
|
9u, 124u, 9u, 124u, 9u, 124u, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char _deserialize_text_key_spans[] = {
|
||||||
|
0, 114, 13, 10, 13, 10, 10, 13,
|
||||||
|
10, 1, 13, 10, 14, 116, 116, 0,
|
||||||
|
114, 116, 116, 116, 116, 116, 116, 116,
|
||||||
|
116, 116, 116
|
||||||
|
};
|
||||||
|
|
||||||
|
static const short _deserialize_text_index_offsets[] = {
|
||||||
|
0, 0, 115, 129, 140, 154, 165, 176,
|
||||||
|
190, 201, 203, 217, 228, 243, 360, 477,
|
||||||
|
478, 593, 710, 827, 944, 1061, 1178, 1295,
|
||||||
|
1412, 1529, 1646
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char _deserialize_text_indicies[] = {
|
||||||
|
0, 0, 0, 0, 0, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
0, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
2, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
3, 3, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 4, 4, 1, 1, 1, 1, 1,
|
||||||
|
1, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 4, 4, 1, 5, 1, 1, 6,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 1, 8, 9, 9, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 1, 10, 1, 1,
|
||||||
|
11, 12, 12, 12, 12, 12, 12, 12,
|
||||||
|
12, 12, 1, 13, 14, 14, 14, 14,
|
||||||
|
14, 14, 14, 14, 14, 1, 15, 16,
|
||||||
|
16, 16, 16, 16, 16, 16, 16, 16,
|
||||||
|
1, 17, 1, 1, 18, 19, 19, 19,
|
||||||
|
19, 19, 19, 19, 19, 19, 1, 20,
|
||||||
|
21, 21, 21, 21, 21, 21, 21, 21,
|
||||||
|
21, 1, 22, 1, 23, 1, 1, 24,
|
||||||
|
25, 25, 25, 25, 25, 25, 25, 25,
|
||||||
|
25, 1, 26, 27, 27, 27, 27, 27,
|
||||||
|
27, 27, 27, 27, 1, 22, 1, 1,
|
||||||
|
1, 21, 21, 21, 21, 21, 21, 21,
|
||||||
|
21, 21, 21, 1, 28, 28, 28, 28,
|
||||||
|
28, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 28, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 29, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
30, 1, 1, 31, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
32, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 33,
|
||||||
|
1, 34, 34, 34, 34, 34, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
34, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 35, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 36, 1, 1, 0,
|
||||||
|
0, 0, 0, 0, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 0, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 2, 3,
|
||||||
|
3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 4,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 1, 1, 1, 1, 1, 1, 4,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 1, 28, 28, 28, 28, 28, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 28, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 29, 1, 1, 1,
|
||||||
|
1, 37, 37, 37, 37, 37, 37, 37,
|
||||||
|
37, 37, 37, 1, 1, 1, 30, 1,
|
||||||
|
1, 31, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 32, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 33, 1, 38,
|
||||||
|
38, 38, 38, 38, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 38, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 39, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 40, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 41, 1, 42, 42, 42, 42,
|
||||||
|
42, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 42, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
43, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 44,
|
||||||
|
1, 42, 42, 42, 42, 42, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
42, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
14, 14, 14, 14, 14, 14, 14, 14,
|
||||||
|
14, 14, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 43, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 44, 1, 38, 38,
|
||||||
|
38, 38, 38, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 38, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 39, 1, 1, 1, 9, 9, 9,
|
||||||
|
9, 9, 9, 9, 9, 9, 9, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 40, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 41, 1, 45, 45, 45, 45, 45,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 45, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 46, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 47, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 48,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 49, 1,
|
||||||
|
50, 50, 50, 50, 50, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 50,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 51, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 52, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 53, 1, 50, 50, 50,
|
||||||
|
50, 50, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 50, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 51,
|
||||||
|
1, 1, 1, 1, 27, 27, 27, 27,
|
||||||
|
27, 27, 27, 27, 27, 27, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 52, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
53, 1, 45, 45, 45, 45, 45, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 45, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 46, 1, 1, 1,
|
||||||
|
1, 54, 54, 54, 54, 54, 54, 54,
|
||||||
|
54, 54, 54, 1, 1, 1, 1, 1,
|
||||||
|
1, 47, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 48, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 49, 1, 28,
|
||||||
|
28, 28, 28, 28, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 28, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 29, 1, 55, 55, 1, 55, 55,
|
||||||
|
55, 55, 55, 55, 55, 55, 55, 55,
|
||||||
|
1, 1, 1, 30, 1, 1, 31, 55,
|
||||||
|
55, 55, 55, 55, 55, 55, 55, 55,
|
||||||
|
55, 55, 55, 55, 55, 55, 55, 55,
|
||||||
|
55, 55, 55, 55, 55, 55, 55, 55,
|
||||||
|
55, 1, 1, 32, 1, 55, 1, 55,
|
||||||
|
55, 55, 55, 55, 55, 55, 55, 55,
|
||||||
|
55, 55, 55, 55, 55, 55, 55, 55,
|
||||||
|
55, 55, 55, 55, 55, 55, 55, 55,
|
||||||
|
55, 1, 33, 1, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char _deserialize_text_trans_targs[] = {
|
||||||
|
1, 0, 13, 17, 26, 3, 18, 21,
|
||||||
|
18, 21, 5, 19, 20, 19, 20, 22,
|
||||||
|
25, 8, 9, 12, 9, 12, 10, 11,
|
||||||
|
23, 24, 23, 24, 14, 2, 6, 7,
|
||||||
|
15, 16, 14, 15, 16, 17, 14, 4,
|
||||||
|
15, 16, 14, 15, 16, 14, 2, 7,
|
||||||
|
15, 16, 14, 2, 15, 16, 25, 26
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char _deserialize_text_trans_actions[] = {
|
||||||
|
0, 0, 1, 1, 1, 2, 2, 2,
|
||||||
|
0, 0, 2, 2, 2, 0, 0, 2,
|
||||||
|
2, 2, 2, 2, 0, 0, 3, 2,
|
||||||
|
2, 2, 0, 0, 4, 5, 5, 5,
|
||||||
|
4, 4, 0, 0, 0, 0, 6, 7,
|
||||||
|
6, 6, 8, 8, 8, 9, 10, 10,
|
||||||
|
9, 9, 11, 12, 11, 11, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char _deserialize_text_eof_actions[] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 4, 0, 0,
|
||||||
|
0, 4, 6, 8, 8, 6, 9, 11,
|
||||||
|
11, 9, 4
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int deserialize_text_start = 1;
|
||||||
|
static const int deserialize_text_first_final = 13;
|
||||||
|
static const int deserialize_text_error = 0;
|
||||||
|
|
||||||
|
static const int deserialize_text_en_main = 1;
|
||||||
|
|
||||||
|
|
||||||
|
#line 91 "hb-buffer-deserialize-text.rl"
|
||||||
|
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
_hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer,
|
||||||
|
const char *buf,
|
||||||
|
unsigned int buf_len,
|
||||||
|
const char **end_ptr,
|
||||||
|
hb_font_t *font)
|
||||||
|
{
|
||||||
|
const char *p = buf, *pe = buf + buf_len;
|
||||||
|
|
||||||
|
/* Ensure we have positions. */
|
||||||
|
(void) hb_buffer_get_glyph_positions (buffer, nullptr);
|
||||||
|
|
||||||
|
while (p < pe && ISSPACE (*p))
|
||||||
|
p++;
|
||||||
|
if (p < pe && *p == (buffer->len ? '|' : '['))
|
||||||
|
{
|
||||||
|
*end_ptr = ++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *eof = pe, *tok = nullptr;
|
||||||
|
int cs;
|
||||||
|
hb_glyph_info_t info = {0};
|
||||||
|
hb_glyph_position_t pos = {0};
|
||||||
|
|
||||||
|
#line 343 "hb-buffer-deserialize-text.hh"
|
||||||
|
{
|
||||||
|
cs = deserialize_text_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#line 348 "hb-buffer-deserialize-text.hh"
|
||||||
|
{
|
||||||
|
int _slen;
|
||||||
|
int _trans;
|
||||||
|
const unsigned char *_keys;
|
||||||
|
const char *_inds;
|
||||||
|
if ( p == pe )
|
||||||
|
goto _test_eof;
|
||||||
|
if ( cs == 0 )
|
||||||
|
goto _out;
|
||||||
|
_resume:
|
||||||
|
_keys = _deserialize_text_trans_keys + (cs<<1);
|
||||||
|
_inds = _deserialize_text_indicies + _deserialize_text_index_offsets[cs];
|
||||||
|
|
||||||
|
_slen = _deserialize_text_key_spans[cs];
|
||||||
|
_trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
|
||||||
|
(*p) <= _keys[1] ?
|
||||||
|
(*p) - _keys[0] : _slen ];
|
||||||
|
|
||||||
|
cs = _deserialize_text_trans_targs[_trans];
|
||||||
|
|
||||||
|
if ( _deserialize_text_trans_actions[_trans] == 0 )
|
||||||
|
goto _again;
|
||||||
|
|
||||||
|
switch ( _deserialize_text_trans_actions[_trans] ) {
|
||||||
|
case 2:
|
||||||
|
#line 51 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
tok = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
#line 55 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
if (!hb_font_glyph_from_string (font,
|
||||||
|
tok, p - tok,
|
||||||
|
&info.codepoint))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
#line 62 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
#line 63 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.x_offset )) return false; }
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
#line 64 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
#line 65 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
#line 38 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
memset (&info, 0, sizeof (info));
|
||||||
|
memset (&pos , 0, sizeof (pos ));
|
||||||
|
}
|
||||||
|
#line 51 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
tok = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
#line 55 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
if (!hb_font_glyph_from_string (font,
|
||||||
|
tok, p - tok,
|
||||||
|
&info.codepoint))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#line 43 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
#line 62 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
#line 64 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
#line 65 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
#line 66 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#line 480 "hb-buffer-deserialize-text.hh"
|
||||||
|
}
|
||||||
|
|
||||||
|
_again:
|
||||||
|
if ( cs == 0 )
|
||||||
|
goto _out;
|
||||||
|
if ( ++p != pe )
|
||||||
|
goto _resume;
|
||||||
|
_test_eof: {}
|
||||||
|
if ( p == eof )
|
||||||
|
{
|
||||||
|
switch ( _deserialize_text_eof_actions[cs] ) {
|
||||||
|
case 4:
|
||||||
|
#line 55 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
if (!hb_font_glyph_from_string (font,
|
||||||
|
tok, p - tok,
|
||||||
|
&info.codepoint))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#line 43 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
#line 62 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
#line 64 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
#line 65 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
#line 66 "hb-buffer-deserialize-text.rl"
|
||||||
|
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
|
||||||
|
#line 43 "hb-buffer-deserialize-text.rl"
|
||||||
|
{
|
||||||
|
buffer->add_info (info);
|
||||||
|
if (buffer->in_error)
|
||||||
|
return false;
|
||||||
|
buffer->pos[buffer->len - 1] = pos;
|
||||||
|
*end_ptr = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#line 557 "hb-buffer-deserialize-text.hh"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_out: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#line 119 "hb-buffer-deserialize-text.rl"
|
||||||
|
|
||||||
|
|
||||||
|
*end_ptr = p;
|
||||||
|
|
||||||
|
return p == pe && *(p-1) != ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HB_BUFFER_DESERIALIZE_TEXT_HH */
|
@ -100,7 +100,7 @@ _hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer,
|
|||||||
const char *p = buf, *pe = buf + buf_len;
|
const char *p = buf, *pe = buf + buf_len;
|
||||||
|
|
||||||
/* Ensure we have positions. */
|
/* Ensure we have positions. */
|
||||||
(void) hb_buffer_get_glyph_positions (buffer, NULL);
|
(void) hb_buffer_get_glyph_positions (buffer, nullptr);
|
||||||
|
|
||||||
while (p < pe && ISSPACE (*p))
|
while (p < pe && ISSPACE (*p))
|
||||||
p++;
|
p++;
|
||||||
@ -109,7 +109,7 @@ _hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer,
|
|||||||
*end_ptr = ++p;
|
*end_ptr = ++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *eof = pe, *tok = NULL;
|
const char *eof = pe, *tok = nullptr;
|
||||||
int cs;
|
int cs;
|
||||||
hb_glyph_info_t info = {0};
|
hb_glyph_info_t info = {0};
|
||||||
hb_glyph_position_t pos = {0};
|
hb_glyph_position_t pos = {0};
|
||||||
|
@ -35,8 +35,8 @@
|
|||||||
#include "hb-unicode-private.hh"
|
#include "hb-unicode-private.hh"
|
||||||
|
|
||||||
|
|
||||||
#ifndef HB_BUFFER_MAX_EXPANSION_FACTOR
|
#ifndef HB_BUFFER_MAX_LEN_FACTOR
|
||||||
#define HB_BUFFER_MAX_EXPANSION_FACTOR 32
|
#define HB_BUFFER_MAX_LEN_FACTOR 32
|
||||||
#endif
|
#endif
|
||||||
#ifndef HB_BUFFER_MAX_LEN_MIN
|
#ifndef HB_BUFFER_MAX_LEN_MIN
|
||||||
#define HB_BUFFER_MAX_LEN_MIN 8192
|
#define HB_BUFFER_MAX_LEN_MIN 8192
|
||||||
@ -45,11 +45,22 @@
|
|||||||
#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
|
#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ASSERT_STATIC (sizeof (hb_glyph_info_t) == 20);
|
#ifndef HB_BUFFER_MAX_OPS_FACTOR
|
||||||
ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
|
#define HB_BUFFER_MAX_OPS_FACTOR 64
|
||||||
|
#endif
|
||||||
|
#ifndef HB_BUFFER_MAX_OPS_MIN
|
||||||
|
#define HB_BUFFER_MAX_OPS_MIN 1024
|
||||||
|
#endif
|
||||||
|
#ifndef HB_BUFFER_MAX_OPS_DEFAULT
|
||||||
|
#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static_assert ((sizeof (hb_glyph_info_t) == 20), "");
|
||||||
|
static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
|
||||||
|
|
||||||
HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
|
HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
|
||||||
HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
|
HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
|
||||||
|
HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
|
||||||
|
|
||||||
enum hb_buffer_scratch_flags_t {
|
enum hb_buffer_scratch_flags_t {
|
||||||
HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u,
|
HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u,
|
||||||
@ -57,6 +68,9 @@ enum hb_buffer_scratch_flags_t {
|
|||||||
HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u,
|
HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u,
|
||||||
HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u,
|
HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u,
|
||||||
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u,
|
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u,
|
||||||
|
HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u,
|
||||||
|
HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000020u,
|
||||||
|
|
||||||
/* Reserved for complex shapers' internal use. */
|
/* Reserved for complex shapers' internal use. */
|
||||||
HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
|
HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
|
||||||
HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u,
|
HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u,
|
||||||
@ -79,8 +93,9 @@ struct hb_buffer_t {
|
|||||||
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
|
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
|
||||||
hb_buffer_cluster_level_t cluster_level;
|
hb_buffer_cluster_level_t cluster_level;
|
||||||
hb_codepoint_t replacement; /* U+FFFD or something else. */
|
hb_codepoint_t replacement; /* U+FFFD or something else. */
|
||||||
hb_buffer_scratch_flags_t scratch_flags; /* Have space-flallback, etc. */
|
hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
|
||||||
unsigned int max_len; /* Maximum allowed len. */
|
unsigned int max_len; /* Maximum allowed len. */
|
||||||
|
int max_ops; /* Maximum allowed operations. */
|
||||||
|
|
||||||
/* Buffer contents */
|
/* Buffer contents */
|
||||||
hb_buffer_content_type_t content_type;
|
hb_buffer_content_type_t content_type;
|
||||||
@ -99,17 +114,6 @@ struct hb_buffer_t {
|
|||||||
hb_glyph_info_t *out_info;
|
hb_glyph_info_t *out_info;
|
||||||
hb_glyph_position_t *pos;
|
hb_glyph_position_t *pos;
|
||||||
|
|
||||||
inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
|
|
||||||
inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
|
|
||||||
|
|
||||||
inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
|
|
||||||
inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
|
|
||||||
|
|
||||||
inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; }
|
|
||||||
inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; }
|
|
||||||
|
|
||||||
inline bool has_separate_output (void) const { return info != out_info; }
|
|
||||||
|
|
||||||
unsigned int serial;
|
unsigned int serial;
|
||||||
|
|
||||||
/* Text before / after the main buffer contents.
|
/* Text before / after the main buffer contents.
|
||||||
@ -129,12 +133,16 @@ struct hb_buffer_t {
|
|||||||
#ifndef HB_NDEBUG
|
#ifndef HB_NDEBUG
|
||||||
uint8_t allocated_var_bits;
|
uint8_t allocated_var_bits;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Methods */
|
||||||
|
|
||||||
inline void allocate_var (unsigned int start, unsigned int count)
|
inline void allocate_var (unsigned int start, unsigned int count)
|
||||||
{
|
{
|
||||||
#ifndef HB_NDEBUG
|
#ifndef HB_NDEBUG
|
||||||
unsigned int end = start + count;
|
unsigned int end = start + count;
|
||||||
assert (end <= 8);
|
assert (end <= 8);
|
||||||
unsigned int bits = (1<<end) - (1<<start);
|
unsigned int bits = (1u<<end) - (1u<<start);
|
||||||
assert (0 == (allocated_var_bits & bits));
|
assert (0 == (allocated_var_bits & bits));
|
||||||
allocated_var_bits |= bits;
|
allocated_var_bits |= bits;
|
||||||
#endif
|
#endif
|
||||||
@ -144,7 +152,7 @@ struct hb_buffer_t {
|
|||||||
#ifndef HB_NDEBUG
|
#ifndef HB_NDEBUG
|
||||||
unsigned int end = start + count;
|
unsigned int end = start + count;
|
||||||
assert (end <= 8);
|
assert (end <= 8);
|
||||||
unsigned int bits = (1<<end) - (1<<start);
|
unsigned int bits = (1u<<end) - (1u<<start);
|
||||||
assert (bits == (allocated_var_bits & bits));
|
assert (bits == (allocated_var_bits & bits));
|
||||||
allocated_var_bits &= ~bits;
|
allocated_var_bits &= ~bits;
|
||||||
#endif
|
#endif
|
||||||
@ -154,7 +162,7 @@ struct hb_buffer_t {
|
|||||||
#ifndef HB_NDEBUG
|
#ifndef HB_NDEBUG
|
||||||
unsigned int end = start + count;
|
unsigned int end = start + count;
|
||||||
assert (end <= 8);
|
assert (end <= 8);
|
||||||
unsigned int bits = (1<<end) - (1<<start);
|
unsigned int bits = (1u<<end) - (1u<<start);
|
||||||
assert (bits == (allocated_var_bits & bits));
|
assert (bits == (allocated_var_bits & bits));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -165,8 +173,17 @@ struct hb_buffer_t {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
|
||||||
|
inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
|
||||||
|
|
||||||
|
inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
|
||||||
|
inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
|
||||||
|
|
||||||
|
inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; }
|
||||||
|
inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; }
|
||||||
|
|
||||||
|
inline bool has_separate_output (void) const { return info != out_info; }
|
||||||
|
|
||||||
/* Methods */
|
|
||||||
|
|
||||||
HB_INTERNAL void reset (void);
|
HB_INTERNAL void reset (void);
|
||||||
HB_INTERNAL void clear (void);
|
HB_INTERNAL void clear (void);
|
||||||
@ -232,25 +249,31 @@ struct hb_buffer_t {
|
|||||||
for (unsigned int j = 0; j < len; j++)
|
for (unsigned int j = 0; j < len; j++)
|
||||||
info[j].mask |= mask;
|
info[j].mask |= mask;
|
||||||
}
|
}
|
||||||
HB_INTERNAL void set_masks (hb_mask_t value,
|
HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
|
||||||
hb_mask_t mask,
|
unsigned int cluster_start, unsigned int cluster_end);
|
||||||
unsigned int cluster_start,
|
|
||||||
unsigned int cluster_end);
|
|
||||||
|
|
||||||
HB_INTERNAL void merge_clusters (unsigned int start,
|
inline void merge_clusters (unsigned int start, unsigned int end)
|
||||||
unsigned int end)
|
|
||||||
{
|
{
|
||||||
if (end - start < 2)
|
if (end - start < 2)
|
||||||
return;
|
return;
|
||||||
merge_clusters_impl (start, end);
|
merge_clusters_impl (start, end);
|
||||||
}
|
}
|
||||||
HB_INTERNAL void merge_clusters_impl (unsigned int start,
|
HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
|
||||||
unsigned int end);
|
HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
|
||||||
HB_INTERNAL void merge_out_clusters (unsigned int start,
|
|
||||||
unsigned int end);
|
|
||||||
/* Merge clusters for deleting current glyph, and skip it. */
|
/* Merge clusters for deleting current glyph, and skip it. */
|
||||||
HB_INTERNAL void delete_glyph (void);
|
HB_INTERNAL void delete_glyph (void);
|
||||||
|
|
||||||
|
inline void unsafe_to_break (unsigned int start,
|
||||||
|
unsigned int end)
|
||||||
|
{
|
||||||
|
if (end - start < 2)
|
||||||
|
return;
|
||||||
|
unsafe_to_break_impl (start, end);
|
||||||
|
}
|
||||||
|
HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
|
||||||
|
HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
|
||||||
|
|
||||||
|
|
||||||
/* Internal methods */
|
/* Internal methods */
|
||||||
HB_INTERNAL bool enlarge (unsigned int size);
|
HB_INTERNAL bool enlarge (unsigned int size);
|
||||||
|
|
||||||
@ -282,9 +305,78 @@ struct hb_buffer_t {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
|
HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
|
||||||
|
{
|
||||||
|
if (inf.cluster != cluster)
|
||||||
|
{
|
||||||
|
if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
|
||||||
|
inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||||
|
else
|
||||||
|
inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||||
|
}
|
||||||
|
inf.cluster = cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int
|
||||||
|
_unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
|
||||||
|
unsigned int start, unsigned int end,
|
||||||
|
unsigned int cluster) const
|
||||||
|
{
|
||||||
|
for (unsigned int i = start; i < end; i++)
|
||||||
|
cluster = MIN<unsigned int> (cluster, infos[i].cluster);
|
||||||
|
return cluster;
|
||||||
|
}
|
||||||
|
inline void
|
||||||
|
_unsafe_to_break_set_mask (hb_glyph_info_t *infos,
|
||||||
|
unsigned int start, unsigned int end,
|
||||||
|
unsigned int cluster)
|
||||||
|
{
|
||||||
|
for (unsigned int i = start; i < end; i++)
|
||||||
|
if (cluster != infos[i].cluster)
|
||||||
|
{
|
||||||
|
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
|
||||||
|
infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
unsafe_to_break_all (void)
|
||||||
|
{
|
||||||
|
unsafe_to_break_impl (0, len);
|
||||||
|
}
|
||||||
|
inline void
|
||||||
|
safe_to_break_all (void)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < len; i++)
|
||||||
|
info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Loop over clusters. Duplicated in foreach_syllable(). */
|
||||||
|
#define foreach_cluster(buffer, start, end) \
|
||||||
|
for (unsigned int \
|
||||||
|
_count = buffer->len, \
|
||||||
|
start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
|
||||||
|
start < _count; \
|
||||||
|
start = end, end = _next_cluster (buffer, start))
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
_next_cluster (hb_buffer_t *buffer, unsigned int start)
|
||||||
|
{
|
||||||
|
hb_glyph_info_t *info = buffer->info;
|
||||||
|
unsigned int count = buffer->len;
|
||||||
|
|
||||||
|
unsigned int cluster = info[start].cluster;
|
||||||
|
while (++start < count && cluster == info[start].cluster)
|
||||||
|
;
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
|
#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
|
||||||
b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
|
b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
|
||||||
sizeof (b->info[0].var))
|
sizeof (b->info[0].var))
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
static const char *serialize_formats[] = {
|
static const char *serialize_formats[] = {
|
||||||
"text",
|
"text",
|
||||||
"json",
|
"json",
|
||||||
NULL
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,7 +90,7 @@ hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
|
|||||||
case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0];
|
case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0];
|
||||||
case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1];
|
case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1];
|
||||||
default:
|
default:
|
||||||
case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return NULL;
|
case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,11 +104,12 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
|
|||||||
hb_font_t *font,
|
hb_font_t *font,
|
||||||
hb_buffer_serialize_flags_t flags)
|
hb_buffer_serialize_flags_t flags)
|
||||||
{
|
{
|
||||||
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
|
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
|
||||||
hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ?
|
hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ?
|
||||||
NULL : hb_buffer_get_glyph_positions (buffer, NULL);
|
nullptr : hb_buffer_get_glyph_positions (buffer, nullptr);
|
||||||
|
|
||||||
*buf_consumed = 0;
|
*buf_consumed = 0;
|
||||||
|
hb_position_t x = 0, y = 0;
|
||||||
for (unsigned int i = start; i < end; i++)
|
for (unsigned int i = start; i < end; i++)
|
||||||
{
|
{
|
||||||
char b[1024];
|
char b[1024];
|
||||||
@ -145,10 +146,17 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
|
|||||||
|
|
||||||
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
|
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
|
||||||
{
|
{
|
||||||
p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
|
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
|
||||||
pos[i].x_offset, pos[i].y_offset);
|
x+pos[i].x_offset, y+pos[i].y_offset));
|
||||||
p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
|
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
|
||||||
pos[i].x_advance, pos[i].y_advance);
|
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
|
||||||
|
pos[i].x_advance, pos[i].y_advance));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
|
||||||
|
{
|
||||||
|
if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
|
||||||
|
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
|
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
|
||||||
@ -156,9 +164,9 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
|
|||||||
hb_glyph_extents_t extents;
|
hb_glyph_extents_t extents;
|
||||||
hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
|
hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
|
||||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
|
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
|
||||||
extents.x_bearing, extents.y_bearing));
|
extents.x_bearing, extents.y_bearing));
|
||||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
|
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
|
||||||
extents.width, extents.height));
|
extents.width, extents.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
*p++ = '}';
|
*p++ = '}';
|
||||||
@ -173,6 +181,12 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
|
|||||||
*buf = '\0';
|
*buf = '\0';
|
||||||
} else
|
} else
|
||||||
return i - start;
|
return i - start;
|
||||||
|
|
||||||
|
if (pos && (flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
|
||||||
|
{
|
||||||
|
x += pos[i].x_advance;
|
||||||
|
y += pos[i].y_advance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return end - start;
|
return end - start;
|
||||||
@ -188,11 +202,12 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
|
|||||||
hb_font_t *font,
|
hb_font_t *font,
|
||||||
hb_buffer_serialize_flags_t flags)
|
hb_buffer_serialize_flags_t flags)
|
||||||
{
|
{
|
||||||
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
|
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
|
||||||
hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ?
|
hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ?
|
||||||
NULL : hb_buffer_get_glyph_positions (buffer, NULL);
|
nullptr : hb_buffer_get_glyph_positions (buffer, nullptr);
|
||||||
|
|
||||||
*buf_consumed = 0;
|
*buf_consumed = 0;
|
||||||
|
hb_position_t x = 0, y = 0;
|
||||||
for (unsigned int i = start; i < end; i++)
|
for (unsigned int i = start; i < end; i++)
|
||||||
{
|
{
|
||||||
char b[1024];
|
char b[1024];
|
||||||
@ -217,13 +232,22 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
|
|||||||
|
|
||||||
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
|
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
|
||||||
{
|
{
|
||||||
if (pos[i].x_offset || pos[i].y_offset)
|
if (x+pos[i].x_offset || y+pos[i].y_offset)
|
||||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", pos[i].x_offset, pos[i].y_offset));
|
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset));
|
||||||
|
|
||||||
*p++ = '+';
|
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
|
||||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
|
{
|
||||||
if (pos[i].y_advance)
|
*p++ = '+';
|
||||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
|
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
|
||||||
|
if (pos[i].y_advance)
|
||||||
|
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
|
||||||
|
{
|
||||||
|
if (info[i].mask &HB_GLYPH_FLAG_DEFINED)
|
||||||
|
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
|
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
|
||||||
@ -243,6 +267,12 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
|
|||||||
*buf = '\0';
|
*buf = '\0';
|
||||||
} else
|
} else
|
||||||
return i - start;
|
return i - start;
|
||||||
|
|
||||||
|
if (pos && (flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
|
||||||
|
{
|
||||||
|
x += pos[i].x_advance;
|
||||||
|
y += pos[i].y_advance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return end - start;
|
return end - start;
|
||||||
@ -311,6 +341,8 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
|
|||||||
if (!buf_consumed)
|
if (!buf_consumed)
|
||||||
buf_consumed = &sconsumed;
|
buf_consumed = &sconsumed;
|
||||||
*buf_consumed = 0;
|
*buf_consumed = 0;
|
||||||
|
if (buf_size)
|
||||||
|
*buf = '\0';
|
||||||
|
|
||||||
assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
|
assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
|
||||||
buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
|
buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
|
||||||
@ -408,8 +440,8 @@ hb_bool_t
|
|||||||
hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
|
hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
|
||||||
const char *buf,
|
const char *buf,
|
||||||
int buf_len, /* -1 means nul-terminated */
|
int buf_len, /* -1 means nul-terminated */
|
||||||
const char **end_ptr, /* May be NULL */
|
const char **end_ptr, /* May be nullptr */
|
||||||
hb_font_t *font, /* May be NULL */
|
hb_font_t *font, /* May be nullptr */
|
||||||
hb_buffer_serialize_format_t format)
|
hb_buffer_serialize_format_t format)
|
||||||
{
|
{
|
||||||
const char *end;
|
const char *end;
|
||||||
|
240
src/hb-buffer.cc
240
src/hb-buffer.cc
@ -31,10 +31,6 @@
|
|||||||
#include "hb-utf-private.hh"
|
#include "hb-utf-private.hh"
|
||||||
|
|
||||||
|
|
||||||
#ifndef HB_DEBUG_BUFFER
|
|
||||||
#define HB_DEBUG_BUFFER (HB_DEBUG+0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION: hb-buffer
|
* SECTION: hb-buffer
|
||||||
* @title: Buffers
|
* @title: Buffers
|
||||||
@ -52,7 +48,7 @@
|
|||||||
*
|
*
|
||||||
* Checks the equality of two #hb_segment_properties_t's.
|
* Checks the equality of two #hb_segment_properties_t's.
|
||||||
*
|
*
|
||||||
* Return value: (transfer full):
|
* Return value:
|
||||||
* %true if all properties of @a equal those of @b, false otherwise.
|
* %true if all properties of @a equal those of @b, false otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.9.7
|
* Since: 0.9.7
|
||||||
@ -124,8 +120,8 @@ hb_buffer_t::enlarge (unsigned int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned int new_allocated = allocated;
|
unsigned int new_allocated = allocated;
|
||||||
hb_glyph_position_t *new_pos = NULL;
|
hb_glyph_position_t *new_pos = nullptr;
|
||||||
hb_glyph_info_t *new_info = NULL;
|
hb_glyph_info_t *new_info = nullptr;
|
||||||
bool separate_out = out_info != info;
|
bool separate_out = out_info != info;
|
||||||
|
|
||||||
if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
|
if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
|
||||||
@ -134,7 +130,7 @@ hb_buffer_t::enlarge (unsigned int size)
|
|||||||
while (size >= new_allocated)
|
while (size >= new_allocated)
|
||||||
new_allocated += (new_allocated >> 1) + 32;
|
new_allocated += (new_allocated >> 1) + 32;
|
||||||
|
|
||||||
ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0]));
|
static_assert ((sizeof (info[0]) == sizeof (pos[0])), "");
|
||||||
if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
|
if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@ -183,6 +179,12 @@ hb_buffer_t::shift_forward (unsigned int count)
|
|||||||
if (unlikely (!ensure (len + count))) return false;
|
if (unlikely (!ensure (len + count))) return false;
|
||||||
|
|
||||||
memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0]));
|
memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0]));
|
||||||
|
if (idx + count > len)
|
||||||
|
{
|
||||||
|
/* Under memory failure we might expose this area. At least
|
||||||
|
* clean it up. Oh well... */
|
||||||
|
memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
|
||||||
|
}
|
||||||
len += count;
|
len += count;
|
||||||
idx += count;
|
idx += count;
|
||||||
|
|
||||||
@ -261,7 +263,7 @@ hb_buffer_t::add (hb_codepoint_t codepoint,
|
|||||||
|
|
||||||
memset (glyph, 0, sizeof (*glyph));
|
memset (glyph, 0, sizeof (*glyph));
|
||||||
glyph->codepoint = codepoint;
|
glyph->codepoint = codepoint;
|
||||||
glyph->mask = 1;
|
glyph->mask = 0;
|
||||||
glyph->cluster = cluster;
|
glyph->cluster = cluster;
|
||||||
|
|
||||||
len++;
|
len++;
|
||||||
@ -426,6 +428,8 @@ hb_buffer_t::move_to (unsigned int i)
|
|||||||
/* Tricky part: rewinding... */
|
/* Tricky part: rewinding... */
|
||||||
unsigned int count = out_len - 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;
|
if (unlikely (idx < count && !shift_forward (count + 32))) return false;
|
||||||
|
|
||||||
assert (idx >= count);
|
assert (idx >= count);
|
||||||
@ -542,12 +546,15 @@ hb_buffer_t::merge_clusters_impl (unsigned int start,
|
|||||||
unsigned int end)
|
unsigned int end)
|
||||||
{
|
{
|
||||||
if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
|
if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
|
||||||
|
{
|
||||||
|
unsafe_to_break (start, end);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int cluster = info[start].cluster;
|
unsigned int cluster = info[start].cluster;
|
||||||
|
|
||||||
for (unsigned int i = start + 1; i < end; i++)
|
for (unsigned int i = start + 1; i < end; i++)
|
||||||
cluster = MIN (cluster, info[i].cluster);
|
cluster = MIN<unsigned int> (cluster, info[i].cluster);
|
||||||
|
|
||||||
/* Extend end */
|
/* Extend end */
|
||||||
while (end < len && info[end - 1].cluster == info[end].cluster)
|
while (end < len && info[end - 1].cluster == info[end].cluster)
|
||||||
@ -560,10 +567,10 @@ hb_buffer_t::merge_clusters_impl (unsigned int start,
|
|||||||
/* If we hit the start of buffer, continue in out-buffer. */
|
/* If we hit the start of buffer, continue in out-buffer. */
|
||||||
if (idx == start)
|
if (idx == start)
|
||||||
for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
|
for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
|
||||||
out_info[i - 1].cluster = cluster;
|
set_cluster (out_info[i - 1], cluster);
|
||||||
|
|
||||||
for (unsigned int i = start; i < end; i++)
|
for (unsigned int i = start; i < end; i++)
|
||||||
info[i].cluster = cluster;
|
set_cluster (info[i], cluster);
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
hb_buffer_t::merge_out_clusters (unsigned int start,
|
hb_buffer_t::merge_out_clusters (unsigned int start,
|
||||||
@ -578,7 +585,7 @@ hb_buffer_t::merge_out_clusters (unsigned int start,
|
|||||||
unsigned int cluster = out_info[start].cluster;
|
unsigned int cluster = out_info[start].cluster;
|
||||||
|
|
||||||
for (unsigned int i = start + 1; i < end; i++)
|
for (unsigned int i = start + 1; i < end; i++)
|
||||||
cluster = MIN (cluster, out_info[i].cluster);
|
cluster = MIN<unsigned int> (cluster, out_info[i].cluster);
|
||||||
|
|
||||||
/* Extend start */
|
/* Extend start */
|
||||||
while (start && out_info[start - 1].cluster == out_info[start].cluster)
|
while (start && out_info[start - 1].cluster == out_info[start].cluster)
|
||||||
@ -591,14 +598,16 @@ hb_buffer_t::merge_out_clusters (unsigned int start,
|
|||||||
/* If we hit the end of out-buffer, continue in buffer. */
|
/* If we hit the end of out-buffer, continue in buffer. */
|
||||||
if (end == out_len)
|
if (end == out_len)
|
||||||
for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++)
|
for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++)
|
||||||
info[i].cluster = cluster;
|
set_cluster (info[i], cluster);
|
||||||
|
|
||||||
for (unsigned int i = start; i < end; i++)
|
for (unsigned int i = start; i < end; i++)
|
||||||
out_info[i].cluster = cluster;
|
set_cluster (out_info[i], cluster);
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
hb_buffer_t::delete_glyph ()
|
hb_buffer_t::delete_glyph ()
|
||||||
{
|
{
|
||||||
|
/* The logic here is duplicated in hb_ot_hide_default_ignorables(). */
|
||||||
|
|
||||||
unsigned int cluster = info[idx].cluster;
|
unsigned int cluster = info[idx].cluster;
|
||||||
if (idx + 1 < len && cluster == info[idx + 1].cluster)
|
if (idx + 1 < len && cluster == info[idx + 1].cluster)
|
||||||
{
|
{
|
||||||
@ -611,9 +620,10 @@ hb_buffer_t::delete_glyph ()
|
|||||||
/* Merge cluster backward. */
|
/* Merge cluster backward. */
|
||||||
if (cluster < out_info[out_len - 1].cluster)
|
if (cluster < out_info[out_len - 1].cluster)
|
||||||
{
|
{
|
||||||
|
unsigned int mask = info[idx].mask;
|
||||||
unsigned int old_cluster = out_info[out_len - 1].cluster;
|
unsigned int old_cluster = out_info[out_len - 1].cluster;
|
||||||
for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--)
|
for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--)
|
||||||
out_info[i - 1].cluster = cluster;
|
set_cluster (out_info[i - 1], cluster, mask);
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -629,6 +639,32 @@ done:
|
|||||||
skip_glyph ();
|
skip_glyph ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end)
|
||||||
|
{
|
||||||
|
unsigned int cluster = (unsigned int) -1;
|
||||||
|
cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster);
|
||||||
|
_unsafe_to_break_set_mask (info, start, end, cluster);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end)
|
||||||
|
{
|
||||||
|
if (!have_output)
|
||||||
|
{
|
||||||
|
unsafe_to_break_impl (start, end);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (start <= out_len);
|
||||||
|
assert (idx <= end);
|
||||||
|
|
||||||
|
unsigned int cluster = (unsigned int) -1;
|
||||||
|
cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster);
|
||||||
|
cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster);
|
||||||
|
_unsafe_to_break_set_mask (out_info, start, out_len, cluster);
|
||||||
|
_unsafe_to_break_set_mask (info, idx, end, cluster);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
hb_buffer_t::guess_segment_properties (void)
|
hb_buffer_t::guess_segment_properties (void)
|
||||||
{
|
{
|
||||||
@ -686,6 +722,7 @@ hb_buffer_create (void)
|
|||||||
return hb_buffer_get_empty ();
|
return hb_buffer_get_empty ();
|
||||||
|
|
||||||
buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
|
buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
|
||||||
|
buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
|
||||||
|
|
||||||
buffer->reset ();
|
buffer->reset ();
|
||||||
|
|
||||||
@ -713,6 +750,7 @@ hb_buffer_get_empty (void)
|
|||||||
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
|
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
|
||||||
HB_BUFFER_SCRATCH_FLAG_DEFAULT,
|
HB_BUFFER_SCRATCH_FLAG_DEFAULT,
|
||||||
HB_BUFFER_MAX_LEN_DEFAULT,
|
HB_BUFFER_MAX_LEN_DEFAULT,
|
||||||
|
HB_BUFFER_MAX_OPS_DEFAULT,
|
||||||
|
|
||||||
HB_BUFFER_CONTENT_TYPE_INVALID,
|
HB_BUFFER_CONTENT_TYPE_INVALID,
|
||||||
HB_SEGMENT_PROPERTIES_DEFAULT,
|
HB_SEGMENT_PROPERTIES_DEFAULT,
|
||||||
@ -1371,6 +1409,23 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
|
|||||||
return (hb_glyph_position_t *) buffer->pos;
|
return (hb_glyph_position_t *) buffer->pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_glyph_info_get_glyph_flags:
|
||||||
|
* @info: a #hb_glyph_info_t.
|
||||||
|
*
|
||||||
|
* Returns glyph flags encoded within a #hb_glyph_info_t.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The #hb_glyph_flags_t encoded within @info.
|
||||||
|
*
|
||||||
|
* Since: 1.5.0
|
||||||
|
**/
|
||||||
|
hb_glyph_flags_t
|
||||||
|
(hb_glyph_info_get_glyph_flags) (const hb_glyph_info_t *info)
|
||||||
|
{
|
||||||
|
return hb_glyph_info_get_glyph_flags (info);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_buffer_reverse:
|
* hb_buffer_reverse:
|
||||||
* @buffer: an #hb_buffer_t.
|
* @buffer: an #hb_buffer_t.
|
||||||
@ -1658,6 +1713,58 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_buffer_append:
|
||||||
|
* @buffer: an #hb_buffer_t.
|
||||||
|
* @source: source #hb_buffer_t.
|
||||||
|
* @start: start index into source buffer to copy. Use 0 to copy from start of buffer.
|
||||||
|
* @end: end index into source buffer to copy. Use (unsigned int) -1 to copy to end of buffer.
|
||||||
|
*
|
||||||
|
* Append (part of) contents of another buffer to this buffer.
|
||||||
|
*
|
||||||
|
* Since: 1.5.0
|
||||||
|
**/
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_buffer_append (hb_buffer_t *buffer,
|
||||||
|
hb_buffer_t *source,
|
||||||
|
unsigned int start,
|
||||||
|
unsigned int end)
|
||||||
|
{
|
||||||
|
assert (!buffer->have_output && !source->have_output);
|
||||||
|
assert (buffer->have_positions == source->have_positions ||
|
||||||
|
!buffer->len || !source->len);
|
||||||
|
assert (buffer->content_type == source->content_type ||
|
||||||
|
!buffer->len || !source->len);
|
||||||
|
|
||||||
|
if (end > source->len)
|
||||||
|
end = source->len;
|
||||||
|
if (start > end)
|
||||||
|
start = end;
|
||||||
|
if (start == end)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!buffer->len)
|
||||||
|
buffer->content_type = source->content_type;
|
||||||
|
if (!buffer->have_positions && source->have_positions)
|
||||||
|
buffer->clear_positions ();
|
||||||
|
|
||||||
|
if (buffer->len + (end - start) < buffer->len) /* Overflows. */
|
||||||
|
{
|
||||||
|
buffer->in_error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int orig_len = buffer->len;
|
||||||
|
hb_buffer_set_length (buffer, buffer->len + (end - start));
|
||||||
|
if (buffer->in_error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
|
||||||
|
if (buffer->have_positions)
|
||||||
|
memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compare_info_codepoint (const hb_glyph_info_t *pa,
|
compare_info_codepoint (const hb_glyph_info_t *pa,
|
||||||
const hb_glyph_info_t *pb)
|
const hb_glyph_info_t *pb)
|
||||||
@ -1728,7 +1835,8 @@ void
|
|||||||
hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
|
hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
|
||||||
{
|
{
|
||||||
assert (buffer->have_positions);
|
assert (buffer->have_positions);
|
||||||
assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
|
assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS ||
|
||||||
|
(!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
|
||||||
|
|
||||||
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
|
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
|
||||||
|
|
||||||
@ -1767,6 +1875,98 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Comparing buffers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_buffer_diff:
|
||||||
|
*
|
||||||
|
* If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
|
||||||
|
* and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most
|
||||||
|
* callers if just comparing two buffers is needed.
|
||||||
|
*
|
||||||
|
* Since: 1.5.0
|
||||||
|
**/
|
||||||
|
hb_buffer_diff_flags_t
|
||||||
|
hb_buffer_diff (hb_buffer_t *buffer,
|
||||||
|
hb_buffer_t *reference,
|
||||||
|
hb_codepoint_t dottedcircle_glyph,
|
||||||
|
unsigned int position_fuzz)
|
||||||
|
{
|
||||||
|
if (buffer->content_type != reference->content_type && buffer->len && reference->len)
|
||||||
|
return HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH;
|
||||||
|
|
||||||
|
hb_buffer_diff_flags_t result = HB_BUFFER_DIFF_FLAG_EQUAL;
|
||||||
|
bool contains = dottedcircle_glyph != (hb_codepoint_t) -1;
|
||||||
|
|
||||||
|
unsigned int count = reference->len;
|
||||||
|
|
||||||
|
if (buffer->len != count)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* we can't compare glyph-by-glyph, but we do want to know if there
|
||||||
|
* are .notdef or dottedcircle glyphs present in the reference buffer
|
||||||
|
*/
|
||||||
|
const hb_glyph_info_t *info = reference->info;
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (contains && info[i].codepoint == dottedcircle_glyph)
|
||||||
|
result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
|
||||||
|
if (contains && info[i].codepoint == 0)
|
||||||
|
result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT;
|
||||||
|
}
|
||||||
|
result |= HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH;
|
||||||
|
return hb_buffer_diff_flags_t (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count)
|
||||||
|
return hb_buffer_diff_flags_t (result);
|
||||||
|
|
||||||
|
const hb_glyph_info_t *buf_info = buffer->info;
|
||||||
|
const hb_glyph_info_t *ref_info = reference->info;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (buf_info->codepoint != ref_info->codepoint)
|
||||||
|
result |= HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH;
|
||||||
|
if (buf_info->cluster != ref_info->cluster)
|
||||||
|
result |= HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH;
|
||||||
|
if ((buf_info->mask & ~ref_info->mask & HB_GLYPH_FLAG_DEFINED))
|
||||||
|
result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH;
|
||||||
|
if (contains && ref_info->codepoint == dottedcircle_glyph)
|
||||||
|
result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
|
||||||
|
if (contains && ref_info->codepoint == 0)
|
||||||
|
result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT;
|
||||||
|
buf_info++;
|
||||||
|
ref_info++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS)
|
||||||
|
{
|
||||||
|
assert (buffer->have_positions);
|
||||||
|
const hb_glyph_position_t *buf_pos = buffer->pos;
|
||||||
|
const hb_glyph_position_t *ref_pos = reference->pos;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if ((unsigned int) abs (buf_pos->x_advance - ref_pos->x_advance) > position_fuzz ||
|
||||||
|
(unsigned int) abs (buf_pos->y_advance - ref_pos->y_advance) > position_fuzz ||
|
||||||
|
(unsigned int) abs (buf_pos->x_offset - ref_pos->x_offset) > position_fuzz ||
|
||||||
|
(unsigned int) abs (buf_pos->y_offset - ref_pos->y_offset) > position_fuzz)
|
||||||
|
{
|
||||||
|
result |= HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf_pos++;
|
||||||
|
ref_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Debugging.
|
* Debugging.
|
||||||
*/
|
*/
|
||||||
@ -1795,9 +1995,9 @@ hb_buffer_set_message_func (hb_buffer_t *buffer,
|
|||||||
buffer->message_data = user_data;
|
buffer->message_data = user_data;
|
||||||
buffer->message_destroy = destroy;
|
buffer->message_destroy = destroy;
|
||||||
} else {
|
} else {
|
||||||
buffer->message_func = NULL;
|
buffer->message_func = nullptr;
|
||||||
buffer->message_data = NULL;
|
buffer->message_data = nullptr;
|
||||||
buffer->message_destroy = NULL;
|
buffer->message_destroy = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
108
src/hb-buffer.h
108
src/hb-buffer.h
@ -63,7 +63,7 @@ HB_BEGIN_DECLS
|
|||||||
*/
|
*/
|
||||||
typedef struct hb_glyph_info_t {
|
typedef struct hb_glyph_info_t {
|
||||||
hb_codepoint_t codepoint;
|
hb_codepoint_t codepoint;
|
||||||
hb_mask_t mask;
|
hb_mask_t mask; /* Holds hb_glyph_flags_t after hb_shape(), plus other things. */
|
||||||
uint32_t cluster;
|
uint32_t cluster;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
@ -71,6 +71,37 @@ typedef struct hb_glyph_info_t {
|
|||||||
hb_var_int_t var2;
|
hb_var_int_t var2;
|
||||||
} hb_glyph_info_t;
|
} hb_glyph_info_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_glyph_flags_t:
|
||||||
|
* @HB_GLYPH_FLAG_UNSAFE_TO_BREAK: Indicates that if input text is broken at the
|
||||||
|
* beginning of the cluster this glyph is part of,
|
||||||
|
* then both sides need to be re-shaped, as the
|
||||||
|
* result might be different. On the flip side,
|
||||||
|
* it means that when this flag is not present,
|
||||||
|
* then it's safe to break the glyph-run at the
|
||||||
|
* beginning of this cluster, and the two sides
|
||||||
|
* represent the exact same result one would get
|
||||||
|
* if breaking input text at the beginning of
|
||||||
|
* this cluster and shaping the two sides
|
||||||
|
* separately. This can be used to optimize
|
||||||
|
* paragraph layout, by avoiding re-shaping
|
||||||
|
* of each line after line-breaking, or limiting
|
||||||
|
* the reshaping to a small piece around the
|
||||||
|
* breaking point only.
|
||||||
|
*/
|
||||||
|
typedef enum { /*< flags >*/
|
||||||
|
HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
|
||||||
|
|
||||||
|
HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */
|
||||||
|
} hb_glyph_flags_t;
|
||||||
|
|
||||||
|
HB_EXTERN hb_glyph_flags_t
|
||||||
|
hb_glyph_info_get_glyph_flags (const hb_glyph_info_t *info);
|
||||||
|
|
||||||
|
#define hb_glyph_info_get_glyph_flags(info) \
|
||||||
|
((hb_glyph_flags_t) ((unsigned int) (info)->mask & HB_GLYPH_FLAG_DEFINED))
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_glyph_position_t:
|
* hb_glyph_position_t:
|
||||||
* @x_advance: how much the line advances after drawing this glyph when setting
|
* @x_advance: how much the line advances after drawing this glyph when setting
|
||||||
@ -119,8 +150,8 @@ typedef struct hb_segment_properties_t {
|
|||||||
#define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \
|
#define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \
|
||||||
HB_SCRIPT_INVALID, \
|
HB_SCRIPT_INVALID, \
|
||||||
HB_LANGUAGE_INVALID, \
|
HB_LANGUAGE_INVALID, \
|
||||||
NULL, \
|
(void *) 0, \
|
||||||
NULL}
|
(void *) 0}
|
||||||
|
|
||||||
HB_EXTERN hb_bool_t
|
HB_EXTERN hb_bool_t
|
||||||
hb_segment_properties_equal (const hb_segment_properties_t *a,
|
hb_segment_properties_equal (const hb_segment_properties_t *a,
|
||||||
@ -163,6 +194,7 @@ HB_EXTERN void *
|
|||||||
hb_buffer_get_user_data (hb_buffer_t *buffer,
|
hb_buffer_get_user_data (hb_buffer_t *buffer,
|
||||||
hb_user_data_key_t *key);
|
hb_user_data_key_t *key);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_buffer_content_type_t:
|
* hb_buffer_content_type_t:
|
||||||
* @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer.
|
* @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer.
|
||||||
@ -233,13 +265,21 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
|
|||||||
* of the text without the full context.
|
* of the text without the full context.
|
||||||
* @HB_BUFFER_FLAG_EOT: flag indicating that special handling of the end of text
|
* @HB_BUFFER_FLAG_EOT: flag indicating that special handling of the end of text
|
||||||
* paragraph can be applied to this buffer, similar to
|
* paragraph can be applied to this buffer, similar to
|
||||||
* @HB_BUFFER_FLAG_EOT.
|
* @HB_BUFFER_FLAG_BOT.
|
||||||
* @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES:
|
* @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES:
|
||||||
* flag indication that character with Default_Ignorable
|
* flag indication that character with Default_Ignorable
|
||||||
* Unicode property should use the corresponding glyph
|
* Unicode property should use the corresponding glyph
|
||||||
* from the font, instead of hiding them (currently done
|
* from the font, instead of hiding them (done by
|
||||||
* by replacing them with the space glyph and zeroing the
|
* replacing them with the space glyph and zeroing the
|
||||||
* advance width.)
|
* advance width.) This flag takes precedence over
|
||||||
|
* @HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES.
|
||||||
|
* @HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES:
|
||||||
|
* flag indication that character with Default_Ignorable
|
||||||
|
* Unicode property should be removed from glyph string
|
||||||
|
* instead of hiding them (done by replacing them with the
|
||||||
|
* space glyph and zeroing the advance width.)
|
||||||
|
* @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES takes
|
||||||
|
* precedence over this flag. Since: 1.8.0
|
||||||
*
|
*
|
||||||
* Since: 0.9.20
|
* Since: 0.9.20
|
||||||
*/
|
*/
|
||||||
@ -247,7 +287,8 @@ typedef enum { /*< flags >*/
|
|||||||
HB_BUFFER_FLAG_DEFAULT = 0x00000000u,
|
HB_BUFFER_FLAG_DEFAULT = 0x00000000u,
|
||||||
HB_BUFFER_FLAG_BOT = 0x00000001u, /* Beginning-of-text */
|
HB_BUFFER_FLAG_BOT = 0x00000001u, /* Beginning-of-text */
|
||||||
HB_BUFFER_FLAG_EOT = 0x00000002u, /* End-of-text */
|
HB_BUFFER_FLAG_EOT = 0x00000002u, /* End-of-text */
|
||||||
HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u
|
HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u,
|
||||||
|
HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u
|
||||||
} hb_buffer_flags_t;
|
} hb_buffer_flags_t;
|
||||||
|
|
||||||
HB_EXTERN void
|
HB_EXTERN void
|
||||||
@ -359,6 +400,11 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
|
|||||||
unsigned int item_offset,
|
unsigned int item_offset,
|
||||||
int item_length);
|
int item_length);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_buffer_append (hb_buffer_t *buffer,
|
||||||
|
hb_buffer_t *source,
|
||||||
|
unsigned int start,
|
||||||
|
unsigned int end);
|
||||||
|
|
||||||
HB_EXTERN hb_bool_t
|
HB_EXTERN hb_bool_t
|
||||||
hb_buffer_set_length (hb_buffer_t *buffer,
|
hb_buffer_set_length (hb_buffer_t *buffer,
|
||||||
@ -393,6 +439,9 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
|
|||||||
* @HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS: do not serialize glyph position information.
|
* @HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS: do not serialize glyph position information.
|
||||||
* @HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES: do no serialize glyph name.
|
* @HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES: do no serialize glyph name.
|
||||||
* @HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS: serialize glyph extents.
|
* @HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS: serialize glyph extents.
|
||||||
|
* @HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS: serialize glyph flags. Since: 1.5.0
|
||||||
|
* @HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES: do not serialize glyph advances,
|
||||||
|
* glyph offsets will reflect absolute glyph positions. Since: 1.8.0
|
||||||
*
|
*
|
||||||
* Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs().
|
* Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs().
|
||||||
*
|
*
|
||||||
@ -403,7 +452,9 @@ typedef enum { /*< flags >*/
|
|||||||
HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u,
|
HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u,
|
||||||
HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u,
|
HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u,
|
||||||
HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u,
|
HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u,
|
||||||
HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u
|
HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u,
|
||||||
|
HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS = 0x00000010u,
|
||||||
|
HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES = 0x00000020u
|
||||||
} hb_buffer_serialize_flags_t;
|
} hb_buffer_serialize_flags_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -452,6 +503,45 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
|
|||||||
hb_buffer_serialize_format_t format);
|
hb_buffer_serialize_format_t format);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compare buffers
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum { /*< flags >*/
|
||||||
|
HB_BUFFER_DIFF_FLAG_EQUAL = 0x0000,
|
||||||
|
|
||||||
|
/* Buffers with different content_type cannot be meaningfully compared
|
||||||
|
* in any further detail. */
|
||||||
|
HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH = 0x0001,
|
||||||
|
|
||||||
|
/* For buffers with differing length, the per-glyph comparison is not
|
||||||
|
* attempted, though we do still scan reference for dottedcircle / .notdef
|
||||||
|
* glyphs. */
|
||||||
|
HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH = 0x0002,
|
||||||
|
|
||||||
|
/* We want to know if dottedcircle / .notdef glyphs are present in the
|
||||||
|
* reference, as we may not care so much about other differences in this
|
||||||
|
* case. */
|
||||||
|
HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT = 0x0004,
|
||||||
|
HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT = 0x0008,
|
||||||
|
|
||||||
|
/* If the buffers have the same length, we compare them glyph-by-glyph
|
||||||
|
* and report which aspect(s) of the glyph info/position are different. */
|
||||||
|
HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH = 0x0010,
|
||||||
|
HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH = 0x0020,
|
||||||
|
HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH = 0x0040,
|
||||||
|
HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH = 0x0080
|
||||||
|
|
||||||
|
} hb_buffer_diff_flags_t;
|
||||||
|
|
||||||
|
/* Compare the contents of two buffers, report types of differences. */
|
||||||
|
HB_EXTERN hb_buffer_diff_flags_t
|
||||||
|
hb_buffer_diff (hb_buffer_t *buffer,
|
||||||
|
hb_buffer_t *reference,
|
||||||
|
hb_codepoint_t dottedcircle_glyph,
|
||||||
|
unsigned int position_fuzz);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Debugging.
|
* Debugging.
|
||||||
*/
|
*/
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2012 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_CACHE_PRIVATE_HH
|
|
||||||
#define HB_CACHE_PRIVATE_HH
|
|
||||||
|
|
||||||
#include "hb-private.hh"
|
|
||||||
|
|
||||||
|
|
||||||
/* Implements a lock-free cache for int->int functions. */
|
|
||||||
|
|
||||||
template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits>
|
|
||||||
struct hb_cache_t
|
|
||||||
{
|
|
||||||
ASSERT_STATIC (key_bits >= cache_bits);
|
|
||||||
ASSERT_STATIC (key_bits + value_bits - cache_bits < 8 * sizeof (unsigned int));
|
|
||||||
|
|
||||||
inline void clear (void)
|
|
||||||
{
|
|
||||||
memset (values, 255, sizeof (values));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool get (unsigned int key, unsigned int *value)
|
|
||||||
{
|
|
||||||
unsigned int k = key & ((1<<cache_bits)-1);
|
|
||||||
unsigned int v = values[k];
|
|
||||||
if ((v >> value_bits) != (key >> cache_bits))
|
|
||||||
return false;
|
|
||||||
*value = v & ((1<<value_bits)-1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool set (unsigned int key, unsigned int value)
|
|
||||||
{
|
|
||||||
if (unlikely ((key >> key_bits) || (value >> value_bits)))
|
|
||||||
return false; /* Overflows */
|
|
||||||
unsigned int k = key & ((1<<cache_bits)-1);
|
|
||||||
unsigned int v = ((key>>cache_bits)<<value_bits) | value;
|
|
||||||
values[k] = v;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int values[1<<cache_bits];
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef hb_cache_t<21, 16, 8> hb_cmap_cache_t;
|
|
||||||
typedef hb_cache_t<16, 24, 8> hb_advance_cache_t;
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HB_CACHE_PRIVATE_HH */
|
|
473
src/hb-common.cc
473
src/hb-common.cc
@ -32,6 +32,9 @@
|
|||||||
#include "hb-object-private.hh"
|
#include "hb-object-private.hh"
|
||||||
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#ifdef HAVE_XLOCALE_H
|
||||||
|
#include <xlocale.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* hb_options_t */
|
/* hb_options_t */
|
||||||
@ -82,13 +85,13 @@ hb_tag_from_string (const char *str, int len)
|
|||||||
for (; i < 4; i++)
|
for (; i < 4; i++)
|
||||||
tag[i] = ' ';
|
tag[i] = ' ';
|
||||||
|
|
||||||
return HB_TAG_CHAR4 (tag);
|
return HB_TAG (tag[0], tag[1], tag[2], tag[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_tag_to_string:
|
* hb_tag_to_string:
|
||||||
* @tag:
|
* @tag:
|
||||||
* @buf: (array fixed-size=4):
|
* @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t):
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@ -186,8 +189,10 @@ lang_equal (hb_language_t v1,
|
|||||||
const unsigned char *p1 = (const unsigned char *) v1;
|
const unsigned char *p1 = (const unsigned char *) v1;
|
||||||
const unsigned char *p2 = (const unsigned char *) v2;
|
const unsigned char *p2 = (const unsigned char *) v2;
|
||||||
|
|
||||||
while (*p1 && *p1 == canon_map[*p2])
|
while (*p1 && *p1 == canon_map[*p2]) {
|
||||||
p1++, p2++;
|
p1++;
|
||||||
|
p2++;
|
||||||
|
}
|
||||||
|
|
||||||
return *p1 == canon_map[*p2];
|
return *p1 == canon_map[*p2];
|
||||||
}
|
}
|
||||||
@ -219,9 +224,18 @@ struct hb_language_item_t {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline hb_language_item_t & operator = (const char *s) {
|
inline hb_language_item_t & operator = (const char *s) {
|
||||||
lang = (hb_language_t) strdup (s);
|
/* If a custom allocated is used calling strdup() pairs
|
||||||
for (unsigned char *p = (unsigned char *) lang; *p; p++)
|
badly with a call to the custom free() in finish() below.
|
||||||
*p = canon_map[*p];
|
Therefore don't call strdup(), implement its behavior.
|
||||||
|
*/
|
||||||
|
size_t len = strlen(s) + 1;
|
||||||
|
lang = (hb_language_t) malloc(len);
|
||||||
|
if (likely (lang))
|
||||||
|
{
|
||||||
|
memcpy((unsigned char *) lang, s, len);
|
||||||
|
for (unsigned char *p = (unsigned char *) lang; *p; p++)
|
||||||
|
*p = canon_map[*p];
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -235,8 +249,8 @@ struct hb_language_item_t {
|
|||||||
static hb_language_item_t *langs;
|
static hb_language_item_t *langs;
|
||||||
|
|
||||||
#ifdef HB_USE_ATEXIT
|
#ifdef HB_USE_ATEXIT
|
||||||
static
|
static void
|
||||||
void free_langs (void)
|
free_langs (void)
|
||||||
{
|
{
|
||||||
while (langs) {
|
while (langs) {
|
||||||
hb_language_item_t *next = langs->next;
|
hb_language_item_t *next = langs->next;
|
||||||
@ -260,9 +274,14 @@ retry:
|
|||||||
/* Not found; allocate one. */
|
/* Not found; allocate one. */
|
||||||
hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t));
|
hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t));
|
||||||
if (unlikely (!lang))
|
if (unlikely (!lang))
|
||||||
return NULL;
|
return nullptr;
|
||||||
lang->next = first_lang;
|
lang->next = first_lang;
|
||||||
*lang = key;
|
*lang = key;
|
||||||
|
if (unlikely (!lang->lang))
|
||||||
|
{
|
||||||
|
free (lang);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
|
if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
|
||||||
lang->finish ();
|
lang->finish ();
|
||||||
@ -299,7 +318,7 @@ hb_language_from_string (const char *str, int len)
|
|||||||
if (!str || !len || !*str)
|
if (!str || !len || !*str)
|
||||||
return HB_LANGUAGE_INVALID;
|
return HB_LANGUAGE_INVALID;
|
||||||
|
|
||||||
hb_language_item_t *item = NULL;
|
hb_language_item_t *item = nullptr;
|
||||||
if (len >= 0)
|
if (len >= 0)
|
||||||
{
|
{
|
||||||
/* NUL-terminate it. */
|
/* NUL-terminate it. */
|
||||||
@ -330,7 +349,7 @@ hb_language_from_string (const char *str, int len)
|
|||||||
const char *
|
const char *
|
||||||
hb_language_to_string (hb_language_t language)
|
hb_language_to_string (hb_language_t language)
|
||||||
{
|
{
|
||||||
/* This is actually NULL-safe! */
|
/* This is actually nullptr-safe! */
|
||||||
return language->s;
|
return language->s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +369,7 @@ hb_language_get_default (void)
|
|||||||
|
|
||||||
hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
|
hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
|
||||||
if (unlikely (language == HB_LANGUAGE_INVALID)) {
|
if (unlikely (language == HB_LANGUAGE_INVALID)) {
|
||||||
language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1);
|
language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1);
|
||||||
(void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
|
(void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,6 +524,7 @@ hb_script_get_horizontal_direction (hb_script_t script)
|
|||||||
case HB_SCRIPT_PSALTER_PAHLAVI:
|
case HB_SCRIPT_PSALTER_PAHLAVI:
|
||||||
|
|
||||||
/* Unicode-8.0 additions */
|
/* Unicode-8.0 additions */
|
||||||
|
case HB_SCRIPT_HATRAN:
|
||||||
case HB_SCRIPT_OLD_HUNGARIAN:
|
case HB_SCRIPT_OLD_HUNGARIAN:
|
||||||
|
|
||||||
/* Unicode-9.0 additions */
|
/* Unicode-9.0 additions */
|
||||||
@ -543,9 +563,9 @@ hb_user_data_array_t::set (hb_user_data_key_t *key,
|
|||||||
void *
|
void *
|
||||||
hb_user_data_array_t::get (hb_user_data_key_t *key)
|
hb_user_data_array_t::get (hb_user_data_key_t *key)
|
||||||
{
|
{
|
||||||
hb_user_data_item_t item = {NULL, NULL, NULL};
|
hb_user_data_item_t item = {nullptr, nullptr, nullptr};
|
||||||
|
|
||||||
return items.find (key, &item, lock) ? item.data : NULL;
|
return items.find (key, &item, lock) ? item.data : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -605,3 +625,426 @@ hb_version_atleast (unsigned int major,
|
|||||||
{
|
{
|
||||||
return HB_VERSION_ATLEAST (major, minor, micro);
|
return HB_VERSION_ATLEAST (major, minor, micro);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* hb_feature_t and hb_variation_t */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_space (const char **pp, const char *end)
|
||||||
|
{
|
||||||
|
while (*pp < end && ISSPACE (**pp))
|
||||||
|
(*pp)++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_char (const char **pp, const char *end, char c)
|
||||||
|
{
|
||||||
|
parse_space (pp, end);
|
||||||
|
|
||||||
|
if (*pp == end || **pp != c)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
(*pp)++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_uint (const char **pp, const char *end, unsigned int *pv)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
|
||||||
|
strncpy (buf, *pp, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
char *p = buf;
|
||||||
|
char *pend = p;
|
||||||
|
unsigned int v;
|
||||||
|
|
||||||
|
/* Intentionally use strtol instead of strtoul, such that
|
||||||
|
* -1 turns into "big number"... */
|
||||||
|
errno = 0;
|
||||||
|
v = strtol (p, &pend, 0);
|
||||||
|
if (errno || p == pend)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*pv = v;
|
||||||
|
*pp += pend - p;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_uint32 (const char **pp, const char *end, uint32_t *pv)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
|
||||||
|
strncpy (buf, *pp, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
char *p = buf;
|
||||||
|
char *pend = p;
|
||||||
|
unsigned int v;
|
||||||
|
|
||||||
|
/* Intentionally use strtol instead of strtoul, such that
|
||||||
|
* -1 turns into "big number"... */
|
||||||
|
errno = 0;
|
||||||
|
v = strtol (p, &pend, 0);
|
||||||
|
if (errno || p == pend)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*pv = v;
|
||||||
|
*pp += pend - p;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L)
|
||||||
|
#define USE_XLOCALE 1
|
||||||
|
#define HB_LOCALE_T locale_t
|
||||||
|
#define HB_CREATE_LOCALE(locName) newlocale (LC_ALL_MASK, locName, nullptr)
|
||||||
|
#define HB_FREE_LOCALE(loc) freelocale (loc)
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define USE_XLOCALE 1
|
||||||
|
#define HB_LOCALE_T _locale_t
|
||||||
|
#define HB_CREATE_LOCALE(locName) _create_locale (LC_ALL, locName)
|
||||||
|
#define HB_FREE_LOCALE(loc) _free_locale (loc)
|
||||||
|
#define strtod_l(a, b, c) _strtod_l ((a), (b), (c))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_XLOCALE
|
||||||
|
|
||||||
|
static HB_LOCALE_T C_locale;
|
||||||
|
|
||||||
|
#ifdef HB_USE_ATEXIT
|
||||||
|
static void
|
||||||
|
free_C_locale (void)
|
||||||
|
{
|
||||||
|
if (C_locale)
|
||||||
|
HB_FREE_LOCALE (C_locale);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static HB_LOCALE_T
|
||||||
|
get_C_locale (void)
|
||||||
|
{
|
||||||
|
retry:
|
||||||
|
HB_LOCALE_T C = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
|
||||||
|
|
||||||
|
if (unlikely (!C))
|
||||||
|
{
|
||||||
|
C = HB_CREATE_LOCALE ("C");
|
||||||
|
|
||||||
|
if (!hb_atomic_ptr_cmpexch (&C_locale, nullptr, C))
|
||||||
|
{
|
||||||
|
HB_FREE_LOCALE (C_locale);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HB_USE_ATEXIT
|
||||||
|
atexit (free_C_locale); /* First person registers atexit() callback. */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_float (const char **pp, const char *end, float *pv)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
|
||||||
|
strncpy (buf, *pp, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
char *p = buf;
|
||||||
|
char *pend = p;
|
||||||
|
float v;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
#ifdef USE_XLOCALE
|
||||||
|
v = strtod_l (p, &pend, get_C_locale ());
|
||||||
|
#else
|
||||||
|
v = strtod (p, &pend);
|
||||||
|
#endif
|
||||||
|
if (errno || p == pend)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*pv = v;
|
||||||
|
*pp += pend - p;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_bool (const char **pp, const char *end, uint32_t *pv)
|
||||||
|
{
|
||||||
|
parse_space (pp, end);
|
||||||
|
|
||||||
|
const char *p = *pp;
|
||||||
|
while (*pp < end && ISALPHA(**pp))
|
||||||
|
(*pp)++;
|
||||||
|
|
||||||
|
/* CSS allows on/off as aliases 1/0. */
|
||||||
|
if (*pp - p == 2 && 0 == strncmp (p, "on", 2))
|
||||||
|
*pv = 1;
|
||||||
|
else if (*pp - p == 3 && 0 == strncmp (p, "off", 3))
|
||||||
|
*pv = 0;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hb_feature_t */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
|
||||||
|
{
|
||||||
|
if (parse_char (pp, end, '-'))
|
||||||
|
feature->value = 0;
|
||||||
|
else {
|
||||||
|
parse_char (pp, end, '+');
|
||||||
|
feature->value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_tag (const char **pp, const char *end, hb_tag_t *tag)
|
||||||
|
{
|
||||||
|
parse_space (pp, end);
|
||||||
|
|
||||||
|
char quote = 0;
|
||||||
|
|
||||||
|
if (*pp < end && (**pp == '\'' || **pp == '"'))
|
||||||
|
{
|
||||||
|
quote = **pp;
|
||||||
|
(*pp)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *p = *pp;
|
||||||
|
while (*pp < end && ISALNUM(**pp))
|
||||||
|
(*pp)++;
|
||||||
|
|
||||||
|
if (p == *pp || *pp - p > 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*tag = hb_tag_from_string (p, *pp - p);
|
||||||
|
|
||||||
|
if (quote)
|
||||||
|
{
|
||||||
|
/* CSS expects exactly four bytes. And we only allow quotations for
|
||||||
|
* CSS compatibility. So, enforce the length. */
|
||||||
|
if (*pp - p != 4)
|
||||||
|
return false;
|
||||||
|
if (*pp == end || **pp != quote)
|
||||||
|
return false;
|
||||||
|
(*pp)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
|
||||||
|
{
|
||||||
|
parse_space (pp, end);
|
||||||
|
|
||||||
|
bool has_start;
|
||||||
|
|
||||||
|
feature->start = 0;
|
||||||
|
feature->end = (unsigned int) -1;
|
||||||
|
|
||||||
|
if (!parse_char (pp, end, '['))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
has_start = parse_uint (pp, end, &feature->start);
|
||||||
|
|
||||||
|
if (parse_char (pp, end, ':')) {
|
||||||
|
parse_uint (pp, end, &feature->end);
|
||||||
|
} else {
|
||||||
|
if (has_start)
|
||||||
|
feature->end = feature->start + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parse_char (pp, end, ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
|
||||||
|
{
|
||||||
|
bool had_equal = parse_char (pp, end, '=');
|
||||||
|
bool had_value = parse_uint32 (pp, end, &feature->value) ||
|
||||||
|
parse_bool (pp, end, &feature->value);
|
||||||
|
/* CSS doesn't use equal-sign between tag and value.
|
||||||
|
* If there was an equal-sign, then there *must* be a value.
|
||||||
|
* A value without an equal-sign is ok, but not required. */
|
||||||
|
return !had_equal || had_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
|
||||||
|
{
|
||||||
|
return parse_feature_value_prefix (pp, end, feature) &&
|
||||||
|
parse_tag (pp, end, &feature->tag) &&
|
||||||
|
parse_feature_indices (pp, end, feature) &&
|
||||||
|
parse_feature_value_postfix (pp, end, feature) &&
|
||||||
|
parse_space (pp, end) &&
|
||||||
|
*pp == end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_feature_from_string:
|
||||||
|
* @str: (array length=len) (element-type uint8_t): a string to parse
|
||||||
|
* @len: length of @str, or -1 if string is %NULL terminated
|
||||||
|
* @feature: (out): the #hb_feature_t to initialize with the parsed values
|
||||||
|
*
|
||||||
|
* Parses a string into a #hb_feature_t.
|
||||||
|
*
|
||||||
|
* TODO: document the syntax here.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* %true if @str is successfully parsed, %false otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.9.5
|
||||||
|
**/
|
||||||
|
hb_bool_t
|
||||||
|
hb_feature_from_string (const char *str, int len,
|
||||||
|
hb_feature_t *feature)
|
||||||
|
{
|
||||||
|
hb_feature_t feat;
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
len = strlen (str);
|
||||||
|
|
||||||
|
if (likely (parse_one_feature (&str, str + len, &feat)))
|
||||||
|
{
|
||||||
|
if (feature)
|
||||||
|
*feature = feat;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feature)
|
||||||
|
memset (feature, 0, sizeof (*feature));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_feature_to_string:
|
||||||
|
* @feature: an #hb_feature_t to convert
|
||||||
|
* @buf: (array length=size) (out): output string
|
||||||
|
* @size: the allocated size of @buf
|
||||||
|
*
|
||||||
|
* Converts a #hb_feature_t into a %NULL-terminated string in the format
|
||||||
|
* understood by hb_feature_from_string(). The client in responsible for
|
||||||
|
* allocating big enough size for @buf, 128 bytes is more than enough.
|
||||||
|
*
|
||||||
|
* Since: 0.9.5
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
hb_feature_to_string (hb_feature_t *feature,
|
||||||
|
char *buf, unsigned int size)
|
||||||
|
{
|
||||||
|
if (unlikely (!size)) return;
|
||||||
|
|
||||||
|
char s[128];
|
||||||
|
unsigned int len = 0;
|
||||||
|
if (feature->value == 0)
|
||||||
|
s[len++] = '-';
|
||||||
|
hb_tag_to_string (feature->tag, s + len);
|
||||||
|
len += 4;
|
||||||
|
while (len && s[len - 1] == ' ')
|
||||||
|
len--;
|
||||||
|
if (feature->start != 0 || feature->end != (unsigned int) -1)
|
||||||
|
{
|
||||||
|
s[len++] = '[';
|
||||||
|
if (feature->start)
|
||||||
|
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
|
||||||
|
if (feature->end != feature->start + 1) {
|
||||||
|
s[len++] = ':';
|
||||||
|
if (feature->end != (unsigned int) -1)
|
||||||
|
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
|
||||||
|
}
|
||||||
|
s[len++] = ']';
|
||||||
|
}
|
||||||
|
if (feature->value > 1)
|
||||||
|
{
|
||||||
|
s[len++] = '=';
|
||||||
|
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
|
||||||
|
}
|
||||||
|
assert (len < ARRAY_LENGTH (s));
|
||||||
|
len = MIN (len, size - 1);
|
||||||
|
memcpy (buf, s, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hb_variation_t */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_variation_value (const char **pp, const char *end, hb_variation_t *variation)
|
||||||
|
{
|
||||||
|
parse_char (pp, end, '='); /* Optional. */
|
||||||
|
return parse_float (pp, end, &variation->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_one_variation (const char **pp, const char *end, hb_variation_t *variation)
|
||||||
|
{
|
||||||
|
return parse_tag (pp, end, &variation->tag) &&
|
||||||
|
parse_variation_value (pp, end, variation) &&
|
||||||
|
parse_space (pp, end) &&
|
||||||
|
*pp == end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_variation_from_string:
|
||||||
|
*
|
||||||
|
* Since: 1.4.2
|
||||||
|
*/
|
||||||
|
hb_bool_t
|
||||||
|
hb_variation_from_string (const char *str, int len,
|
||||||
|
hb_variation_t *variation)
|
||||||
|
{
|
||||||
|
hb_variation_t var;
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
len = strlen (str);
|
||||||
|
|
||||||
|
if (likely (parse_one_variation (&str, str + len, &var)))
|
||||||
|
{
|
||||||
|
if (variation)
|
||||||
|
*variation = var;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (variation)
|
||||||
|
memset (variation, 0, sizeof (*variation));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_variation_to_string:
|
||||||
|
*
|
||||||
|
* Since: 1.4.2
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
hb_variation_to_string (hb_variation_t *variation,
|
||||||
|
char *buf, unsigned int size)
|
||||||
|
{
|
||||||
|
if (unlikely (!size)) return;
|
||||||
|
|
||||||
|
char s[128];
|
||||||
|
unsigned int len = 0;
|
||||||
|
hb_tag_to_string (variation->tag, s + len);
|
||||||
|
len += 4;
|
||||||
|
while (len && s[len - 1] == ' ')
|
||||||
|
len--;
|
||||||
|
s[len++] = '=';
|
||||||
|
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value));
|
||||||
|
|
||||||
|
assert (len < ARRAY_LENGTH (s));
|
||||||
|
len = MIN (len, size - 1);
|
||||||
|
memcpy (buf, s, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
}
|
||||||
|
@ -43,30 +43,16 @@
|
|||||||
# endif /* !__cplusplus */
|
# endif /* !__cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined (HB_DONT_DEFINE_STDINT)
|
|
||||||
|
|
||||||
#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
|
#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
|
||||||
defined (_sgi) || defined (__sun) || defined (sun) || \
|
defined (_sgi) || defined (__sun) || defined (sun) || \
|
||||||
defined (__digital__) || defined (__HP_cc)
|
defined (__digital__) || defined (__HP_cc)
|
||||||
# include <inttypes.h>
|
# include <inttypes.h>
|
||||||
#elif defined (_AIX)
|
#elif defined (_AIX)
|
||||||
# include <sys/inttypes.h>
|
# include <sys/inttypes.h>
|
||||||
/* VS 2010 (_MSC_VER 1600) has stdint.h */
|
|
||||||
#elif defined (_MSC_VER) && _MSC_VER < 1600
|
|
||||||
typedef __int8 int8_t;
|
|
||||||
typedef unsigned __int8 uint8_t;
|
|
||||||
typedef __int16 int16_t;
|
|
||||||
typedef unsigned __int16 uint16_t;
|
|
||||||
typedef __int32 int32_t;
|
|
||||||
typedef unsigned __int32 uint32_t;
|
|
||||||
typedef __int64 int64_t;
|
|
||||||
typedef unsigned __int64 uint64_t;
|
|
||||||
#else
|
#else
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HB_BEGIN_DECLS
|
HB_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
||||||
@ -148,7 +134,7 @@ hb_language_from_string (const char *str, int len);
|
|||||||
HB_EXTERN const char *
|
HB_EXTERN const char *
|
||||||
hb_language_to_string (hb_language_t language);
|
hb_language_to_string (hb_language_t language);
|
||||||
|
|
||||||
#define HB_LANGUAGE_INVALID ((hb_language_t) NULL)
|
#define HB_LANGUAGE_INVALID ((hb_language_t) 0)
|
||||||
|
|
||||||
HB_EXTERN hb_language_t
|
HB_EXTERN hb_language_t
|
||||||
hb_language_get_default (void);
|
hb_language_get_default (void);
|
||||||
@ -321,6 +307,14 @@ typedef enum
|
|||||||
/*9.0*/ HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'),
|
/*9.0*/ HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'),
|
||||||
/*9.0*/ HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'),
|
/*9.0*/ HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since 1.6.0
|
||||||
|
*/
|
||||||
|
/*10.0*/HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'),
|
||||||
|
/*10.0*/HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'),
|
||||||
|
/*10.0*/HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'),
|
||||||
|
/*10.0*/HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'),
|
||||||
|
|
||||||
/* No script set. */
|
/* No script set. */
|
||||||
HB_SCRIPT_INVALID = HB_TAG_NONE,
|
HB_SCRIPT_INVALID = HB_TAG_NONE,
|
||||||
|
|
||||||
@ -362,6 +356,42 @@ typedef struct hb_user_data_key_t {
|
|||||||
typedef void (*hb_destroy_func_t) (void *user_data);
|
typedef void (*hb_destroy_func_t) (void *user_data);
|
||||||
|
|
||||||
|
|
||||||
|
/* Font features and variations. */
|
||||||
|
|
||||||
|
typedef struct hb_feature_t {
|
||||||
|
hb_tag_t tag;
|
||||||
|
uint32_t value;
|
||||||
|
unsigned int start;
|
||||||
|
unsigned int end;
|
||||||
|
} hb_feature_t;
|
||||||
|
|
||||||
|
HB_EXTERN hb_bool_t
|
||||||
|
hb_feature_from_string (const char *str, int len,
|
||||||
|
hb_feature_t *feature);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_feature_to_string (hb_feature_t *feature,
|
||||||
|
char *buf, unsigned int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_variation_t:
|
||||||
|
*
|
||||||
|
* Since: 1.4.2
|
||||||
|
*/
|
||||||
|
typedef struct hb_variation_t {
|
||||||
|
hb_tag_t tag;
|
||||||
|
float value;
|
||||||
|
} hb_variation_t;
|
||||||
|
|
||||||
|
HB_EXTERN hb_bool_t
|
||||||
|
hb_variation_from_string (const char *str, int len,
|
||||||
|
hb_variation_t *variation);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_variation_to_string (hb_variation_t *variation,
|
||||||
|
char *buf, unsigned int size);
|
||||||
|
|
||||||
|
|
||||||
HB_END_DECLS
|
HB_END_DECLS
|
||||||
|
|
||||||
#endif /* HB_COMMON_H */
|
#endif /* HB_COMMON_H */
|
||||||
|
@ -27,15 +27,34 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define HB_SHAPER coretext
|
#define HB_SHAPER coretext
|
||||||
|
|
||||||
|
#include "hb-private.hh"
|
||||||
|
#include "hb-debug.hh"
|
||||||
#include "hb-shaper-impl-private.hh"
|
#include "hb-shaper-impl-private.hh"
|
||||||
|
|
||||||
#include "hb-coretext.h"
|
#include "hb-coretext.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
|
||||||
|
#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
|
||||||
|
|
||||||
#ifndef HB_DEBUG_CORETEXT
|
static CGFloat
|
||||||
#define HB_DEBUG_CORETEXT (HB_DEBUG+0)
|
coretext_font_size_from_ptem (float ptem)
|
||||||
#endif
|
{
|
||||||
|
/* CoreText points are CSS pixels (96 per inch),
|
||||||
|
* NOT typographic points (72 per inch).
|
||||||
|
*
|
||||||
|
* https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
|
||||||
|
*/
|
||||||
|
ptem *= 96.f / 72.f;
|
||||||
|
return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem;
|
||||||
|
}
|
||||||
|
static float
|
||||||
|
coretext_font_size_to_ptem (CGFloat size)
|
||||||
|
{
|
||||||
|
size *= 72.f / 96.f;
|
||||||
|
return size <= 0.f ? 0 : size;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
release_table_data (void *user_data)
|
release_table_data (void *user_data)
|
||||||
@ -50,32 +69,32 @@ reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
|||||||
CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
|
CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
|
||||||
CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
|
CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
|
||||||
if (unlikely (!cf_data))
|
if (unlikely (!cf_data))
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
|
const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
|
||||||
const size_t length = CFDataGetLength (cf_data);
|
const size_t length = CFDataGetLength (cf_data);
|
||||||
if (!data || !length)
|
if (!data || !length)
|
||||||
return NULL;
|
{
|
||||||
|
CFRelease (cf_data);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
|
return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
|
||||||
reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
|
reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
|
||||||
release_table_data);
|
release_table_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_face_t *
|
static void
|
||||||
hb_coretext_face_create (CGFontRef cg_font)
|
_hb_cg_font_release (void *data)
|
||||||
{
|
{
|
||||||
return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), (hb_destroy_func_t) CGFontRelease);
|
CGFontRelease ((CGFontRef) data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face)
|
HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
|
||||||
HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font)
|
HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
|
||||||
|
fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5
|
||||||
|
)
|
||||||
/*
|
|
||||||
* shaper face data
|
|
||||||
*/
|
|
||||||
|
|
||||||
static CTFontDescriptorRef
|
static CTFontDescriptorRef
|
||||||
get_last_resort_font_desc (void)
|
get_last_resort_font_desc (void)
|
||||||
@ -104,7 +123,7 @@ static void
|
|||||||
release_data (void *info, const void *data, size_t size)
|
release_data (void *info, const void *data, size_t size)
|
||||||
{
|
{
|
||||||
assert (hb_blob_get_length ((hb_blob_t *) info) == size &&
|
assert (hb_blob_get_length ((hb_blob_t *) info) == size &&
|
||||||
hb_blob_get_data ((hb_blob_t *) info, NULL) == data);
|
hb_blob_get_data ((hb_blob_t *) info, nullptr) == data);
|
||||||
|
|
||||||
hb_blob_destroy ((hb_blob_t *) info);
|
hb_blob_destroy ((hb_blob_t *) info);
|
||||||
}
|
}
|
||||||
@ -112,8 +131,8 @@ release_data (void *info, const void *data, size_t size)
|
|||||||
static CGFontRef
|
static CGFontRef
|
||||||
create_cg_font (hb_face_t *face)
|
create_cg_font (hb_face_t *face)
|
||||||
{
|
{
|
||||||
CGFontRef cg_font = NULL;
|
CGFontRef cg_font = nullptr;
|
||||||
if (face->destroy == (hb_destroy_func_t) CGFontRelease)
|
if (face->destroy == _hb_cg_font_release)
|
||||||
{
|
{
|
||||||
cg_font = CGFontRetain ((CGFontRef) face->user_data);
|
cg_font = CGFontRetain ((CGFontRef) face->user_data);
|
||||||
}
|
}
|
||||||
@ -140,75 +159,118 @@ create_cg_font (hb_face_t *face)
|
|||||||
static CTFontRef
|
static CTFontRef
|
||||||
create_ct_font (CGFontRef cg_font, CGFloat font_size)
|
create_ct_font (CGFontRef cg_font, CGFloat font_size)
|
||||||
{
|
{
|
||||||
CTFontRef ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, NULL, NULL);
|
CTFontRef ct_font = nullptr;
|
||||||
|
|
||||||
|
/* CoreText does not enable trak table usage / tracking when creating a CTFont
|
||||||
|
* using CTFontCreateWithGraphicsFont. The only way of enabling tracking seems
|
||||||
|
* to be through the CTFontCreateUIFontForLanguage call. */
|
||||||
|
CFStringRef cg_postscript_name = CGFontCopyPostScriptName (cg_font);
|
||||||
|
if (CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSText")) ||
|
||||||
|
CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSDisplay")))
|
||||||
|
{
|
||||||
|
CTFontUIFontType font_type = kCTFontUIFontSystem;
|
||||||
|
if (CFStringHasSuffix (cg_postscript_name, CFSTR ("-Bold")))
|
||||||
|
font_type = kCTFontUIFontEmphasizedSystem;
|
||||||
|
|
||||||
|
ct_font = CTFontCreateUIFontForLanguage (font_type, font_size, nullptr);
|
||||||
|
CFStringRef ct_result_name = CTFontCopyPostScriptName(ct_font);
|
||||||
|
if (CFStringCompare (ct_result_name, cg_postscript_name, 0) != kCFCompareEqualTo)
|
||||||
|
{
|
||||||
|
CFRelease(ct_font);
|
||||||
|
ct_font = nullptr;
|
||||||
|
}
|
||||||
|
CFRelease (ct_result_name);
|
||||||
|
}
|
||||||
|
CFRelease (cg_postscript_name);
|
||||||
|
|
||||||
|
if (!ct_font)
|
||||||
|
ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, nullptr, nullptr);
|
||||||
|
|
||||||
if (unlikely (!ct_font)) {
|
if (unlikely (!ct_font)) {
|
||||||
DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
|
DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* crbug.com/576941 and crbug.com/625902 and the investigation in the latter
|
||||||
|
* bug indicate that the cascade list reconfiguration occasionally causes
|
||||||
|
* crashes in CoreText on OS X 10.9, thus let's skip this step on older
|
||||||
|
* operating system versions. Except for the emoji font, where _not_
|
||||||
|
* reconfiguring the cascade list causes CoreText crashes. For details, see
|
||||||
|
* crbug.com/549610 */
|
||||||
|
// 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h
|
||||||
|
if (&CTGetCoreTextVersion != nullptr && CTGetCoreTextVersion() < 0x00070000) {
|
||||||
|
CFStringRef fontName = CTFontCopyPostScriptName (ct_font);
|
||||||
|
bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo;
|
||||||
|
CFRelease (fontName);
|
||||||
|
if (!isEmojiFont)
|
||||||
|
return ct_font;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute);
|
||||||
|
|
||||||
/* Create font copy with cascade list that has LastResort first; this speeds up CoreText
|
/* Create font copy with cascade list that has LastResort first; this speeds up CoreText
|
||||||
* font fallback which we don't need anyway. */
|
* font fallback which we don't need anyway. */
|
||||||
{
|
{
|
||||||
CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc ();
|
CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc ();
|
||||||
CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, NULL, last_resort_font_desc);
|
CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, nullptr, last_resort_font_desc);
|
||||||
CFRelease (last_resort_font_desc);
|
CFRelease (last_resort_font_desc);
|
||||||
if (new_ct_font)
|
if (new_ct_font)
|
||||||
{
|
{
|
||||||
CFRelease (ct_font);
|
/* The CTFontCreateCopyWithAttributes call fails to stay on the same font
|
||||||
ct_font = new_ct_font;
|
* when reconfiguring the cascade list and may switch to a different font
|
||||||
|
* when there are fonts that go by the same name, since the descriptor is
|
||||||
|
* just name and size.
|
||||||
|
*
|
||||||
|
* Avoid reconfiguring the cascade lists if the new font is outside the
|
||||||
|
* system locations that we cannot access from the sandboxed renderer
|
||||||
|
* process in Blink. This can be detected by the new file URL location
|
||||||
|
* that the newly found font points to. */
|
||||||
|
CFURLRef new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute);
|
||||||
|
// Keep reconfigured font if URL cannot be retrieved (seems to be the case
|
||||||
|
// on Mac OS 10.12 Sierra), speculative fix for crbug.com/625606
|
||||||
|
if (!original_url || !new_url || CFEqual (original_url, new_url)) {
|
||||||
|
CFRelease (ct_font);
|
||||||
|
ct_font = new_ct_font;
|
||||||
|
} else {
|
||||||
|
CFRelease (new_ct_font);
|
||||||
|
DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed.");
|
||||||
|
}
|
||||||
|
if (new_url)
|
||||||
|
CFRelease (new_url);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed");
|
DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ct_font;
|
if (original_url)
|
||||||
|
CFRelease (original_url);
|
||||||
|
return ct_font;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hb_coretext_shaper_face_data_t {
|
|
||||||
CGFontRef cg_font;
|
|
||||||
CTFontRef ct_font;
|
|
||||||
};
|
|
||||||
|
|
||||||
hb_coretext_shaper_face_data_t *
|
hb_coretext_shaper_face_data_t *
|
||||||
_hb_coretext_shaper_face_data_create (hb_face_t *face)
|
_hb_coretext_shaper_face_data_create (hb_face_t *face)
|
||||||
{
|
{
|
||||||
hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t));
|
CGFontRef cg_font = create_cg_font (face);
|
||||||
if (unlikely (!data))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
data->cg_font = create_cg_font (face);
|
if (unlikely (!cg_font))
|
||||||
if (unlikely (!data->cg_font))
|
|
||||||
{
|
{
|
||||||
DEBUG_MSG (CORETEXT, face, "CGFont creation failed..");
|
DEBUG_MSG (CORETEXT, face, "CGFont creation failed..");
|
||||||
free (data);
|
return nullptr;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We use 36pt size instead of UPEM, because CoreText implements the 'trak' table,
|
return (hb_coretext_shaper_face_data_t *) cg_font;
|
||||||
* which can make the font too tight at large sizes. 36pt should be a good semi-neutral
|
|
||||||
* size.
|
|
||||||
*
|
|
||||||
* Since we always create CTFont at a fixed size, our CTFont lives in face_data
|
|
||||||
* instead of font_data. Which is good, because when people change scale on
|
|
||||||
* hb_font_t, we won't need to update our CTFont. */
|
|
||||||
data->ct_font = create_ct_font (data->cg_font, 36.);
|
|
||||||
if (unlikely (!data->ct_font))
|
|
||||||
{
|
|
||||||
DEBUG_MSG (CORETEXT, face, "CTFont creation failed.");
|
|
||||||
CFRelease (data->cg_font);
|
|
||||||
free (data);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
|
_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
|
||||||
{
|
{
|
||||||
CFRelease (data->ct_font);
|
CFRelease ((CGFontRef) data);
|
||||||
CFRelease (data->cg_font);
|
}
|
||||||
free (data);
|
|
||||||
|
hb_face_t *
|
||||||
|
hb_coretext_face_create (CGFontRef cg_font)
|
||||||
|
{
|
||||||
|
return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -217,29 +279,66 @@ _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
|
|||||||
CGFontRef
|
CGFontRef
|
||||||
hb_coretext_face_get_cg_font (hb_face_t *face)
|
hb_coretext_face_get_cg_font (hb_face_t *face)
|
||||||
{
|
{
|
||||||
if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL;
|
if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
|
||||||
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
|
return (CGFontRef) HB_SHAPER_DATA_GET (face);
|
||||||
return face_data->cg_font;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* shaper font data
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct hb_coretext_shaper_font_data_t {};
|
|
||||||
|
|
||||||
hb_coretext_shaper_font_data_t *
|
hb_coretext_shaper_font_data_t *
|
||||||
_hb_coretext_shaper_font_data_create (hb_font_t *font HB_UNUSED)
|
_hb_coretext_shaper_font_data_create (hb_font_t *font)
|
||||||
{
|
{
|
||||||
return (hb_coretext_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
hb_face_t *face = font->face;
|
||||||
|
if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
|
||||||
|
CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
|
||||||
|
|
||||||
|
CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem));
|
||||||
|
|
||||||
|
if (unlikely (!ct_font))
|
||||||
|
{
|
||||||
|
DEBUG_MSG (CORETEXT, font, "CGFont creation failed..");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (hb_coretext_shaper_font_data_t *) ct_font;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
|
_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
|
||||||
{
|
{
|
||||||
|
CFRelease ((CTFontRef) data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since: 1.7.2
|
||||||
|
*/
|
||||||
|
hb_font_t *
|
||||||
|
hb_coretext_font_create (CTFontRef ct_font)
|
||||||
|
{
|
||||||
|
CGFontRef cg_font = CTFontCopyGraphicsFont (ct_font, nullptr);
|
||||||
|
hb_face_t *face = hb_coretext_face_create (cg_font);
|
||||||
|
CFRelease (cg_font);
|
||||||
|
hb_font_t *font = hb_font_create (face);
|
||||||
|
hb_face_destroy (face);
|
||||||
|
|
||||||
|
if (unlikely (hb_object_is_inert (font)))
|
||||||
|
return font;
|
||||||
|
|
||||||
|
hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
|
||||||
|
|
||||||
|
/* Let there be dragons here... */
|
||||||
|
HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font);
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
CTFontRef
|
||||||
|
hb_coretext_font_get_ct_font (hb_font_t *font)
|
||||||
|
{
|
||||||
|
if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr;
|
||||||
|
return (CTFontRef) HB_SHAPER_DATA_GET (font);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* shaper shape_plan data
|
* shaper shape_plan data
|
||||||
@ -250,7 +349,9 @@ struct hb_coretext_shaper_shape_plan_data_t {};
|
|||||||
hb_coretext_shaper_shape_plan_data_t *
|
hb_coretext_shaper_shape_plan_data_t *
|
||||||
_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||||
const hb_feature_t *user_features HB_UNUSED,
|
const hb_feature_t *user_features HB_UNUSED,
|
||||||
unsigned int num_user_features HB_UNUSED)
|
unsigned int num_user_features HB_UNUSED,
|
||||||
|
const int *coords HB_UNUSED,
|
||||||
|
unsigned int num_coords HB_UNUSED)
|
||||||
{
|
{
|
||||||
return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||||
}
|
}
|
||||||
@ -260,15 +361,6 @@ _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CTFontRef
|
|
||||||
hb_coretext_font_get_ct_font (hb_font_t *font)
|
|
||||||
{
|
|
||||||
hb_face_t *face = font->face;
|
|
||||||
if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL;
|
|
||||||
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
|
|
||||||
return face_data->ct_font;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* shaper
|
* shaper
|
||||||
@ -283,7 +375,9 @@ struct active_feature_t {
|
|||||||
feature_record_t rec;
|
feature_record_t rec;
|
||||||
unsigned int order;
|
unsigned int order;
|
||||||
|
|
||||||
static int cmp (const active_feature_t *a, const active_feature_t *b) {
|
static int cmp (const void *pa, const void *pb) {
|
||||||
|
const active_feature_t *a = (const active_feature_t *) pa;
|
||||||
|
const active_feature_t *b = (const active_feature_t *) pb;
|
||||||
return a->rec.feature < b->rec.feature ? -1 : a->rec.feature > b->rec.feature ? 1 :
|
return a->rec.feature < b->rec.feature ? -1 : a->rec.feature > b->rec.feature ? 1 :
|
||||||
a->order < b->order ? -1 : a->order > b->order ? 1 :
|
a->order < b->order ? -1 : a->order > b->order ? 1 :
|
||||||
a->rec.setting < b->rec.setting ? -1 : a->rec.setting > b->rec.setting ? 1 :
|
a->rec.setting < b->rec.setting ? -1 : a->rec.setting > b->rec.setting ? 1 :
|
||||||
@ -299,7 +393,9 @@ struct feature_event_t {
|
|||||||
bool start;
|
bool start;
|
||||||
active_feature_t feature;
|
active_feature_t feature;
|
||||||
|
|
||||||
static int cmp (const feature_event_t *a, const feature_event_t *b) {
|
static int cmp (const void *pa, const void *pb) {
|
||||||
|
const feature_event_t *a = (const feature_event_t *) pa;
|
||||||
|
const feature_event_t *b = (const feature_event_t *) pb;
|
||||||
return a->index < b->index ? -1 : a->index > b->index ? 1 :
|
return a->index < b->index ? -1 : a->index > b->index ? 1 :
|
||||||
a->start < b->start ? -1 : a->start > b->start ? 1 :
|
a->start < b->start ? -1 : a->start > b->start ? 1 :
|
||||||
active_feature_t::cmp (&a->feature, &b->feature);
|
active_feature_t::cmp (&a->feature, &b->feature);
|
||||||
@ -498,9 +594,10 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||||||
unsigned int num_features)
|
unsigned int num_features)
|
||||||
{
|
{
|
||||||
hb_face_t *face = font->face;
|
hb_face_t *face = font->face;
|
||||||
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
|
CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
|
||||||
|
CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font);
|
||||||
|
|
||||||
CGFloat ct_font_size = CTFontGetSize (face_data->ct_font);
|
CGFloat ct_font_size = CTFontGetSize (ct_font);
|
||||||
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
|
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
|
||||||
CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
|
CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
|
||||||
|
|
||||||
@ -601,22 +698,23 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||||||
/* active_features.qsort (); */
|
/* active_features.qsort (); */
|
||||||
for (unsigned int j = 0; j < active_features.len; j++)
|
for (unsigned int j = 0; j < active_features.len; j++)
|
||||||
{
|
{
|
||||||
CFStringRef keys[2] = {
|
CFStringRef keys[] = {
|
||||||
kCTFontFeatureTypeIdentifierKey,
|
kCTFontFeatureTypeIdentifierKey,
|
||||||
kCTFontFeatureSelectorIdentifierKey
|
kCTFontFeatureSelectorIdentifierKey
|
||||||
};
|
};
|
||||||
CFNumberRef values[2] = {
|
CFNumberRef values[] = {
|
||||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature),
|
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature),
|
||||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting)
|
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting)
|
||||||
};
|
};
|
||||||
|
static_assert ((ARRAY_LENGTH_CONST (keys) == ARRAY_LENGTH_CONST (values)), "");
|
||||||
CFDictionaryRef dict = CFDictionaryCreate (kCFAllocatorDefault,
|
CFDictionaryRef dict = CFDictionaryCreate (kCFAllocatorDefault,
|
||||||
(const void **) keys,
|
(const void **) keys,
|
||||||
(const void **) values,
|
(const void **) values,
|
||||||
2,
|
ARRAY_LENGTH (keys),
|
||||||
&kCFTypeDictionaryKeyCallBacks,
|
&kCFTypeDictionaryKeyCallBacks,
|
||||||
&kCFTypeDictionaryValueCallBacks);
|
&kCFTypeDictionaryValueCallBacks);
|
||||||
CFRelease (values[0]);
|
for (unsigned int i = 0; i < ARRAY_LENGTH (values); i++)
|
||||||
CFRelease (values[1]);
|
CFRelease (values[i]);
|
||||||
|
|
||||||
CFArrayAppendValue (features_array, dict);
|
CFArrayAppendValue (features_array, dict);
|
||||||
CFRelease (dict);
|
CFRelease (dict);
|
||||||
@ -634,12 +732,12 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||||||
CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes);
|
CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes);
|
||||||
CFRelease (attributes);
|
CFRelease (attributes);
|
||||||
|
|
||||||
range->font = CTFontCreateCopyWithAttributes (face_data->ct_font, 0.0, NULL, font_desc);
|
range->font = CTFontCreateCopyWithAttributes (ct_font, 0.0, nullptr, font_desc);
|
||||||
CFRelease (font_desc);
|
CFRelease (font_desc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
range->font = NULL;
|
range->font = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
range->index_first = last_index;
|
range->index_first = last_index;
|
||||||
@ -659,9 +757,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||||||
active_features.remove (feature - active_features.array);
|
active_features.remove (feature - active_features.array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!range_records.len) /* No active feature found. */
|
|
||||||
goto fail_features;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -695,7 +790,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||||||
pchars[chars_len++] = 0xFFFDu;
|
pchars[chars_len++] = 0xFFFDu;
|
||||||
else {
|
else {
|
||||||
pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
|
pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
|
||||||
pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
|
pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,14 +807,14 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||||||
|
|
||||||
#define FAIL(...) \
|
#define FAIL(...) \
|
||||||
HB_STMT_START { \
|
HB_STMT_START { \
|
||||||
DEBUG_MSG (CORETEXT, NULL, __VA_ARGS__); \
|
DEBUG_MSG (CORETEXT, nullptr, __VA_ARGS__); \
|
||||||
ret = false; \
|
ret = false; \
|
||||||
goto fail; \
|
goto fail; \
|
||||||
} HB_STMT_END;
|
} HB_STMT_END;
|
||||||
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
CFStringRef string_ref = NULL;
|
CFStringRef string_ref = nullptr;
|
||||||
CTLineRef line = NULL;
|
CTLineRef line = nullptr;
|
||||||
|
|
||||||
if (0)
|
if (0)
|
||||||
{
|
{
|
||||||
@ -731,8 +826,8 @@ resize_and_retry:
|
|||||||
assert (line);
|
assert (line);
|
||||||
CFRelease (string_ref);
|
CFRelease (string_ref);
|
||||||
CFRelease (line);
|
CFRelease (line);
|
||||||
string_ref = NULL;
|
string_ref = nullptr;
|
||||||
line = NULL;
|
line = nullptr;
|
||||||
|
|
||||||
/* Get previous start-of-scratch-area, that we use later for readjusting
|
/* Get previous start-of-scratch-area, that we use later for readjusting
|
||||||
* our existing scratch arrays. */
|
* our existing scratch arrays. */
|
||||||
@ -753,7 +848,7 @@ resize_and_retry:
|
|||||||
scratch_size -= old_scratch_used;
|
scratch_size -= old_scratch_used;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
string_ref = CFStringCreateWithCharactersNoCopy (NULL,
|
string_ref = CFStringCreateWithCharactersNoCopy (nullptr,
|
||||||
pchars, chars_len,
|
pchars, chars_len,
|
||||||
kCFAllocatorNull);
|
kCFAllocatorNull);
|
||||||
if (unlikely (!string_ref))
|
if (unlikely (!string_ref))
|
||||||
@ -785,15 +880,18 @@ resize_and_retry:
|
|||||||
kCFStringEncodingUTF8,
|
kCFStringEncodingUTF8,
|
||||||
kCFAllocatorNull);
|
kCFAllocatorNull);
|
||||||
if (unlikely (!lang))
|
if (unlikely (!lang))
|
||||||
|
{
|
||||||
|
CFRelease (attr_string);
|
||||||
FAIL ("CFStringCreateWithCStringNoCopy failed");
|
FAIL ("CFStringCreateWithCStringNoCopy failed");
|
||||||
|
}
|
||||||
CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
|
CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
|
||||||
kCTLanguageAttributeName, lang);
|
kCTLanguageAttributeName, lang);
|
||||||
CFRelease (lang);
|
CFRelease (lang);
|
||||||
}
|
}
|
||||||
CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
|
CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
|
||||||
kCTFontAttributeName, face_data->ct_font);
|
kCTFontAttributeName, ct_font);
|
||||||
|
|
||||||
if (num_features)
|
if (num_features && range_records.len)
|
||||||
{
|
{
|
||||||
unsigned int start = 0;
|
unsigned int start = 0;
|
||||||
range_record_t *last_range = &range_records[0];
|
range_record_t *last_range = &range_records[0];
|
||||||
@ -819,6 +917,30 @@ resize_and_retry:
|
|||||||
CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, chars_len - start),
|
CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, chars_len - start),
|
||||||
kCTFontAttributeName, last_range->font);
|
kCTFontAttributeName, last_range->font);
|
||||||
}
|
}
|
||||||
|
/* Enable/disable kern if requested.
|
||||||
|
*
|
||||||
|
* Note: once kern is disabled, reenabling it doesn't currently seem to work in CoreText.
|
||||||
|
*/
|
||||||
|
if (num_features)
|
||||||
|
{
|
||||||
|
unsigned int zeroint = 0;
|
||||||
|
CFNumberRef zero = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &zeroint);
|
||||||
|
for (unsigned int i = 0; i < num_features; i++)
|
||||||
|
{
|
||||||
|
const hb_feature_t &feature = features[i];
|
||||||
|
if (feature.tag == HB_TAG('k','e','r','n') &&
|
||||||
|
feature.start < chars_len && feature.start < feature.end)
|
||||||
|
{
|
||||||
|
CFRange feature_range = CFRangeMake (feature.start,
|
||||||
|
MIN (feature.end, chars_len) - feature.start);
|
||||||
|
if (feature.value)
|
||||||
|
CFAttributedStringRemoveAttribute (attr_string, feature_range, kCTKernAttributeName);
|
||||||
|
else
|
||||||
|
CFAttributedStringSetAttribute (attr_string, feature_range, kCTKernAttributeName, zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CFRelease (zero);
|
||||||
|
}
|
||||||
|
|
||||||
int level = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
|
int level = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
|
||||||
CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &level);
|
CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &level);
|
||||||
@ -828,8 +950,12 @@ resize_and_retry:
|
|||||||
1,
|
1,
|
||||||
&kCFTypeDictionaryKeyCallBacks,
|
&kCFTypeDictionaryKeyCallBacks,
|
||||||
&kCFTypeDictionaryValueCallBacks);
|
&kCFTypeDictionaryValueCallBacks);
|
||||||
|
CFRelease (level_number);
|
||||||
if (unlikely (!options))
|
if (unlikely (!options))
|
||||||
|
{
|
||||||
|
CFRelease (attr_string);
|
||||||
FAIL ("CFDictionaryCreate failed");
|
FAIL ("CFDictionaryCreate failed");
|
||||||
|
}
|
||||||
|
|
||||||
CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOptions (attr_string, options);
|
CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOptions (attr_string, options);
|
||||||
CFRelease (options);
|
CFRelease (options);
|
||||||
@ -845,7 +971,7 @@ resize_and_retry:
|
|||||||
|
|
||||||
CFArrayRef glyph_runs = CTLineGetGlyphRuns (line);
|
CFArrayRef glyph_runs = CTLineGetGlyphRuns (line);
|
||||||
unsigned int num_runs = CFArrayGetCount (glyph_runs);
|
unsigned int num_runs = CFArrayGetCount (glyph_runs);
|
||||||
DEBUG_MSG (CORETEXT, NULL, "Num runs: %d", num_runs);
|
DEBUG_MSG (CORETEXT, nullptr, "Num runs: %d", num_runs);
|
||||||
|
|
||||||
buffer->len = 0;
|
buffer->len = 0;
|
||||||
uint32_t status_and = ~0, status_or = 0;
|
uint32_t status_and = ~0, status_or = 0;
|
||||||
@ -871,7 +997,7 @@ resize_and_retry:
|
|||||||
status_or |= run_status;
|
status_or |= run_status;
|
||||||
status_and &= run_status;
|
status_and &= run_status;
|
||||||
DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
|
DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
|
||||||
double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL);
|
double run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr);
|
||||||
if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
|
if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
|
||||||
run_advance = -run_advance;
|
run_advance = -run_advance;
|
||||||
DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance);
|
DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance);
|
||||||
@ -884,7 +1010,7 @@ resize_and_retry:
|
|||||||
*/
|
*/
|
||||||
CFDictionaryRef attributes = CTRunGetAttributes (run);
|
CFDictionaryRef attributes = CTRunGetAttributes (run);
|
||||||
CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName));
|
CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName));
|
||||||
if (!CFEqual (run_ct_font, face_data->ct_font))
|
if (!CFEqual (run_ct_font, ct_font))
|
||||||
{
|
{
|
||||||
/* The run doesn't use our main font instance. We have to figure out
|
/* The run doesn't use our main font instance. We have to figure out
|
||||||
* whether font fallback happened, or this is just CoreText giving us
|
* whether font fallback happened, or this is just CoreText giving us
|
||||||
@ -906,7 +1032,7 @@ resize_and_retry:
|
|||||||
* However, even that wouldn't work if we were passed in the CGFont to
|
* However, even that wouldn't work if we were passed in the CGFont to
|
||||||
* construct a hb_face to begin with.
|
* construct a hb_face to begin with.
|
||||||
*
|
*
|
||||||
* See: http://github.com/behdad/harfbuzz/pull/36
|
* See: http://github.com/harfbuzz/harfbuzz/pull/36
|
||||||
*
|
*
|
||||||
* Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
|
* Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
|
||||||
*/
|
*/
|
||||||
@ -919,16 +1045,16 @@ resize_and_retry:
|
|||||||
}
|
}
|
||||||
if (!matched)
|
if (!matched)
|
||||||
{
|
{
|
||||||
CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0);
|
CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, nullptr);
|
||||||
if (run_cg_font)
|
if (run_cg_font)
|
||||||
{
|
{
|
||||||
matched = CFEqual (run_cg_font, face_data->cg_font);
|
matched = CFEqual (run_cg_font, cg_font);
|
||||||
CFRelease (run_cg_font);
|
CFRelease (run_cg_font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!matched)
|
if (!matched)
|
||||||
{
|
{
|
||||||
CFStringRef font_ps_name = CTFontCopyName (face_data->ct_font, kCTFontPostScriptNameKey);
|
CFStringRef font_ps_name = CTFontCopyName (ct_font, kCTFontPostScriptNameKey);
|
||||||
CFStringRef run_ps_name = CTFontCopyName (run_ct_font, kCTFontPostScriptNameKey);
|
CFStringRef run_ps_name = CTFontCopyName (run_ct_font, kCTFontPostScriptNameKey);
|
||||||
CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name, 0);
|
CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name, 0);
|
||||||
CFRelease (run_ps_name);
|
CFRelease (run_ps_name);
|
||||||
@ -997,7 +1123,7 @@ resize_and_retry:
|
|||||||
|
|
||||||
/* Testing used to indicate that CTRunGetGlyphsPtr, etc (almost?) always
|
/* Testing used to indicate that CTRunGetGlyphsPtr, etc (almost?) always
|
||||||
* succeed, and so copying data to our own buffer will be rare. Reports
|
* succeed, and so copying data to our own buffer will be rare. Reports
|
||||||
* have it that this changed in OS X 10.10 Yosemite, and NULL is returned
|
* have it that this changed in OS X 10.10 Yosemite, and nullptr is returned
|
||||||
* frequently. At any rate, we can test that codepath by setting USE_PTR
|
* frequently. At any rate, we can test that codepath by setting USE_PTR
|
||||||
* to false. */
|
* to false. */
|
||||||
|
|
||||||
@ -1013,13 +1139,13 @@ resize_and_retry:
|
|||||||
|
|
||||||
{ /* Setup glyphs */
|
{ /* Setup glyphs */
|
||||||
SCRATCH_SAVE();
|
SCRATCH_SAVE();
|
||||||
const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL;
|
const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : nullptr;
|
||||||
if (!glyphs) {
|
if (!glyphs) {
|
||||||
ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry);
|
ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry);
|
||||||
CTRunGetGlyphs (run, range_all, glyph_buf);
|
CTRunGetGlyphs (run, range_all, glyph_buf);
|
||||||
glyphs = glyph_buf;
|
glyphs = glyph_buf;
|
||||||
}
|
}
|
||||||
const CFIndex* string_indices = USE_PTR ? CTRunGetStringIndicesPtr (run) : NULL;
|
const CFIndex* string_indices = USE_PTR ? CTRunGetStringIndicesPtr (run) : nullptr;
|
||||||
if (!string_indices) {
|
if (!string_indices) {
|
||||||
ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs, goto resize_and_retry);
|
ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs, goto resize_and_retry);
|
||||||
CTRunGetStringIndices (run, range_all, index_buf);
|
CTRunGetStringIndices (run, range_all, index_buf);
|
||||||
@ -1041,7 +1167,7 @@ resize_and_retry:
|
|||||||
* advance (in the advance direction only), and for last glyph we set
|
* advance (in the advance direction only), and for last glyph we set
|
||||||
* whatever is needed to make the whole run's advance add up. */
|
* whatever is needed to make the whole run's advance add up. */
|
||||||
SCRATCH_SAVE();
|
SCRATCH_SAVE();
|
||||||
const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL;
|
const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : nullptr;
|
||||||
if (!positions) {
|
if (!positions) {
|
||||||
ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs, goto resize_and_retry);
|
ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs, goto resize_and_retry);
|
||||||
CTRunGetPositions (run, range_all, position_buf);
|
CTRunGetPositions (run, range_all, position_buf);
|
||||||
@ -1092,7 +1218,7 @@ resize_and_retry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel,
|
/* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel,
|
||||||
* or if it does, it doesn't resepct it. So we get runs with wrong
|
* or if it does, it doesn't respect it. So we get runs with wrong
|
||||||
* directions. As such, disable the assert... It wouldn't crash, but
|
* directions. As such, disable the assert... It wouldn't crash, but
|
||||||
* cursoring will be off...
|
* cursoring will be off...
|
||||||
*
|
*
|
||||||
@ -1117,6 +1243,7 @@ resize_and_retry:
|
|||||||
pos->x_advance = info->mask;
|
pos->x_advance = info->mask;
|
||||||
pos->x_offset = info->var1.i32;
|
pos->x_offset = info->var1.i32;
|
||||||
pos->y_offset = info->var2.i32;
|
pos->y_offset = info->var2.i32;
|
||||||
|
|
||||||
info++, pos++;
|
info++, pos++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1125,6 +1252,7 @@ resize_and_retry:
|
|||||||
pos->y_advance = info->mask;
|
pos->y_advance = info->mask;
|
||||||
pos->x_offset = info->var1.i32;
|
pos->x_offset = info->var1.i32;
|
||||||
pos->y_offset = info->var2.i32;
|
pos->y_offset = info->var2.i32;
|
||||||
|
|
||||||
info++, pos++;
|
info++, pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1162,6 +1290,8 @@ resize_and_retry:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer->unsafe_to_break_all ();
|
||||||
|
|
||||||
#undef FAIL
|
#undef FAIL
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -1182,6 +1312,9 @@ fail:
|
|||||||
* AAT shaper
|
* AAT shaper
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face)
|
||||||
|
HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* shaper face data
|
* shaper face data
|
||||||
*/
|
*/
|
||||||
@ -1191,22 +1324,20 @@ struct hb_coretext_aat_shaper_face_data_t {};
|
|||||||
hb_coretext_aat_shaper_face_data_t *
|
hb_coretext_aat_shaper_face_data_t *
|
||||||
_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
|
_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
|
||||||
{
|
{
|
||||||
hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT);
|
static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX};
|
||||||
/* Umm, we just reference the table to check whether it exists.
|
|
||||||
* Maybe add better API for this? */
|
|
||||||
if (!hb_blob_get_length (mort_blob))
|
|
||||||
{
|
|
||||||
hb_blob_destroy (mort_blob);
|
|
||||||
mort_blob = face->reference_table (HB_CORETEXT_TAG_MORX);
|
|
||||||
if (!hb_blob_get_length (mort_blob))
|
|
||||||
{
|
|
||||||
hb_blob_destroy (mort_blob);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hb_blob_destroy (mort_blob);
|
|
||||||
|
|
||||||
return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL;
|
for (unsigned int i = 0; i < ARRAY_LENGTH (tags); i++)
|
||||||
|
{
|
||||||
|
hb_blob_t *blob = face->reference_table (tags[i]);
|
||||||
|
if (hb_blob_get_length (blob))
|
||||||
|
{
|
||||||
|
hb_blob_destroy (blob);
|
||||||
|
return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
|
||||||
|
}
|
||||||
|
hb_blob_destroy (blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1224,7 +1355,7 @@ struct hb_coretext_aat_shaper_font_data_t {};
|
|||||||
hb_coretext_aat_shaper_font_data_t *
|
hb_coretext_aat_shaper_font_data_t *
|
||||||
_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
|
_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
|
||||||
{
|
{
|
||||||
return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL;
|
return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1242,7 +1373,9 @@ struct hb_coretext_aat_shaper_shape_plan_data_t {};
|
|||||||
hb_coretext_aat_shaper_shape_plan_data_t *
|
hb_coretext_aat_shaper_shape_plan_data_t *
|
||||||
_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||||
const hb_feature_t *user_features HB_UNUSED,
|
const hb_feature_t *user_features HB_UNUSED,
|
||||||
unsigned int num_user_features HB_UNUSED)
|
unsigned int num_user_features HB_UNUSED,
|
||||||
|
const int *coords HB_UNUSED,
|
||||||
|
unsigned int num_coords HB_UNUSED)
|
||||||
{
|
{
|
||||||
return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||||
}
|
}
|
||||||
|
@ -42,11 +42,15 @@ HB_BEGIN_DECLS
|
|||||||
|
|
||||||
#define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t')
|
#define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t')
|
||||||
#define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
|
#define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
|
||||||
|
#define HB_CORETEXT_TAG_KERX HB_TAG('k','e','r','x')
|
||||||
|
|
||||||
|
|
||||||
HB_EXTERN hb_face_t *
|
HB_EXTERN hb_face_t *
|
||||||
hb_coretext_face_create (CGFontRef cg_font);
|
hb_coretext_face_create (CGFontRef cg_font);
|
||||||
|
|
||||||
|
HB_EXTERN hb_font_t *
|
||||||
|
hb_coretext_font_create (CTFontRef ct_font);
|
||||||
|
|
||||||
|
|
||||||
HB_EXTERN CGFontRef
|
HB_EXTERN CGFontRef
|
||||||
hb_coretext_face_get_cg_font (hb_face_t *face);
|
hb_coretext_face_get_cg_font (hb_face_t *face);
|
||||||
|
444
src/hb-debug.hh
Normal file
444
src/hb-debug.hh
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2017 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_DEBUG_HH
|
||||||
|
#define HB_DEBUG_HH
|
||||||
|
|
||||||
|
#include "hb-private.hh"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG
|
||||||
|
#define HB_DEBUG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
_hb_debug (unsigned int level,
|
||||||
|
unsigned int max_level)
|
||||||
|
{
|
||||||
|
return level < max_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
|
||||||
|
#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_hb_print_func (const char *func)
|
||||||
|
{
|
||||||
|
if (func)
|
||||||
|
{
|
||||||
|
unsigned int func_len = strlen (func);
|
||||||
|
/* Skip "static" */
|
||||||
|
if (0 == strncmp (func, "static ", 7))
|
||||||
|
func += 7;
|
||||||
|
/* Skip "typename" */
|
||||||
|
if (0 == strncmp (func, "typename ", 9))
|
||||||
|
func += 9;
|
||||||
|
/* Skip return type */
|
||||||
|
const char *space = strchr (func, ' ');
|
||||||
|
if (space)
|
||||||
|
func = space + 1;
|
||||||
|
/* Skip parameter list */
|
||||||
|
const char *paren = strchr (func, '(');
|
||||||
|
if (paren)
|
||||||
|
func_len = paren - func;
|
||||||
|
fprintf (stderr, "%.*s", func_len, func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int max_level> static inline void
|
||||||
|
_hb_debug_msg_va (const char *what,
|
||||||
|
const void *obj,
|
||||||
|
const char *func,
|
||||||
|
bool indented,
|
||||||
|
unsigned int level,
|
||||||
|
int level_dir,
|
||||||
|
const char *message,
|
||||||
|
va_list ap) HB_PRINTF_FUNC(7, 0);
|
||||||
|
template <int max_level> static inline void
|
||||||
|
_hb_debug_msg_va (const char *what,
|
||||||
|
const void *obj,
|
||||||
|
const char *func,
|
||||||
|
bool indented,
|
||||||
|
unsigned int level,
|
||||||
|
int level_dir,
|
||||||
|
const char *message,
|
||||||
|
va_list ap)
|
||||||
|
{
|
||||||
|
if (!_hb_debug (level, max_level))
|
||||||
|
return;
|
||||||
|
|
||||||
|
fprintf (stderr, "%-10s", what ? what : "");
|
||||||
|
|
||||||
|
if (obj)
|
||||||
|
fprintf (stderr, "(%*p) ", (unsigned int) (2 * sizeof (void *)), obj);
|
||||||
|
else
|
||||||
|
fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), "");
|
||||||
|
|
||||||
|
if (indented) {
|
||||||
|
#define VBAR "\342\224\202" /* U+2502 BOX DRAWINGS LIGHT VERTICAL */
|
||||||
|
#define VRBAR "\342\224\234" /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
|
||||||
|
#define DLBAR "\342\225\256" /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
|
||||||
|
#define ULBAR "\342\225\257" /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
|
||||||
|
#define LBAR "\342\225\264" /* U+2574 BOX DRAWINGS LIGHT LEFT */
|
||||||
|
static const char bars[] =
|
||||||
|
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
|
||||||
|
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
|
||||||
|
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
|
||||||
|
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
|
||||||
|
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
|
||||||
|
fprintf (stderr, "%2u %s" VRBAR "%s",
|
||||||
|
level,
|
||||||
|
bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
|
||||||
|
level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
|
||||||
|
} else
|
||||||
|
fprintf (stderr, " " VRBAR LBAR);
|
||||||
|
|
||||||
|
_hb_print_func (func);
|
||||||
|
|
||||||
|
if (message)
|
||||||
|
{
|
||||||
|
fprintf (stderr, ": ");
|
||||||
|
vfprintf (stderr, message, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf (stderr, "\n");
|
||||||
|
}
|
||||||
|
template <> inline void
|
||||||
|
_hb_debug_msg_va<0> (const char *what HB_UNUSED,
|
||||||
|
const void *obj HB_UNUSED,
|
||||||
|
const char *func HB_UNUSED,
|
||||||
|
bool indented HB_UNUSED,
|
||||||
|
unsigned int level HB_UNUSED,
|
||||||
|
int level_dir HB_UNUSED,
|
||||||
|
const char *message HB_UNUSED,
|
||||||
|
va_list ap HB_UNUSED) {}
|
||||||
|
|
||||||
|
template <int max_level> static inline void
|
||||||
|
_hb_debug_msg (const char *what,
|
||||||
|
const void *obj,
|
||||||
|
const char *func,
|
||||||
|
bool indented,
|
||||||
|
unsigned int level,
|
||||||
|
int level_dir,
|
||||||
|
const char *message,
|
||||||
|
...) HB_PRINTF_FUNC(7, 8);
|
||||||
|
template <int max_level> static inline void
|
||||||
|
_hb_debug_msg (const char *what,
|
||||||
|
const void *obj,
|
||||||
|
const char *func,
|
||||||
|
bool indented,
|
||||||
|
unsigned int level,
|
||||||
|
int level_dir,
|
||||||
|
const char *message,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start (ap, message);
|
||||||
|
_hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
template <> inline void
|
||||||
|
_hb_debug_msg<0> (const char *what HB_UNUSED,
|
||||||
|
const void *obj HB_UNUSED,
|
||||||
|
const char *func HB_UNUSED,
|
||||||
|
bool indented HB_UNUSED,
|
||||||
|
unsigned int level HB_UNUSED,
|
||||||
|
int level_dir HB_UNUSED,
|
||||||
|
const char *message HB_UNUSED,
|
||||||
|
...) HB_PRINTF_FUNC(7, 8);
|
||||||
|
template <> inline void
|
||||||
|
_hb_debug_msg<0> (const char *what HB_UNUSED,
|
||||||
|
const void *obj HB_UNUSED,
|
||||||
|
const char *func HB_UNUSED,
|
||||||
|
bool indented HB_UNUSED,
|
||||||
|
unsigned int level HB_UNUSED,
|
||||||
|
int level_dir HB_UNUSED,
|
||||||
|
const char *message HB_UNUSED,
|
||||||
|
...) {}
|
||||||
|
|
||||||
|
#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
|
||||||
|
#define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, false, 0, 0, __VA_ARGS__)
|
||||||
|
#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Printer
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct hb_printer_t {
|
||||||
|
const char *print (const T&) { return "something"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hb_printer_t<bool> {
|
||||||
|
const char *print (bool v) { return v ? "true" : "false"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hb_printer_t<hb_void_t> {
|
||||||
|
const char *print (hb_void_t) { return ""; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trace
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline void _hb_warn_no_return (bool returned)
|
||||||
|
{
|
||||||
|
if (unlikely (!returned)) {
|
||||||
|
fprintf (stderr, "OUCH, returned with no call to return_trace(). This is a bug, please report.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <int max_level, typename ret_t>
|
||||||
|
struct hb_auto_trace_t
|
||||||
|
{
|
||||||
|
explicit inline hb_auto_trace_t (unsigned int *plevel_,
|
||||||
|
const char *what_,
|
||||||
|
const void *obj_,
|
||||||
|
const char *func,
|
||||||
|
const char *message,
|
||||||
|
...) HB_PRINTF_FUNC(6, 7)
|
||||||
|
: plevel (plevel_), what (what_), obj (obj_), returned (false)
|
||||||
|
{
|
||||||
|
if (plevel) ++*plevel;
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start (ap, message);
|
||||||
|
_hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
inline ~hb_auto_trace_t (void)
|
||||||
|
{
|
||||||
|
_hb_warn_no_return<ret_t> (returned);
|
||||||
|
if (!returned) {
|
||||||
|
_hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1, " ");
|
||||||
|
}
|
||||||
|
if (plevel) --*plevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ret_t ret (ret_t v, unsigned int line = 0)
|
||||||
|
{
|
||||||
|
if (unlikely (returned)) {
|
||||||
|
fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n");
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
_hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1,
|
||||||
|
"return %s (line %d)",
|
||||||
|
hb_printer_t<ret_t>().print (v), line);
|
||||||
|
if (plevel) --*plevel;
|
||||||
|
plevel = nullptr;
|
||||||
|
returned = true;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int *plevel;
|
||||||
|
const char *what;
|
||||||
|
const void *obj;
|
||||||
|
bool returned;
|
||||||
|
};
|
||||||
|
template <typename ret_t> /* Make sure we don't use hb_auto_trace_t when not tracing. */
|
||||||
|
struct hb_auto_trace_t<0, ret_t>
|
||||||
|
{
|
||||||
|
explicit inline hb_auto_trace_t (unsigned int *plevel_,
|
||||||
|
const char *what_,
|
||||||
|
const void *obj_,
|
||||||
|
const char *func,
|
||||||
|
const char *message,
|
||||||
|
...) HB_PRINTF_FUNC(6, 7) {}
|
||||||
|
|
||||||
|
inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* For disabled tracing; optimize out everything.
|
||||||
|
* https://github.com/harfbuzz/harfbuzz/pull/605 */
|
||||||
|
template <typename ret_t>
|
||||||
|
struct hb_no_trace_t {
|
||||||
|
inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define return_trace(RET) return trace.ret (RET, __LINE__)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instances.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_ARABIC
|
||||||
|
#define HB_DEBUG_ARABIC (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_BLOB
|
||||||
|
#define HB_DEBUG_BLOB (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_CORETEXT
|
||||||
|
#define HB_DEBUG_CORETEXT (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_DIRECTWRITE
|
||||||
|
#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_FT
|
||||||
|
#define HB_DEBUG_FT (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_GET_COVERAGE
|
||||||
|
#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_OBJECT
|
||||||
|
#define HB_DEBUG_OBJECT (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_SHAPE_PLAN
|
||||||
|
#define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_UNISCRIBE
|
||||||
|
#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* With tracing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_APPLY
|
||||||
|
#define HB_DEBUG_APPLY (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
#if HB_DEBUG_APPLY
|
||||||
|
#define TRACE_APPLY(this) \
|
||||||
|
hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
|
||||||
|
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
|
||||||
|
"idx %d gid %u lookup %d", \
|
||||||
|
c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index)
|
||||||
|
#else
|
||||||
|
#define TRACE_APPLY(this) hb_no_trace_t<bool> trace
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_CLOSURE
|
||||||
|
#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
#if HB_DEBUG_CLOSURE
|
||||||
|
#define TRACE_CLOSURE(this) \
|
||||||
|
hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
|
||||||
|
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
|
||||||
|
" ")
|
||||||
|
#else
|
||||||
|
#define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_COLLECT_GLYPHS
|
||||||
|
#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
#if HB_DEBUG_COLLECT_GLYPHS
|
||||||
|
#define TRACE_COLLECT_GLYPHS(this) \
|
||||||
|
hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
|
||||||
|
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
|
||||||
|
" ")
|
||||||
|
#else
|
||||||
|
#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_SANITIZE
|
||||||
|
#define HB_DEBUG_SANITIZE (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
#if HB_DEBUG_SANITIZE
|
||||||
|
#define TRACE_SANITIZE(this) \
|
||||||
|
hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
|
||||||
|
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
|
||||||
|
" ");
|
||||||
|
#else
|
||||||
|
#define TRACE_SANITIZE(this) hb_no_trace_t<bool> trace
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_SERIALIZE
|
||||||
|
#define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
#if HB_DEBUG_SERIALIZE
|
||||||
|
#define TRACE_SERIALIZE(this) \
|
||||||
|
hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
|
||||||
|
(&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
|
||||||
|
" ");
|
||||||
|
#else
|
||||||
|
#define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_SUBSET
|
||||||
|
#define HB_DEBUG_SUBSET (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
#if HB_DEBUG_SUBSET
|
||||||
|
#define TRACE_SUBSET(this) \
|
||||||
|
hb_auto_trace_t<HB_DEBUG_SUBSET, bool> trace \
|
||||||
|
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
|
||||||
|
" ");
|
||||||
|
#else
|
||||||
|
#define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_WOULD_APPLY
|
||||||
|
#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
#if HB_DEBUG_WOULD_APPLY
|
||||||
|
#define TRACE_WOULD_APPLY(this) \
|
||||||
|
hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
|
||||||
|
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
|
||||||
|
"%d glyphs", c->len);
|
||||||
|
#else
|
||||||
|
#define TRACE_WOULD_APPLY(this) hb_no_trace_t<bool> trace
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_DISPATCH
|
||||||
|
#define HB_DEBUG_DISPATCH ( \
|
||||||
|
HB_DEBUG_APPLY + \
|
||||||
|
HB_DEBUG_CLOSURE + \
|
||||||
|
HB_DEBUG_COLLECT_GLYPHS + \
|
||||||
|
HB_DEBUG_SANITIZE + \
|
||||||
|
HB_DEBUG_SERIALIZE + \
|
||||||
|
HB_DEBUG_SUBSET + \
|
||||||
|
HB_DEBUG_WOULD_APPLY + \
|
||||||
|
0)
|
||||||
|
#endif
|
||||||
|
#if HB_DEBUG_DISPATCH
|
||||||
|
#define TRACE_DISPATCH(this, format) \
|
||||||
|
hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
|
||||||
|
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
|
||||||
|
"format %d", (int) format);
|
||||||
|
#else
|
||||||
|
#define TRACE_DISPATCH(this, format) hb_no_trace_t<typename context_t::return_t> trace
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HB_DEBUG_HH */
|
@ -34,6 +34,7 @@
|
|||||||
#include "hb-common.h"
|
#include "hb-common.h"
|
||||||
#include "hb-unicode.h"
|
#include "hb-unicode.h"
|
||||||
#include "hb-font.h"
|
#include "hb-font.h"
|
||||||
|
#include "hb-set.h"
|
||||||
|
|
||||||
HB_BEGIN_DECLS
|
HB_BEGIN_DECLS
|
||||||
|
|
||||||
@ -54,6 +55,9 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
|
|||||||
hb_font_get_glyph_func_t func,
|
hb_font_get_glyph_func_t func,
|
||||||
void *user_data, hb_destroy_func_t destroy);
|
void *user_data, hb_destroy_func_t destroy);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_set_invert (hb_set_t *set);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HB_END_DECLS
|
HB_END_DECLS
|
||||||
|
@ -22,199 +22,202 @@
|
|||||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "hb-private.hh"
|
||||||
|
#include "hb-debug.hh"
|
||||||
#define HB_SHAPER directwrite
|
#define HB_SHAPER directwrite
|
||||||
#include "hb-shaper-impl-private.hh"
|
#include "hb-shaper-impl-private.hh"
|
||||||
|
|
||||||
#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
|
#include <DWrite_1.h>
|
||||||
#include <DWrite.h>
|
|
||||||
#else
|
|
||||||
#include <DWrite_1.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "hb-directwrite.h"
|
#include "hb-directwrite.h"
|
||||||
|
|
||||||
#include "hb-open-file-private.hh"
|
|
||||||
#include "hb-ot-name-table.hh"
|
HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, face)
|
||||||
#include "hb-ot-tag.h"
|
HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, font)
|
||||||
|
|
||||||
|
|
||||||
#ifndef HB_DEBUG_DIRECTWRITE
|
/*
|
||||||
#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
|
* DirectWrite font stream helpers
|
||||||
#endif
|
*/
|
||||||
|
|
||||||
|
// This is a font loader which provides only one font (unlike its original design).
|
||||||
|
// For a better implementation which was also source of this
|
||||||
|
// and DWriteFontFileStream, have a look at to NativeFontResourceDWrite.cpp in Mozilla
|
||||||
|
class DWriteFontFileLoader : public IDWriteFontFileLoader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
IDWriteFontFileStream *mFontFileStream;
|
||||||
|
public:
|
||||||
|
DWriteFontFileLoader (IDWriteFontFileStream *fontFileStream) {
|
||||||
|
mFontFileStream = fontFileStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IUnknown interface
|
||||||
|
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) { return S_OK; }
|
||||||
|
IFACEMETHOD_(ULONG, AddRef)() { return 1; }
|
||||||
|
IFACEMETHOD_(ULONG, Release)() { return 1; }
|
||||||
|
|
||||||
|
// IDWriteFontFileLoader methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const* fontFileReferenceKey,
|
||||||
|
UINT32 fontFileReferenceKeySize,
|
||||||
|
OUT IDWriteFontFileStream** fontFileStream)
|
||||||
|
{
|
||||||
|
*fontFileStream = mFontFileStream;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DWriteFontFileStream : public IDWriteFontFileStream
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t *mData;
|
||||||
|
uint32_t mSize;
|
||||||
|
public:
|
||||||
|
DWriteFontFileStream(uint8_t *aData, uint32_t aSize)
|
||||||
|
{
|
||||||
|
mData = aData;
|
||||||
|
mSize = aSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IUnknown interface
|
||||||
|
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) { return S_OK; }
|
||||||
|
IFACEMETHOD_(ULONG, AddRef)() { return 1; }
|
||||||
|
IFACEMETHOD_(ULONG, Release)() { return 1; }
|
||||||
|
|
||||||
|
// IDWriteFontFileStream methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart,
|
||||||
|
UINT64 fileOffset,
|
||||||
|
UINT64 fragmentSize,
|
||||||
|
OUT void** fragmentContext)
|
||||||
|
{
|
||||||
|
// We are required to do bounds checking.
|
||||||
|
if (fileOffset + fragmentSize > mSize) {
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// truncate the 64 bit fileOffset to size_t sized index into mData
|
||||||
|
size_t index = static_cast<size_t> (fileOffset);
|
||||||
|
|
||||||
|
// We should be alive for the duration of this.
|
||||||
|
*fragmentStart = &mData[index];
|
||||||
|
*fragmentContext = nullptr;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext) { }
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize)
|
||||||
|
{
|
||||||
|
*fileSize = mSize;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, face)
|
|
||||||
HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, font)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* shaper face data
|
* shaper face data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct hb_directwrite_shaper_face_data_t {
|
struct hb_directwrite_shaper_face_data_t {
|
||||||
HANDLE fh;
|
IDWriteFactory *dwriteFactory;
|
||||||
wchar_t face_name[LF_FACESIZE];
|
IDWriteFontFile *fontFile;
|
||||||
|
IDWriteFontFileStream *fontFileStream;
|
||||||
|
IDWriteFontFileLoader *fontFileLoader;
|
||||||
|
IDWriteFontFace *fontFace;
|
||||||
|
hb_blob_t *faceBlob;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* face_name should point to a wchar_t[LF_FACESIZE] object. */
|
|
||||||
static void
|
|
||||||
_hb_generate_unique_face_name(wchar_t *face_name, unsigned int *plen)
|
|
||||||
{
|
|
||||||
/* We'll create a private name for the font from a UUID using a simple,
|
|
||||||
* somewhat base64-like encoding scheme */
|
|
||||||
const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
|
|
||||||
UUID id;
|
|
||||||
UuidCreate ((UUID*)&id);
|
|
||||||
ASSERT_STATIC (2 + 3 * (16 / 2) < LF_FACESIZE);
|
|
||||||
unsigned int name_str_len = 0;
|
|
||||||
face_name[name_str_len++] = 'F';
|
|
||||||
face_name[name_str_len++] = '_';
|
|
||||||
unsigned char *p = (unsigned char *)&id;
|
|
||||||
for (unsigned int i = 0; i < 16; i += 2)
|
|
||||||
{
|
|
||||||
/* Spread the 16 bits from two bytes of the UUID across three chars of face_name,
|
|
||||||
* using the bits in groups of 5,5,6 to select chars from enc.
|
|
||||||
* This will generate 24 characters; with the 'F_' prefix we already provided,
|
|
||||||
* the name will be 26 chars (plus the NUL terminator), so will always fit within
|
|
||||||
* face_name (LF_FACESIZE = 32). */
|
|
||||||
face_name[name_str_len++] = enc[p[i] >> 3];
|
|
||||||
face_name[name_str_len++] = enc[((p[i] << 2) | (p[i + 1] >> 6)) & 0x1f];
|
|
||||||
face_name[name_str_len++] = enc[p[i + 1] & 0x3f];
|
|
||||||
}
|
|
||||||
face_name[name_str_len] = 0;
|
|
||||||
if (plen)
|
|
||||||
*plen = name_str_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destroys blob. */
|
|
||||||
static hb_blob_t *
|
|
||||||
_hb_rename_font(hb_blob_t *blob, wchar_t *new_name)
|
|
||||||
{
|
|
||||||
/* Create a copy of the font data, with the 'name' table replaced by a
|
|
||||||
* table that names the font with our private F_* name created above.
|
|
||||||
* For simplicity, we just append a new 'name' table and update the
|
|
||||||
* sfnt directory; the original table is left in place, but unused.
|
|
||||||
*
|
|
||||||
* The new table will contain just 5 name IDs: family, style, unique,
|
|
||||||
* full, PS. All of them point to the same name data with our unique name.
|
|
||||||
*/
|
|
||||||
|
|
||||||
blob = OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (blob);
|
|
||||||
|
|
||||||
unsigned int length, new_length, name_str_len;
|
|
||||||
const char *orig_sfnt_data = hb_blob_get_data (blob, &length);
|
|
||||||
|
|
||||||
_hb_generate_unique_face_name (new_name, &name_str_len);
|
|
||||||
|
|
||||||
static const uint16_t name_IDs[] = { 1, 2, 3, 4, 6 };
|
|
||||||
|
|
||||||
unsigned int name_table_length = OT::name::min_size +
|
|
||||||
ARRAY_LENGTH(name_IDs) * OT::NameRecord::static_size +
|
|
||||||
name_str_len * 2; /* for name data in UTF16BE form */
|
|
||||||
unsigned int name_table_offset = (length + 3) & ~3;
|
|
||||||
|
|
||||||
new_length = name_table_offset + ((name_table_length + 3) & ~3);
|
|
||||||
void *new_sfnt_data = calloc(1, new_length);
|
|
||||||
if (!new_sfnt_data)
|
|
||||||
{
|
|
||||||
hb_blob_destroy (blob);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(new_sfnt_data, orig_sfnt_data, length);
|
|
||||||
|
|
||||||
OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
|
|
||||||
name.format.set (0);
|
|
||||||
name.count.set (ARRAY_LENGTH (name_IDs));
|
|
||||||
name.stringOffset.set (name.get_size());
|
|
||||||
for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++)
|
|
||||||
{
|
|
||||||
OT::NameRecord &record = name.nameRecord[i];
|
|
||||||
record.platformID.set(3);
|
|
||||||
record.encodingID.set(1);
|
|
||||||
record.languageID.set(0x0409u); /* English */
|
|
||||||
record.nameID.set(name_IDs[i]);
|
|
||||||
record.length.set(name_str_len * 2);
|
|
||||||
record.offset.set(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy string data from new_name, converting wchar_t to UTF16BE. */
|
|
||||||
unsigned char *p = &OT::StructAfter<unsigned char>(name);
|
|
||||||
for (unsigned int i = 0; i < name_str_len; i++)
|
|
||||||
{
|
|
||||||
*p++ = new_name[i] >> 8;
|
|
||||||
*p++ = new_name[i] & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust name table entry to point to new name table */
|
|
||||||
const OT::OpenTypeFontFile &file = *(OT::OpenTypeFontFile *) (new_sfnt_data);
|
|
||||||
unsigned int face_count = file.get_face_count ();
|
|
||||||
for (unsigned int face_index = 0; face_index < face_count; face_index++)
|
|
||||||
{
|
|
||||||
/* Note: doing multiple edits (ie. TTC) can be unsafe. There may be
|
|
||||||
* toe-stepping. But we don't really care. */
|
|
||||||
const OT::OpenTypeFontFace &face = file.get_face (face_index);
|
|
||||||
unsigned int index;
|
|
||||||
if (face.find_table_index (HB_OT_TAG_name, &index))
|
|
||||||
{
|
|
||||||
OT::TableRecord &record = const_cast<OT::TableRecord &> (face.get_table (index));
|
|
||||||
record.checkSum.set_for_data (&name, name_table_length);
|
|
||||||
record.offset.set (name_table_offset);
|
|
||||||
record.length.set (name_table_length);
|
|
||||||
}
|
|
||||||
else if (face_index == 0) /* Fail if first face doesn't have 'name' table. */
|
|
||||||
{
|
|
||||||
free (new_sfnt_data);
|
|
||||||
hb_blob_destroy (blob);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The checkSumAdjustment field in the 'head' table is now wrong,
|
|
||||||
* but that doesn't actually seem to cause any problems so we don't
|
|
||||||
* bother. */
|
|
||||||
|
|
||||||
hb_blob_destroy (blob);
|
|
||||||
return hb_blob_create ((const char *)new_sfnt_data, new_length,
|
|
||||||
HB_MEMORY_MODE_WRITABLE, NULL, free);
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_directwrite_shaper_face_data_t *
|
hb_directwrite_shaper_face_data_t *
|
||||||
_hb_directwrite_shaper_face_data_create(hb_face_t *face)
|
_hb_directwrite_shaper_face_data_create(hb_face_t *face)
|
||||||
{
|
{
|
||||||
hb_directwrite_shaper_face_data_t *data =
|
hb_directwrite_shaper_face_data_t *data =
|
||||||
(hb_directwrite_shaper_face_data_t *) calloc (1, sizeof (hb_directwrite_shaper_face_data_t));
|
(hb_directwrite_shaper_face_data_t *) malloc (sizeof (hb_directwrite_shaper_face_data_t));
|
||||||
if (unlikely (!data))
|
if (unlikely (!data))
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
|
// TODO: factory and fontFileLoader should be cached separately
|
||||||
|
IDWriteFactory* dwriteFactory;
|
||||||
|
DWriteCreateFactory (
|
||||||
|
DWRITE_FACTORY_TYPE_SHARED,
|
||||||
|
__uuidof (IDWriteFactory),
|
||||||
|
(IUnknown**) &dwriteFactory
|
||||||
|
);
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
hb_blob_t *blob = hb_face_reference_blob (face);
|
hb_blob_t *blob = hb_face_reference_blob (face);
|
||||||
if (unlikely (!hb_blob_get_length (blob)))
|
IDWriteFontFileStream *fontFileStream = new DWriteFontFileStream (
|
||||||
DEBUG_MSG(DIRECTWRITE, face, "Face has empty blob");
|
(uint8_t*) hb_blob_get_data (blob, nullptr), hb_blob_get_length (blob));
|
||||||
|
|
||||||
blob = _hb_rename_font (blob, data->face_name);
|
IDWriteFontFileLoader *fontFileLoader = new DWriteFontFileLoader (fontFileStream);
|
||||||
if (unlikely (!blob))
|
dwriteFactory->RegisterFontFileLoader (fontFileLoader);
|
||||||
{
|
|
||||||
free(data);
|
IDWriteFontFile *fontFile;
|
||||||
return NULL;
|
uint64_t fontFileKey = 0;
|
||||||
|
hr = dwriteFactory->CreateCustomFontFileReference (&fontFileKey, sizeof (fontFileKey),
|
||||||
|
fontFileLoader, &fontFile);
|
||||||
|
|
||||||
|
#define FAIL(...) \
|
||||||
|
HB_STMT_START { \
|
||||||
|
DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
|
||||||
|
return false; \
|
||||||
|
} HB_STMT_END;
|
||||||
|
|
||||||
|
if (FAILED (hr)) {
|
||||||
|
FAIL ("Failed to load font file from data!");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD num_fonts_installed;
|
BOOL isSupported;
|
||||||
data->fh = AddFontMemResourceEx ((void *)hb_blob_get_data(blob, NULL),
|
DWRITE_FONT_FILE_TYPE fileType;
|
||||||
hb_blob_get_length (blob),
|
DWRITE_FONT_FACE_TYPE faceType;
|
||||||
0, &num_fonts_installed);
|
UINT32 numberOfFaces;
|
||||||
if (unlikely (!data->fh))
|
hr = fontFile->Analyze (&isSupported, &fileType, &faceType, &numberOfFaces);
|
||||||
{
|
if (FAILED (hr) || !isSupported) {
|
||||||
DEBUG_MSG (DIRECTWRITE, face, "Face AddFontMemResourceEx() failed");
|
FAIL ("Font file is not supported.");
|
||||||
free (data);
|
return false;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef FAIL
|
||||||
|
|
||||||
|
IDWriteFontFace *fontFace;
|
||||||
|
dwriteFactory->CreateFontFace (faceType, 1, &fontFile, 0,
|
||||||
|
DWRITE_FONT_SIMULATIONS_NONE, &fontFace);
|
||||||
|
|
||||||
|
data->dwriteFactory = dwriteFactory;
|
||||||
|
data->fontFile = fontFile;
|
||||||
|
data->fontFileStream = fontFileStream;
|
||||||
|
data->fontFileLoader = fontFileLoader;
|
||||||
|
data->fontFace = fontFace;
|
||||||
|
data->faceBlob = blob;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data)
|
_hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data)
|
||||||
{
|
{
|
||||||
RemoveFontMemResourceEx(data->fh);
|
if (data->fontFace)
|
||||||
free(data);
|
data->fontFace->Release ();
|
||||||
|
if (data->fontFile)
|
||||||
|
data->fontFile->Release ();
|
||||||
|
if (data->dwriteFactory) {
|
||||||
|
if (data->fontFileLoader)
|
||||||
|
data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader);
|
||||||
|
data->dwriteFactory->Release ();
|
||||||
|
}
|
||||||
|
if (data->fontFileLoader)
|
||||||
|
delete data->fontFileLoader;
|
||||||
|
if (data->fontFileStream)
|
||||||
|
delete data->fontFileStream;
|
||||||
|
if (data->faceBlob)
|
||||||
|
hb_blob_destroy (data->faceBlob);
|
||||||
|
if (data)
|
||||||
|
free (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -223,60 +226,17 @@ _hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct hb_directwrite_shaper_font_data_t {
|
struct hb_directwrite_shaper_font_data_t {
|
||||||
HDC hdc;
|
|
||||||
LOGFONTW log_font;
|
|
||||||
HFONT hfont;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
|
||||||
populate_log_font (LOGFONTW *lf,
|
|
||||||
hb_font_t *font)
|
|
||||||
{
|
|
||||||
memset (lf, 0, sizeof (*lf));
|
|
||||||
lf->lfHeight = -font->y_scale;
|
|
||||||
lf->lfCharSet = DEFAULT_CHARSET;
|
|
||||||
|
|
||||||
hb_face_t *face = font->face;
|
|
||||||
hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
|
|
||||||
|
|
||||||
memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_directwrite_shaper_font_data_t *
|
hb_directwrite_shaper_font_data_t *
|
||||||
_hb_directwrite_shaper_font_data_create (hb_font_t *font)
|
_hb_directwrite_shaper_font_data_create (hb_font_t *font)
|
||||||
{
|
{
|
||||||
if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return NULL;
|
if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return nullptr;
|
||||||
|
|
||||||
hb_directwrite_shaper_font_data_t *data =
|
hb_directwrite_shaper_font_data_t *data =
|
||||||
(hb_directwrite_shaper_font_data_t *) calloc (1, sizeof (hb_directwrite_shaper_font_data_t));
|
(hb_directwrite_shaper_font_data_t *) malloc (sizeof (hb_directwrite_shaper_font_data_t));
|
||||||
if (unlikely (!data))
|
if (unlikely (!data))
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
data->hdc = GetDC (NULL);
|
|
||||||
|
|
||||||
if (unlikely (!populate_log_font (&data->log_font, font)))
|
|
||||||
{
|
|
||||||
DEBUG_MSG (DIRECTWRITE, font, "Font populate_log_font() failed");
|
|
||||||
_hb_directwrite_shaper_font_data_destroy (data);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->hfont = CreateFontIndirectW (&data->log_font);
|
|
||||||
if (unlikely (!data->hfont))
|
|
||||||
{
|
|
||||||
DEBUG_MSG (DIRECTWRITE, font, "Font CreateFontIndirectW() failed");
|
|
||||||
_hb_directwrite_shaper_font_data_destroy (data);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SelectObject (data->hdc, data->hfont))
|
|
||||||
{
|
|
||||||
DEBUG_MSG (DIRECTWRITE, font, "Font SelectObject() failed");
|
|
||||||
_hb_directwrite_shaper_font_data_destroy (data);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -284,29 +244,9 @@ _hb_directwrite_shaper_font_data_create (hb_font_t *font)
|
|||||||
void
|
void
|
||||||
_hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data)
|
_hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data)
|
||||||
{
|
{
|
||||||
if (data->hdc)
|
|
||||||
ReleaseDC (NULL, data->hdc);
|
|
||||||
if (data->hfont)
|
|
||||||
DeleteObject (data->hfont);
|
|
||||||
free (data);
|
free (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGFONTW *
|
|
||||||
hb_directwrite_font_get_logfontw (hb_font_t *font)
|
|
||||||
{
|
|
||||||
if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL;
|
|
||||||
hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
|
|
||||||
return &font_data->log_font;
|
|
||||||
}
|
|
||||||
|
|
||||||
HFONT
|
|
||||||
hb_directwrite_font_get_hfont (hb_font_t *font)
|
|
||||||
{
|
|
||||||
if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL;
|
|
||||||
hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
|
|
||||||
return font_data->hfont;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* shaper shape_plan data
|
* shaper shape_plan data
|
||||||
@ -316,8 +256,10 @@ struct hb_directwrite_shaper_shape_plan_data_t {};
|
|||||||
|
|
||||||
hb_directwrite_shaper_shape_plan_data_t *
|
hb_directwrite_shaper_shape_plan_data_t *
|
||||||
_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||||
const hb_feature_t *user_features HB_UNUSED,
|
const hb_feature_t *user_features HB_UNUSED,
|
||||||
unsigned int num_user_features HB_UNUSED)
|
unsigned int num_user_features HB_UNUSED,
|
||||||
|
const int *coords HB_UNUSED,
|
||||||
|
unsigned int num_coords HB_UNUSED)
|
||||||
{
|
{
|
||||||
return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||||
}
|
}
|
||||||
@ -327,7 +269,7 @@ _hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Most of here TextAnalysis is originally written by Bas Schouten for Mozilla project
|
// Most of TextAnalysis is originally written by Bas Schouten for Mozilla project
|
||||||
// but now is relicensed to MIT for HarfBuzz use
|
// but now is relicensed to MIT for HarfBuzz use
|
||||||
class TextAnalysis
|
class TextAnalysis
|
||||||
: public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink
|
: public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink
|
||||||
@ -369,7 +311,7 @@ public:
|
|||||||
, mTextLength(textLength)
|
, mTextLength(textLength)
|
||||||
, mLocaleName(localeName)
|
, mLocaleName(localeName)
|
||||||
, mReadingDirection(readingDirection)
|
, mReadingDirection(readingDirection)
|
||||||
, mCurrentRun(NULL) { };
|
, mCurrentRun(nullptr) { };
|
||||||
|
|
||||||
~TextAnalysis() {
|
~TextAnalysis() {
|
||||||
// delete runs, except mRunHead which is part of the TextAnalysis object
|
// delete runs, except mRunHead which is part of the TextAnalysis object
|
||||||
@ -393,7 +335,7 @@ public:
|
|||||||
mRunHead.mTextLength = mTextLength;
|
mRunHead.mTextLength = mTextLength;
|
||||||
mRunHead.mBidiLevel =
|
mRunHead.mBidiLevel =
|
||||||
(mReadingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
|
(mReadingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
|
||||||
mRunHead.nextRun = NULL;
|
mRunHead.nextRun = nullptr;
|
||||||
mCurrentRun = &mRunHead;
|
mCurrentRun = &mRunHead;
|
||||||
|
|
||||||
// Call each of the analyzers in sequence, recording their results.
|
// Call each of the analyzers in sequence, recording their results.
|
||||||
@ -412,7 +354,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (textPosition >= mTextLength) {
|
if (textPosition >= mTextLength) {
|
||||||
// No text at this position, valid query though.
|
// No text at this position, valid query though.
|
||||||
*textString = NULL;
|
*textString = nullptr;
|
||||||
*textLength = 0;
|
*textLength = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -428,8 +370,8 @@ public:
|
|||||||
{
|
{
|
||||||
if (textPosition == 0 || textPosition > mTextLength) {
|
if (textPosition == 0 || textPosition > mTextLength) {
|
||||||
// Either there is no text before here (== 0), or this
|
// Either there is no text before here (== 0), or this
|
||||||
// is an invalid position. The query is considered valid thouh.
|
// is an invalid position. The query is considered valid though.
|
||||||
*textString = NULL;
|
*textString = nullptr;
|
||||||
*textLength = 0;
|
*textLength = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -444,7 +386,8 @@ public:
|
|||||||
|
|
||||||
IFACEMETHODIMP GetLocaleName(uint32_t textPosition,
|
IFACEMETHODIMP GetLocaleName(uint32_t textPosition,
|
||||||
uint32_t* textLength,
|
uint32_t* textLength,
|
||||||
wchar_t const** localeName) {
|
wchar_t const** localeName)
|
||||||
|
{
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,7 +397,7 @@ public:
|
|||||||
OUT IDWriteNumberSubstitution** numberSubstitution)
|
OUT IDWriteNumberSubstitution** numberSubstitution)
|
||||||
{
|
{
|
||||||
// We do not support number substitution.
|
// We do not support number substitution.
|
||||||
*numberSubstitution = NULL;
|
*numberSubstitution = nullptr;
|
||||||
*textLength = mTextLength - textPosition;
|
*textLength = mTextLength - textPosition;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@ -469,7 +412,8 @@ public:
|
|||||||
{
|
{
|
||||||
SetCurrentRun(textPosition);
|
SetCurrentRun(textPosition);
|
||||||
SplitCurrentRun(textPosition);
|
SplitCurrentRun(textPosition);
|
||||||
while (textLength > 0) {
|
while (textLength > 0)
|
||||||
|
{
|
||||||
Run *run = FetchNextRun(&textLength);
|
Run *run = FetchNextRun(&textLength);
|
||||||
run->mScript = *scriptAnalysis;
|
run->mScript = *scriptAnalysis;
|
||||||
}
|
}
|
||||||
@ -502,10 +446,12 @@ protected:
|
|||||||
Run *origRun = mCurrentRun;
|
Run *origRun = mCurrentRun;
|
||||||
// Split the tail if needed (the length remaining is less than the
|
// Split the tail if needed (the length remaining is less than the
|
||||||
// current run's size).
|
// current run's size).
|
||||||
if (*textLength < mCurrentRun->mTextLength) {
|
if (*textLength < mCurrentRun->mTextLength)
|
||||||
SplitCurrentRun(mCurrentRun->mTextStart + *textLength);
|
{
|
||||||
|
SplitCurrentRun (mCurrentRun->mTextStart + *textLength);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// Just advance the current run.
|
// Just advance the current run.
|
||||||
mCurrentRun = mCurrentRun->nextRun;
|
mCurrentRun = mCurrentRun->nextRun;
|
||||||
}
|
}
|
||||||
@ -522,12 +468,14 @@ protected:
|
|||||||
// this will usually just return early. If not, find the
|
// this will usually just return early. If not, find the
|
||||||
// corresponding run for the text position.
|
// corresponding run for the text position.
|
||||||
|
|
||||||
if (mCurrentRun && mCurrentRun->ContainsTextPosition(textPosition)) {
|
if (mCurrentRun && mCurrentRun->ContainsTextPosition (textPosition))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Run *run = &mRunHead; run; run = run->nextRun) {
|
for (Run *run = &mRunHead; run; run = run->nextRun) {
|
||||||
if (run->ContainsTextPosition(textPosition)) {
|
if (run->ContainsTextPosition (textPosition))
|
||||||
|
{
|
||||||
mCurrentRun = run;
|
mCurrentRun = run;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -538,13 +486,15 @@ protected:
|
|||||||
|
|
||||||
void SplitCurrentRun(uint32_t splitPosition)
|
void SplitCurrentRun(uint32_t splitPosition)
|
||||||
{
|
{
|
||||||
if (!mCurrentRun) {
|
if (!mCurrentRun)
|
||||||
|
{
|
||||||
//NS_ASSERTION(false, "SplitCurrentRun called without current run.");
|
//NS_ASSERTION(false, "SplitCurrentRun called without current run.");
|
||||||
// Shouldn't be calling this when no current run is set!
|
// Shouldn't be calling this when no current run is set!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Split the current run.
|
// Split the current run.
|
||||||
if (splitPosition <= mCurrentRun->mTextStart) {
|
if (splitPosition <= mCurrentRun->mTextStart)
|
||||||
|
{
|
||||||
// No need to split, already the start of a run
|
// No need to split, already the start of a run
|
||||||
// or before it. Usually the first.
|
// or before it. Usually the first.
|
||||||
return;
|
return;
|
||||||
@ -590,42 +540,22 @@ static inline uint32_t hb_uint32_swap (const uint32_t v)
|
|||||||
* shaper
|
* shaper
|
||||||
*/
|
*/
|
||||||
|
|
||||||
hb_bool_t
|
static hb_bool_t
|
||||||
_hb_directwrite_shape(hb_shape_plan_t *shape_plan,
|
_hb_directwrite_shape_full(hb_shape_plan_t *shape_plan,
|
||||||
hb_font_t *font,
|
hb_font_t *font,
|
||||||
hb_buffer_t *buffer,
|
hb_buffer_t *buffer,
|
||||||
const hb_feature_t *features,
|
const hb_feature_t *features,
|
||||||
unsigned int num_features)
|
unsigned int num_features,
|
||||||
|
float lineWidth)
|
||||||
{
|
{
|
||||||
hb_face_t *face = font->face;
|
hb_face_t *face = font->face;
|
||||||
hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
|
hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
|
||||||
hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
|
hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
|
||||||
|
IDWriteFactory *dwriteFactory = face_data->dwriteFactory;
|
||||||
|
IDWriteFontFace *fontFace = face_data->fontFace;
|
||||||
|
|
||||||
// factory probably should be cached
|
|
||||||
#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
|
|
||||||
IDWriteFactory* dwriteFactory;
|
|
||||||
#else
|
|
||||||
IDWriteFactory1* dwriteFactory;
|
|
||||||
#endif
|
|
||||||
DWriteCreateFactory (
|
|
||||||
DWRITE_FACTORY_TYPE_SHARED,
|
|
||||||
__uuidof (IDWriteFactory),
|
|
||||||
(IUnknown**) &dwriteFactory
|
|
||||||
);
|
|
||||||
|
|
||||||
IDWriteGdiInterop *gdiInterop;
|
|
||||||
dwriteFactory->GetGdiInterop (&gdiInterop);
|
|
||||||
IDWriteFontFace* fontFace;
|
|
||||||
gdiInterop->CreateFontFaceFromHdc (font_data->hdc, &fontFace);
|
|
||||||
|
|
||||||
#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
|
|
||||||
IDWriteTextAnalyzer* analyzer;
|
IDWriteTextAnalyzer* analyzer;
|
||||||
dwriteFactory->CreateTextAnalyzer(&analyzer);
|
dwriteFactory->CreateTextAnalyzer(&analyzer);
|
||||||
#else
|
|
||||||
IDWriteTextAnalyzer* analyzer0;
|
|
||||||
dwriteFactory->CreateTextAnalyzer (&analyzer0);
|
|
||||||
IDWriteTextAnalyzer1* analyzer = (IDWriteTextAnalyzer1*) analyzer0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned int scratch_size;
|
unsigned int scratch_size;
|
||||||
hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
|
hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
|
||||||
@ -653,7 +583,7 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
|
|||||||
textString[chars_len++] = 0xFFFDu;
|
textString[chars_len++] = 0xFFFDu;
|
||||||
else {
|
else {
|
||||||
textString[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
|
textString[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
|
||||||
textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
|
textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -672,7 +602,6 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
// TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES
|
// TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES
|
||||||
|
|
||||||
DWRITE_READING_DIRECTION readingDirection = buffer->props.direction ?
|
DWRITE_READING_DIRECTION readingDirection = buffer->props.direction ?
|
||||||
@ -686,13 +615,14 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
|
|||||||
*/
|
*/
|
||||||
uint32_t textLength = buffer->len;
|
uint32_t textLength = buffer->len;
|
||||||
|
|
||||||
TextAnalysis analysis(textString, textLength, NULL, readingDirection);
|
TextAnalysis analysis(textString, textLength, nullptr, readingDirection);
|
||||||
TextAnalysis::Run *runHead;
|
TextAnalysis::Run *runHead;
|
||||||
|
HRESULT hr;
|
||||||
hr = analysis.GenerateResults(analyzer, &runHead);
|
hr = analysis.GenerateResults(analyzer, &runHead);
|
||||||
|
|
||||||
#define FAIL(...) \
|
#define FAIL(...) \
|
||||||
HB_STMT_START { \
|
HB_STMT_START { \
|
||||||
DEBUG_MSG (DIRECTWRITE, NULL, __VA_ARGS__); \
|
DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
|
||||||
return false; \
|
return false; \
|
||||||
} HB_STMT_END;
|
} HB_STMT_END;
|
||||||
|
|
||||||
@ -707,7 +637,7 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
|
|||||||
bool isRightToLeft = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
|
bool isRightToLeft = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
|
||||||
|
|
||||||
const wchar_t localeName[20] = {0};
|
const wchar_t localeName[20] = {0};
|
||||||
if (buffer->props.language != NULL)
|
if (buffer->props.language != nullptr)
|
||||||
{
|
{
|
||||||
mbstowcs ((wchar_t*) localeName,
|
mbstowcs ((wchar_t*) localeName,
|
||||||
hb_language_to_string (buffer->props.language), 20);
|
hb_language_to_string (buffer->props.language), 20);
|
||||||
@ -731,24 +661,22 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
|
|||||||
(const DWRITE_TYPOGRAPHIC_FEATURES*) &singleFeatures;
|
(const DWRITE_TYPOGRAPHIC_FEATURES*) &singleFeatures;
|
||||||
const uint32_t featureRangeLengths[] = { textLength };
|
const uint32_t featureRangeLengths[] = { textLength };
|
||||||
|
|
||||||
retry_getglyphs:
|
uint16_t* clusterMap = (uint16_t*) malloc (textLength * sizeof (uint16_t));
|
||||||
uint16_t* clusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
|
|
||||||
uint16_t* glyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
|
|
||||||
DWRITE_SHAPING_TEXT_PROPERTIES* textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*)
|
DWRITE_SHAPING_TEXT_PROPERTIES* textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*)
|
||||||
malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_TEXT_PROPERTIES));
|
malloc (textLength * sizeof (DWRITE_SHAPING_TEXT_PROPERTIES));
|
||||||
|
retry_getglyphs:
|
||||||
|
uint16_t* glyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
|
||||||
DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*)
|
DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*)
|
||||||
malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES));
|
malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES));
|
||||||
|
|
||||||
hr = analyzer->GetGlyphs (textString, textLength, fontFace, FALSE,
|
hr = analyzer->GetGlyphs (textString, textLength, fontFace, false,
|
||||||
isRightToLeft, &runHead->mScript, localeName, NULL, &dwFeatures,
|
isRightToLeft, &runHead->mScript, localeName, nullptr, &dwFeatures,
|
||||||
featureRangeLengths, 1, maxGlyphCount, clusterMap, textProperties, glyphIndices,
|
featureRangeLengths, 1, maxGlyphCount, clusterMap, textProperties, glyphIndices,
|
||||||
glyphProperties, &glyphCount);
|
glyphProperties, &glyphCount);
|
||||||
|
|
||||||
if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
|
if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
|
||||||
{
|
{
|
||||||
free (clusterMap);
|
|
||||||
free (glyphIndices);
|
free (glyphIndices);
|
||||||
free (textProperties);
|
|
||||||
free (glyphProperties);
|
free (glyphProperties);
|
||||||
|
|
||||||
maxGlyphCount *= 2;
|
maxGlyphCount *= 2;
|
||||||
@ -789,7 +717,7 @@ retry_getglyphs:
|
|||||||
hr = analyzer->GetGlyphPlacements (textString,
|
hr = analyzer->GetGlyphPlacements (textString,
|
||||||
clusterMap, textProperties, textLength, glyphIndices,
|
clusterMap, textProperties, textLength, glyphIndices,
|
||||||
glyphProperties, glyphCount, fontFace, fontEmSize,
|
glyphProperties, glyphCount, fontFace, fontEmSize,
|
||||||
FALSE, isRightToLeft, &runHead->mScript, localeName,
|
false, isRightToLeft, &runHead->mScript, localeName,
|
||||||
&dwFeatures, featureRangeLengths, 1,
|
&dwFeatures, featureRangeLengths, 1,
|
||||||
glyphAdvances, glyphOffsets);
|
glyphAdvances, glyphOffsets);
|
||||||
|
|
||||||
@ -799,106 +727,106 @@ retry_getglyphs:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
|
IDWriteTextAnalyzer1* analyzer1;
|
||||||
|
analyzer->QueryInterface (&analyzer1);
|
||||||
|
|
||||||
DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities =
|
if (analyzer1 && lineWidth)
|
||||||
(DWRITE_JUSTIFICATION_OPPORTUNITY*)
|
|
||||||
malloc (maxGlyphCount * sizeof (DWRITE_JUSTIFICATION_OPPORTUNITY));
|
|
||||||
hr = analyzer->GetJustificationOpportunities (fontFace, fontEmSize,
|
|
||||||
runHead->mScript, textLength, glyphCount, textString, clusterMap,
|
|
||||||
glyphProperties, justificationOpportunities);
|
|
||||||
|
|
||||||
if (FAILED (hr))
|
|
||||||
{
|
{
|
||||||
FAIL ("Analyzer failed to get justification opportunities.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: get lineWith from somewhere
|
DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities =
|
||||||
float lineWidth = 60000;
|
(DWRITE_JUSTIFICATION_OPPORTUNITY*)
|
||||||
|
malloc (maxGlyphCount * sizeof (DWRITE_JUSTIFICATION_OPPORTUNITY));
|
||||||
|
hr = analyzer1->GetJustificationOpportunities (fontFace, fontEmSize,
|
||||||
|
runHead->mScript, textLength, glyphCount, textString, clusterMap,
|
||||||
|
glyphProperties, justificationOpportunities);
|
||||||
|
|
||||||
float* justifiedGlyphAdvances =
|
if (FAILED (hr))
|
||||||
(float*) malloc (maxGlyphCount * sizeof (float));
|
{
|
||||||
DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*)
|
FAIL ("Analyzer failed to get justification opportunities.");
|
||||||
malloc (glyphCount * sizeof (DWRITE_GLYPH_OFFSET));
|
return false;
|
||||||
hr = analyzer->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities,
|
}
|
||||||
glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets);
|
|
||||||
|
|
||||||
if (FAILED (hr))
|
float* justifiedGlyphAdvances =
|
||||||
{
|
(float*) malloc (maxGlyphCount * sizeof (float));
|
||||||
FAIL ("Analyzer failed to get justified glyph advances.");
|
DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*)
|
||||||
return false;
|
malloc (glyphCount * sizeof (DWRITE_GLYPH_OFFSET));
|
||||||
}
|
hr = analyzer1->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities,
|
||||||
|
glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets);
|
||||||
|
|
||||||
DWRITE_SCRIPT_PROPERTIES scriptProperties;
|
if (FAILED (hr))
|
||||||
hr = analyzer->GetScriptProperties (runHead->mScript, &scriptProperties);
|
{
|
||||||
if (FAILED (hr))
|
FAIL("Analyzer failed to get justified glyph advances.");
|
||||||
{
|
return false;
|
||||||
FAIL ("Analyzer failed to get script properties.");
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uint32_t justificationCharacter = scriptProperties.justificationCharacter;
|
|
||||||
|
|
||||||
// if a script justificationCharacter is not space, it can have GetJustifiedGlyphs
|
DWRITE_SCRIPT_PROPERTIES scriptProperties;
|
||||||
if (justificationCharacter != 32)
|
hr = analyzer1->GetScriptProperties (runHead->mScript, &scriptProperties);
|
||||||
{
|
if (FAILED (hr))
|
||||||
retry_getjustifiedglyphs:
|
{
|
||||||
uint16_t* modifiedClusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
|
FAIL("Analyzer failed to get script properties.");
|
||||||
uint16_t* modifiedGlyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
|
return false;
|
||||||
float* modifiedGlyphAdvances = (float*) malloc (maxGlyphCount * sizeof (float));
|
}
|
||||||
DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*)
|
uint32_t justificationCharacter = scriptProperties.justificationCharacter;
|
||||||
malloc (maxGlyphCount * sizeof (DWRITE_GLYPH_OFFSET));
|
|
||||||
uint32_t actualGlyphsCount;
|
// if a script justificationCharacter is not space, it can have GetJustifiedGlyphs
|
||||||
hr = analyzer->GetJustifiedGlyphs (fontFace, fontEmSize, runHead->mScript,
|
if (justificationCharacter != 32)
|
||||||
|
{
|
||||||
|
uint16_t* modifiedClusterMap = (uint16_t*) malloc (textLength * sizeof (uint16_t));
|
||||||
|
retry_getjustifiedglyphs:
|
||||||
|
uint16_t* modifiedGlyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
|
||||||
|
float* modifiedGlyphAdvances = (float*) malloc (maxGlyphCount * sizeof (float));
|
||||||
|
DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*)
|
||||||
|
malloc (maxGlyphCount * sizeof (DWRITE_GLYPH_OFFSET));
|
||||||
|
uint32_t actualGlyphsCount;
|
||||||
|
hr = analyzer1->GetJustifiedGlyphs (fontFace, fontEmSize, runHead->mScript,
|
||||||
textLength, glyphCount, maxGlyphCount, clusterMap, glyphIndices,
|
textLength, glyphCount, maxGlyphCount, clusterMap, glyphIndices,
|
||||||
glyphAdvances, justifiedGlyphAdvances, justifiedGlyphOffsets,
|
glyphAdvances, justifiedGlyphAdvances, justifiedGlyphOffsets,
|
||||||
glyphProperties, &actualGlyphsCount, modifiedClusterMap, modifiedGlyphIndices,
|
glyphProperties, &actualGlyphsCount, modifiedClusterMap, modifiedGlyphIndices,
|
||||||
modifiedGlyphAdvances, modifiedGlyphOffsets);
|
modifiedGlyphAdvances, modifiedGlyphOffsets);
|
||||||
|
|
||||||
if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))
|
if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))
|
||||||
{
|
{
|
||||||
maxGlyphCount = actualGlyphsCount;
|
maxGlyphCount = actualGlyphsCount;
|
||||||
free (modifiedClusterMap);
|
free (modifiedGlyphIndices);
|
||||||
free (modifiedGlyphIndices);
|
free (modifiedGlyphAdvances);
|
||||||
free (modifiedGlyphAdvances);
|
free (modifiedGlyphOffsets);
|
||||||
free (modifiedGlyphOffsets);
|
|
||||||
|
|
||||||
maxGlyphCount = actualGlyphsCount;
|
maxGlyphCount = actualGlyphsCount;
|
||||||
|
|
||||||
goto retry_getjustifiedglyphs;
|
goto retry_getjustifiedglyphs;
|
||||||
|
}
|
||||||
|
if (FAILED (hr))
|
||||||
|
{
|
||||||
|
FAIL ("Analyzer failed to get justified glyphs.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
free (clusterMap);
|
||||||
|
free (glyphIndices);
|
||||||
|
free (glyphAdvances);
|
||||||
|
free (glyphOffsets);
|
||||||
|
|
||||||
|
glyphCount = actualGlyphsCount;
|
||||||
|
clusterMap = modifiedClusterMap;
|
||||||
|
glyphIndices = modifiedGlyphIndices;
|
||||||
|
glyphAdvances = modifiedGlyphAdvances;
|
||||||
|
glyphOffsets = modifiedGlyphOffsets;
|
||||||
|
|
||||||
|
free (justifiedGlyphAdvances);
|
||||||
|
free (justifiedGlyphOffsets);
|
||||||
}
|
}
|
||||||
if (FAILED (hr))
|
else
|
||||||
{
|
{
|
||||||
FAIL ("Analyzer failed to get justified glyphs.");
|
free (glyphAdvances);
|
||||||
return false;
|
free (glyphOffsets);
|
||||||
|
|
||||||
|
glyphAdvances = justifiedGlyphAdvances;
|
||||||
|
glyphOffsets = justifiedGlyphOffsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
free (clusterMap);
|
free (justificationOpportunities);
|
||||||
free (glyphIndices);
|
|
||||||
free (glyphAdvances);
|
|
||||||
free (glyphOffsets);
|
|
||||||
|
|
||||||
glyphCount = actualGlyphsCount;
|
|
||||||
clusterMap = modifiedClusterMap;
|
|
||||||
glyphIndices = modifiedGlyphIndices;
|
|
||||||
glyphAdvances = modifiedGlyphAdvances;
|
|
||||||
glyphOffsets = modifiedGlyphOffsets;
|
|
||||||
|
|
||||||
free(justifiedGlyphAdvances);
|
|
||||||
free(justifiedGlyphOffsets);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
free(glyphAdvances);
|
|
||||||
free(glyphOffsets);
|
|
||||||
|
|
||||||
glyphAdvances = justifiedGlyphAdvances;
|
|
||||||
glyphOffsets = justifiedGlyphOffsets;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(justificationOpportunities);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Ok, we've got everything we need, now compose output buffer,
|
/* Ok, we've got everything we need, now compose output buffer,
|
||||||
* very, *very*, carefully! */
|
* very, *very*, carefully! */
|
||||||
@ -968,3 +896,36 @@ retry_getjustifiedglyphs:
|
|||||||
/* Wow, done! */
|
/* Wow, done! */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
_hb_directwrite_shape(hb_shape_plan_t *shape_plan,
|
||||||
|
hb_font_t *font,
|
||||||
|
hb_buffer_t *buffer,
|
||||||
|
const hb_feature_t *features,
|
||||||
|
unsigned int num_features)
|
||||||
|
{
|
||||||
|
return _hb_directwrite_shape_full(shape_plan, font, buffer,
|
||||||
|
features, num_features, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public [experimental] API
|
||||||
|
*/
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_directwrite_shape_experimental_width(hb_font_t *font,
|
||||||
|
hb_buffer_t *buffer,
|
||||||
|
const hb_feature_t *features,
|
||||||
|
unsigned int num_features,
|
||||||
|
float width)
|
||||||
|
{
|
||||||
|
static char *shapers = "directwrite";
|
||||||
|
hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face,
|
||||||
|
&buffer->props, features, num_features, &shapers);
|
||||||
|
hb_bool_t res = _hb_directwrite_shape_full (shape_plan, font, buffer,
|
||||||
|
features, num_features, width);
|
||||||
|
|
||||||
|
buffer->unsafe_to_break_all ();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
@ -29,6 +29,10 @@
|
|||||||
|
|
||||||
HB_BEGIN_DECLS
|
HB_BEGIN_DECLS
|
||||||
|
|
||||||
|
HB_EXTERN hb_bool_t
|
||||||
|
hb_directwrite_shape_experimental_width(hb_font_t *font, hb_buffer_t *buffer,
|
||||||
|
const hb_feature_t *features, unsigned int num_features, float width);
|
||||||
|
|
||||||
HB_END_DECLS
|
HB_END_DECLS
|
||||||
|
|
||||||
#endif /* HB_UNISCRIBE_H */
|
#endif /* HB_DIRECTWRITE_H */
|
||||||
|
161
src/hb-dsalgs.hh
Normal file
161
src/hb-dsalgs.hh
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2017 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_DSALGS_HH
|
||||||
|
#define HB_DSALGS_HH
|
||||||
|
|
||||||
|
#include "hb-private.hh"
|
||||||
|
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
hb_bsearch_r (const void *key, const void *base,
|
||||||
|
size_t nmemb, size_t size,
|
||||||
|
int (*compar)(const void *_key, const void *_item, void *_arg),
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
int min = 0, max = (int) nmemb - 1;
|
||||||
|
while (min <= max)
|
||||||
|
{
|
||||||
|
int mid = (min + max) / 2;
|
||||||
|
const void *p = (const void *) (((const char *) base) + (mid * size));
|
||||||
|
int c = compar (key, p, arg);
|
||||||
|
if (c < 0)
|
||||||
|
max = mid - 1;
|
||||||
|
else if (c > 0)
|
||||||
|
min = mid + 1;
|
||||||
|
else
|
||||||
|
return (void *) p;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* From https://github.com/noporpoise/sort_r */
|
||||||
|
|
||||||
|
/* Isaac Turner 29 April 2014 Public Domain */
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
hb_sort_r function to be exported.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
base is the array to be sorted
|
||||||
|
nel is the number of elements in the array
|
||||||
|
width is the size in bytes of each element of the array
|
||||||
|
compar is the comparison function
|
||||||
|
arg is a pointer to be passed to the comparison function
|
||||||
|
|
||||||
|
void hb_sort_r(void *base, size_t nel, size_t width,
|
||||||
|
int (*compar)(const void *_a, const void *_b, void *_arg),
|
||||||
|
void *arg);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* swap a, b iff a>b */
|
||||||
|
/* __restrict is same as restrict but better support on old machines */
|
||||||
|
static int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w,
|
||||||
|
int (*compar)(const void *_a, const void *_b,
|
||||||
|
void *_arg),
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
char tmp, *end = a+w;
|
||||||
|
if(compar(a, b, arg) > 0) {
|
||||||
|
for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; }
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: quicksort is not stable, equivalent values may be swapped */
|
||||||
|
static inline void sort_r_simple(void *base, size_t nel, size_t w,
|
||||||
|
int (*compar)(const void *_a, const void *_b,
|
||||||
|
void *_arg),
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
char *b = (char *)base, *end = b + nel*w;
|
||||||
|
if(nel < 7) {
|
||||||
|
/* Insertion sort for arbitrarily small inputs */
|
||||||
|
char *pi, *pj;
|
||||||
|
for(pi = b+w; pi < end; pi += w) {
|
||||||
|
for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* nel > 6; Quicksort */
|
||||||
|
|
||||||
|
/* Use median of first, middle and last items as pivot */
|
||||||
|
char *x, *y, *xend, ch;
|
||||||
|
char *pl, *pr;
|
||||||
|
char *last = b+w*(nel-1), *tmp;
|
||||||
|
char *l[3];
|
||||||
|
l[0] = b;
|
||||||
|
l[1] = b+w*(nel/2);
|
||||||
|
l[2] = last;
|
||||||
|
|
||||||
|
if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
|
||||||
|
if(compar(l[1],l[2],arg) > 0) {
|
||||||
|
tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */
|
||||||
|
if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* swap l[id], l[2] to put pivot as last element */
|
||||||
|
for(x = l[1], y = last, xend = x+w; x<xend; x++, y++) {
|
||||||
|
ch = *x; *x = *y; *y = ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl = b;
|
||||||
|
pr = last;
|
||||||
|
|
||||||
|
while(pl < pr) {
|
||||||
|
for(; pl < pr; pl += w) {
|
||||||
|
if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
|
||||||
|
pr -= w; /* pivot now at pl */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(; pl < pr; pr -= w) {
|
||||||
|
if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
|
||||||
|
pl += w; /* pivot now at pr */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_r_simple(b, (pl-b)/w, w, compar, arg);
|
||||||
|
sort_r_simple(pl+w, (end-(pl+w))/w, w, compar, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void hb_sort_r(void *base, size_t nel, size_t width,
|
||||||
|
int (*compar)(const void *_a, const void *_b, void *_arg),
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
sort_r_simple(base, nel, width, compar, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HB_DSALGS_HH */
|
@ -50,12 +50,16 @@ struct hb_face_t {
|
|||||||
void *user_data;
|
void *user_data;
|
||||||
hb_destroy_func_t destroy;
|
hb_destroy_func_t destroy;
|
||||||
|
|
||||||
unsigned int index;
|
unsigned int index; /* Face index in a collection, zero-based. */
|
||||||
mutable unsigned int upem;
|
mutable unsigned int upem; /* Units-per-EM. */
|
||||||
mutable unsigned int num_glyphs;
|
mutable unsigned int num_glyphs; /* Number of glyphs. */
|
||||||
|
|
||||||
struct hb_shaper_data_t shaper_data;
|
struct hb_shaper_data_t shaper_data; /* Various shaper data. */
|
||||||
|
|
||||||
|
/* Various non-shaping data. */
|
||||||
|
/* ... */
|
||||||
|
|
||||||
|
/* Cache */
|
||||||
struct plan_node_t {
|
struct plan_node_t {
|
||||||
hb_shape_plan_t *shape_plan;
|
hb_shape_plan_t *shape_plan;
|
||||||
plan_node_t *next;
|
plan_node_t *next;
|
||||||
|
@ -28,17 +28,11 @@
|
|||||||
|
|
||||||
#include "hb-private.hh"
|
#include "hb-private.hh"
|
||||||
|
|
||||||
#include "hb-ot-layout-private.hh"
|
#include "hb-face-private.hh"
|
||||||
|
|
||||||
#include "hb-font-private.hh"
|
|
||||||
#include "hb-open-file-private.hh"
|
#include "hb-open-file-private.hh"
|
||||||
#include "hb-ot-head-table.hh"
|
#include "hb-ot-head-table.hh"
|
||||||
#include "hb-ot-maxp-table.hh"
|
#include "hb-ot-maxp-table.hh"
|
||||||
|
|
||||||
#include "hb-cache-private.hh"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* hb_face_t
|
* hb_face_t
|
||||||
@ -49,9 +43,9 @@ const hb_face_t _hb_face_nil = {
|
|||||||
|
|
||||||
true, /* immutable */
|
true, /* immutable */
|
||||||
|
|
||||||
NULL, /* reference_table_func */
|
nullptr, /* reference_table_func */
|
||||||
NULL, /* user_data */
|
nullptr, /* user_data */
|
||||||
NULL, /* destroy */
|
nullptr, /* destroy */
|
||||||
|
|
||||||
0, /* index */
|
0, /* index */
|
||||||
1000, /* upem */
|
1000, /* upem */
|
||||||
@ -63,7 +57,7 @@ const hb_face_t _hb_face_nil = {
|
|||||||
#undef HB_SHAPER_IMPLEMENT
|
#undef HB_SHAPER_IMPLEMENT
|
||||||
},
|
},
|
||||||
|
|
||||||
NULL, /* shape_plans */
|
nullptr, /* shape_plans */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -115,7 +109,7 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
|
|||||||
|
|
||||||
closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t));
|
closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t));
|
||||||
if (unlikely (!closure))
|
if (unlikely (!closure))
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
closure->blob = blob;
|
closure->blob = blob;
|
||||||
closure->index = index;
|
closure->index = index;
|
||||||
@ -124,8 +118,10 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
|
_hb_face_for_data_closure_destroy (void *data)
|
||||||
{
|
{
|
||||||
|
hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
|
||||||
|
|
||||||
hb_blob_destroy (closure->blob);
|
hb_blob_destroy (closure->blob);
|
||||||
free (closure);
|
free (closure);
|
||||||
}
|
}
|
||||||
@ -168,16 +164,16 @@ hb_face_create (hb_blob_t *blob,
|
|||||||
if (unlikely (!blob))
|
if (unlikely (!blob))
|
||||||
blob = hb_blob_get_empty ();
|
blob = hb_blob_get_empty ();
|
||||||
|
|
||||||
hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
|
hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>().sanitize (hb_blob_reference (blob)), index);
|
||||||
|
|
||||||
if (unlikely (!closure))
|
if (unlikely (!closure))
|
||||||
return hb_face_get_empty ();
|
return hb_face_get_empty ();
|
||||||
|
|
||||||
face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
|
face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
|
||||||
closure,
|
closure,
|
||||||
(hb_destroy_func_t) _hb_face_for_data_closure_destroy);
|
_hb_face_for_data_closure_destroy);
|
||||||
|
|
||||||
hb_face_set_index (face, index);
|
face->index = index;
|
||||||
|
|
||||||
return face;
|
return face;
|
||||||
}
|
}
|
||||||
@ -428,7 +424,7 @@ hb_face_get_upem (hb_face_t *face)
|
|||||||
void
|
void
|
||||||
hb_face_t::load_upem (void) const
|
hb_face_t::load_upem (void) const
|
||||||
{
|
{
|
||||||
hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (reference_table (HB_OT_TAG_head));
|
hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (reference_table (HB_OT_TAG_head));
|
||||||
const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob);
|
const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob);
|
||||||
upem = head_table->get_upem ();
|
upem = head_table->get_upem ();
|
||||||
hb_blob_destroy (head_blob);
|
hb_blob_destroy (head_blob);
|
||||||
@ -472,10 +468,39 @@ hb_face_get_glyph_count (hb_face_t *face)
|
|||||||
void
|
void
|
||||||
hb_face_t::load_num_glyphs (void) const
|
hb_face_t::load_num_glyphs (void) const
|
||||||
{
|
{
|
||||||
hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>::sanitize (reference_table (HB_OT_TAG_maxp));
|
hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (reference_table (HB_OT_TAG_maxp));
|
||||||
const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob);
|
const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob);
|
||||||
num_glyphs = maxp_table->get_num_glyphs ();
|
num_glyphs = maxp_table->get_num_glyphs ();
|
||||||
hb_blob_destroy (maxp_blob);
|
hb_blob_destroy (maxp_blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_face_get_table_tags:
|
||||||
|
* @face: a face.
|
||||||
|
*
|
||||||
|
* Retrieves table tags for a face, if possible.
|
||||||
|
*
|
||||||
|
* Return value: total number of tables, or 0 if not possible to list.
|
||||||
|
*
|
||||||
|
* Since: 1.6.0
|
||||||
|
**/
|
||||||
|
unsigned int
|
||||||
|
hb_face_get_table_tags (hb_face_t *face,
|
||||||
|
unsigned int start_offset,
|
||||||
|
unsigned int *table_count, /* IN/OUT */
|
||||||
|
hb_tag_t *table_tags /* OUT */)
|
||||||
|
{
|
||||||
|
if (face->destroy != _hb_face_for_data_closure_destroy)
|
||||||
|
{
|
||||||
|
if (table_count)
|
||||||
|
*table_count = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
|
||||||
|
|
||||||
|
const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob);
|
||||||
|
const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
|
||||||
|
|
||||||
|
return ot_face.get_table_tags (start_offset, table_count, table_tags);
|
||||||
|
}
|
||||||
|
@ -71,7 +71,6 @@ hb_face_set_user_data (hb_face_t *face,
|
|||||||
hb_destroy_func_t destroy,
|
hb_destroy_func_t destroy,
|
||||||
hb_bool_t replace);
|
hb_bool_t replace);
|
||||||
|
|
||||||
|
|
||||||
HB_EXTERN void *
|
HB_EXTERN void *
|
||||||
hb_face_get_user_data (hb_face_t *face,
|
hb_face_get_user_data (hb_face_t *face,
|
||||||
hb_user_data_key_t *key);
|
hb_user_data_key_t *key);
|
||||||
@ -111,6 +110,11 @@ hb_face_set_glyph_count (hb_face_t *face,
|
|||||||
HB_EXTERN unsigned int
|
HB_EXTERN unsigned int
|
||||||
hb_face_get_glyph_count (hb_face_t *face);
|
hb_face_get_glyph_count (hb_face_t *face);
|
||||||
|
|
||||||
|
HB_EXTERN unsigned int
|
||||||
|
hb_face_get_table_tags (hb_face_t *face,
|
||||||
|
unsigned int start_offset,
|
||||||
|
unsigned int *table_count, /* IN/OUT */
|
||||||
|
hb_tag_t *table_tags /* OUT */);
|
||||||
|
|
||||||
HB_END_DECLS
|
HB_END_DECLS
|
||||||
|
|
||||||
|
@ -28,6 +28,10 @@
|
|||||||
#include "hb-shaper-impl-private.hh"
|
#include "hb-shaper-impl-private.hh"
|
||||||
|
|
||||||
|
|
||||||
|
HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face)
|
||||||
|
HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* shaper face data
|
* shaper face data
|
||||||
*/
|
*/
|
||||||
@ -73,7 +77,9 @@ struct hb_fallback_shaper_shape_plan_data_t {};
|
|||||||
hb_fallback_shaper_shape_plan_data_t *
|
hb_fallback_shaper_shape_plan_data_t *
|
||||||
_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||||
const hb_feature_t *user_features HB_UNUSED,
|
const hb_feature_t *user_features HB_UNUSED,
|
||||||
unsigned int num_user_features HB_UNUSED)
|
unsigned int num_user_features HB_UNUSED,
|
||||||
|
const int *coords HB_UNUSED,
|
||||||
|
unsigned int num_coords HB_UNUSED)
|
||||||
{
|
{
|
||||||
return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||||
}
|
}
|
||||||
@ -123,7 +129,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
|
|||||||
pos[i].y_advance = 0;
|
pos[i].y_advance = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint);
|
(void) font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint);
|
||||||
font->get_glyph_advance_for_direction (info[i].codepoint,
|
font->get_glyph_advance_for_direction (info[i].codepoint,
|
||||||
direction,
|
direction,
|
||||||
&pos[i].x_advance,
|
&pos[i].x_advance,
|
||||||
@ -137,5 +143,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
|
|||||||
if (HB_DIRECTION_IS_BACKWARD (direction))
|
if (HB_DIRECTION_IS_BACKWARD (direction))
|
||||||
hb_buffer_reverse (buffer);
|
hb_buffer_reverse (buffer);
|
||||||
|
|
||||||
|
buffer->safe_to_break_all ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,12 @@ struct hb_font_t {
|
|||||||
unsigned int x_ppem;
|
unsigned int x_ppem;
|
||||||
unsigned int y_ppem;
|
unsigned int y_ppem;
|
||||||
|
|
||||||
|
float ptem;
|
||||||
|
|
||||||
|
/* Font variation coordinates. */
|
||||||
|
unsigned int num_coords;
|
||||||
|
int *coords;
|
||||||
|
|
||||||
hb_font_funcs_t *klass;
|
hb_font_funcs_t *klass;
|
||||||
void *user_data;
|
void *user_data;
|
||||||
hb_destroy_func_t destroy;
|
hb_destroy_func_t destroy;
|
||||||
@ -116,8 +122,16 @@ struct hb_font_t {
|
|||||||
|
|
||||||
|
|
||||||
/* Convert from font-space to user-space */
|
/* Convert from font-space to user-space */
|
||||||
inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
|
inline int dir_scale (hb_direction_t direction)
|
||||||
inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
|
{ return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
|
||||||
|
inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
|
||||||
|
inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
|
||||||
|
inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
|
||||||
|
inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
|
||||||
|
inline float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
|
||||||
|
inline float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
|
||||||
|
inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
|
||||||
|
{ return em_scale (v, dir_scale (direction)); }
|
||||||
|
|
||||||
/* Convert from parent-font user-space to our user-space */
|
/* Convert from parent-font user-space to our user-space */
|
||||||
inline hb_position_t parent_scale_x_distance (hb_position_t v) {
|
inline hb_position_t parent_scale_x_distance (hb_position_t v) {
|
||||||
@ -292,24 +306,32 @@ struct hb_font_t {
|
|||||||
|
|
||||||
/* A bit higher-level, and with fallback */
|
/* A bit higher-level, and with fallback */
|
||||||
|
|
||||||
|
inline void get_h_extents_with_fallback (hb_font_extents_t *extents)
|
||||||
|
{
|
||||||
|
if (!get_font_h_extents (extents))
|
||||||
|
{
|
||||||
|
extents->ascender = y_scale * .8;
|
||||||
|
extents->descender = extents->ascender - y_scale;
|
||||||
|
extents->line_gap = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void get_v_extents_with_fallback (hb_font_extents_t *extents)
|
||||||
|
{
|
||||||
|
if (!get_font_v_extents (extents))
|
||||||
|
{
|
||||||
|
extents->ascender = x_scale / 2;
|
||||||
|
extents->descender = extents->ascender - x_scale;
|
||||||
|
extents->line_gap = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void get_extents_for_direction (hb_direction_t direction,
|
inline void get_extents_for_direction (hb_direction_t direction,
|
||||||
hb_font_extents_t *extents)
|
hb_font_extents_t *extents)
|
||||||
{
|
{
|
||||||
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
|
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
|
||||||
if (!get_font_h_extents (extents))
|
get_h_extents_with_fallback (extents);
|
||||||
{
|
else
|
||||||
extents->ascender = y_scale * .8;
|
get_v_extents_with_fallback (extents);
|
||||||
extents->descender = y_scale - extents->ascender;
|
|
||||||
extents->line_gap = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!get_font_v_extents (extents))
|
|
||||||
{
|
|
||||||
extents->ascender = x_scale / 2;
|
|
||||||
extents->descender = x_scale - extents->ascender;
|
|
||||||
extents->line_gap = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
|
inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
|
||||||
@ -325,14 +347,38 @@ struct hb_font_t {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal only */
|
|
||||||
inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
|
inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
|
||||||
hb_position_t *x, hb_position_t *y)
|
hb_position_t *x, hb_position_t *y)
|
||||||
{
|
{
|
||||||
*x = get_glyph_h_advance (glyph) / 2;
|
*x = get_glyph_h_advance (glyph) / 2;
|
||||||
|
|
||||||
/* TODO use font_extents.ascender */
|
/* TODO cache this somehow?! */
|
||||||
*y = y_scale;
|
hb_font_extents_t extents;
|
||||||
|
get_h_extents_with_fallback (&extents);
|
||||||
|
*y = extents.ascender;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
|
||||||
|
hb_position_t *x, hb_position_t *y)
|
||||||
|
{
|
||||||
|
if (!get_glyph_h_origin (glyph, x, y) &&
|
||||||
|
get_glyph_v_origin (glyph, x, y))
|
||||||
|
{
|
||||||
|
hb_position_t dx, dy;
|
||||||
|
guess_v_origin_minus_h_origin (glyph, &dx, &dy);
|
||||||
|
*x -= dx; *y -= dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
|
||||||
|
hb_position_t *x, hb_position_t *y)
|
||||||
|
{
|
||||||
|
if (!get_glyph_v_origin (glyph, x, y) &&
|
||||||
|
get_glyph_h_origin (glyph, x, y))
|
||||||
|
{
|
||||||
|
hb_position_t dx, dy;
|
||||||
|
guess_v_origin_minus_h_origin (glyph, &dx, &dy);
|
||||||
|
*x += dx; *y += dy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
|
inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
|
||||||
@ -340,25 +386,9 @@ struct hb_font_t {
|
|||||||
hb_position_t *x, hb_position_t *y)
|
hb_position_t *x, hb_position_t *y)
|
||||||
{
|
{
|
||||||
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
|
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
|
||||||
{
|
get_glyph_h_origin_with_fallback (glyph, x, y);
|
||||||
if (!get_glyph_h_origin (glyph, x, y) &&
|
|
||||||
get_glyph_v_origin (glyph, x, y))
|
|
||||||
{
|
|
||||||
hb_position_t dx, dy;
|
|
||||||
guess_v_origin_minus_h_origin (glyph, &dx, &dy);
|
|
||||||
*x -= dx; *y -= dy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
get_glyph_v_origin_with_fallback (glyph, x, y);
|
||||||
if (!get_glyph_v_origin (glyph, x, y) &&
|
|
||||||
get_glyph_h_origin (glyph, x, y))
|
|
||||||
{
|
|
||||||
hb_position_t dx, dy;
|
|
||||||
guess_v_origin_minus_h_origin (glyph, &dx, &dy);
|
|
||||||
*x += dx; *y += dy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void add_glyph_h_origin (hb_codepoint_t glyph,
|
inline void add_glyph_h_origin (hb_codepoint_t glyph,
|
||||||
@ -366,7 +396,7 @@ struct hb_font_t {
|
|||||||
{
|
{
|
||||||
hb_position_t origin_x, origin_y;
|
hb_position_t origin_x, origin_y;
|
||||||
|
|
||||||
get_glyph_h_origin (glyph, &origin_x, &origin_y);
|
get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
|
||||||
|
|
||||||
*x += origin_x;
|
*x += origin_x;
|
||||||
*y += origin_y;
|
*y += origin_y;
|
||||||
@ -376,7 +406,7 @@ struct hb_font_t {
|
|||||||
{
|
{
|
||||||
hb_position_t origin_x, origin_y;
|
hb_position_t origin_x, origin_y;
|
||||||
|
|
||||||
get_glyph_v_origin (glyph, &origin_x, &origin_y);
|
get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
|
||||||
|
|
||||||
*x += origin_x;
|
*x += origin_x;
|
||||||
*y += origin_y;
|
*y += origin_y;
|
||||||
@ -398,7 +428,7 @@ struct hb_font_t {
|
|||||||
{
|
{
|
||||||
hb_position_t origin_x, origin_y;
|
hb_position_t origin_x, origin_y;
|
||||||
|
|
||||||
get_glyph_h_origin (glyph, &origin_x, &origin_y);
|
get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
|
||||||
|
|
||||||
*x -= origin_x;
|
*x -= origin_x;
|
||||||
*y -= origin_y;
|
*y -= origin_y;
|
||||||
@ -408,7 +438,7 @@ struct hb_font_t {
|
|||||||
{
|
{
|
||||||
hb_position_t origin_x, origin_y;
|
hb_position_t origin_x, origin_y;
|
||||||
|
|
||||||
get_glyph_v_origin (glyph, &origin_x, &origin_y);
|
get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
|
||||||
|
|
||||||
*x -= origin_x;
|
*x -= origin_x;
|
||||||
*y -= origin_y;
|
*y -= origin_y;
|
||||||
@ -504,7 +534,6 @@ struct hb_font_t {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
inline hb_position_t em_scale (int16_t v, int scale)
|
inline hb_position_t em_scale (int16_t v, int scale)
|
||||||
{
|
{
|
||||||
int upem = face->get_upem ();
|
int upem = face->get_upem ();
|
||||||
@ -512,6 +541,14 @@ struct hb_font_t {
|
|||||||
scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
|
scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
|
||||||
return (hb_position_t) (scaled / upem);
|
return (hb_position_t) (scaled / upem);
|
||||||
}
|
}
|
||||||
|
inline hb_position_t em_scalef (float v, int scale)
|
||||||
|
{
|
||||||
|
return (hb_position_t) round (v * scale / face->get_upem ());
|
||||||
|
}
|
||||||
|
inline float em_fscale (int16_t v, int scale)
|
||||||
|
{
|
||||||
|
return (float) v * scale / face->get_upem ();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
|
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
|
||||||
|
221
src/hb-font.cc
221
src/hb-font.cc
@ -28,16 +28,7 @@
|
|||||||
|
|
||||||
#include "hb-private.hh"
|
#include "hb-private.hh"
|
||||||
|
|
||||||
#include "hb-ot-layout-private.hh"
|
|
||||||
|
|
||||||
#include "hb-font-private.hh"
|
#include "hb-font-private.hh"
|
||||||
#include "hb-open-file-private.hh"
|
|
||||||
#include "hb-ot-head-table.hh"
|
|
||||||
#include "hb-ot-maxp-table.hh"
|
|
||||||
|
|
||||||
#include "hb-cache-private.hh"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -45,7 +36,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static hb_bool_t
|
static hb_bool_t
|
||||||
hb_font_get_font_h_extents_nil (hb_font_t *font,
|
hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED,
|
||||||
void *font_data HB_UNUSED,
|
void *font_data HB_UNUSED,
|
||||||
hb_font_extents_t *metrics,
|
hb_font_extents_t *metrics,
|
||||||
void *user_data HB_UNUSED)
|
void *user_data HB_UNUSED)
|
||||||
@ -69,7 +60,7 @@ hb_font_get_font_h_extents_parent (hb_font_t *font,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static hb_bool_t
|
static hb_bool_t
|
||||||
hb_font_get_font_v_extents_nil (hb_font_t *font,
|
hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED,
|
||||||
void *font_data HB_UNUSED,
|
void *font_data HB_UNUSED,
|
||||||
hb_font_extents_t *metrics,
|
hb_font_extents_t *metrics,
|
||||||
void *user_data HB_UNUSED)
|
void *user_data HB_UNUSED)
|
||||||
@ -356,12 +347,12 @@ static const hb_font_funcs_t _hb_font_funcs_nil = {
|
|||||||
true, /* immutable */
|
true, /* immutable */
|
||||||
|
|
||||||
{
|
{
|
||||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
|
||||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
#undef HB_FONT_FUNC_IMPLEMENT
|
#undef HB_FONT_FUNC_IMPLEMENT
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
|
||||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
#undef HB_FONT_FUNC_IMPLEMENT
|
#undef HB_FONT_FUNC_IMPLEMENT
|
||||||
},
|
},
|
||||||
@ -379,12 +370,12 @@ static const hb_font_funcs_t _hb_font_funcs_parent = {
|
|||||||
true, /* immutable */
|
true, /* immutable */
|
||||||
|
|
||||||
{
|
{
|
||||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
|
||||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
#undef HB_FONT_FUNC_IMPLEMENT
|
#undef HB_FONT_FUNC_IMPLEMENT
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
|
||||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
#undef HB_FONT_FUNC_IMPLEMENT
|
#undef HB_FONT_FUNC_IMPLEMENT
|
||||||
},
|
},
|
||||||
@ -572,8 +563,8 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
|
|||||||
ffuncs->destroy.name = destroy; \
|
ffuncs->destroy.name = destroy; \
|
||||||
} else { \
|
} else { \
|
||||||
ffuncs->get.f.name = hb_font_get_##name##_parent; \
|
ffuncs->get.f.name = hb_font_get_##name##_parent; \
|
||||||
ffuncs->user_data.name = NULL; \
|
ffuncs->user_data.name = nullptr; \
|
||||||
ffuncs->destroy.name = NULL; \
|
ffuncs->destroy.name = nullptr; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1166,6 +1157,20 @@ hb_font_create_sub_font (hb_font_t *parent)
|
|||||||
font->y_scale = parent->y_scale;
|
font->y_scale = parent->y_scale;
|
||||||
font->x_ppem = parent->x_ppem;
|
font->x_ppem = parent->x_ppem;
|
||||||
font->y_ppem = parent->y_ppem;
|
font->y_ppem = parent->y_ppem;
|
||||||
|
font->ptem = parent->ptem;
|
||||||
|
|
||||||
|
font->num_coords = parent->num_coords;
|
||||||
|
if (!font->num_coords)
|
||||||
|
font->coords = nullptr;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int size = parent->num_coords * sizeof (parent->coords[0]);
|
||||||
|
font->coords = (int *) malloc (size);
|
||||||
|
if (unlikely (!font->coords))
|
||||||
|
font->num_coords = 0;
|
||||||
|
else
|
||||||
|
memcpy (font->coords, parent->coords, size);
|
||||||
|
}
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
@ -1187,7 +1192,7 @@ hb_font_get_empty (void)
|
|||||||
|
|
||||||
true, /* immutable */
|
true, /* immutable */
|
||||||
|
|
||||||
NULL, /* parent */
|
nullptr, /* parent */
|
||||||
const_cast<hb_face_t *> (&_hb_face_nil),
|
const_cast<hb_face_t *> (&_hb_face_nil),
|
||||||
|
|
||||||
1000, /* x_scale */
|
1000, /* x_scale */
|
||||||
@ -1195,10 +1200,14 @@ hb_font_get_empty (void)
|
|||||||
|
|
||||||
0, /* x_ppem */
|
0, /* x_ppem */
|
||||||
0, /* y_ppem */
|
0, /* y_ppem */
|
||||||
|
0, /* ptem */
|
||||||
|
|
||||||
|
0, /* num_coords */
|
||||||
|
nullptr, /* coords */
|
||||||
|
|
||||||
const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
|
const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
|
||||||
NULL, /* user_data */
|
nullptr, /* user_data */
|
||||||
NULL, /* destroy */
|
nullptr, /* destroy */
|
||||||
|
|
||||||
{
|
{
|
||||||
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
|
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
|
||||||
@ -1250,6 +1259,8 @@ hb_font_destroy (hb_font_t *font)
|
|||||||
hb_face_destroy (font->face);
|
hb_face_destroy (font->face);
|
||||||
hb_font_funcs_destroy (font->klass);
|
hb_font_funcs_destroy (font->klass);
|
||||||
|
|
||||||
|
free (font->coords);
|
||||||
|
|
||||||
free (font);
|
free (font);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1373,6 +1384,32 @@ hb_font_get_parent (hb_font_t *font)
|
|||||||
return font->parent;
|
return font->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_font_set_face:
|
||||||
|
* @font: a font.
|
||||||
|
* @face: new face.
|
||||||
|
*
|
||||||
|
* Sets font-face of @font.
|
||||||
|
*
|
||||||
|
* Since: 1.4.3
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
hb_font_set_face (hb_font_t *font,
|
||||||
|
hb_face_t *face)
|
||||||
|
{
|
||||||
|
if (font->immutable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (unlikely (!face))
|
||||||
|
face = hb_face_get_empty ();
|
||||||
|
|
||||||
|
hb_face_t *old = font->face;
|
||||||
|
|
||||||
|
font->face = hb_face_reference (face);
|
||||||
|
|
||||||
|
hb_face_destroy (old);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_font_get_face:
|
* hb_font_get_face:
|
||||||
* @font: a font.
|
* @font: a font.
|
||||||
@ -1538,6 +1575,148 @@ hb_font_get_ppem (hb_font_t *font,
|
|||||||
if (y_ppem) *y_ppem = font->y_ppem;
|
if (y_ppem) *y_ppem = font->y_ppem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_font_set_ptem:
|
||||||
|
* @font: a font.
|
||||||
|
* @ptem:
|
||||||
|
*
|
||||||
|
* Sets "point size" of the font.
|
||||||
|
*
|
||||||
|
* Since: 1.6.0
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
hb_font_set_ptem (hb_font_t *font, float ptem)
|
||||||
|
{
|
||||||
|
if (font->immutable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
font->ptem = ptem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_font_get_ptem:
|
||||||
|
* @font: a font.
|
||||||
|
*
|
||||||
|
* Gets the "point size" of the font. A value of 0 means unset.
|
||||||
|
*
|
||||||
|
* Return value: Point size.
|
||||||
|
*
|
||||||
|
* Since: 0.9.2
|
||||||
|
**/
|
||||||
|
float
|
||||||
|
hb_font_get_ptem (hb_font_t *font)
|
||||||
|
{
|
||||||
|
return font->ptem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Variations
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
_hb_font_adopt_var_coords_normalized (hb_font_t *font,
|
||||||
|
int *coords, /* 2.14 normalized */
|
||||||
|
unsigned int coords_length)
|
||||||
|
{
|
||||||
|
free (font->coords);
|
||||||
|
|
||||||
|
font->coords = coords;
|
||||||
|
font->num_coords = coords_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_font_set_variations:
|
||||||
|
*
|
||||||
|
* Since: 1.4.2
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
hb_font_set_variations (hb_font_t *font,
|
||||||
|
const hb_variation_t *variations,
|
||||||
|
unsigned int variations_length)
|
||||||
|
{
|
||||||
|
if (font->immutable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!variations_length)
|
||||||
|
{
|
||||||
|
hb_font_set_var_coords_normalized (font, nullptr, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int coords_length = hb_ot_var_get_axis_count (font->face);
|
||||||
|
|
||||||
|
int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
|
||||||
|
if (unlikely (coords_length && !normalized))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hb_ot_var_normalize_variations (font->face,
|
||||||
|
variations, variations_length,
|
||||||
|
normalized, coords_length);
|
||||||
|
_hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_font_set_var_coords_design:
|
||||||
|
*
|
||||||
|
* Since: 1.4.2
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
hb_font_set_var_coords_design (hb_font_t *font,
|
||||||
|
const float *coords,
|
||||||
|
unsigned int coords_length)
|
||||||
|
{
|
||||||
|
if (font->immutable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
|
||||||
|
if (unlikely (coords_length && !normalized))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
|
||||||
|
_hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_font_set_var_coords_normalized:
|
||||||
|
*
|
||||||
|
* Since: 1.4.2
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
hb_font_set_var_coords_normalized (hb_font_t *font,
|
||||||
|
const int *coords, /* 2.14 normalized */
|
||||||
|
unsigned int coords_length)
|
||||||
|
{
|
||||||
|
if (font->immutable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||||
|
if (unlikely (coords_length && !copy))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (coords_length)
|
||||||
|
memcpy (copy, coords, coords_length * sizeof (coords[0]));
|
||||||
|
|
||||||
|
_hb_font_adopt_var_coords_normalized (font, copy, coords_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_font_get_var_coords_normalized:
|
||||||
|
*
|
||||||
|
* Return value is valid as long as variation coordinates of the font
|
||||||
|
* are not modified.
|
||||||
|
*
|
||||||
|
* Since: 1.4.2
|
||||||
|
*/
|
||||||
|
const int *
|
||||||
|
hb_font_get_var_coords_normalized (hb_font_t *font,
|
||||||
|
unsigned int *length)
|
||||||
|
{
|
||||||
|
if (length)
|
||||||
|
*length = font->num_coords;
|
||||||
|
|
||||||
|
return font->coords;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef HB_DISABLE_DEPRECATED
|
#ifndef HB_DISABLE_DEPRECATED
|
||||||
|
|
||||||
@ -1570,7 +1749,7 @@ trampoline_create (FuncType func,
|
|||||||
trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t));
|
trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t));
|
||||||
|
|
||||||
if (unlikely (!trampoline))
|
if (unlikely (!trampoline))
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
trampoline->closure.user_data = user_data;
|
trampoline->closure.user_data = user_data;
|
||||||
trampoline->closure.destroy = destroy;
|
trampoline->closure.destroy = destroy;
|
||||||
|
@ -456,7 +456,7 @@ hb_font_get_glyph_from_name (hb_font_t *font,
|
|||||||
/* high-level funcs, with fallback */
|
/* high-level funcs, with fallback */
|
||||||
|
|
||||||
/* Calls either hb_font_get_nominal_glyph() if variation_selector is 0,
|
/* Calls either hb_font_get_nominal_glyph() if variation_selector is 0,
|
||||||
* otherwise callse hb_font_get_variation_glyph(). */
|
* otherwise calls hb_font_get_variation_glyph(). */
|
||||||
HB_EXTERN hb_bool_t
|
HB_EXTERN hb_bool_t
|
||||||
hb_font_get_glyph (hb_font_t *font,
|
hb_font_get_glyph (hb_font_t *font,
|
||||||
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
|
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
|
||||||
@ -563,6 +563,10 @@ hb_font_set_parent (hb_font_t *font,
|
|||||||
HB_EXTERN hb_font_t *
|
HB_EXTERN hb_font_t *
|
||||||
hb_font_get_parent (hb_font_t *font);
|
hb_font_get_parent (hb_font_t *font);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_font_set_face (hb_font_t *font,
|
||||||
|
hb_face_t *face);
|
||||||
|
|
||||||
HB_EXTERN hb_face_t *
|
HB_EXTERN hb_face_t *
|
||||||
hb_font_get_face (hb_font_t *font);
|
hb_font_get_face (hb_font_t *font);
|
||||||
|
|
||||||
@ -603,6 +607,34 @@ hb_font_get_ppem (hb_font_t *font,
|
|||||||
unsigned int *x_ppem,
|
unsigned int *x_ppem,
|
||||||
unsigned int *y_ppem);
|
unsigned int *y_ppem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point size per EM. Used for optical-sizing in CoreText.
|
||||||
|
* A value of zero means "not set".
|
||||||
|
*/
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_font_set_ptem (hb_font_t *font, float ptem);
|
||||||
|
|
||||||
|
HB_EXTERN float
|
||||||
|
hb_font_get_ptem (hb_font_t *font);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_font_set_variations (hb_font_t *font,
|
||||||
|
const hb_variation_t *variations,
|
||||||
|
unsigned int variations_length);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_font_set_var_coords_design (hb_font_t *font,
|
||||||
|
const float *coords,
|
||||||
|
unsigned int coords_length);
|
||||||
|
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_font_set_var_coords_normalized (hb_font_t *font,
|
||||||
|
const int *coords, /* 2.14 normalized */
|
||||||
|
unsigned int coords_length);
|
||||||
|
|
||||||
|
HB_EXTERN const int *
|
||||||
|
hb_font_get_var_coords_normalized (hb_font_t *font,
|
||||||
|
unsigned int *length);
|
||||||
|
|
||||||
HB_END_DECLS
|
HB_END_DECLS
|
||||||
|
|
||||||
|
186
src/hb-ft.cc
186
src/hb-ft.cc
@ -28,21 +28,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hb-private.hh"
|
#include "hb-private.hh"
|
||||||
|
#include "hb-debug.hh"
|
||||||
|
|
||||||
#include "hb-ft.h"
|
#include "hb-ft.h"
|
||||||
|
|
||||||
#include "hb-font-private.hh"
|
#include "hb-font-private.hh"
|
||||||
|
|
||||||
#include FT_ADVANCES_H
|
#include FT_ADVANCES_H
|
||||||
|
#include FT_MULTIPLE_MASTERS_H
|
||||||
#include FT_TRUETYPE_TABLES_H
|
#include FT_TRUETYPE_TABLES_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HB_DEBUG_FT
|
|
||||||
#define HB_DEBUG_FT (HB_DEBUG+0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
*
|
*
|
||||||
* In general, this file does a fine job of what it's supposed to do.
|
* In general, this file does a fine job of what it's supposed to do.
|
||||||
@ -62,7 +58,7 @@
|
|||||||
*
|
*
|
||||||
* - In the future, we should add constructors to create fonts in font space?
|
* - In the future, we should add constructors to create fonts in font space?
|
||||||
*
|
*
|
||||||
* - FT_Load_Glyph() is exteremely costly. Do something about it?
|
* - FT_Load_Glyph() is extremely costly. Do something about it?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -70,18 +66,20 @@ struct hb_ft_font_t
|
|||||||
{
|
{
|
||||||
FT_Face ft_face;
|
FT_Face ft_face;
|
||||||
int load_flags;
|
int load_flags;
|
||||||
|
bool symbol; /* Whether selected cmap is symbol cmap. */
|
||||||
bool unref; /* Whether to destroy ft_face when done. */
|
bool unref; /* Whether to destroy ft_face when done. */
|
||||||
};
|
};
|
||||||
|
|
||||||
static hb_ft_font_t *
|
static hb_ft_font_t *
|
||||||
_hb_ft_font_create (FT_Face ft_face, bool unref)
|
_hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
|
||||||
{
|
{
|
||||||
hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t));
|
hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t));
|
||||||
|
|
||||||
if (unlikely (!ft_font))
|
if (unlikely (!ft_font))
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
ft_font->ft_face = ft_face;
|
ft_font->ft_face = ft_face;
|
||||||
|
ft_font->symbol = symbol;
|
||||||
ft_font->unref = unref;
|
ft_font->unref = unref;
|
||||||
|
|
||||||
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
|
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
|
||||||
@ -90,10 +88,18 @@ _hb_ft_font_create (FT_Face ft_face, bool unref)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_hb_ft_font_destroy (hb_ft_font_t *ft_font)
|
_hb_ft_face_destroy (void *data)
|
||||||
{
|
{
|
||||||
|
FT_Done_Face ((FT_Face) data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_hb_ft_font_destroy (void *data)
|
||||||
|
{
|
||||||
|
hb_ft_font_t *ft_font = (hb_ft_font_t *) data;
|
||||||
|
|
||||||
if (ft_font->unref)
|
if (ft_font->unref)
|
||||||
FT_Done_Face (ft_font->ft_face);
|
_hb_ft_face_destroy (ft_font->ft_face);
|
||||||
|
|
||||||
free (ft_font);
|
free (ft_font);
|
||||||
}
|
}
|
||||||
@ -113,7 +119,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
|
|||||||
if (font->immutable)
|
if (font->immutable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
|
if (font->destroy != _hb_ft_font_destroy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
|
hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
|
||||||
@ -133,7 +139,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
|
|||||||
int
|
int
|
||||||
hb_ft_font_get_load_flags (hb_font_t *font)
|
hb_ft_font_get_load_flags (hb_font_t *font)
|
||||||
{
|
{
|
||||||
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
|
if (font->destroy != _hb_ft_font_destroy)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
|
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
|
||||||
@ -144,8 +150,8 @@ hb_ft_font_get_load_flags (hb_font_t *font)
|
|||||||
FT_Face
|
FT_Face
|
||||||
hb_ft_font_get_face (hb_font_t *font)
|
hb_ft_font_get_face (hb_font_t *font)
|
||||||
{
|
{
|
||||||
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
|
if (font->destroy != _hb_ft_font_destroy)
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
|
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
|
||||||
|
|
||||||
@ -165,7 +171,21 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
|
|||||||
unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
|
unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
|
||||||
|
|
||||||
if (unlikely (!g))
|
if (unlikely (!g))
|
||||||
return false;
|
{
|
||||||
|
if (unlikely (ft_font->symbol) && unicode <= 0x00FFu)
|
||||||
|
{
|
||||||
|
/* For symbol-encoded OpenType fonts, we duplicate the
|
||||||
|
* U+F000..F0FF range at U+0000..U+00FF. That's what
|
||||||
|
* Windows seems to do, and that's hinted about at:
|
||||||
|
* http://www.microsoft.com/typography/otspec/recom.htm
|
||||||
|
* under "Non-Standard (Symbol) Fonts". */
|
||||||
|
g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode);
|
||||||
|
if (!g)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
*glyph = g;
|
*glyph = g;
|
||||||
return true;
|
return true;
|
||||||
@ -397,7 +417,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hb_font_funcs_t *static_ft_funcs = NULL;
|
static hb_font_funcs_t *static_ft_funcs = nullptr;
|
||||||
|
|
||||||
#ifdef HB_USE_ATEXIT
|
#ifdef HB_USE_ATEXIT
|
||||||
static
|
static
|
||||||
@ -417,24 +437,24 @@ retry:
|
|||||||
{
|
{
|
||||||
funcs = hb_font_funcs_create ();
|
funcs = hb_font_funcs_create ();
|
||||||
|
|
||||||
hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, NULL, NULL);
|
hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
|
||||||
//hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, NULL, NULL);
|
//hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
|
||||||
hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, NULL, NULL);
|
hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
|
||||||
hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, NULL, NULL);
|
hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
|
||||||
hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL);
|
hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, nullptr, nullptr);
|
||||||
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL);
|
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
|
||||||
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL);
|
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
|
||||||
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, NULL, NULL);
|
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
|
||||||
hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, NULL, NULL);
|
hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
|
||||||
//hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL);
|
//hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr);
|
||||||
hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, NULL, NULL);
|
hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
|
||||||
hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, NULL, NULL);
|
hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
|
||||||
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, NULL, NULL);
|
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
|
||||||
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, NULL, NULL);
|
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
|
||||||
|
|
||||||
hb_font_funcs_make_immutable (funcs);
|
hb_font_funcs_make_immutable (funcs);
|
||||||
|
|
||||||
if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, NULL, funcs)) {
|
if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, nullptr, funcs)) {
|
||||||
hb_font_funcs_destroy (funcs);
|
hb_font_funcs_destroy (funcs);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
@ -444,10 +464,12 @@ retry:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
|
||||||
|
|
||||||
hb_font_set_funcs (font,
|
hb_font_set_funcs (font,
|
||||||
funcs,
|
funcs,
|
||||||
_hb_ft_font_create (ft_face, unref),
|
_hb_ft_font_create (ft_face, symbol, unref),
|
||||||
(hb_destroy_func_t) _hb_ft_font_destroy);
|
_hb_ft_font_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -461,17 +483,17 @@ reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
|||||||
|
|
||||||
/* Note: FreeType like HarfBuzz uses the NONE tag for fetching the entire blob */
|
/* Note: FreeType like HarfBuzz uses the NONE tag for fetching the entire blob */
|
||||||
|
|
||||||
error = FT_Load_Sfnt_Table (ft_face, tag, 0, NULL, &length);
|
error = FT_Load_Sfnt_Table (ft_face, tag, 0, nullptr, &length);
|
||||||
if (error)
|
if (error)
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
buffer = (FT_Byte *) malloc (length);
|
buffer = (FT_Byte *) malloc (length);
|
||||||
if (buffer == NULL)
|
if (!buffer)
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
|
error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
|
||||||
if (error)
|
if (error)
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
return hb_blob_create ((const char *) buffer, length,
|
return hb_blob_create ((const char *) buffer, length,
|
||||||
HB_MEMORY_MODE_WRITABLE,
|
HB_MEMORY_MODE_WRITABLE,
|
||||||
@ -494,7 +516,7 @@ hb_ft_face_create (FT_Face ft_face,
|
|||||||
{
|
{
|
||||||
hb_face_t *face;
|
hb_face_t *face;
|
||||||
|
|
||||||
if (ft_face->stream->read == NULL) {
|
if (!ft_face->stream->read) {
|
||||||
hb_blob_t *blob;
|
hb_blob_t *blob;
|
||||||
|
|
||||||
blob = hb_blob_create ((const char *) ft_face->stream->base,
|
blob = hb_blob_create ((const char *) ft_face->stream->base,
|
||||||
@ -526,7 +548,7 @@ hb_face_t *
|
|||||||
hb_ft_face_create_referenced (FT_Face ft_face)
|
hb_ft_face_create_referenced (FT_Face ft_face)
|
||||||
{
|
{
|
||||||
FT_Reference_Face (ft_face);
|
FT_Reference_Face (ft_face);
|
||||||
return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
|
return hb_ft_face_create (ft_face, _hb_ft_face_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -552,7 +574,7 @@ hb_ft_face_create_cached (FT_Face ft_face)
|
|||||||
if (ft_face->generic.finalizer)
|
if (ft_face->generic.finalizer)
|
||||||
ft_face->generic.finalizer (ft_face);
|
ft_face->generic.finalizer (ft_face);
|
||||||
|
|
||||||
ft_face->generic.data = hb_ft_face_create (ft_face, NULL);
|
ft_face->generic.data = hb_ft_face_create (ft_face, nullptr);
|
||||||
ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize;
|
ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,16 +603,61 @@ hb_ft_font_create (FT_Face ft_face,
|
|||||||
font = hb_font_create (face);
|
font = hb_font_create (face);
|
||||||
hb_face_destroy (face);
|
hb_face_destroy (face);
|
||||||
_hb_ft_font_set_funcs (font, ft_face, false);
|
_hb_ft_font_set_funcs (font, ft_face, false);
|
||||||
|
hb_ft_font_changed (font);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_ft_font_changed (hb_font_t *font)
|
||||||
|
{
|
||||||
|
if (font->destroy != _hb_ft_font_destroy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
|
||||||
|
FT_Face ft_face = ft_font->ft_face;
|
||||||
|
|
||||||
hb_font_set_scale (font,
|
hb_font_set_scale (font,
|
||||||
(int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16),
|
(int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16),
|
||||||
(int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16));
|
(int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16));
|
||||||
#if 0 /* hb-ft works in no-hinting model */
|
#if 0 /* hb-ft works in no-hinting model */
|
||||||
hb_font_set_ppem (font,
|
hb_font_set_ppem (font,
|
||||||
ft_face->size->metrics.x_ppem,
|
ft_face->size->metrics.x_ppem,
|
||||||
ft_face->size->metrics.y_ppem);
|
ft_face->size->metrics.y_ppem);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return font;
|
#ifdef HAVE_FT_GET_VAR_BLEND_COORDINATES
|
||||||
|
FT_MM_Var *mm_var = nullptr;
|
||||||
|
if (!FT_Get_MM_Var (ft_face, &mm_var))
|
||||||
|
{
|
||||||
|
FT_Fixed *ft_coords = (FT_Fixed *) calloc (mm_var->num_axis, sizeof (FT_Fixed));
|
||||||
|
int *coords = (int *) calloc (mm_var->num_axis, sizeof (int));
|
||||||
|
if (coords && ft_coords)
|
||||||
|
{
|
||||||
|
if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords))
|
||||||
|
{
|
||||||
|
bool nonzero = false;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < mm_var->num_axis; ++i)
|
||||||
|
{
|
||||||
|
coords[i] = ft_coords[i] >>= 2;
|
||||||
|
nonzero = nonzero || coords[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nonzero)
|
||||||
|
hb_font_set_var_coords_normalized (font, coords, mm_var->num_axis);
|
||||||
|
else
|
||||||
|
hb_font_set_var_coords_normalized (font, nullptr, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free (coords);
|
||||||
|
free (ft_coords);
|
||||||
|
#ifdef HAVE_FT_DONE_MM_VAR
|
||||||
|
FT_Done_MM_Var (ft_face->glyph->library, mm_var);
|
||||||
|
#else
|
||||||
|
free (mm_var);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -606,7 +673,7 @@ hb_font_t *
|
|||||||
hb_ft_font_create_referenced (FT_Face ft_face)
|
hb_ft_font_create_referenced (FT_Face ft_face)
|
||||||
{
|
{
|
||||||
FT_Reference_Face (ft_face);
|
FT_Reference_Face (ft_face);
|
||||||
return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
|
return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -632,9 +699,9 @@ retry:
|
|||||||
{
|
{
|
||||||
/* Not found; allocate one. */
|
/* Not found; allocate one. */
|
||||||
if (FT_Init_FreeType (&library))
|
if (FT_Init_FreeType (&library))
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
if (!hb_atomic_ptr_cmpexch (&ft_library, NULL, library)) {
|
if (!hb_atomic_ptr_cmpexch (&ft_library, nullptr, library)) {
|
||||||
FT_Done_FreeType (library);
|
FT_Done_FreeType (library);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
@ -662,7 +729,7 @@ hb_ft_font_set_funcs (hb_font_t *font)
|
|||||||
if (unlikely (!blob_length))
|
if (unlikely (!blob_length))
|
||||||
DEBUG_MSG (FT, font, "Font face has empty blob");
|
DEBUG_MSG (FT, font, "Font face has empty blob");
|
||||||
|
|
||||||
FT_Face ft_face = NULL;
|
FT_Face ft_face = nullptr;
|
||||||
FT_Error err = FT_New_Memory_Face (get_ft_library (),
|
FT_Error err = FT_New_Memory_Face (get_ft_library (),
|
||||||
(const FT_Byte *) blob_data,
|
(const FT_Byte *) blob_data,
|
||||||
blob_length,
|
blob_length,
|
||||||
@ -675,7 +742,8 @@ hb_ft_font_set_funcs (hb_font_t *font)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
|
if (FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE))
|
||||||
|
FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL);
|
||||||
|
|
||||||
FT_Set_Char_Size (ft_face,
|
FT_Set_Char_Size (ft_face,
|
||||||
abs (font->x_scale), abs (font->y_scale),
|
abs (font->x_scale), abs (font->y_scale),
|
||||||
@ -688,9 +756,25 @@ hb_ft_font_set_funcs (hb_font_t *font)
|
|||||||
{
|
{
|
||||||
FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
|
FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
|
||||||
0, font->y_scale < 0 ? -1 : +1};
|
0, font->y_scale < 0 ? -1 : +1};
|
||||||
FT_Set_Transform (ft_face, &matrix, NULL);
|
FT_Set_Transform (ft_face, &matrix, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_FT_SET_VAR_BLEND_COORDINATES
|
||||||
|
unsigned int num_coords;
|
||||||
|
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
|
||||||
|
if (num_coords)
|
||||||
|
{
|
||||||
|
FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
|
||||||
|
if (ft_coords)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < num_coords; i++)
|
||||||
|
ft_coords[i] = coords[i] << 2;
|
||||||
|
FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
|
||||||
|
free (ft_coords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ft_face->generic.data = blob;
|
ft_face->generic.data = blob;
|
||||||
ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
|
ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
|
||||||
|
|
||||||
|
@ -116,7 +116,13 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
|
|||||||
HB_EXTERN int
|
HB_EXTERN int
|
||||||
hb_ft_font_get_load_flags (hb_font_t *font);
|
hb_ft_font_get_load_flags (hb_font_t *font);
|
||||||
|
|
||||||
/* Makes an hb_font_t use FreeType internally to implement font functions. */
|
/* Call when size or variations settings on underlying FT_Face change. */
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_ft_font_changed (hb_font_t *font);
|
||||||
|
|
||||||
|
/* Makes an hb_font_t use FreeType internally to implement font functions.
|
||||||
|
* Note: this internally creates an FT_Face. Use it when you create your
|
||||||
|
* hb_face_t using hb_face_create(). */
|
||||||
HB_EXTERN void
|
HB_EXTERN void
|
||||||
hb_ft_font_set_funcs (hb_font_t *font);
|
hb_ft_font_set_funcs (hb_font_t *font);
|
||||||
|
|
||||||
|
@ -364,22 +364,52 @@ hb_glib_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
|||||||
return utf8_decomposed_len;
|
return utf8_decomposed_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static hb_unicode_funcs_t *static_glib_funcs = nullptr;
|
||||||
|
|
||||||
|
#ifdef HB_USE_ATEXIT
|
||||||
|
static
|
||||||
|
void free_static_glib_funcs (void)
|
||||||
|
{
|
||||||
|
hb_unicode_funcs_destroy (static_glib_funcs);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
hb_unicode_funcs_t *
|
hb_unicode_funcs_t *
|
||||||
hb_glib_get_unicode_funcs (void)
|
hb_glib_get_unicode_funcs (void)
|
||||||
{
|
{
|
||||||
static const hb_unicode_funcs_t _hb_glib_unicode_funcs = {
|
retry:
|
||||||
HB_OBJECT_HEADER_STATIC,
|
hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_glib_funcs);
|
||||||
|
|
||||||
NULL, /* parent */
|
if (unlikely (!funcs))
|
||||||
true, /* immutable */
|
{
|
||||||
{
|
funcs = hb_unicode_funcs_create (nullptr);
|
||||||
#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_glib_unicode_##name,
|
|
||||||
|
#define HB_UNICODE_FUNC_IMPLEMENT(name) \
|
||||||
|
hb_unicode_funcs_set_##name##_func (funcs, hb_glib_unicode_##name, nullptr, nullptr);
|
||||||
HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
|
HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
#undef HB_UNICODE_FUNC_IMPLEMENT
|
#undef HB_UNICODE_FUNC_IMPLEMENT
|
||||||
|
|
||||||
|
hb_unicode_funcs_make_immutable (funcs);
|
||||||
|
|
||||||
|
if (!hb_atomic_ptr_cmpexch (&static_glib_funcs, nullptr, funcs)) {
|
||||||
|
hb_unicode_funcs_destroy (funcs);
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HB_USE_ATEXIT
|
||||||
|
atexit (free_static_glib_funcs); /* First person registers atexit() callback. */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
|
return hb_unicode_funcs_reference (funcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GLIB_CHECK_VERSION(2,31,10)
|
||||||
|
|
||||||
|
static void
|
||||||
|
_hb_g_bytes_unref (void *data)
|
||||||
|
{
|
||||||
|
g_bytes_unref ((GBytes *) data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -396,5 +426,6 @@ hb_glib_blob_create (GBytes *gbytes)
|
|||||||
size,
|
size,
|
||||||
HB_MEMORY_MODE_READONLY,
|
HB_MEMORY_MODE_READONLY,
|
||||||
g_bytes_ref (gbytes),
|
g_bytes_ref (gbytes),
|
||||||
(hb_destroy_func_t) g_bytes_unref);
|
_hb_g_bytes_unref);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -46,9 +46,10 @@ hb_glib_script_from_script (hb_script_t script);
|
|||||||
HB_EXTERN hb_unicode_funcs_t *
|
HB_EXTERN hb_unicode_funcs_t *
|
||||||
hb_glib_get_unicode_funcs (void);
|
hb_glib_get_unicode_funcs (void);
|
||||||
|
|
||||||
|
#if GLIB_CHECK_VERSION(2,31,10)
|
||||||
HB_EXTERN hb_blob_t *
|
HB_EXTERN hb_blob_t *
|
||||||
hb_glib_blob_create (GBytes *gbytes);
|
hb_glib_blob_create (GBytes *gbytes);
|
||||||
|
#endif
|
||||||
|
|
||||||
HB_END_DECLS
|
HB_END_DECLS
|
||||||
|
|
||||||
|
@ -42,7 +42,8 @@ HB_BEGIN_DECLS
|
|||||||
/*** END file-header ***/
|
/*** END file-header ***/
|
||||||
|
|
||||||
/*** BEGIN value-header ***/
|
/*** BEGIN value-header ***/
|
||||||
HB_EXTERN GType @enum_name@_get_type (void) G_GNUC_CONST;
|
HB_EXTERN GType
|
||||||
|
@enum_name@_get_type (void) G_GNUC_CONST;
|
||||||
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
|
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
|
||||||
|
|
||||||
/*** END value-header ***/
|
/*** END value-header ***/
|
||||||
|
@ -58,7 +58,7 @@ hb_gobject_##name##_get_type (void) \
|
|||||||
static hb_##name##_t *_hb_##name##_reference (const hb_##name##_t *l) \
|
static hb_##name##_t *_hb_##name##_reference (const hb_##name##_t *l) \
|
||||||
{ \
|
{ \
|
||||||
hb_##name##_t *c = (hb_##name##_t *) calloc (1, sizeof (hb_##name##_t)); \
|
hb_##name##_t *c = (hb_##name##_t *) calloc (1, sizeof (hb_##name##_t)); \
|
||||||
if (unlikely (!c)) return NULL; \
|
if (unlikely (!c)) return nullptr; \
|
||||||
*c = *l; \
|
*c = *l; \
|
||||||
return c; \
|
return c; \
|
||||||
} \
|
} \
|
||||||
@ -78,3 +78,6 @@ HB_DEFINE_VALUE_TYPE (glyph_info)
|
|||||||
HB_DEFINE_VALUE_TYPE (glyph_position)
|
HB_DEFINE_VALUE_TYPE (glyph_position)
|
||||||
HB_DEFINE_VALUE_TYPE (segment_properties)
|
HB_DEFINE_VALUE_TYPE (segment_properties)
|
||||||
HB_DEFINE_VALUE_TYPE (user_data_key)
|
HB_DEFINE_VALUE_TYPE (user_data_key)
|
||||||
|
|
||||||
|
HB_DEFINE_VALUE_TYPE (ot_math_glyph_variant)
|
||||||
|
HB_DEFINE_VALUE_TYPE (ot_math_glyph_part)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user