Merge with master
This commit is contained in:
commit
101850f9e6
@ -3,6 +3,8 @@
|
||||
set -x
|
||||
set -o errexit -o nounset
|
||||
|
||||
if test "x$TRAVIS_SECURE_ENV_VARS" != xtrue; then exit; fi
|
||||
|
||||
BRANCH="$TRAVIS_BRANCH"
|
||||
if test "x$BRANCH" != xmaster; then exit; fi
|
||||
|
||||
@ -16,18 +18,19 @@ mkdir $DOCSDIR
|
||||
cd $DOCSDIR
|
||||
|
||||
cp ../docs/html/* .
|
||||
#cp ../docs/CNAME .
|
||||
|
||||
git init
|
||||
git config user.name "Travis CI"
|
||||
git config user.email "travis@harfbuzz.org"
|
||||
set +x
|
||||
echo "git remote add upstream \"https://\$GH_TOKEN@github.com/$TRAVIS_REPO_SLUG.git\""
|
||||
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/harfbuzz/harfbuzz.github.io.git"
|
||||
set -x
|
||||
git fetch upstream
|
||||
git reset upstream/gh-pages
|
||||
git reset upstream/master
|
||||
|
||||
touch .
|
||||
git add -A .
|
||||
git commit -m "Rebuild docs for $REVISION"
|
||||
git push -q upstream HEAD:gh-pages
|
||||
git commit -m "Rebuild docs for https://github.com/harfbuzz/harfbuzz/commit/$REVISION"
|
||||
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
|
||||
sudo: required # For Trusty beta
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
dist: trusty
|
||||
|
||||
language: cpp
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
|
||||
env:
|
||||
global:
|
||||
- CPPFLAGS=""
|
||||
- CFLAGS="-Werror --coverage"
|
||||
- CXXFLAGS="-Werror -Wno-deprecated-register --coverage" # glib uses register and clang raises a warning
|
||||
- CFLAGS="-Werror -Werror=unused-function --coverage"
|
||||
- CXXFLAGS="-Werror -Werror=unused-function -Wno-deprecated-register --coverage" # glib uses register and clang raises a warning
|
||||
- LDFLAGS="--coverage"
|
||||
install:
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then pip install --user nose; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then pip install --user cpp-coveralls; fi # for coveralls.io code coverage tracking
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then export PATH=$HOME/.local/bin:$PATH; fi # Make sure we can find the above Python packages
|
||||
- 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
|
||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew link --force icu4c; fi # icu4c is keg-only
|
||||
script:
|
||||
- NOCONFIGURE=1 ./autogen.sh
|
||||
- export CONFIGURE_OPTS="--with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2"
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" -a "$CC" == "gcc" ]; then export CONFIGURE_OPTS="$CONFIGURE_OPTS --enable-gtk-doc"; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then export CONFIGURE_OPTS="$CONFIGURE_OPTS --with-coretext"; fi
|
||||
- ./configure $CONFIGURE_OPTS
|
||||
- make
|
||||
- make check
|
||||
- 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
|
||||
after_success:
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" -a "$CC" == "gcc" -a "$TRAVIS_SECURE_ENV_VARS" == "true" ]; then bash .ci/deploy-docs.sh; fi
|
||||
- CONFIGURE_OPTS="--with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2"
|
||||
- NOCONFIGURE=1
|
||||
# COVERITY_SCAN_TOKEN
|
||||
- secure: "Vw1UUHsAr4t3xuvOqqBsFAORptmNcQRrcGJnzSX7jDODBIRNfnU2LIBTagrPNKfSUhyQgCHqt1gX9iWNWvVfy3sDOXr2MXZeoqmF6Y1mS35J0rA/EPJgRHsdkxygkmFnXVeQkEuI55BINkaSoOpAeunmXKJNw1p9JVw368Fm/tU="
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
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 --enable-gtk-doc
|
||||
- make
|
||||
- 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:
|
||||
irc: "irc.freenode.org#harfbuzz"
|
||||
email: harfbuzz@lists.freedesktop.org
|
||||
email: harfbuzz-bots-chatter@googlegroups.com
|
||||
|
||||
addons:
|
||||
apt:
|
||||
@ -47,4 +75,14 @@ addons:
|
||||
- libcairo2-dev # for utils
|
||||
- libicu-dev # for extra unicode functions
|
||||
- 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,
|
||||
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:
|
||||
* sudo yum install gcc gcc-c++ freetype-devel glib2-devel cairo-devel
|
||||
|
||||
on the Mac, using MacPorts:
|
||||
* sudo port install freetype glib2 cairo
|
||||
sudo yum install gcc gcc-c++ freetype-devel glib2-devel cairo-devel
|
||||
|
||||
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:
|
||||
* 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
|
||||
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
|
||||
under util/. From the tarball, NMake Makefiles are also provided in win32/,
|
||||
which supports building HarfBuzz using Visual Studio, with a README.txt that
|
||||
gives instructions on building using NMake.
|
||||
library in `src/`, and a few utility programs including `hb-view` and `hb-shape`
|
||||
under `util/`.
|
||||
|
||||
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,
|
||||
on Ubuntu / Debian:
|
||||
* sudo apt-get install autoconf automake libtool pkg-config ragel gtk-doc-tools
|
||||
run `autogen.sh` for the first time. Namely, `pkg-config` and `ragel`.
|
||||
|
||||
Again, on Ubuntu / Debian:
|
||||
|
||||
sudo apt-get install autoconf automake libtool pkg-config ragel gtk-doc-tools
|
||||
|
||||
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:
|
||||
* sudo port install autoconf automake libtool pkgconfig ragel gtk-doc
|
||||
|
||||
sudo port install autoconf automake libtool pkgconfig ragel gtk-doc
|
||||
|
||||
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:
|
||||
|
||||
* 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
|
||||
|
||||
SUBDIRS = src util test docs win32
|
||||
SUBDIRS = src util test docs
|
||||
|
||||
EXTRA_DIST = \
|
||||
autogen.sh \
|
||||
harfbuzz.doap \
|
||||
Android.mk \
|
||||
README.python \
|
||||
BUILD.md \
|
||||
RELEASING.md \
|
||||
CMakeLists.txt \
|
||||
replace-enum-strings.cmake \
|
||||
$(NULL)
|
||||
|
||||
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
|
||||
Monday, May 2, 2016
|
||||
@ -109,7 +478,7 @@ Tuesday, February 23, 2016
|
||||
- CoreText: Drastically speed up font initialization.
|
||||
- CoreText: Fix tiny leak.
|
||||
- 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.
|
||||
|
||||
|
||||
@ -125,8 +494,8 @@ Friday, February 19, 2016
|
||||
- Allow GPOS cursive connection on marks, and fix the interaction with
|
||||
mark attachment. This work resulted in some changes to how mark
|
||||
attachments work. See:
|
||||
https://github.com/behdad/harfbuzz/issues/211
|
||||
https://github.com/behdad/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2
|
||||
https://github.com/harfbuzz/harfbuzz/issues/211
|
||||
https://github.com/harfbuzz/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2
|
||||
- Graphite2 shaper: improved negative advance handling (eg. Nastaliq).
|
||||
- Add nmake-based build system for Windows.
|
||||
- Minor speedup.
|
||||
@ -167,7 +536,7 @@ Wednesday, November 26, 2015
|
||||
====================================
|
||||
|
||||
- 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.
|
||||
- API changes:
|
||||
* 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.
|
||||
https://github.com/behdad/harfbuzz/issues/141
|
||||
https://github.com/harfbuzz/harfbuzz/issues/141
|
||||
- Disable use of decompose_compatibility() callback.
|
||||
- Implement "shaping" of various Unicode space characters, even
|
||||
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
|
||||
U+2010 HYPHEN.
|
||||
- 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()
|
||||
back to FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING. This was changed in
|
||||
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
|
||||
@ -224,7 +593,7 @@ Tuesday, October 13, 2015
|
||||
====================================
|
||||
|
||||
- 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.
|
||||
We now have continuous fuzzing set up, to avoid issues like
|
||||
these creeping in again.
|
||||
@ -495,7 +864,7 @@ Wednesday, July 16, 2014
|
||||
U+FFFD REPLACEMENT CHARACTER now.
|
||||
- With all changes in this release, the buffer will contain fully
|
||||
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 minor invalid buffer access.
|
||||
- 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)
|
||||
[![Coverage Status](https://img.shields.io/coveralls/behdad/harfbuzz.svg)](https://coveralls.io/r/behdad/harfbuzz)
|
||||
[![Build Status](https://travis-ci.org/harfbuzz/harfbuzz.svg)](https://travis-ci.org/harfbuzz/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/)
|
||||
|
||||
This is HarfBuzz, a text shaping library.
|
||||
@ -9,3 +12,5 @@ For bug reports, mailing list, and other information please visit:
|
||||
http://harfbuzz.org/
|
||||
|
||||
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:
|
||||
=============
|
||||
|
||||
- AAT 'morx' implementation.
|
||||
|
||||
- Return "safe-to-break" bit from shaping.
|
||||
|
||||
- Implement 'rand' feature.
|
||||
|
||||
- mask propagation? (when ligation, "or" the masks).
|
||||
|
||||
|
||||
API issues:
|
||||
===========
|
||||
|
||||
- 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()?
|
||||
|
||||
|
||||
@ -39,7 +29,7 @@ API additions
|
||||
|
||||
- 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
|
||||
|
||||
@ -50,20 +40,3 @@ hb-view / hb-shape enhancements:
|
||||
===============================
|
||||
|
||||
- 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`
|
||||
cd $srcdir
|
||||
|
||||
echo -n "checking for ragel... "
|
||||
which ragel || {
|
||||
echo "You need to install ragel... See http://www.complang.org/ragel/"
|
||||
exit 1
|
||||
}
|
||||
#echo -n "checking for ragel... "
|
||||
#which ragel || {
|
||||
# echo "You need to install ragel... See http://www.complang.org/ragel/"
|
||||
# exit 1
|
||||
#}
|
||||
|
||||
echo -n "checking for pkg-config... "
|
||||
which pkg-config || {
|
||||
@ -42,5 +42,7 @@ echo "running autoreconf --force --install --verbose"
|
||||
autoreconf --force --install --verbose || exit $?
|
||||
|
||||
cd $olddir
|
||||
echo "running configure $@"
|
||||
test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
|
||||
test -n "$NOCONFIGURE" || {
|
||||
echo "running configure $@"
|
||||
"$srcdir/configure" "$@"
|
||||
}
|
||||
|
77
configure.ac
77
configure.ac
@ -1,7 +1,7 @@
|
||||
AC_PREREQ([2.64])
|
||||
AC_INIT([HarfBuzz],
|
||||
[1.2.7],
|
||||
[https://github.com/behdad/harfbuzz/issues/new],
|
||||
[1.7.5],
|
||||
[https://github.com/harfbuzz/harfbuzz/issues/new],
|
||||
[harfbuzz],
|
||||
[http://harfbuzz.org/])
|
||||
|
||||
@ -9,8 +9,7 @@ AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
|
||||
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_CONDITIONAL(AUTOMAKE_OLDER_THAN_1_13, test $am__api_version = 1.11 -o $am__api_version = 1.12)
|
||||
AM_INIT_AUTOMAKE([1.13.0 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
# Initialize libtool
|
||||
@ -19,9 +18,13 @@ LT_PREREQ([2.2])
|
||||
LT_INIT([disable-static])
|
||||
|
||||
# Check for programs
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_PROG_CC
|
||||
AC_PROG_CC_C99
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_CXX
|
||||
dnl AX_CXX_COMPILE_STDCXX(11, noext, optional)
|
||||
AC_SYS_LARGEFILE
|
||||
PKG_PROG_PKG_CONFIG([0.20])
|
||||
AM_MISSING_PROG([RAGEL], [ragel])
|
||||
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
|
||||
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
|
||||
have_gtk_doc=false
|
||||
m4_ifdef([GTK_DOC_CHECK], [
|
||||
@ -66,9 +76,9 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
|
||||
AM_CONDITIONAL([ENABLE_GTK_DOC], false)
|
||||
])
|
||||
|
||||
# Functions and headers
|
||||
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty)
|
||||
AC_CHECK_HEADERS(unistd.h sys/mman.h)
|
||||
# Functions, and headers
|
||||
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l setlinebuf)
|
||||
AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h)
|
||||
|
||||
# Compiler flags
|
||||
AC_CANONICAL_HOST
|
||||
@ -78,9 +88,6 @@ if test "x$GCC" = "xyes"; then
|
||||
# Make symbols link locally
|
||||
LDFLAGS="$LDFLAGS -Bsymbolic-functions"
|
||||
|
||||
# Make sure we don't link to libstdc++
|
||||
CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions"
|
||||
|
||||
# Assorted warnings
|
||||
CXXFLAGS="$CXXFLAGS -Wcast-align"
|
||||
|
||||
@ -145,7 +152,7 @@ AC_ARG_WITH(glib,
|
||||
[Use glib @<:@default=auto@:>@])],,
|
||||
[with_glib=auto])
|
||||
have_glib=false
|
||||
GLIB_DEPS="glib-2.0 >= 2.16"
|
||||
GLIB_DEPS="glib-2.0 >= 2.19.1"
|
||||
AC_SUBST(GLIB_DEPS)
|
||||
if test "x$with_glib" = "xyes" -o "x$with_glib" = "xauto"; then
|
||||
PKG_CHECK_MODULES(GLIB, $GLIB_DEPS, have_glib=true, :)
|
||||
@ -162,7 +169,7 @@ dnl ===========================================================================
|
||||
|
||||
AC_ARG_WITH(gobject,
|
||||
[AS_HELP_STRING([--with-gobject=@<:@yes/no/auto@:>@],
|
||||
[Use gobject @<:@default=auto@:>@])],,
|
||||
[Use gobject @<:@default=no@:>@])],,
|
||||
[with_gobject=no])
|
||||
have_gobject=false
|
||||
if test "x$with_gobject" = "xyes" -o "x$with_gobject" = "xauto"; then
|
||||
@ -177,6 +184,7 @@ if $have_gobject; then
|
||||
AC_SUBST(GLIB_MKENUMS)
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_GOBJECT, $have_gobject)
|
||||
AC_SUBST(have_gobject)
|
||||
|
||||
dnl ===========================================================================
|
||||
|
||||
@ -287,9 +295,13 @@ AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin")
|
||||
|
||||
dnl ===========================================================================
|
||||
|
||||
have_ucdn=true
|
||||
if $have_glib || $have_icu && test "x$with_icu" = "xbuiltin"; then
|
||||
have_ucdn=false
|
||||
AC_ARG_WITH(ucdn,
|
||||
[AS_HELP_STRING([--with-ucdn=@<:@yes/no@:>@],
|
||||
[Use builtin UCDN library @<:@default=yes@:>@])],,
|
||||
[with_ucdn=yes])
|
||||
have_ucdn=false
|
||||
if test "x$with_ucdn" = "xyes"; then
|
||||
have_ucdn=true
|
||||
fi
|
||||
if $have_ucdn; then
|
||||
AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions])
|
||||
@ -307,6 +319,16 @@ GRAPHITE2_DEPS="graphite2"
|
||||
AC_SUBST(GRAPHITE2_DEPS)
|
||||
if test "x$with_graphite2" = "xyes" -o "x$with_graphite2" = "xauto"; then
|
||||
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
|
||||
if test "x$with_graphite2" = "xyes" -a "x$have_graphite2" != "xtrue"; then
|
||||
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
|
||||
if $have_freetype; then
|
||||
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
|
||||
AM_CONDITIONAL(HAVE_FREETYPE, $have_freetype)
|
||||
|
||||
@ -401,12 +427,13 @@ if test "x$with_coretext" = "xyes" -o "x$with_coretext" = "xauto"; then
|
||||
else
|
||||
# On iOS CoreText and CoreGraphics are stand-alone frameworks
|
||||
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
|
||||
|
||||
if $have_coretext; then
|
||||
CORETEXT_CFLAGS=
|
||||
CORETEXT_LIBS="-framework CoreText -framework CoreGraphics"
|
||||
CORETEXT_LIBS="-framework CoreText -framework CoreGraphics -framework CoreFoundation"
|
||||
AC_SUBST(CORETEXT_CFLAGS)
|
||||
AC_SUBST(CORETEXT_LIBS)
|
||||
fi
|
||||
@ -465,16 +492,20 @@ AC_CONFIG_FILES([
|
||||
Makefile
|
||||
src/Makefile
|
||||
src/hb-version.h
|
||||
src/harfbuzz-config.cmake
|
||||
src/hb-ucdn/Makefile
|
||||
util/Makefile
|
||||
test/Makefile
|
||||
test/api/Makefile
|
||||
test/fuzzing/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/version.xml
|
||||
win32/Makefile
|
||||
win32/config.h.win32
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
@ -484,18 +515,18 @@ AC_MSG_NOTICE([
|
||||
Build configuration:
|
||||
|
||||
Unicode callbacks (you want at least one):
|
||||
Builtin (UCDN): ${have_ucdn}
|
||||
Glib: ${have_glib}
|
||||
ICU: ${have_icu}
|
||||
UCDN: ${have_ucdn}
|
||||
|
||||
Font callbacks (the more the better):
|
||||
Font callbacks (the more the merrier):
|
||||
FreeType: ${have_freetype}
|
||||
|
||||
Tools used for command-line utilities:
|
||||
Cairo: ${have_cairo}
|
||||
Fontconfig: ${have_fontconfig}
|
||||
|
||||
Additional shapers (the more the better):
|
||||
Additional shapers (the more the merrier):
|
||||
Graphite2: ${have_graphite2}
|
||||
|
||||
Platform shapers (not normally needed):
|
||||
@ -504,7 +535,7 @@ Platform shapers (not normally needed):
|
||||
DirectWrite: ${have_directwrite}
|
||||
|
||||
Other features:
|
||||
Documentation: ${have_gtk_doc}
|
||||
Documentation: ${enable_gtk_doc}
|
||||
GObject bindings: ${have_gobject}
|
||||
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.
|
||||
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
|
||||
HTML_IMAGES= \
|
||||
HarfBuzz.png
|
||||
HarfBuzz.png \
|
||||
HarfBuzz.svg
|
||||
|
||||
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
|
||||
# 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
|
||||
#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
|
||||
if ENABLE_GTK_DOC
|
||||
TESTS_ENVIRONMENT = cd $(srcdir) && \
|
||||
|
@ -22,7 +22,7 @@
|
||||
source tree is available
|
||||
<ulink url="http://cgit.freedesktop.org/harfbuzz/">here</ulink>.
|
||||
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.
|
||||
</para>
|
||||
<para>
|
||||
@ -60,7 +60,7 @@
|
||||
</partinfo>
|
||||
<title>Reference manual</title>
|
||||
<chapter>
|
||||
<title>Harfbuzz API</title>
|
||||
<title>HarfBuzz API</title>
|
||||
<xi:include href="xml/hb.xml"/>
|
||||
<xi:include href="xml/hb-common.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-font.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"/>
|
||||
|
||||
@ -175,6 +176,30 @@
|
||||
<title>Index of new symbols in 1.1.3</title>
|
||||
<xi:include href="xml/api-index-1.1.3.xml"><xi:fallback /></xi:include>
|
||||
</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">
|
||||
<title>Index of deprecated API</title>
|
||||
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
|
||||
|
@ -9,6 +9,7 @@ HB_EXTERN
|
||||
<FILE>hb-blob</FILE>
|
||||
hb_blob_create
|
||||
hb_blob_create_sub_blob
|
||||
hb_blob_copy_writable_or_fail
|
||||
hb_blob_destroy
|
||||
hb_blob_get_data
|
||||
hb_blob_get_data_writable
|
||||
@ -41,6 +42,7 @@ hb_buffer_add_utf32
|
||||
hb_buffer_add_utf16
|
||||
hb_buffer_add_utf8
|
||||
hb_buffer_add_latin1
|
||||
hb_buffer_append
|
||||
hb_buffer_set_content_type
|
||||
hb_buffer_get_content_type
|
||||
hb_buffer_set_direction
|
||||
@ -77,9 +79,12 @@ hb_buffer_serialize_format_to_string
|
||||
hb_buffer_serialize_list_formats
|
||||
hb_segment_properties_equal
|
||||
hb_segment_properties_hash
|
||||
hb_buffer_diff
|
||||
hb_buffer_set_message_func
|
||||
hb_buffer_t
|
||||
hb_glyph_info_get_glyph_flags
|
||||
hb_glyph_info_t
|
||||
hb_glyph_flags_t
|
||||
hb_glyph_position_t
|
||||
hb_buffer_content_type_t
|
||||
hb_buffer_flags_t
|
||||
@ -87,6 +92,7 @@ hb_buffer_cluster_level_t
|
||||
hb_segment_properties_t
|
||||
hb_buffer_serialize_format_t
|
||||
hb_buffer_serialize_flags_t
|
||||
hb_buffer_diff_flags_t
|
||||
hb_buffer_message_func_t
|
||||
</SECTION>
|
||||
|
||||
@ -144,13 +150,18 @@ uint8_t
|
||||
HB_BUFFER_FLAGS_DEFAULT
|
||||
HB_BUFFER_SERIALIZE_FLAGS_DEFAULT
|
||||
HB_SCRIPT_CANADIAN_ABORIGINAL
|
||||
hb_font_funcs_set_glyph_func
|
||||
hb_font_get_glyph_func_t
|
||||
hb_set_invert
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-coretext</FILE>
|
||||
HB_CORETEXT_TAG_KERX
|
||||
HB_CORETEXT_TAG_MORT
|
||||
HB_CORETEXT_TAG_MORX
|
||||
hb_coretext_face_create
|
||||
hb_coretext_font_create
|
||||
hb_coretext_face_get_cg_font
|
||||
hb_coretext_font_get_ct_font
|
||||
</SECTION>
|
||||
@ -161,6 +172,7 @@ hb_face_create
|
||||
hb_face_create_for_tables
|
||||
hb_face_destroy
|
||||
hb_face_get_empty
|
||||
hb_face_get_table_tags
|
||||
hb_face_get_glyph_count
|
||||
hb_face_get_index
|
||||
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_extents_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_kerning_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_kerning_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_variation_glyph_func
|
||||
hb_font_funcs_t
|
||||
hb_font_get_empty
|
||||
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_from_name
|
||||
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_func_t
|
||||
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_origin
|
||||
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_ppem
|
||||
hb_font_get_ptem
|
||||
hb_font_get_scale
|
||||
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_to_string
|
||||
hb_font_is_immutable
|
||||
hb_font_make_immutable
|
||||
hb_font_reference
|
||||
hb_font_set_face
|
||||
hb_font_set_funcs
|
||||
hb_font_set_funcs_data
|
||||
hb_font_set_parent
|
||||
hb_font_set_ppem
|
||||
hb_font_set_ptem
|
||||
hb_font_set_scale
|
||||
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_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_h_extents
|
||||
hb_font_get_v_extents
|
||||
hb_font_set_parent
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
@ -270,6 +296,7 @@ hb_ft_face_create_cached
|
||||
hb_ft_face_create_referenced
|
||||
hb_ft_font_create
|
||||
hb_ft_font_create_referenced
|
||||
hb_ft_font_changed
|
||||
hb_ft_font_get_face
|
||||
hb_ft_font_set_load_flags
|
||||
hb_ft_font_get_load_flags
|
||||
@ -289,6 +316,7 @@ hb_glib_blob_create
|
||||
HB_GOBJECT_TYPE_BLOB
|
||||
HB_GOBJECT_TYPE_BUFFER
|
||||
HB_GOBJECT_TYPE_BUFFER_CONTENT_TYPE
|
||||
HB_GOBJECT_TYPE_BUFFER_DIFF_FLAGS
|
||||
HB_GOBJECT_TYPE_BUFFER_FLAGS
|
||||
HB_GOBJECT_TYPE_BUFFER_SERIALIZE_FLAGS
|
||||
HB_GOBJECT_TYPE_BUFFER_SERIALIZE_FORMAT
|
||||
@ -296,8 +324,14 @@ HB_GOBJECT_TYPE_DIRECTION
|
||||
HB_GOBJECT_TYPE_FACE
|
||||
HB_GOBJECT_TYPE_FONT
|
||||
HB_GOBJECT_TYPE_FONT_FUNCS
|
||||
HB_GOBJECT_TYPE_GLYPH_FLAGS
|
||||
HB_GOBJECT_TYPE_MEMORY_MODE
|
||||
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_SHAPE_PLAN
|
||||
HB_GOBJECT_TYPE_UNICODE_COMBINING_CLASS
|
||||
@ -312,6 +346,7 @@ HB_GOBJECT_TYPE_SET
|
||||
HB_GOBJECT_TYPE_USER_DATA_KEY
|
||||
hb_gobject_blob_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_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_font_funcs_get_type
|
||||
hb_gobject_font_get_type
|
||||
hb_gobject_glyph_flags_get_type
|
||||
hb_gobject_memory_mode_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_shape_plan_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_NO_FEATURE_INDEX
|
||||
HB_OT_LAYOUT_NO_SCRIPT_INDEX
|
||||
HB_OT_LAYOUT_NO_VARIATIONS_INDEX
|
||||
HB_OT_TAG_GDEF
|
||||
HB_OT_TAG_GPOS
|
||||
HB_OT_TAG_GSUB
|
||||
HB_OT_TAG_JSTF
|
||||
hb_ot_layout_collect_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_glyph_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_get_language_tags
|
||||
hb_ot_layout_table_choose_script
|
||||
hb_ot_layout_table_find_feature_variations
|
||||
hb_ot_layout_table_find_script
|
||||
hb_ot_layout_table_get_feature_tags
|
||||
hb_ot_layout_table_get_script_tags
|
||||
@ -416,6 +460,43 @@ Xhb_ot_layout_lookup_position
|
||||
Xhb_ot_layout_lookup_substitute
|
||||
</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>
|
||||
<FILE>hb-ot-tag</FILE>
|
||||
HB_OT_TAG_DEFAULT_LANGUAGE
|
||||
@ -444,11 +525,12 @@ hb_set_get_population
|
||||
hb_set_get_user_data
|
||||
hb_set_has
|
||||
hb_set_intersect
|
||||
hb_set_invert
|
||||
hb_set_is_empty
|
||||
hb_set_is_equal
|
||||
hb_set_next
|
||||
hb_set_previous
|
||||
hb_set_next_range
|
||||
hb_set_previous_range
|
||||
hb_set_reference
|
||||
hb_set_set
|
||||
hb_set_set_user_data
|
||||
@ -460,8 +542,8 @@ hb_set_union
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-shape</FILE>
|
||||
hb_feature_from_string
|
||||
hb_feature_t
|
||||
hb_feature_from_string
|
||||
hb_feature_to_string
|
||||
hb_shape
|
||||
hb_shape_full
|
||||
@ -472,6 +554,8 @@ hb_shape_list_shapers
|
||||
<FILE>hb-shape-plan</FILE>
|
||||
hb_shape_plan_create
|
||||
hb_shape_plan_create_cached
|
||||
hb_shape_plan_create2
|
||||
hb_shape_plan_create_cached2
|
||||
hb_shape_plan_destroy
|
||||
hb_shape_plan_execute
|
||||
hb_shape_plan_get_empty
|
||||
@ -526,6 +610,8 @@ hb_unicode_script_func_t
|
||||
<FILE>hb-uniscribe</FILE>
|
||||
hb_uniscribe_font_get_hfont
|
||||
hb_uniscribe_font_get_logfontw
|
||||
<SUBSECTION Private>
|
||||
hb_directwrite_shape_experimental_width
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<chapter id="buffers-language-script-and-direction">
|
||||
<title>Buffers, language, script and direction</title>
|
||||
<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
|
||||
the text that we want and then customize the properties of the
|
||||
buffer.
|
||||
@ -15,7 +15,7 @@
|
||||
default values and ready to accept your Unicode strings.
|
||||
</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
|
||||
a buffer, you can call <literal>hb_buffer_destroy()</literal>:
|
||||
</para>
|
||||
@ -27,7 +27,7 @@
|
||||
<para>
|
||||
This will destroy the object and free its associated memory -
|
||||
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
|
||||
else destroying it, you should increase its reference count:
|
||||
</para>
|
||||
@ -53,8 +53,8 @@ void somefunc(hb_buffer_t *buffer) {
|
||||
<section id="adding-text-to-the-buffer">
|
||||
<title>Adding text to the buffer</title>
|
||||
<para>
|
||||
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
|
||||
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
|
||||
of Unicode codepoints, but your input string is probably in one of
|
||||
the standard Unicode character encodings (UTF-8, UTF-16, UTF-32)
|
||||
</para>
|
||||
|
@ -290,11 +290,11 @@
|
||||
0 ,3,2,4
|
||||
</programlisting>
|
||||
<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.
|
||||
</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 (e.g. left-to-right Arabic). But that's too much of a
|
||||
corner case to worry about.
|
||||
|
@ -6,7 +6,7 @@
|
||||
</para>
|
||||
</section>
|
||||
<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>
|
||||
</section>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<chapter id="hello-harfbuzz">
|
||||
<title>Hello, Harfbuzz</title>
|
||||
<title>Hello, HarfBuzz</title>
|
||||
<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.
|
||||
</para>
|
||||
<orderedlist numeration="arabic">
|
||||
@ -91,23 +91,23 @@
|
||||
hb_font_destroy(hb_ft_font);
|
||||
</programlisting>
|
||||
<section id="what-harfbuzz-doesnt-do">
|
||||
<title>What Harfbuzz doesn't do</title>
|
||||
<title>What HarfBuzz doesn't do</title>
|
||||
<para>
|
||||
The code above will take a UTF8 string, shape it, and give you the
|
||||
information required to lay it out correctly on a single
|
||||
horizontal (or vertical) line using the font provided. That is the
|
||||
extent of Harfbuzz's responsibility.
|
||||
extent of HarfBuzz's responsibility.
|
||||
</para>
|
||||
<para>
|
||||
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>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<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
|
||||
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
|
||||
from the logical order in which the Unicode text is stored. In
|
||||
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
|
||||
algorithm as an annex to the Unicode Standard which tells you how
|
||||
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
|
||||
this for you.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<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
|
||||
<emphasis>huge</emphasis> breakfast", and you expect
|
||||
"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>breakfast</literal> using your Roman font again.
|
||||
Similarly if you change font, font size, script, language or
|
||||
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
|
||||
properties.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<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
|
||||
along a <emphasis>single line</emphasis> of, notionally,
|
||||
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.
|
||||
</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
|
||||
about paragraphs, lines or line lengths. Nor will it adjust the
|
||||
space between words to fit them proportionally into a line. If you
|
||||
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
|
||||
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.
|
||||
@ -171,12 +171,12 @@ ABC אבג DEF
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<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
|
||||
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
|
||||
started using Harfbuzz. Now we are going to use the remainder of
|
||||
Harfbuzz's API to refine that example and improve our text shaping
|
||||
started using HarfBuzz. Now we are going to use the remainder of
|
||||
HarfBuzz's API to refine that example and improve our text shaping
|
||||
capabilities.
|
||||
</para>
|
||||
</section>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<chapter id="install-harfbuzz">
|
||||
<title>Install Harfbuzz</title>
|
||||
<title>Install HarfBuzz</title>
|
||||
<section id="download">
|
||||
<title id="download.title">Download</title>
|
||||
<para>
|
||||
@ -12,7 +12,7 @@
|
||||
<para>
|
||||
The canonical source tree is available
|
||||
<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>
|
||||
The API that comes with <filename class='headerfile'>hb.h</filename> will
|
||||
@ -50,7 +50,7 @@
|
||||
and hb-shape under <filename>util/</filename>.
|
||||
</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,
|
||||
pkg-config and <ulink url="http://www.complang.org/ragel/">ragel</ulink>.
|
||||
Again, on Ubuntu / Debian:
|
||||
|
@ -1,7 +1,7 @@
|
||||
<chapter id="what-is-harfbuzz">
|
||||
<title>What is Harfbuzz?</title>
|
||||
<title>What is HarfBuzz?</title>
|
||||
<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
|
||||
Unicode string.
|
||||
</para>
|
||||
@ -9,17 +9,17 @@
|
||||
<title>Why do I need it?</title>
|
||||
<para>
|
||||
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
|
||||
in Firefox, LibreOffice and Chromium. Unless you are
|
||||
<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.
|
||||
</para>
|
||||
<para>
|
||||
However, if you <emphasis>are</emphasis> writing a layout engine
|
||||
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:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
@ -95,20 +95,20 @@
|
||||
<para>
|
||||
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;
|
||||
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
|
||||
implementor of a text layout engine.
|
||||
</para>
|
||||
</section>
|
||||
<section id="why-is-it-called-harfbuzz">
|
||||
<title>Why is it called Harfbuzz?</title>
|
||||
<title>Why is it called HarfBuzz?</title>
|
||||
<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
|
||||
within the source code copyright declarations) but was then
|
||||
abstracted out to its own project. This project is maintained by
|
||||
Behdad Esfahbod, and named Harfbuzz. Originally, it was a shaping
|
||||
engine for OpenType fonts - "Harfbuzz" is the Persian
|
||||
Behdad Esfahbod, and named HarfBuzz. Originally, it was a shaping
|
||||
engine for OpenType fonts - "HarfBuzz" is the Persian
|
||||
for "open type".
|
||||
</para>
|
||||
</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,
|
||||
# gnome-doc-utils, yelp.m4, mallard, intltool, gsettings, dejagnu, appdata,
|
||||
# appstream.
|
||||
# appstream, hotdoc.
|
||||
#
|
||||
# This makefile provides the following targets:
|
||||
#
|
||||
@ -86,6 +86,7 @@ GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL = \
|
||||
ar-lib \
|
||||
compile \
|
||||
config.guess \
|
||||
config.rpath \
|
||||
config.sub \
|
||||
depcomp \
|
||||
install-sh \
|
||||
@ -120,6 +121,47 @@ GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL = \
|
||||
lt~obsolete.m4 \
|
||||
; do echo "$$MACRO_DIR/$$x"; done; \
|
||||
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" \
|
||||
; do echo /$$x; done; \
|
||||
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 \
|
||||
for lc in $(HELP_LINGUAS); do \
|
||||
for x in \
|
||||
@ -235,6 +286,7 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
|
||||
fi; \
|
||||
if test -f $(srcdir)/po/Makefile.in.in; then \
|
||||
for x in \
|
||||
ABOUT-NLS \
|
||||
po/Makefile.in.in \
|
||||
po/Makefile.in.in~ \
|
||||
po/Makefile.in \
|
||||
@ -243,6 +295,7 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
|
||||
po/POTFILES \
|
||||
po/Rules-quot \
|
||||
po/stamp-it \
|
||||
po/stamp-po \
|
||||
po/.intltool-merge-cache \
|
||||
"po/*.gmo" \
|
||||
"po/*.header" \
|
||||
@ -274,7 +327,7 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
|
||||
if test "x$(am__dirstamp)" = x; then :; else \
|
||||
echo "$(am__dirstamp)"; \
|
||||
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 \
|
||||
"*.lo" \
|
||||
".libs" "_libs" \
|
||||
|
@ -13,7 +13,7 @@
|
||||
<!--download-page
|
||||
rdf:resource=""/-->
|
||||
<bug-database
|
||||
rdf:resource="http://bugs.freedesktop.org/enter_bug.cgi?product=harfbuzz"/>
|
||||
rdf:resource="https://github.com/harfbuzz/harfbuzz/issues" />
|
||||
|
||||
<maintainer>
|
||||
<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
|
||||
@ -19,10 +19,10 @@
|
||||
# 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,
|
||||
# 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
|
||||
#
|
||||
# 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:
|
||||
#
|
||||
# LIBS="$PTHREAD_LIBS $LIBS"
|
||||
@ -30,8 +30,8 @@
|
||||
# CC="$PTHREAD_CC"
|
||||
#
|
||||
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
||||
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
|
||||
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
|
||||
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||
#
|
||||
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
||||
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
||||
@ -67,7 +67,7 @@
|
||||
# Public License for more details.
|
||||
#
|
||||
# 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
|
||||
# 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
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 18
|
||||
#serial 24
|
||||
|
||||
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
||||
AC_DEFUN([AX_PTHREAD], [
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
AC_REQUIRE([AC_PROG_SED])
|
||||
AC_LANG_PUSH([C])
|
||||
ax_pthread_ok=no
|
||||
|
||||
# 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.
|
||||
|
||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||
# etcetera environment variables, and if threads linking works using
|
||||
# them:
|
||||
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
||||
save_CFLAGS="$CFLAGS"
|
||||
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
|
||||
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"
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
||||
AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
|
||||
AC_MSG_RESULT($ax_pthread_ok)
|
||||
if test x"$ax_pthread_ok" = xno; then
|
||||
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
|
||||
AC_MSG_RESULT([$ax_pthread_ok])
|
||||
if test "x$ax_pthread_ok" = "xno"; then
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
fi
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CC="$ax_pthread_save_CC"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
fi
|
||||
|
||||
# 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 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
|
||||
# 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
|
||||
# other compiler flags to prevent continual compiler warnings
|
||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
||||
# -pthreads: Solaris/gcc
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
|
||||
# (Note: HP C rejects this with "bad form for `-t' option")
|
||||
# -pthreads: Solaris/gcc (Note: HP C also rejects)
|
||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||
# doesn't hurt to check since this sometimes defines pthreads too;
|
||||
# also defines -D_REENTRANT)
|
||||
# ... -mt is also the pthreads flag for HP/aCC
|
||||
# doesn't hurt to check since this sometimes defines pthreads and
|
||||
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
|
||||
# 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
|
||||
# --thread-safe: KAI C++
|
||||
# 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*)
|
||||
|
||||
# On Solaris (at least, for some versions), libc contains stubbed
|
||||
# (non-functional) versions of the pthreads routines, so link-based
|
||||
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
||||
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
||||
# a function called by this macro, so we could check for that, but
|
||||
# who knows whether they'll stub that too in a future libc.) So,
|
||||
# we'll just look for -pthreads and -lpthread first:
|
||||
# tests will erroneously succeed. (N.B.: The stubs are missing
|
||||
# pthread_cleanup_push, or rather a function called by this macro,
|
||||
# so we could check for that, but who knows whether they'll stub
|
||||
# that too in a future libc.) So we'll check first for the
|
||||
# standard Solaris way of linking pthreads (-mt -lpthread).
|
||||
|
||||
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
darwin*)
|
||||
ax_pthread_flags="-pthread $ax_pthread_flags"
|
||||
ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test x"$ax_pthread_ok" = xno; then
|
||||
for flag in $ax_pthread_flags; do
|
||||
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
|
||||
|
||||
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)
|
||||
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])
|
||||
PTHREAD_CFLAGS="$flag"
|
||||
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
|
||||
PTHREAD_CFLAGS="$ax_pthread_try_flag"
|
||||
;;
|
||||
|
||||
pthread-config)
|
||||
AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
|
||||
if test x"$ax_pthread_config" = xno; then continue; fi
|
||||
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
|
||||
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
|
||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
||||
PTHREAD_LIBS="-l$flag"
|
||||
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
|
||||
PTHREAD_LIBS="-l$ax_pthread_try_flag"
|
||||
;;
|
||||
esac
|
||||
|
||||
save_LIBS="$LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
|
||||
# Check for various functions. We must include pthread.h,
|
||||
# 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
|
||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||
# We try pthread_create on general principles.
|
||||
|
||||
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 *start_routine(void *a) { return a; }],
|
||||
[pthread_t th; pthread_attr_t attr;
|
||||
@ -213,16 +379,14 @@ for flag in $ax_pthread_flags; do
|
||||
pthread_attr_init(&attr);
|
||||
pthread_cleanup_push(routine, 0);
|
||||
pthread_cleanup_pop(0) /* ; */])],
|
||||
[ax_pthread_ok=yes],
|
||||
[])
|
||||
[ax_pthread_ok=yes],
|
||||
[])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
AC_MSG_RESULT($ax_pthread_ok)
|
||||
if test "x$ax_pthread_ok" = xyes; then
|
||||
break;
|
||||
fi
|
||||
AC_MSG_RESULT([$ax_pthread_ok])
|
||||
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
|
||||
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
@ -230,76 +394,88 @@ done
|
||||
fi
|
||||
|
||||
# Various other checks:
|
||||
if test "x$ax_pthread_ok" = xyes; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
|
||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||
AC_MSG_CHECKING([for joinable pthread attribute])
|
||||
attr_name=unknown
|
||||
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||
[int attr = $attr; return attr /* ; */])],
|
||||
[attr_name=$attr; break],
|
||||
[])
|
||||
done
|
||||
AC_MSG_RESULT($attr_name)
|
||||
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
||||
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
|
||||
[Define to necessary symbol if this constant
|
||||
uses a non-standard name on your system.])
|
||||
fi
|
||||
AC_CACHE_CHECK([for joinable pthread attribute],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
|
||||
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||
[int attr = $ax_pthread_attr; return attr /* ; */])],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
|
||||
[])
|
||||
done
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
|
||||
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
|
||||
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
|
||||
[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])
|
||||
flag=no
|
||||
case ${host_os} in
|
||||
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
|
||||
osf* | hpux*) flag="-D_REENTRANT";;
|
||||
solaris*)
|
||||
if test "$GCC" = "yes"; then
|
||||
flag="-D_REENTRANT"
|
||||
else
|
||||
flag="-mt -D_REENTRANT"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT(${flag})
|
||||
if test "x$flag" != xno; then
|
||||
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
||||
fi
|
||||
AC_CACHE_CHECK([whether more special flags are required for pthreads],
|
||||
[ax_cv_PTHREAD_SPECIAL_FLAGS],
|
||||
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
|
||||
case $host_os in
|
||||
solaris*)
|
||||
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
|
||||
;;
|
||||
esac
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
|
||||
test "x$ax_pthread_special_flags_added" != "xyes"],
|
||||
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
|
||||
ax_pthread_special_flags_added=yes])
|
||||
|
||||
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
||||
ax_cv_PTHREAD_PRIO_INHERIT, [
|
||||
AC_LINK_IFELSE([
|
||||
AC_LANG_PROGRAM([[#include <pthread.h>]], [[int i = PTHREAD_PRIO_INHERIT;]])],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT],
|
||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
||||
[[int i = PTHREAD_PRIO_INHERIT;]])],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
|
||||
AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
|
||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
|
||||
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="$save_CFLAGS"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
# More AIX lossage: must compile with xlc_r or cc_r
|
||||
if test x"$GCC" != xyes; then
|
||||
AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
|
||||
else
|
||||
PTHREAD_CC=$CC
|
||||
# More AIX lossage: compile with *_r variant
|
||||
if test "x$GCC" != "xyes"; then
|
||||
case $host_os in
|
||||
aix*)
|
||||
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
|
||||
else
|
||||
PTHREAD_CC="$CC"
|
||||
fi
|
||||
|
||||
AC_SUBST(PTHREAD_LIBS)
|
||||
AC_SUBST(PTHREAD_CFLAGS)
|
||||
AC_SUBST(PTHREAD_CC)
|
||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
||||
|
||||
AC_SUBST([PTHREAD_LIBS])
|
||||
AC_SUBST([PTHREAD_CFLAGS])
|
||||
AC_SUBST([PTHREAD_CC])
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
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])
|
||||
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])
|
||||
:
|
||||
else
|
||||
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
|
||||
|
||||
NULL =
|
||||
SUBDIRS =
|
||||
DIST_SUBDIRS =
|
||||
BUILT_SOURCES =
|
||||
@ -8,12 +9,14 @@ CLEANFILES =
|
||||
DISTCLEANFILES =
|
||||
MAINTAINERCLEANFILES =
|
||||
DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
|
||||
TESTS =
|
||||
check_PROGRAMS =
|
||||
|
||||
# The following warning options are useful for debugging: -Wpadded
|
||||
#AM_CXXFLAGS =
|
||||
|
||||
# Convenience targets:
|
||||
lib: $(BUILT_SOURCES) libharfbuzz.la
|
||||
lib: $(BUILT_SOURCES) libharfbuzz.la libharfbuzz-subset.la
|
||||
fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la
|
||||
|
||||
lib_LTLIBRARIES = libharfbuzz.la
|
||||
@ -25,11 +28,21 @@ HBLIBS =
|
||||
HBNONPCLIBS =
|
||||
HBDEPS =
|
||||
HBSOURCES = $(HB_BASE_sources)
|
||||
HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
|
||||
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
|
||||
HBSOURCES += $(HB_OT_sources)
|
||||
HBSOURCES += $(HB_OT_RAGEL_GENERATED_sources)
|
||||
HBHEADERS += $(HB_OT_headers)
|
||||
endif
|
||||
|
||||
@ -97,6 +110,9 @@ SUBDIRS += hb-ucdn
|
||||
HBCFLAGS += -I$(srcdir)/hb-ucdn
|
||||
HBLIBS += hb-ucdn/libhb-ucdn.la
|
||||
HBSOURCES += $(HB_UCDN_sources)
|
||||
hb-ucdn/libhb-ucdn.la: ucdn
|
||||
ucdn:
|
||||
@$(MAKE) $(AM_MAKEFLAGS) -C hb-ucdn
|
||||
endif
|
||||
DIST_SUBDIRS += hb-ucdn
|
||||
|
||||
@ -108,40 +124,69 @@ HBLIBS += $(HBNONPCLIBS)
|
||||
if OS_WIN32
|
||||
export_symbols = -export-symbols 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
|
||||
# Use a C linker for GCC, not C++; Don't link to libstdc++
|
||||
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
|
||||
libharfbuzz_la_LINK = $(CXXLINK) $(libharfbuzz_la_LDFLAGS)
|
||||
chosen_linker = $(CXXLINK)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS) $(HBNODISTHEADERS)
|
||||
libharfbuzz_la_CPPFLAGS = $(HBCFLAGS)
|
||||
libharfbuzz_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) $(export_symbols) -no-undefined
|
||||
base_link_flags = $(AM_LDFLAGS) -lm -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
|
||||
libharfbuzz_la_LINK = $(chosen_linker) $(libharfbuzz_la_LDFLAGS)
|
||||
libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS)
|
||||
libharfbuzz_la_CPPFLAGS = $(HBCFLAGS) $(HBNOLIBCXXFLAGS)
|
||||
libharfbuzz_la_LDFLAGS = $(base_link_flags) $(export_symbols)
|
||||
libharfbuzz_la_LIBADD = $(HBLIBS)
|
||||
EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency)
|
||||
pkginclude_HEADERS = $(HBHEADERS)
|
||||
nodist_pkginclude_HEADERS = $(HBNODISTHEADERS)
|
||||
nodist_pkginclude_HEADERS =
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
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_MAX_NESTING_LEVEL=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_DEFAULT=128 \
|
||||
-DHB_BUFFER_MAX_OPS_FACTOR=8 \
|
||||
-DHB_BUFFER_MAX_OPS_MIN=64 \
|
||||
-DHB_BUFFER_MAX_OPS_DEFAULT=1024 \
|
||||
$(NULL)
|
||||
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_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS) $(FUZZING_CPPFLAGS)
|
||||
libharfbuzz_fuzzing_la_LDFLAGS = $(libharfbuzz_la_LDFLAGS)
|
||||
libharfbuzz_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(FUZZING_CPPFLAGS)
|
||||
libharfbuzz_fuzzing_la_LDFLAGS = $(AM_LDFLAGS)
|
||||
libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD)
|
||||
EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES)
|
||||
CLEANFILES += libharfbuzz-fuzzing.la
|
||||
@ -155,9 +200,10 @@ HBHEADERS += $(HB_ICU_headers)
|
||||
else
|
||||
lib_LTLIBRARIES += libharfbuzz-icu.la
|
||||
libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
|
||||
libharfbuzz_icu_la_CPPFLAGS = $(ICU_CFLAGS)
|
||||
libharfbuzz_icu_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
|
||||
libharfbuzz_icu_la_CPPFLAGS = $(HBCFLAGS) $(ICU_CFLAGS)
|
||||
libharfbuzz_icu_la_LDFLAGS = $(base_link_flags) $(export_symbols_icu)
|
||||
libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la
|
||||
EXTRA_libharfbuzz_icu_la_DEPENDENCIES = $(harfbuzz_icu_def_dependency)
|
||||
pkginclude_HEADERS += $(HB_ICU_headers)
|
||||
pkgconfig_DATA += harfbuzz-icu.pc
|
||||
endif
|
||||
@ -166,13 +212,15 @@ EXTRA_DIST += harfbuzz-icu.pc.in
|
||||
|
||||
if HAVE_GOBJECT
|
||||
lib_LTLIBRARIES += libharfbuzz-gobject.la
|
||||
libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_sources)
|
||||
nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_ENUM_sources)
|
||||
libharfbuzz_gobject_la_CPPFLAGS = $(GOBJECT_CFLAGS)
|
||||
libharfbuzz_gobject_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
|
||||
libharfbuzz_gobject_la_LINK = $(chosen_linker) $(libharfbuzz_gobject_la_LDFLAGS)
|
||||
libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_DIST_sources)
|
||||
nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_NODIST_sources)
|
||||
libharfbuzz_gobject_la_CPPFLAGS = $(HBCFLAGS) $(HBNOLIBCXXFLAGS) $(GOBJECT_CFLAGS)
|
||||
libharfbuzz_gobject_la_LDFLAGS = $(base_link_flags)
|
||||
libharfbuzz_gobject_la_LIBADD = $(GOBJECT_LIBS) libharfbuzz.la
|
||||
pkginclude_HEADERS += $(HB_GOBJECT_headers)
|
||||
nodist_pkginclude_HEADERS += $(HB_GOBJECT_ENUM_headers)
|
||||
EXTRA_libharfbuzz_gobject_la_DEPENDENCIES = $(harfbuzz_gobject_def_dependency)
|
||||
pkginclude_HEADERS += $(HB_GOBJECT_DIST_headers)
|
||||
nodist_pkginclude_HEADERS += $(HB_GOBJECT_NODIST_headers)
|
||||
pkgconfig_DATA += harfbuzz-gobject.pc
|
||||
|
||||
BUILT_SOURCES += \
|
||||
@ -212,23 +260,27 @@ EXTRA_DIST += \
|
||||
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)
|
||||
$(AM_V_GEN) (echo EXPORTS; \
|
||||
(cat $^ || echo 'hb_ERROR ()' ) | \
|
||||
$(EGREP) '^hb_.* \(' | \
|
||||
sed -e 's/ (.*//' | \
|
||||
LANG=C sort; \
|
||||
echo LIBRARY libharfbuzz-0.dll; \
|
||||
) >"$@"
|
||||
@ ! grep -q hb_ERROR "$@" \
|
||||
|| ($(RM) "$@"; false)
|
||||
$(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@
|
||||
harfbuzz-subset.def: $(HB_SUBSET_headers)
|
||||
$(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@
|
||||
harfbuzz-icu.def: $(HB_ICU_headers)
|
||||
$(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@
|
||||
harfbuzz-gobject.def: $(HB_GOBJECT_headers)
|
||||
$(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@
|
||||
|
||||
|
||||
GENERATORS = \
|
||||
gen-arabic-table.py \
|
||||
gen-indic-table.py \
|
||||
gen-use-table.py \
|
||||
gen-def.py \
|
||||
$(NULL)
|
||||
EXTRA_DIST += $(GENERATORS)
|
||||
|
||||
@ -251,21 +303,16 @@ built-sources: $(BUILT_SOURCES)
|
||||
.PHONY: unicode-tables arabic-table indic-table use-table built-sources
|
||||
|
||||
RAGEL_GENERATED = \
|
||||
$(srcdir)/hb-buffer-deserialize-json.hh \
|
||||
$(srcdir)/hb-buffer-deserialize-text.hh \
|
||||
$(srcdir)/hb-ot-shape-complex-indic-machine.hh \
|
||||
$(srcdir)/hb-ot-shape-complex-myanmar-machine.hh \
|
||||
$(srcdir)/hb-ot-shape-complex-use-machine.hh \
|
||||
$(patsubst %,$(srcdir)/%,$(HB_BASE_RAGEL_GENERATED_sources)) \
|
||||
$(patsubst %,$(srcdir)/%,$(HB_OT_RAGEL_GENERATED_sources)) \
|
||||
$(NULL)
|
||||
BUILT_SOURCES += $(RAGEL_GENERATED)
|
||||
EXTRA_DIST += \
|
||||
hb-buffer-deserialize-json.rl \
|
||||
hb-buffer-deserialize-text.rl \
|
||||
hb-ot-shape-complex-indic-machine.rl \
|
||||
hb-ot-shape-complex-myanmar-machine.rl \
|
||||
hb-ot-shape-complex-use-machine.rl \
|
||||
$(HB_BASE_RAGEL_sources) \
|
||||
$(HB_OT_RAGEL_sources) \
|
||||
$(NULL)
|
||||
MAINTAINERCLEANFILES += $(RAGEL_GENERATED)
|
||||
# We decided to add ragel-generated files to git...
|
||||
#MAINTAINERCLEANFILES += $(RAGEL_GENERATED)
|
||||
$(srcdir)/%.hh: $(srcdir)/%.rl
|
||||
$(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \
|
||||
|| ($(RM) "$@"; false)
|
||||
@ -301,30 +348,55 @@ test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
dist_check_SCRIPTS = \
|
||||
check-c-linkage-decls.sh \
|
||||
check-defs.sh \
|
||||
check-externs.sh \
|
||||
check-header-guards.sh \
|
||||
check-includes.sh \
|
||||
check-libstdc++.sh \
|
||||
check-static-inits.sh \
|
||||
check-symbols.sh \
|
||||
$(NULL)
|
||||
TESTS += $(dist_check_SCRIPTS)
|
||||
|
||||
check_PROGRAMS = \
|
||||
test-ot-tag \
|
||||
if !WITH_LIBSTDCXX
|
||||
dist_check_SCRIPTS += \
|
||||
check-libstdc++.sh \
|
||||
$(NULL)
|
||||
test_ot_color_SOURCES = hb-ot-color.cc
|
||||
test_ot_color_CPPFLAGS = $(HBCFLAGS) -DMAIN
|
||||
test_ot_color_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
endif
|
||||
|
||||
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_CPPFLAGS = $(HBCFLAGS) -DMAIN
|
||||
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 = \
|
||||
srcdir="$(srcdir)" \
|
||||
MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
|
||||
HBSOURCES="$(HBSOURCES)" \
|
||||
HBHEADERS="$(HBHEADERS) $(HBNODISTHEADERS)" \
|
||||
HBHEADERS="$(HBHEADERS)" \
|
||||
$(NULL)
|
||||
|
||||
if HAVE_INTROSPECTION
|
||||
@ -354,12 +426,9 @@ HarfBuzz_0_0_gir_LIBS = \
|
||||
$(NULL)
|
||||
HarfBuzz_0_0_gir_FILES = \
|
||||
$(HBHEADERS) \
|
||||
$(HBNODISTHEADERS) \
|
||||
$(HBSOURCES) \
|
||||
$(HB_GOBJECT_ENUM_sources) \
|
||||
$(HB_GOBJECT_ENUM_headers) \
|
||||
$(HB_GOBJECT_sources) \
|
||||
$(HB_GOBJECT_STRUCTS_headers) \
|
||||
$(HB_GOBJECT_headers) \
|
||||
$(NULL)
|
||||
|
||||
girdir = $(datadir)/gir-1.0
|
||||
|
@ -1,17 +1,14 @@
|
||||
NULL =
|
||||
|
||||
# Base and default-included sources and headers
|
||||
|
||||
HB_BASE_sources = \
|
||||
hb-atomic-private.hh \
|
||||
hb-blob.cc \
|
||||
hb-buffer-deserialize-json.hh \
|
||||
hb-buffer-deserialize-text.hh \
|
||||
hb-buffer-private.hh \
|
||||
hb-buffer-serialize.cc \
|
||||
hb-buffer.cc \
|
||||
hb-cache-private.hh \
|
||||
hb-common.cc \
|
||||
hb-debug.hh \
|
||||
hb-dsalgs.hh \
|
||||
hb-face-private.hh \
|
||||
hb-face.cc \
|
||||
hb-font-private.hh \
|
||||
@ -20,17 +17,23 @@ HB_BASE_sources = \
|
||||
hb-object-private.hh \
|
||||
hb-open-file-private.hh \
|
||||
hb-open-type-private.hh \
|
||||
hb-ot-cbdt-table.hh \
|
||||
hb-ot-cmap-table.hh \
|
||||
hb-ot-glyf-table.hh \
|
||||
hb-ot-hdmx-table.hh \
|
||||
hb-ot-head-table.hh \
|
||||
hb-ot-hhea-table.hh \
|
||||
hb-ot-hmtx-table.hh \
|
||||
hb-ot-kern-table.hh \
|
||||
hb-ot-maxp-table.hh \
|
||||
hb-ot-name-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-tag.cc \
|
||||
hb-private.hh \
|
||||
hb-set-digest-private.hh \
|
||||
hb-set-private.hh \
|
||||
hb-set.cc \
|
||||
hb-shape.cc \
|
||||
@ -40,12 +43,22 @@ HB_BASE_sources = \
|
||||
hb-shaper-impl-private.hh \
|
||||
hb-shaper-private.hh \
|
||||
hb-shaper.cc \
|
||||
hb-string-array.hh \
|
||||
hb-unicode-private.hh \
|
||||
hb-unicode.cc \
|
||||
hb-utf-private.hh \
|
||||
hb-warning.cc \
|
||||
$(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.h \
|
||||
hb-blob.h \
|
||||
@ -58,19 +71,24 @@ HB_BASE_headers = \
|
||||
hb-shape.h \
|
||||
hb-shape-plan.h \
|
||||
hb-unicode.h \
|
||||
$(NULL)
|
||||
|
||||
HB_NODIST_headers = \
|
||||
hb-version.h \
|
||||
$(NULL)
|
||||
|
||||
HB_FALLBACK_sources = hb-fallback-shape.cc
|
||||
HB_FALLBACK_sources = \
|
||||
hb-fallback-shape.cc \
|
||||
$(NULL)
|
||||
|
||||
HB_OT_sources = \
|
||||
hb-ot-color.cc \
|
||||
hb-ot-cpal-table.hh \
|
||||
hb-aat-layout.cc \
|
||||
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-layout.cc \
|
||||
hb-ot-layout-base-table.hh \
|
||||
hb-ot-layout-common-private.hh \
|
||||
hb-ot-layout-gdef-table.hh \
|
||||
hb-ot-layout-gpos-table.hh \
|
||||
@ -78,8 +96,12 @@ HB_OT_sources = \
|
||||
hb-ot-layout-gsub-table.hh \
|
||||
hb-ot-layout-jstf-table.hh \
|
||||
hb-ot-layout-private.hh \
|
||||
hb-ot-color.cc \
|
||||
hb-ot-cpal-table.hh \
|
||||
hb-ot-map.cc \
|
||||
hb-ot-map-private.hh \
|
||||
hb-ot-math.cc \
|
||||
hb-ot-math-table.hh \
|
||||
hb-ot-shape.cc \
|
||||
hb-ot-shape-complex-arabic.cc \
|
||||
hb-ot-shape-complex-arabic-fallback.hh \
|
||||
@ -90,15 +112,15 @@ HB_OT_sources = \
|
||||
hb-ot-shape-complex-hangul.cc \
|
||||
hb-ot-shape-complex-hebrew.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-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-machine.hh \
|
||||
hb-ot-shape-complex-thai.cc \
|
||||
hb-ot-shape-complex-tibetan.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-table.cc \
|
||||
hb-ot-shape-complex-private.hh \
|
||||
@ -107,6 +129,24 @@ HB_OT_sources = \
|
||||
hb-ot-shape-fallback-private.hh \
|
||||
hb-ot-shape-fallback.cc \
|
||||
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)
|
||||
|
||||
HB_OT_headers = \
|
||||
@ -114,8 +154,11 @@ HB_OT_headers = \
|
||||
hb-ot-color.h \
|
||||
hb-ot-font.h \
|
||||
hb-ot-layout.h \
|
||||
hb-ot-math.h \
|
||||
hb-ot-base.h \
|
||||
hb-ot-shape.h \
|
||||
hb-ot-tag.h \
|
||||
hb-ot-var.h \
|
||||
$(NULL)
|
||||
|
||||
# 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_headers = hb-icu.h
|
||||
|
||||
HB_GOBJECT_sources = hb-gobject-structs.cc
|
||||
HB_GOBJECT_STRUCTS_headers = hb-gobject-structs.h
|
||||
HB_GOBJECT_headers = hb-gobject.h $(HB_GOBJECT_STRUCTS_headers)
|
||||
# Sources for libharfbuzz-subset
|
||||
HB_SUBSET_sources = \
|
||||
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_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
|
||||
|
||||
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
|
||||
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
|
||||
echo "Ouch, file $x does not have HB_BEGIN_DECLS / HB_END_DECLS, but it should"
|
||||
stat=1
|
||||
fi
|
||||
done
|
||||
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
|
||||
echo "Ouch, file $x has HB_BEGIN_DECLS / HB_END_DECLS, but it shouldn't"
|
||||
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=.
|
||||
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'`
|
||||
|
||||
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;
|
||||
xx=`echo "$x" | sed 's@.*/@@'`
|
||||
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)'
|
||||
|
||||
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
|
||||
done |
|
||||
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)'
|
||||
|
||||
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
|
||||
done |
|
||||
grep -v '"hb-.*private[.]hh"' |
|
||||
@ -34,7 +34,7 @@ grep -v 'hb-private[.]hh:' |
|
||||
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
|
||||
test -f "$srcdir/$x" && x="$srcdir/$x"
|
||||
grep '#.*\<include\>.*<.*hb' "$x" /dev/null >&2 && stat=1
|
||||
|
@ -4,27 +4,37 @@ LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
test -z "$srcdir" && srcdir=.
|
||||
test -z "$libs" && libs=.libs
|
||||
stat=0
|
||||
|
||||
|
||||
if which ldd 2>/dev/null >/dev/null; then
|
||||
:
|
||||
LDD=ldd
|
||||
else
|
||||
echo "check-libstdc++.sh: 'ldd' not found; skipping test"
|
||||
exit 77
|
||||
# macOS specific tool
|
||||
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
|
||||
|
||||
tested=false
|
||||
for suffix in so dylib; do
|
||||
so=.libs/libharfbuzz.$suffix
|
||||
if ! test -f "$so"; then continue; fi
|
||||
# harfbuzz-icu links to libstdc++ because icu does.
|
||||
# harfbuzz-subset uses libstdc++.
|
||||
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++"
|
||||
if ldd $so | grep 'libstdc[+][+]\|libc[+][+]'; then
|
||||
echo "Ouch, linked to libstdc++ or libc++"
|
||||
stat=1
|
||||
fi
|
||||
tested=true
|
||||
echo "Checking that we are not linking to libstdc++ or libc++ in $so"
|
||||
if $LDD $so | grep 'libstdc[+][+]\|libc[+][+]'; then
|
||||
echo "Ouch, linked to libstdc++ or libc++"
|
||||
stat=1
|
||||
fi
|
||||
tested=true
|
||||
done
|
||||
done
|
||||
if ! $tested; then
|
||||
echo "check-libstdc++.sh: libharfbuzz shared library not found; skipping test"
|
||||
|
@ -4,6 +4,7 @@ LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
test -z "$srcdir" && srcdir=.
|
||||
test -z "$libs" && libs=.libs
|
||||
stat=0
|
||||
|
||||
|
||||
@ -14,7 +15,7 @@ else
|
||||
exit 77
|
||||
fi
|
||||
|
||||
OBJS=.libs/*.o
|
||||
OBJS=$libs/*.o
|
||||
if test "x`echo $OBJS`" = "x$OBJS" 2>/dev/null >/dev/null; then
|
||||
echo "check-static-inits.sh: object files not found; skipping test"
|
||||
exit 77
|
||||
|
@ -4,8 +4,10 @@ LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
test -z "$srcdir" && srcdir=.
|
||||
test -z "$libs" && libs=.libs
|
||||
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
|
||||
:
|
||||
@ -14,29 +16,46 @@ else
|
||||
exit 77
|
||||
fi
|
||||
|
||||
echo "Checking that we are not exposing internal symbols"
|
||||
tested=false
|
||||
for suffix in so dylib; do
|
||||
so=.libs/libharfbuzz.$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`"
|
||||
for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do
|
||||
for suffix in so dylib; do
|
||||
so=$libs/lib$soname.$suffix
|
||||
if ! test -f "$so"; then continue; fi
|
||||
|
||||
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 _
|
||||
if test $suffix = dylib; then prefix="_$prefix"; fi
|
||||
EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`"
|
||||
|
||||
echo "Processing $so"
|
||||
if echo "$EXPORTED_SYMBOLS" | grep -v "^${prefix}_"; then
|
||||
echo "Ouch, internal symbols exposed"
|
||||
stat=1
|
||||
fi
|
||||
prefix=$symprefix`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'`
|
||||
|
||||
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
|
||||
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
|
||||
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:
|
||||
if p not in [start>>page_bits, end>>page_bits]: continue
|
||||
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 ""
|
||||
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()])
|
||||
for p in sorted(pages):
|
||||
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 ():
|
||||
if p != u>>page_bits: continue
|
||||
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 ""
|
||||
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
|
||||
data[0][0x034F] = defaults[0]
|
||||
data[0][0x2060] = defaults[0]
|
||||
data[0][0x20F0] = defaults[0]
|
||||
for u in range (0xFE00, 0xFE0F + 1):
|
||||
data[0][u] = defaults[0]
|
||||
|
||||
@ -117,6 +118,7 @@ property_names = [
|
||||
'Top_And_Right',
|
||||
'Top_And_Left',
|
||||
'Top_And_Left_And_Right',
|
||||
'Bottom_And_Left',
|
||||
'Bottom_And_Right',
|
||||
'Top_And_Bottom_And_Right',
|
||||
'Overstruck',
|
||||
@ -153,7 +155,7 @@ def is_BASE(U, UISC, UGC):
|
||||
def is_BASE_IND(U, UISC, UGC):
|
||||
#SPEC-DRAFT return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po)
|
||||
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
|
||||
)
|
||||
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):
|
||||
#SPEC-DRAFT return UISC == Consonant_Subjoined
|
||||
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):
|
||||
return UISC in [Virama, Invisible_Stacker]
|
||||
def is_HALANT_NUM(U, UISC, UGC):
|
||||
@ -198,9 +202,7 @@ def is_OTHER(U, UISC, UGC):
|
||||
def is_Reserved(U, UISC, UGC):
|
||||
return UGC == 'Cn'
|
||||
def is_REPHA(U, UISC, UGC):
|
||||
#return UISC == Consonant_Preceding_Repha
|
||||
#SPEC-OUTDATED hack to categorize Consonant_With_Stacker and Consonant_Prefixed
|
||||
return UISC in [Consonant_Preceding_Repha, Consonant_With_Stacker, Consonant_Prefixed]
|
||||
return UISC in [Consonant_Preceding_Repha, Consonant_Prefixed]
|
||||
def is_SYM(U, UISC, UGC):
|
||||
if U == 0x25CC: return False #SPEC-DRAFT
|
||||
#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):
|
||||
return 0xFE00 <= U <= 0xFE0F
|
||||
def is_VOWEL(U, UISC, UGC):
|
||||
# https://github.com/roozbehp/unicode-data/issues/6
|
||||
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):
|
||||
# https://github.com/roozbehp/unicode-data/issues/6
|
||||
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 = {
|
||||
'B': is_BASE,
|
||||
@ -227,6 +231,7 @@ use_mapping = {
|
||||
'M': is_CONS_MED,
|
||||
'CM': is_CONS_MOD,
|
||||
'SUB': is_CONS_SUB,
|
||||
'CS': is_CONS_WITH_STACKER,
|
||||
'H': is_HALANT,
|
||||
'HN': is_HALANT_NUM,
|
||||
'ZWNJ': is_ZWNJ,
|
||||
@ -250,7 +255,7 @@ use_positions = {
|
||||
},
|
||||
'M': {
|
||||
'Abv': [Top],
|
||||
'Blw': [Bottom],
|
||||
'Blw': [Bottom, Bottom_And_Left],
|
||||
'Pst': [Right],
|
||||
'Pre': [Left],
|
||||
},
|
||||
@ -292,12 +297,23 @@ def map_to_use(data):
|
||||
if U == 0x17DD: UISC = Vowel_Dependent
|
||||
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
|
||||
# the nasalization marks, maybe only for U+1CE9..U+1CF1.
|
||||
if U == 0x1CED: UISC = Tone_Mark
|
||||
|
||||
evals = [(k, v(U,UISC,UGC)) for k,v in items]
|
||||
values = [k for k,v in evals if v]
|
||||
# TODO: https://github.com/harfbuzz/harfbuzz/issues/525
|
||||
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)
|
||||
USE = values[0]
|
||||
|
||||
@ -336,12 +352,6 @@ def map_to_use(data):
|
||||
defaults = ('O', 'No_Block')
|
||||
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 "/*"
|
||||
print " * The following table is generated by running:"
|
||||
@ -439,20 +449,17 @@ page_bits = 12
|
||||
print "}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy)
|
||||
print
|
||||
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 " switch (u >> %d)" % page_bits
|
||||
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):
|
||||
print " case 0x%0Xu:" % p
|
||||
for (start,end) in zip (starts, ends):
|
||||
if p not in [start>>page_bits, end>>page_bits]: continue
|
||||
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)
|
||||
for u,d in singles.items ():
|
||||
if p != u>>page_bits: continue
|
||||
print " if (unlikely (u == 0x%04Xu)) return %s;" % (u, d[0])
|
||||
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)
|
||||
print " break;"
|
||||
print ""
|
||||
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%
|
||||
|
||||
Libs: -L${libdir} -lharfbuzz
|
||||
Libs.private: %libs_private%
|
||||
Libs.private: -lm %libs_private%
|
||||
Requires.private: %requires_private%
|
||||
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))
|
||||
|
||||
|
||||
#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)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
#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__)
|
||||
|
||||
#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();
|
||||
int result = __fetch_and_add(AI, V);
|
||||
__isync();
|
||||
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();
|
||||
int result = __compare_and_swaplp (P, &O, N);
|
||||
__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;
|
||||
#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_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)
|
||||
|
||||
|
@ -26,10 +26,11 @@
|
||||
|
||||
/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */
|
||||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#endif
|
||||
|
||||
#include "hb-private.hh"
|
||||
#include "hb-debug.hh"
|
||||
|
||||
#include "hb-object-private.hh"
|
||||
|
||||
@ -44,12 +45,6 @@
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
|
||||
#ifndef HB_DEBUG_BLOB
|
||||
#define HB_DEBUG_BLOB (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
|
||||
struct hb_blob_t {
|
||||
hb_object_header_t header;
|
||||
ASSERT_POD ();
|
||||
@ -72,8 +67,8 @@ _hb_blob_destroy_user_data (hb_blob_t *blob)
|
||||
{
|
||||
if (blob->destroy) {
|
||||
blob->destroy (blob->user_data);
|
||||
blob->user_data = NULL;
|
||||
blob->destroy = NULL;
|
||||
blob->user_data = nullptr;
|
||||
blob->destroy = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,6 +123,12 @@ hb_blob_create (const char *data,
|
||||
return blob;
|
||||
}
|
||||
|
||||
static void
|
||||
_hb_blob_destroy (void *data)
|
||||
{
|
||||
hb_blob_destroy ((hb_blob_t *) data);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_blob_create_sub_blob:
|
||||
* @parent: Parent blob.
|
||||
@ -164,7 +165,32 @@ hb_blob_create_sub_blob (hb_blob_t *parent,
|
||||
MIN (length, parent->length - offset),
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
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;
|
||||
}
|
||||
@ -188,12 +214,12 @@ hb_blob_get_empty (void)
|
||||
|
||||
true, /* immutable */
|
||||
|
||||
NULL, /* data */
|
||||
nullptr, /* data */
|
||||
0, /* length */
|
||||
HB_MEMORY_MODE_READONLY, /* mode */
|
||||
|
||||
NULL, /* user_data */
|
||||
NULL /* destroy */
|
||||
nullptr, /* user_data */
|
||||
nullptr /* destroy */
|
||||
};
|
||||
|
||||
return const_cast<hb_blob_t *> (&_hb_blob_nil);
|
||||
@ -221,7 +247,7 @@ hb_blob_reference (hb_blob_t *blob)
|
||||
* hb_blob_destroy: (skip)
|
||||
* @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
|
||||
* 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)
|
||||
*length = 0;
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (length)
|
||||
|
@ -44,7 +44,7 @@ HB_BEGIN_DECLS
|
||||
* any such possibility, MODE_DUPLICATE should be used
|
||||
* 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,
|
||||
*
|
||||
* - 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 length);
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
hb_blob_copy_writable_or_fail (hb_blob_t *blob);
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
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;
|
||||
|
||||
/* 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))
|
||||
p++;
|
||||
@ -115,7 +115,7 @@ _hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer,
|
||||
*end_ptr = ++p;
|
||||
}
|
||||
|
||||
const char *tok = NULL;
|
||||
const char *tok = nullptr;
|
||||
int cs;
|
||||
hb_glyph_info_t info = {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;
|
||||
|
||||
/* 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))
|
||||
p++;
|
||||
@ -109,7 +109,7 @@ _hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer,
|
||||
*end_ptr = ++p;
|
||||
}
|
||||
|
||||
const char *eof = pe, *tok = NULL;
|
||||
const char *eof = pe, *tok = nullptr;
|
||||
int cs;
|
||||
hb_glyph_info_t info = {0};
|
||||
hb_glyph_position_t pos = {0};
|
||||
|
@ -35,8 +35,8 @@
|
||||
#include "hb-unicode-private.hh"
|
||||
|
||||
|
||||
#ifndef HB_BUFFER_MAX_EXPANSION_FACTOR
|
||||
#define HB_BUFFER_MAX_EXPANSION_FACTOR 32
|
||||
#ifndef HB_BUFFER_MAX_LEN_FACTOR
|
||||
#define HB_BUFFER_MAX_LEN_FACTOR 32
|
||||
#endif
|
||||
#ifndef HB_BUFFER_MAX_LEN_MIN
|
||||
#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! */
|
||||
#endif
|
||||
|
||||
ASSERT_STATIC (sizeof (hb_glyph_info_t) == 20);
|
||||
ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
|
||||
#ifndef HB_BUFFER_MAX_OPS_FACTOR
|
||||
#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_serialize_flags_t);
|
||||
HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
|
||||
|
||||
enum hb_buffer_scratch_flags_t {
|
||||
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_SPACE_FALLBACK = 0x00000004u,
|
||||
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. */
|
||||
HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
|
||||
HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u,
|
||||
@ -79,8 +93,9 @@ struct hb_buffer_t {
|
||||
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
|
||||
hb_buffer_cluster_level_t cluster_level;
|
||||
hb_codepoint_t replacement; /* U+FFFD or something else. */
|
||||
hb_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. */
|
||||
int max_ops; /* Maximum allowed operations. */
|
||||
|
||||
/* Buffer contents */
|
||||
hb_buffer_content_type_t content_type;
|
||||
@ -99,17 +114,6 @@ struct hb_buffer_t {
|
||||
hb_glyph_info_t *out_info;
|
||||
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;
|
||||
|
||||
/* Text before / after the main buffer contents.
|
||||
@ -129,12 +133,16 @@ struct hb_buffer_t {
|
||||
#ifndef HB_NDEBUG
|
||||
uint8_t allocated_var_bits;
|
||||
#endif
|
||||
|
||||
|
||||
/* Methods */
|
||||
|
||||
inline void allocate_var (unsigned int start, unsigned int count)
|
||||
{
|
||||
#ifndef HB_NDEBUG
|
||||
unsigned int end = start + count;
|
||||
assert (end <= 8);
|
||||
unsigned int bits = (1<<end) - (1<<start);
|
||||
unsigned int bits = (1u<<end) - (1u<<start);
|
||||
assert (0 == (allocated_var_bits & bits));
|
||||
allocated_var_bits |= bits;
|
||||
#endif
|
||||
@ -144,7 +152,7 @@ struct hb_buffer_t {
|
||||
#ifndef HB_NDEBUG
|
||||
unsigned int end = start + count;
|
||||
assert (end <= 8);
|
||||
unsigned int bits = (1<<end) - (1<<start);
|
||||
unsigned int bits = (1u<<end) - (1u<<start);
|
||||
assert (bits == (allocated_var_bits & bits));
|
||||
allocated_var_bits &= ~bits;
|
||||
#endif
|
||||
@ -154,7 +162,7 @@ struct hb_buffer_t {
|
||||
#ifndef HB_NDEBUG
|
||||
unsigned int end = start + count;
|
||||
assert (end <= 8);
|
||||
unsigned int bits = (1<<end) - (1<<start);
|
||||
unsigned int bits = (1u<<end) - (1u<<start);
|
||||
assert (bits == (allocated_var_bits & bits));
|
||||
#endif
|
||||
}
|
||||
@ -165,8 +173,17 @@ struct hb_buffer_t {
|
||||
#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 clear (void);
|
||||
@ -232,25 +249,31 @@ struct hb_buffer_t {
|
||||
for (unsigned int j = 0; j < len; j++)
|
||||
info[j].mask |= mask;
|
||||
}
|
||||
HB_INTERNAL void set_masks (hb_mask_t value,
|
||||
hb_mask_t mask,
|
||||
unsigned int cluster_start,
|
||||
unsigned int cluster_end);
|
||||
HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
|
||||
unsigned int cluster_start, unsigned int cluster_end);
|
||||
|
||||
HB_INTERNAL void merge_clusters (unsigned int start,
|
||||
unsigned int end)
|
||||
inline void merge_clusters (unsigned int start, unsigned int end)
|
||||
{
|
||||
if (end - start < 2)
|
||||
return;
|
||||
merge_clusters_impl (start, end);
|
||||
}
|
||||
HB_INTERNAL void merge_clusters_impl (unsigned int start,
|
||||
unsigned int end);
|
||||
HB_INTERNAL void merge_out_clusters (unsigned int start,
|
||||
unsigned int end);
|
||||
HB_INTERNAL void merge_clusters_impl (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. */
|
||||
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 */
|
||||
HB_INTERNAL bool enlarge (unsigned int size);
|
||||
|
||||
@ -282,9 +305,78 @@ struct hb_buffer_t {
|
||||
return ret;
|
||||
}
|
||||
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) \
|
||||
b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
|
||||
sizeof (b->info[0].var))
|
||||
|
@ -30,7 +30,7 @@
|
||||
static const char *serialize_formats[] = {
|
||||
"text",
|
||||
"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_JSON: return serialize_formats[1];
|
||||
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_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) ?
|
||||
NULL : hb_buffer_get_glyph_positions (buffer, NULL);
|
||||
nullptr : hb_buffer_get_glyph_positions (buffer, nullptr);
|
||||
|
||||
*buf_consumed = 0;
|
||||
hb_position_t x = 0, y = 0;
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
char b[1024];
|
||||
@ -145,10 +146,17 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
|
||||
|
||||
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
|
||||
{
|
||||
p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
|
||||
pos[i].x_offset, pos[i].y_offset);
|
||||
p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
|
||||
pos[i].x_advance, pos[i].y_advance);
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
|
||||
x+pos[i].x_offset, y+pos[i].y_offset));
|
||||
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
|
||||
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)
|
||||
@ -156,9 +164,9 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
|
||||
hb_glyph_extents_t 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",
|
||||
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",
|
||||
extents.width, extents.height));
|
||||
extents.width, extents.height));
|
||||
}
|
||||
|
||||
*p++ = '}';
|
||||
@ -173,6 +181,12 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
|
||||
*buf = '\0';
|
||||
} else
|
||||
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;
|
||||
@ -188,11 +202,12 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
|
||||
hb_font_t *font,
|
||||
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) ?
|
||||
NULL : hb_buffer_get_glyph_positions (buffer, NULL);
|
||||
nullptr : hb_buffer_get_glyph_positions (buffer, nullptr);
|
||||
|
||||
*buf_consumed = 0;
|
||||
hb_position_t x = 0, y = 0;
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
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 (pos[i].x_offset || pos[i].y_offset)
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", 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", x+pos[i].x_offset, y+pos[i].y_offset));
|
||||
|
||||
*p++ = '+';
|
||||
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_NO_ADVANCES))
|
||||
{
|
||||
*p++ = '+';
|
||||
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)
|
||||
@ -243,6 +267,12 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
|
||||
*buf = '\0';
|
||||
} else
|
||||
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;
|
||||
@ -311,6 +341,8 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
|
||||
if (!buf_consumed)
|
||||
buf_consumed = &sconsumed;
|
||||
*buf_consumed = 0;
|
||||
if (buf_size)
|
||||
*buf = '\0';
|
||||
|
||||
assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
|
||||
buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
|
||||
@ -408,8 +440,8 @@ hb_bool_t
|
||||
hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
|
||||
const char *buf,
|
||||
int buf_len, /* -1 means nul-terminated */
|
||||
const char **end_ptr, /* May be NULL */
|
||||
hb_font_t *font, /* May be NULL */
|
||||
const char **end_ptr, /* May be nullptr */
|
||||
hb_font_t *font, /* May be nullptr */
|
||||
hb_buffer_serialize_format_t format)
|
||||
{
|
||||
const char *end;
|
||||
|
240
src/hb-buffer.cc
240
src/hb-buffer.cc
@ -31,10 +31,6 @@
|
||||
#include "hb-utf-private.hh"
|
||||
|
||||
|
||||
#ifndef HB_DEBUG_BUFFER
|
||||
#define HB_DEBUG_BUFFER (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION: hb-buffer
|
||||
* @title: Buffers
|
||||
@ -52,7 +48,7 @@
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Since: 0.9.7
|
||||
@ -124,8 +120,8 @@ hb_buffer_t::enlarge (unsigned int size)
|
||||
}
|
||||
|
||||
unsigned int new_allocated = allocated;
|
||||
hb_glyph_position_t *new_pos = NULL;
|
||||
hb_glyph_info_t *new_info = NULL;
|
||||
hb_glyph_position_t *new_pos = nullptr;
|
||||
hb_glyph_info_t *new_info = nullptr;
|
||||
bool separate_out = out_info != info;
|
||||
|
||||
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)
|
||||
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]))))
|
||||
goto done;
|
||||
|
||||
@ -183,6 +179,12 @@ hb_buffer_t::shift_forward (unsigned int count)
|
||||
if (unlikely (!ensure (len + count))) return false;
|
||||
|
||||
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;
|
||||
idx += count;
|
||||
|
||||
@ -261,7 +263,7 @@ hb_buffer_t::add (hb_codepoint_t codepoint,
|
||||
|
||||
memset (glyph, 0, sizeof (*glyph));
|
||||
glyph->codepoint = codepoint;
|
||||
glyph->mask = 1;
|
||||
glyph->mask = 0;
|
||||
glyph->cluster = cluster;
|
||||
|
||||
len++;
|
||||
@ -426,6 +428,8 @@ hb_buffer_t::move_to (unsigned int i)
|
||||
/* Tricky part: rewinding... */
|
||||
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;
|
||||
|
||||
assert (idx >= count);
|
||||
@ -542,12 +546,15 @@ hb_buffer_t::merge_clusters_impl (unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
|
||||
{
|
||||
unsafe_to_break (start, end);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int cluster = info[start].cluster;
|
||||
|
||||
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 */
|
||||
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 (idx == start)
|
||||
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++)
|
||||
info[i].cluster = cluster;
|
||||
set_cluster (info[i], cluster);
|
||||
}
|
||||
void
|
||||
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;
|
||||
|
||||
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 */
|
||||
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 (end == out_len)
|
||||
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++)
|
||||
out_info[i].cluster = cluster;
|
||||
set_cluster (out_info[i], cluster);
|
||||
}
|
||||
void
|
||||
hb_buffer_t::delete_glyph ()
|
||||
{
|
||||
/* The logic here is duplicated in hb_ot_hide_default_ignorables(). */
|
||||
|
||||
unsigned int cluster = info[idx].cluster;
|
||||
if (idx + 1 < len && cluster == info[idx + 1].cluster)
|
||||
{
|
||||
@ -611,9 +620,10 @@ hb_buffer_t::delete_glyph ()
|
||||
/* Merge cluster backward. */
|
||||
if (cluster < out_info[out_len - 1].cluster)
|
||||
{
|
||||
unsigned int mask = info[idx].mask;
|
||||
unsigned int old_cluster = out_info[out_len - 1].cluster;
|
||||
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;
|
||||
}
|
||||
@ -629,6 +639,32 @@ done:
|
||||
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
|
||||
hb_buffer_t::guess_segment_properties (void)
|
||||
{
|
||||
@ -686,6 +722,7 @@ hb_buffer_create (void)
|
||||
return hb_buffer_get_empty ();
|
||||
|
||||
buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
|
||||
buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
|
||||
|
||||
buffer->reset ();
|
||||
|
||||
@ -713,6 +750,7 @@ hb_buffer_get_empty (void)
|
||||
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
|
||||
HB_BUFFER_SCRATCH_FLAG_DEFAULT,
|
||||
HB_BUFFER_MAX_LEN_DEFAULT,
|
||||
HB_BUFFER_MAX_OPS_DEFAULT,
|
||||
|
||||
HB_BUFFER_CONTENT_TYPE_INVALID,
|
||||
HB_SEGMENT_PROPERTIES_DEFAULT,
|
||||
@ -1371,6 +1409,23 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
|
||||
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:
|
||||
* @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
|
||||
compare_info_codepoint (const hb_glyph_info_t *pa,
|
||||
const hb_glyph_info_t *pb)
|
||||
@ -1728,7 +1835,8 @@ void
|
||||
hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
|
||||
{
|
||||
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);
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
@ -1795,9 +1995,9 @@ hb_buffer_set_message_func (hb_buffer_t *buffer,
|
||||
buffer->message_data = user_data;
|
||||
buffer->message_destroy = destroy;
|
||||
} else {
|
||||
buffer->message_func = NULL;
|
||||
buffer->message_data = NULL;
|
||||
buffer->message_destroy = NULL;
|
||||
buffer->message_func = nullptr;
|
||||
buffer->message_data = nullptr;
|
||||
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 {
|
||||
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;
|
||||
|
||||
/*< private >*/
|
||||
@ -71,6 +71,37 @@ typedef struct hb_glyph_info_t {
|
||||
hb_var_int_t var2;
|
||||
} 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:
|
||||
* @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, \
|
||||
HB_SCRIPT_INVALID, \
|
||||
HB_LANGUAGE_INVALID, \
|
||||
NULL, \
|
||||
NULL}
|
||||
(void *) 0, \
|
||||
(void *) 0}
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
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_user_data_key_t *key);
|
||||
|
||||
|
||||
/**
|
||||
* hb_buffer_content_type_t:
|
||||
* @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.
|
||||
* @HB_BUFFER_FLAG_EOT: flag indicating that special handling of the end of text
|
||||
* paragraph can be applied to this buffer, similar to
|
||||
* @HB_BUFFER_FLAG_EOT.
|
||||
* @HB_BUFFER_FLAG_BOT.
|
||||
* @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES:
|
||||
* flag indication that character with Default_Ignorable
|
||||
* Unicode property should use the corresponding glyph
|
||||
* from the font, instead of hiding them (currently done
|
||||
* by replacing them with the space glyph and zeroing the
|
||||
* advance width.)
|
||||
* from the font, instead of hiding them (done by
|
||||
* replacing them with the space glyph and zeroing the
|
||||
* 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
|
||||
*/
|
||||
@ -247,7 +287,8 @@ typedef enum { /*< flags >*/
|
||||
HB_BUFFER_FLAG_DEFAULT = 0x00000000u,
|
||||
HB_BUFFER_FLAG_BOT = 0x00000001u, /* Beginning-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_EXTERN void
|
||||
@ -359,6 +400,11 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
|
||||
unsigned int item_offset,
|
||||
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_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_GLYPH_NAMES: do no serialize glyph name.
|
||||
* @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().
|
||||
*
|
||||
@ -403,7 +452,9 @@ typedef enum { /*< flags >*/
|
||||
HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u,
|
||||
HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u,
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -452,6 +503,45 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
|
||||
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.
|
||||
*/
|
||||
|
@ -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 <locale.h>
|
||||
#ifdef HAVE_XLOCALE_H
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* hb_options_t */
|
||||
@ -82,13 +85,13 @@ hb_tag_from_string (const char *str, int len)
|
||||
for (; i < 4; i++)
|
||||
tag[i] = ' ';
|
||||
|
||||
return HB_TAG_CHAR4 (tag);
|
||||
return HB_TAG (tag[0], tag[1], tag[2], tag[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_tag_to_string:
|
||||
* @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 *p2 = (const unsigned char *) v2;
|
||||
|
||||
while (*p1 && *p1 == canon_map[*p2])
|
||||
p1++, p2++;
|
||||
while (*p1 && *p1 == canon_map[*p2]) {
|
||||
p1++;
|
||||
p2++;
|
||||
}
|
||||
|
||||
return *p1 == canon_map[*p2];
|
||||
}
|
||||
@ -219,9 +224,18 @@ struct hb_language_item_t {
|
||||
}
|
||||
|
||||
inline hb_language_item_t & operator = (const char *s) {
|
||||
lang = (hb_language_t) strdup (s);
|
||||
for (unsigned char *p = (unsigned char *) lang; *p; p++)
|
||||
*p = canon_map[*p];
|
||||
/* If a custom allocated is used calling strdup() pairs
|
||||
badly with a call to the custom free() in finish() below.
|
||||
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;
|
||||
}
|
||||
@ -235,8 +249,8 @@ struct hb_language_item_t {
|
||||
static hb_language_item_t *langs;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
static
|
||||
void free_langs (void)
|
||||
static void
|
||||
free_langs (void)
|
||||
{
|
||||
while (langs) {
|
||||
hb_language_item_t *next = langs->next;
|
||||
@ -260,9 +274,14 @@ retry:
|
||||
/* Not found; allocate one. */
|
||||
hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t));
|
||||
if (unlikely (!lang))
|
||||
return NULL;
|
||||
return nullptr;
|
||||
lang->next = first_lang;
|
||||
*lang = key;
|
||||
if (unlikely (!lang->lang))
|
||||
{
|
||||
free (lang);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
|
||||
lang->finish ();
|
||||
@ -299,7 +318,7 @@ hb_language_from_string (const char *str, int len)
|
||||
if (!str || !len || !*str)
|
||||
return HB_LANGUAGE_INVALID;
|
||||
|
||||
hb_language_item_t *item = NULL;
|
||||
hb_language_item_t *item = nullptr;
|
||||
if (len >= 0)
|
||||
{
|
||||
/* NUL-terminate it. */
|
||||
@ -330,7 +349,7 @@ hb_language_from_string (const char *str, int len)
|
||||
const char *
|
||||
hb_language_to_string (hb_language_t language)
|
||||
{
|
||||
/* This is actually NULL-safe! */
|
||||
/* This is actually nullptr-safe! */
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -505,6 +524,7 @@ hb_script_get_horizontal_direction (hb_script_t script)
|
||||
case HB_SCRIPT_PSALTER_PAHLAVI:
|
||||
|
||||
/* Unicode-8.0 additions */
|
||||
case HB_SCRIPT_HATRAN:
|
||||
case HB_SCRIPT_OLD_HUNGARIAN:
|
||||
|
||||
/* Unicode-9.0 additions */
|
||||
@ -543,9 +563,9 @@ hb_user_data_array_t::set (hb_user_data_key_t *key,
|
||||
void *
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 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
|
||||
|
||||
#if !defined (HB_DONT_DEFINE_STDINT)
|
||||
|
||||
#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
|
||||
defined (_sgi) || defined (__sun) || defined (sun) || \
|
||||
defined (__digital__) || defined (__HP_cc)
|
||||
# include <inttypes.h>
|
||||
#elif defined (_AIX)
|
||||
# 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
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
@ -148,7 +134,7 @@ hb_language_from_string (const char *str, int len);
|
||||
HB_EXTERN const char *
|
||||
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_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_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. */
|
||||
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);
|
||||
|
||||
|
||||
/* 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
|
||||
|
||||
#endif /* HB_COMMON_H */
|
||||
|
@ -27,15 +27,34 @@
|
||||
*/
|
||||
|
||||
#define HB_SHAPER coretext
|
||||
|
||||
#include "hb-private.hh"
|
||||
#include "hb-debug.hh"
|
||||
#include "hb-shaper-impl-private.hh"
|
||||
|
||||
#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
|
||||
#define HB_DEBUG_CORETEXT (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
static CGFloat
|
||||
coretext_font_size_from_ptem (float ptem)
|
||||
{
|
||||
/* 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
|
||||
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);
|
||||
CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
|
||||
if (unlikely (!cf_data))
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
|
||||
const size_t length = CFDataGetLength (cf_data);
|
||||
if (!data || !length)
|
||||
return NULL;
|
||||
{
|
||||
CFRelease (cf_data);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
|
||||
reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
|
||||
release_table_data);
|
||||
}
|
||||
|
||||
hb_face_t *
|
||||
hb_coretext_face_create (CGFontRef cg_font)
|
||||
static void
|
||||
_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_DECLARE(coretext, font)
|
||||
|
||||
|
||||
/*
|
||||
* shaper face data
|
||||
*/
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
|
||||
fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5
|
||||
)
|
||||
|
||||
static CTFontDescriptorRef
|
||||
get_last_resort_font_desc (void)
|
||||
@ -104,7 +123,7 @@ static void
|
||||
release_data (void *info, const void *data, size_t 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);
|
||||
}
|
||||
@ -112,8 +131,8 @@ release_data (void *info, const void *data, size_t size)
|
||||
static CGFontRef
|
||||
create_cg_font (hb_face_t *face)
|
||||
{
|
||||
CGFontRef cg_font = NULL;
|
||||
if (face->destroy == (hb_destroy_func_t) CGFontRelease)
|
||||
CGFontRef cg_font = nullptr;
|
||||
if (face->destroy == _hb_cg_font_release)
|
||||
{
|
||||
cg_font = CGFontRetain ((CGFontRef) face->user_data);
|
||||
}
|
||||
@ -140,75 +159,118 @@ create_cg_font (hb_face_t *face)
|
||||
static CTFontRef
|
||||
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)) {
|
||||
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
|
||||
* font fallback which we don't need anyway. */
|
||||
{
|
||||
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);
|
||||
if (new_ct_font)
|
||||
{
|
||||
CFRelease (ct_font);
|
||||
ct_font = new_ct_font;
|
||||
/* The CTFontCreateCopyWithAttributes call fails to stay on the same 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
|
||||
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_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));
|
||||
if (unlikely (!data))
|
||||
return NULL;
|
||||
CGFontRef cg_font = create_cg_font (face);
|
||||
|
||||
data->cg_font = create_cg_font (face);
|
||||
if (unlikely (!data->cg_font))
|
||||
if (unlikely (!cg_font))
|
||||
{
|
||||
DEBUG_MSG (CORETEXT, face, "CGFont creation failed..");
|
||||
free (data);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* We use 36pt size instead of UPEM, because CoreText implements the 'trak' table,
|
||||
* 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;
|
||||
return (hb_coretext_shaper_face_data_t *) cg_font;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
|
||||
{
|
||||
CFRelease (data->ct_font);
|
||||
CFRelease (data->cg_font);
|
||||
free (data);
|
||||
CFRelease ((CGFontRef) 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
|
||||
hb_coretext_face_get_cg_font (hb_face_t *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->cg_font;
|
||||
if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
|
||||
return (CGFontRef) HB_SHAPER_DATA_GET (face);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* shaper font data
|
||||
*/
|
||||
|
||||
struct 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
|
||||
_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
|
||||
@ -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_create (hb_shape_plan_t *shape_plan 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;
|
||||
}
|
||||
@ -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
|
||||
@ -283,7 +375,9 @@ struct active_feature_t {
|
||||
feature_record_t rec;
|
||||
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 :
|
||||
a->order < b->order ? -1 : a->order > b->order ? 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;
|
||||
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 :
|
||||
a->start < b->start ? -1 : a->start > b->start ? 1 :
|
||||
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)
|
||||
{
|
||||
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 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 (); */
|
||||
for (unsigned int j = 0; j < active_features.len; j++)
|
||||
{
|
||||
CFStringRef keys[2] = {
|
||||
CFStringRef keys[] = {
|
||||
kCTFontFeatureTypeIdentifierKey,
|
||||
kCTFontFeatureSelectorIdentifierKey
|
||||
};
|
||||
CFNumberRef values[2] = {
|
||||
CFNumberRef values[] = {
|
||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature),
|
||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting)
|
||||
};
|
||||
static_assert ((ARRAY_LENGTH_CONST (keys) == ARRAY_LENGTH_CONST (values)), "");
|
||||
CFDictionaryRef dict = CFDictionaryCreate (kCFAllocatorDefault,
|
||||
(const void **) keys,
|
||||
(const void **) values,
|
||||
2,
|
||||
ARRAY_LENGTH (keys),
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
CFRelease (values[0]);
|
||||
CFRelease (values[1]);
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (values); i++)
|
||||
CFRelease (values[i]);
|
||||
|
||||
CFArrayAppendValue (features_array, dict);
|
||||
CFRelease (dict);
|
||||
@ -634,12 +732,12 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (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);
|
||||
}
|
||||
else
|
||||
{
|
||||
range->font = NULL;
|
||||
range->font = nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (!range_records.len) /* No active feature found. */
|
||||
goto fail_features;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -695,7 +790,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
pchars[chars_len++] = 0xFFFDu;
|
||||
else {
|
||||
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(...) \
|
||||
HB_STMT_START { \
|
||||
DEBUG_MSG (CORETEXT, NULL, __VA_ARGS__); \
|
||||
DEBUG_MSG (CORETEXT, nullptr, __VA_ARGS__); \
|
||||
ret = false; \
|
||||
goto fail; \
|
||||
} HB_STMT_END;
|
||||
|
||||
bool ret = true;
|
||||
CFStringRef string_ref = NULL;
|
||||
CTLineRef line = NULL;
|
||||
CFStringRef string_ref = nullptr;
|
||||
CTLineRef line = nullptr;
|
||||
|
||||
if (0)
|
||||
{
|
||||
@ -731,8 +826,8 @@ resize_and_retry:
|
||||
assert (line);
|
||||
CFRelease (string_ref);
|
||||
CFRelease (line);
|
||||
string_ref = NULL;
|
||||
line = NULL;
|
||||
string_ref = nullptr;
|
||||
line = nullptr;
|
||||
|
||||
/* Get previous start-of-scratch-area, that we use later for readjusting
|
||||
* our existing scratch arrays. */
|
||||
@ -753,7 +848,7 @@ resize_and_retry:
|
||||
scratch_size -= old_scratch_used;
|
||||
}
|
||||
{
|
||||
string_ref = CFStringCreateWithCharactersNoCopy (NULL,
|
||||
string_ref = CFStringCreateWithCharactersNoCopy (nullptr,
|
||||
pchars, chars_len,
|
||||
kCFAllocatorNull);
|
||||
if (unlikely (!string_ref))
|
||||
@ -785,15 +880,18 @@ resize_and_retry:
|
||||
kCFStringEncodingUTF8,
|
||||
kCFAllocatorNull);
|
||||
if (unlikely (!lang))
|
||||
{
|
||||
CFRelease (attr_string);
|
||||
FAIL ("CFStringCreateWithCStringNoCopy failed");
|
||||
}
|
||||
CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
|
||||
kCTLanguageAttributeName, lang);
|
||||
CFRelease (lang);
|
||||
}
|
||||
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;
|
||||
range_record_t *last_range = &range_records[0];
|
||||
@ -819,6 +917,30 @@ resize_and_retry:
|
||||
CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, chars_len - start),
|
||||
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;
|
||||
CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &level);
|
||||
@ -828,8 +950,12 @@ resize_and_retry:
|
||||
1,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
CFRelease (level_number);
|
||||
if (unlikely (!options))
|
||||
{
|
||||
CFRelease (attr_string);
|
||||
FAIL ("CFDictionaryCreate failed");
|
||||
}
|
||||
|
||||
CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOptions (attr_string, options);
|
||||
CFRelease (options);
|
||||
@ -845,7 +971,7 @@ resize_and_retry:
|
||||
|
||||
CFArrayRef glyph_runs = CTLineGetGlyphRuns (line);
|
||||
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;
|
||||
uint32_t status_and = ~0, status_or = 0;
|
||||
@ -871,7 +997,7 @@ resize_and_retry:
|
||||
status_or |= run_status;
|
||||
status_and &= 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))
|
||||
run_advance = -run_advance;
|
||||
DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance);
|
||||
@ -884,7 +1010,7 @@ resize_and_retry:
|
||||
*/
|
||||
CFDictionaryRef attributes = CTRunGetAttributes (run);
|
||||
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
|
||||
* 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
|
||||
* 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
|
||||
*/
|
||||
@ -919,16 +1045,16 @@ resize_and_retry:
|
||||
}
|
||||
if (!matched)
|
||||
{
|
||||
CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0);
|
||||
CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, nullptr);
|
||||
if (run_cg_font)
|
||||
{
|
||||
matched = CFEqual (run_cg_font, face_data->cg_font);
|
||||
matched = CFEqual (run_cg_font, cg_font);
|
||||
CFRelease (run_cg_font);
|
||||
}
|
||||
}
|
||||
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);
|
||||
CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name, 0);
|
||||
CFRelease (run_ps_name);
|
||||
@ -997,7 +1123,7 @@ resize_and_retry:
|
||||
|
||||
/* Testing used to indicate that CTRunGetGlyphsPtr, etc (almost?) always
|
||||
* 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
|
||||
* to false. */
|
||||
|
||||
@ -1013,13 +1139,13 @@ resize_and_retry:
|
||||
|
||||
{ /* Setup glyphs */
|
||||
SCRATCH_SAVE();
|
||||
const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL;
|
||||
const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : nullptr;
|
||||
if (!glyphs) {
|
||||
ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry);
|
||||
CTRunGetGlyphs (run, range_all, 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) {
|
||||
ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs, goto resize_and_retry);
|
||||
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
|
||||
* whatever is needed to make the whole run's advance add up. */
|
||||
SCRATCH_SAVE();
|
||||
const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL;
|
||||
const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : nullptr;
|
||||
if (!positions) {
|
||||
ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs, goto resize_and_retry);
|
||||
CTRunGetPositions (run, range_all, position_buf);
|
||||
@ -1092,7 +1218,7 @@ resize_and_retry:
|
||||
}
|
||||
|
||||
/* 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
|
||||
* cursoring will be off...
|
||||
*
|
||||
@ -1117,6 +1243,7 @@ resize_and_retry:
|
||||
pos->x_advance = info->mask;
|
||||
pos->x_offset = info->var1.i32;
|
||||
pos->y_offset = info->var2.i32;
|
||||
|
||||
info++, pos++;
|
||||
}
|
||||
else
|
||||
@ -1125,6 +1252,7 @@ resize_and_retry:
|
||||
pos->y_advance = info->mask;
|
||||
pos->x_offset = info->var1.i32;
|
||||
pos->y_offset = info->var2.i32;
|
||||
|
||||
info++, pos++;
|
||||
}
|
||||
|
||||
@ -1162,6 +1290,8 @@ resize_and_retry:
|
||||
}
|
||||
}
|
||||
|
||||
buffer->unsafe_to_break_all ();
|
||||
|
||||
#undef FAIL
|
||||
|
||||
fail:
|
||||
@ -1182,6 +1312,9 @@ fail:
|
||||
* AAT shaper
|
||||
*/
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font)
|
||||
|
||||
/*
|
||||
* 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_create (hb_face_t *face)
|
||||
{
|
||||
hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT);
|
||||
/* 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);
|
||||
static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX};
|
||||
|
||||
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
|
||||
@ -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_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
|
||||
@ -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_create (hb_shape_plan_t *shape_plan 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;
|
||||
}
|
||||
|
@ -42,11 +42,15 @@ HB_BEGIN_DECLS
|
||||
|
||||
#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_KERX HB_TAG('k','e','r','x')
|
||||
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_coretext_face_create (CGFontRef cg_font);
|
||||
|
||||
HB_EXTERN hb_font_t *
|
||||
hb_coretext_font_create (CTFontRef ct_font);
|
||||
|
||||
|
||||
HB_EXTERN CGFontRef
|
||||
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-unicode.h"
|
||||
#include "hb-font.h"
|
||||
#include "hb-set.h"
|
||||
|
||||
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,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_set_invert (hb_set_t *set);
|
||||
|
||||
#endif
|
||||
|
||||
HB_END_DECLS
|
||||
|
@ -22,199 +22,202 @@
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#include "hb-private.hh"
|
||||
#include "hb-debug.hh"
|
||||
#define HB_SHAPER directwrite
|
||||
#include "hb-shaper-impl-private.hh"
|
||||
|
||||
#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
|
||||
#include <DWrite.h>
|
||||
#else
|
||||
#include <DWrite_1.h>
|
||||
#endif
|
||||
#include <DWrite_1.h>
|
||||
|
||||
#include "hb-directwrite.h"
|
||||
|
||||
#include "hb-open-file-private.hh"
|
||||
#include "hb-ot-name-table.hh"
|
||||
#include "hb-ot-tag.h"
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, face)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, font)
|
||||
|
||||
|
||||
#ifndef HB_DEBUG_DIRECTWRITE
|
||||
#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
|
||||
#endif
|
||||
/*
|
||||
* DirectWrite font stream helpers
|
||||
*/
|
||||
|
||||
// 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
|
||||
*/
|
||||
|
||||
struct hb_directwrite_shaper_face_data_t {
|
||||
HANDLE fh;
|
||||
wchar_t face_name[LF_FACESIZE];
|
||||
IDWriteFactory *dwriteFactory;
|
||||
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_create(hb_face_t *face)
|
||||
{
|
||||
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))
|
||||
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);
|
||||
if (unlikely (!hb_blob_get_length (blob)))
|
||||
DEBUG_MSG(DIRECTWRITE, face, "Face has empty blob");
|
||||
IDWriteFontFileStream *fontFileStream = new DWriteFontFileStream (
|
||||
(uint8_t*) hb_blob_get_data (blob, nullptr), hb_blob_get_length (blob));
|
||||
|
||||
blob = _hb_rename_font (blob, data->face_name);
|
||||
if (unlikely (!blob))
|
||||
{
|
||||
free(data);
|
||||
return NULL;
|
||||
IDWriteFontFileLoader *fontFileLoader = new DWriteFontFileLoader (fontFileStream);
|
||||
dwriteFactory->RegisterFontFileLoader (fontFileLoader);
|
||||
|
||||
IDWriteFontFile *fontFile;
|
||||
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;
|
||||
data->fh = AddFontMemResourceEx ((void *)hb_blob_get_data(blob, NULL),
|
||||
hb_blob_get_length (blob),
|
||||
0, &num_fonts_installed);
|
||||
if (unlikely (!data->fh))
|
||||
{
|
||||
DEBUG_MSG (DIRECTWRITE, face, "Face AddFontMemResourceEx() failed");
|
||||
free (data);
|
||||
return NULL;
|
||||
BOOL isSupported;
|
||||
DWRITE_FONT_FILE_TYPE fileType;
|
||||
DWRITE_FONT_FACE_TYPE faceType;
|
||||
UINT32 numberOfFaces;
|
||||
hr = fontFile->Analyze (&isSupported, &fileType, &faceType, &numberOfFaces);
|
||||
if (FAILED (hr) || !isSupported) {
|
||||
FAIL ("Font file is not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data)
|
||||
{
|
||||
RemoveFontMemResourceEx(data->fh);
|
||||
free(data);
|
||||
if (data->fontFace)
|
||||
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 {
|
||||
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_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 *) 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))
|
||||
return NULL;
|
||||
|
||||
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 nullptr;
|
||||
|
||||
return data;
|
||||
}
|
||||
@ -284,29 +244,9 @@ _hb_directwrite_shaper_font_data_create (hb_font_t *font)
|
||||
void
|
||||
_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);
|
||||
}
|
||||
|
||||
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
|
||||
@ -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_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||
const hb_feature_t *user_features HB_UNUSED,
|
||||
unsigned int num_user_features HB_UNUSED)
|
||||
const hb_feature_t *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;
|
||||
}
|
||||
@ -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
|
||||
class TextAnalysis
|
||||
: public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink
|
||||
@ -369,7 +311,7 @@ public:
|
||||
, mTextLength(textLength)
|
||||
, mLocaleName(localeName)
|
||||
, mReadingDirection(readingDirection)
|
||||
, mCurrentRun(NULL) { };
|
||||
, mCurrentRun(nullptr) { };
|
||||
|
||||
~TextAnalysis() {
|
||||
// delete runs, except mRunHead which is part of the TextAnalysis object
|
||||
@ -393,7 +335,7 @@ public:
|
||||
mRunHead.mTextLength = mTextLength;
|
||||
mRunHead.mBidiLevel =
|
||||
(mReadingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
|
||||
mRunHead.nextRun = NULL;
|
||||
mRunHead.nextRun = nullptr;
|
||||
mCurrentRun = &mRunHead;
|
||||
|
||||
// Call each of the analyzers in sequence, recording their results.
|
||||
@ -412,7 +354,7 @@ public:
|
||||
{
|
||||
if (textPosition >= mTextLength) {
|
||||
// No text at this position, valid query though.
|
||||
*textString = NULL;
|
||||
*textString = nullptr;
|
||||
*textLength = 0;
|
||||
}
|
||||
else {
|
||||
@ -428,8 +370,8 @@ public:
|
||||
{
|
||||
if (textPosition == 0 || textPosition > mTextLength) {
|
||||
// Either there is no text before here (== 0), or this
|
||||
// is an invalid position. The query is considered valid thouh.
|
||||
*textString = NULL;
|
||||
// is an invalid position. The query is considered valid though.
|
||||
*textString = nullptr;
|
||||
*textLength = 0;
|
||||
}
|
||||
else {
|
||||
@ -444,7 +386,8 @@ public:
|
||||
|
||||
IFACEMETHODIMP GetLocaleName(uint32_t textPosition,
|
||||
uint32_t* textLength,
|
||||
wchar_t const** localeName) {
|
||||
wchar_t const** localeName)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -454,7 +397,7 @@ public:
|
||||
OUT IDWriteNumberSubstitution** numberSubstitution)
|
||||
{
|
||||
// We do not support number substitution.
|
||||
*numberSubstitution = NULL;
|
||||
*numberSubstitution = nullptr;
|
||||
*textLength = mTextLength - textPosition;
|
||||
|
||||
return S_OK;
|
||||
@ -469,7 +412,8 @@ public:
|
||||
{
|
||||
SetCurrentRun(textPosition);
|
||||
SplitCurrentRun(textPosition);
|
||||
while (textLength > 0) {
|
||||
while (textLength > 0)
|
||||
{
|
||||
Run *run = FetchNextRun(&textLength);
|
||||
run->mScript = *scriptAnalysis;
|
||||
}
|
||||
@ -502,10 +446,12 @@ protected:
|
||||
Run *origRun = mCurrentRun;
|
||||
// Split the tail if needed (the length remaining is less than the
|
||||
// current run's size).
|
||||
if (*textLength < mCurrentRun->mTextLength) {
|
||||
SplitCurrentRun(mCurrentRun->mTextStart + *textLength);
|
||||
if (*textLength < mCurrentRun->mTextLength)
|
||||
{
|
||||
SplitCurrentRun (mCurrentRun->mTextStart + *textLength);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// Just advance the current run.
|
||||
mCurrentRun = mCurrentRun->nextRun;
|
||||
}
|
||||
@ -522,12 +468,14 @@ protected:
|
||||
// this will usually just return early. If not, find the
|
||||
// corresponding run for the text position.
|
||||
|
||||
if (mCurrentRun && mCurrentRun->ContainsTextPosition(textPosition)) {
|
||||
if (mCurrentRun && mCurrentRun->ContainsTextPosition (textPosition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (Run *run = &mRunHead; run; run = run->nextRun) {
|
||||
if (run->ContainsTextPosition(textPosition)) {
|
||||
if (run->ContainsTextPosition (textPosition))
|
||||
{
|
||||
mCurrentRun = run;
|
||||
return;
|
||||
}
|
||||
@ -538,13 +486,15 @@ protected:
|
||||
|
||||
void SplitCurrentRun(uint32_t splitPosition)
|
||||
{
|
||||
if (!mCurrentRun) {
|
||||
if (!mCurrentRun)
|
||||
{
|
||||
//NS_ASSERTION(false, "SplitCurrentRun called without current run.");
|
||||
// Shouldn't be calling this when no current run is set!
|
||||
return;
|
||||
}
|
||||
// Split the current run.
|
||||
if (splitPosition <= mCurrentRun->mTextStart) {
|
||||
if (splitPosition <= mCurrentRun->mTextStart)
|
||||
{
|
||||
// No need to split, already the start of a run
|
||||
// or before it. Usually the first.
|
||||
return;
|
||||
@ -590,42 +540,22 @@ static inline uint32_t hb_uint32_swap (const uint32_t v)
|
||||
* shaper
|
||||
*/
|
||||
|
||||
hb_bool_t
|
||||
_hb_directwrite_shape(hb_shape_plan_t *shape_plan,
|
||||
static hb_bool_t
|
||||
_hb_directwrite_shape_full(hb_shape_plan_t *shape_plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features)
|
||||
unsigned int num_features,
|
||||
float lineWidth)
|
||||
{
|
||||
hb_face_t *face = font->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);
|
||||
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;
|
||||
dwriteFactory->CreateTextAnalyzer(&analyzer);
|
||||
#else
|
||||
IDWriteTextAnalyzer* analyzer0;
|
||||
dwriteFactory->CreateTextAnalyzer (&analyzer0);
|
||||
IDWriteTextAnalyzer1* analyzer = (IDWriteTextAnalyzer1*) analyzer0;
|
||||
#endif
|
||||
|
||||
unsigned int 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;
|
||||
else {
|
||||
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
|
||||
|
||||
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;
|
||||
|
||||
TextAnalysis analysis(textString, textLength, NULL, readingDirection);
|
||||
TextAnalysis analysis(textString, textLength, nullptr, readingDirection);
|
||||
TextAnalysis::Run *runHead;
|
||||
HRESULT hr;
|
||||
hr = analysis.GenerateResults(analyzer, &runHead);
|
||||
|
||||
#define FAIL(...) \
|
||||
HB_STMT_START { \
|
||||
DEBUG_MSG (DIRECTWRITE, NULL, __VA_ARGS__); \
|
||||
DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
|
||||
return false; \
|
||||
} 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);
|
||||
|
||||
const wchar_t localeName[20] = {0};
|
||||
if (buffer->props.language != NULL)
|
||||
if (buffer->props.language != nullptr)
|
||||
{
|
||||
mbstowcs ((wchar_t*) localeName,
|
||||
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 uint32_t featureRangeLengths[] = { textLength };
|
||||
|
||||
retry_getglyphs:
|
||||
uint16_t* clusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
|
||||
uint16_t* glyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
|
||||
uint16_t* clusterMap = (uint16_t*) malloc (textLength * sizeof (uint16_t));
|
||||
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*)
|
||||
malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES));
|
||||
|
||||
hr = analyzer->GetGlyphs (textString, textLength, fontFace, FALSE,
|
||||
isRightToLeft, &runHead->mScript, localeName, NULL, &dwFeatures,
|
||||
hr = analyzer->GetGlyphs (textString, textLength, fontFace, false,
|
||||
isRightToLeft, &runHead->mScript, localeName, nullptr, &dwFeatures,
|
||||
featureRangeLengths, 1, maxGlyphCount, clusterMap, textProperties, glyphIndices,
|
||||
glyphProperties, &glyphCount);
|
||||
|
||||
if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
|
||||
{
|
||||
free (clusterMap);
|
||||
free (glyphIndices);
|
||||
free (textProperties);
|
||||
free (glyphProperties);
|
||||
|
||||
maxGlyphCount *= 2;
|
||||
@ -789,7 +717,7 @@ retry_getglyphs:
|
||||
hr = analyzer->GetGlyphPlacements (textString,
|
||||
clusterMap, textProperties, textLength, glyphIndices,
|
||||
glyphProperties, glyphCount, fontFace, fontEmSize,
|
||||
FALSE, isRightToLeft, &runHead->mScript, localeName,
|
||||
false, isRightToLeft, &runHead->mScript, localeName,
|
||||
&dwFeatures, featureRangeLengths, 1,
|
||||
glyphAdvances, glyphOffsets);
|
||||
|
||||
@ -799,106 +727,106 @@ retry_getglyphs:
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
|
||||
IDWriteTextAnalyzer1* analyzer1;
|
||||
analyzer->QueryInterface (&analyzer1);
|
||||
|
||||
DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities =
|
||||
(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))
|
||||
if (analyzer1 && lineWidth)
|
||||
{
|
||||
FAIL ("Analyzer failed to get justification opportunities.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: get lineWith from somewhere
|
||||
float lineWidth = 60000;
|
||||
DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities =
|
||||
(DWRITE_JUSTIFICATION_OPPORTUNITY*)
|
||||
malloc (maxGlyphCount * sizeof (DWRITE_JUSTIFICATION_OPPORTUNITY));
|
||||
hr = analyzer1->GetJustificationOpportunities (fontFace, fontEmSize,
|
||||
runHead->mScript, textLength, glyphCount, textString, clusterMap,
|
||||
glyphProperties, justificationOpportunities);
|
||||
|
||||
float* justifiedGlyphAdvances =
|
||||
(float*) malloc (maxGlyphCount * sizeof (float));
|
||||
DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*)
|
||||
malloc (glyphCount * sizeof (DWRITE_GLYPH_OFFSET));
|
||||
hr = analyzer->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities,
|
||||
glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
FAIL ("Analyzer failed to get justification opportunities.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED (hr))
|
||||
{
|
||||
FAIL ("Analyzer failed to get justified glyph advances.");
|
||||
return false;
|
||||
}
|
||||
float* justifiedGlyphAdvances =
|
||||
(float*) malloc (maxGlyphCount * sizeof (float));
|
||||
DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*)
|
||||
malloc (glyphCount * sizeof (DWRITE_GLYPH_OFFSET));
|
||||
hr = analyzer1->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities,
|
||||
glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets);
|
||||
|
||||
DWRITE_SCRIPT_PROPERTIES scriptProperties;
|
||||
hr = analyzer->GetScriptProperties (runHead->mScript, &scriptProperties);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
FAIL ("Analyzer failed to get script properties.");
|
||||
return false;
|
||||
}
|
||||
uint32_t justificationCharacter = scriptProperties.justificationCharacter;
|
||||
if (FAILED (hr))
|
||||
{
|
||||
FAIL("Analyzer failed to get justified glyph advances.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// if a script justificationCharacter is not space, it can have GetJustifiedGlyphs
|
||||
if (justificationCharacter != 32)
|
||||
{
|
||||
retry_getjustifiedglyphs:
|
||||
uint16_t* modifiedClusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
|
||||
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 = analyzer->GetJustifiedGlyphs (fontFace, fontEmSize, runHead->mScript,
|
||||
DWRITE_SCRIPT_PROPERTIES scriptProperties;
|
||||
hr = analyzer1->GetScriptProperties (runHead->mScript, &scriptProperties);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
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
|
||||
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,
|
||||
glyphAdvances, justifiedGlyphAdvances, justifiedGlyphOffsets,
|
||||
glyphProperties, &actualGlyphsCount, modifiedClusterMap, modifiedGlyphIndices,
|
||||
modifiedGlyphAdvances, modifiedGlyphOffsets);
|
||||
|
||||
if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))
|
||||
{
|
||||
maxGlyphCount = actualGlyphsCount;
|
||||
free (modifiedClusterMap);
|
||||
free (modifiedGlyphIndices);
|
||||
free (modifiedGlyphAdvances);
|
||||
free (modifiedGlyphOffsets);
|
||||
if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))
|
||||
{
|
||||
maxGlyphCount = actualGlyphsCount;
|
||||
free (modifiedGlyphIndices);
|
||||
free (modifiedGlyphAdvances);
|
||||
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.");
|
||||
return false;
|
||||
free (glyphAdvances);
|
||||
free (glyphOffsets);
|
||||
|
||||
glyphAdvances = justifiedGlyphAdvances;
|
||||
glyphOffsets = justifiedGlyphOffsets;
|
||||
}
|
||||
|
||||
free (clusterMap);
|
||||
free (glyphIndices);
|
||||
free (glyphAdvances);
|
||||
free (glyphOffsets);
|
||||
free (justificationOpportunities);
|
||||
|
||||
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,
|
||||
* very, *very*, carefully! */
|
||||
@ -968,3 +896,36 @@ retry_getjustifiedglyphs:
|
||||
/* Wow, done! */
|
||||
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_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
|
||||
|
||||
#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;
|
||||
hb_destroy_func_t destroy;
|
||||
|
||||
unsigned int index;
|
||||
mutable unsigned int upem;
|
||||
mutable unsigned int num_glyphs;
|
||||
unsigned int index; /* Face index in a collection, zero-based. */
|
||||
mutable unsigned int upem; /* Units-per-EM. */
|
||||
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 {
|
||||
hb_shape_plan_t *shape_plan;
|
||||
plan_node_t *next;
|
||||
|
@ -28,17 +28,11 @@
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-ot-layout-private.hh"
|
||||
|
||||
#include "hb-font-private.hh"
|
||||
#include "hb-face-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>
|
||||
|
||||
|
||||
/*
|
||||
* hb_face_t
|
||||
@ -49,9 +43,9 @@ const hb_face_t _hb_face_nil = {
|
||||
|
||||
true, /* immutable */
|
||||
|
||||
NULL, /* reference_table_func */
|
||||
NULL, /* user_data */
|
||||
NULL, /* destroy */
|
||||
nullptr, /* reference_table_func */
|
||||
nullptr, /* user_data */
|
||||
nullptr, /* destroy */
|
||||
|
||||
0, /* index */
|
||||
1000, /* upem */
|
||||
@ -63,7 +57,7 @@ const hb_face_t _hb_face_nil = {
|
||||
#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));
|
||||
if (unlikely (!closure))
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
closure->blob = blob;
|
||||
closure->index = index;
|
||||
@ -124,8 +118,10 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
|
||||
}
|
||||
|
||||
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);
|
||||
free (closure);
|
||||
}
|
||||
@ -168,16 +164,16 @@ hb_face_create (hb_blob_t *blob,
|
||||
if (unlikely (!blob))
|
||||
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))
|
||||
return hb_face_get_empty ();
|
||||
|
||||
face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
|
||||
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;
|
||||
}
|
||||
@ -428,7 +424,7 @@ hb_face_get_upem (hb_face_t *face)
|
||||
void
|
||||
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);
|
||||
upem = head_table->get_upem ();
|
||||
hb_blob_destroy (head_blob);
|
||||
@ -472,10 +468,39 @@ hb_face_get_glyph_count (hb_face_t *face)
|
||||
void
|
||||
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);
|
||||
num_glyphs = maxp_table->get_num_glyphs ();
|
||||
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_bool_t replace);
|
||||
|
||||
|
||||
HB_EXTERN void *
|
||||
hb_face_get_user_data (hb_face_t *face,
|
||||
hb_user_data_key_t *key);
|
||||
@ -111,6 +110,11 @@ hb_face_set_glyph_count (hb_face_t *face,
|
||||
HB_EXTERN unsigned int
|
||||
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
|
||||
|
||||
|
@ -28,6 +28,10 @@
|
||||
#include "hb-shaper-impl-private.hh"
|
||||
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font)
|
||||
|
||||
|
||||
/*
|
||||
* 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_create (hb_shape_plan_t *shape_plan 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;
|
||||
}
|
||||
@ -123,7 +129,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||
pos[i].y_advance = 0;
|
||||
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,
|
||||
direction,
|
||||
&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))
|
||||
hb_buffer_reverse (buffer);
|
||||
|
||||
buffer->safe_to_break_all ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -108,6 +108,12 @@ struct hb_font_t {
|
||||
unsigned int x_ppem;
|
||||
unsigned int y_ppem;
|
||||
|
||||
float ptem;
|
||||
|
||||
/* Font variation coordinates. */
|
||||
unsigned int num_coords;
|
||||
int *coords;
|
||||
|
||||
hb_font_funcs_t *klass;
|
||||
void *user_data;
|
||||
hb_destroy_func_t destroy;
|
||||
@ -116,8 +122,16 @@ struct hb_font_t {
|
||||
|
||||
|
||||
/* 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 hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
|
||||
inline int dir_scale (hb_direction_t direction)
|
||||
{ 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 */
|
||||
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 */
|
||||
|
||||
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,
|
||||
hb_font_extents_t *extents)
|
||||
{
|
||||
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
|
||||
if (!get_font_h_extents (extents))
|
||||
{
|
||||
extents->ascender = y_scale * .8;
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
|
||||
get_h_extents_with_fallback (extents);
|
||||
else
|
||||
get_v_extents_with_fallback (extents);
|
||||
}
|
||||
|
||||
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,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
*x = get_glyph_h_advance (glyph) / 2;
|
||||
|
||||
/* TODO use font_extents.ascender */
|
||||
*y = y_scale;
|
||||
/* TODO cache this somehow?! */
|
||||
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,
|
||||
@ -340,25 +386,9 @@ struct hb_font_t {
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
get_glyph_h_origin_with_fallback (glyph, x, y);
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
get_glyph_v_origin_with_fallback (glyph, x, y);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
get_glyph_h_origin (glyph, &origin_x, &origin_y);
|
||||
get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
|
||||
|
||||
*x += origin_x;
|
||||
*y += origin_y;
|
||||
@ -376,7 +406,7 @@ struct hb_font_t {
|
||||
{
|
||||
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;
|
||||
*y += origin_y;
|
||||
@ -398,7 +428,7 @@ struct hb_font_t {
|
||||
{
|
||||
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;
|
||||
*y -= origin_y;
|
||||
@ -408,7 +438,7 @@ struct hb_font_t {
|
||||
{
|
||||
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;
|
||||
*y -= origin_y;
|
||||
@ -504,7 +534,6 @@ struct hb_font_t {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
inline hb_position_t em_scale (int16_t v, int scale)
|
||||
{
|
||||
int upem = face->get_upem ();
|
||||
@ -512,6 +541,14 @@ struct hb_font_t {
|
||||
scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
|
||||
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
|
||||
|
221
src/hb-font.cc
221
src/hb-font.cc
@ -28,16 +28,7 @@
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-ot-layout-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
|
||||
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,
|
||||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
@ -69,7 +60,7 @@ hb_font_get_font_h_extents_parent (hb_font_t *font,
|
||||
}
|
||||
|
||||
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,
|
||||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
@ -356,12 +347,12 @@ static const hb_font_funcs_t _hb_font_funcs_nil = {
|
||||
true, /* immutable */
|
||||
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
},
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
},
|
||||
@ -379,12 +370,12 @@ static const hb_font_funcs_t _hb_font_funcs_parent = {
|
||||
true, /* immutable */
|
||||
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
},
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
},
|
||||
@ -572,8 +563,8 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
|
||||
ffuncs->destroy.name = destroy; \
|
||||
} else { \
|
||||
ffuncs->get.f.name = hb_font_get_##name##_parent; \
|
||||
ffuncs->user_data.name = NULL; \
|
||||
ffuncs->destroy.name = NULL; \
|
||||
ffuncs->user_data.name = nullptr; \
|
||||
ffuncs->destroy.name = nullptr; \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -1166,6 +1157,20 @@ hb_font_create_sub_font (hb_font_t *parent)
|
||||
font->y_scale = parent->y_scale;
|
||||
font->x_ppem = parent->x_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;
|
||||
}
|
||||
@ -1187,7 +1192,7 @@ hb_font_get_empty (void)
|
||||
|
||||
true, /* immutable */
|
||||
|
||||
NULL, /* parent */
|
||||
nullptr, /* parent */
|
||||
const_cast<hb_face_t *> (&_hb_face_nil),
|
||||
|
||||
1000, /* x_scale */
|
||||
@ -1195,10 +1200,14 @@ hb_font_get_empty (void)
|
||||
|
||||
0, /* x_ppem */
|
||||
0, /* y_ppem */
|
||||
0, /* ptem */
|
||||
|
||||
0, /* num_coords */
|
||||
nullptr, /* coords */
|
||||
|
||||
const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
|
||||
NULL, /* user_data */
|
||||
NULL, /* destroy */
|
||||
nullptr, /* user_data */
|
||||
nullptr, /* destroy */
|
||||
|
||||
{
|
||||
#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_font_funcs_destroy (font->klass);
|
||||
|
||||
free (font->coords);
|
||||
|
||||
free (font);
|
||||
}
|
||||
|
||||
@ -1373,6 +1384,32 @@ hb_font_get_parent (hb_font_t *font)
|
||||
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:
|
||||
* @font: a font.
|
||||
@ -1538,6 +1575,148 @@ hb_font_get_ppem (hb_font_t *font,
|
||||
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
|
||||
|
||||
@ -1570,7 +1749,7 @@ trampoline_create (FuncType func,
|
||||
trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t));
|
||||
|
||||
if (unlikely (!trampoline))
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
trampoline->closure.user_data = user_data;
|
||||
trampoline->closure.destroy = destroy;
|
||||
|
@ -456,7 +456,7 @@ hb_font_get_glyph_from_name (hb_font_t *font,
|
||||
/* high-level funcs, with fallback */
|
||||
|
||||
/* 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_font_get_glyph (hb_font_t *font,
|
||||
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_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_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 *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
|
||||
|
||||
|
186
src/hb-ft.cc
186
src/hb-ft.cc
@ -28,21 +28,17 @@
|
||||
*/
|
||||
|
||||
#include "hb-private.hh"
|
||||
#include "hb-debug.hh"
|
||||
|
||||
#include "hb-ft.h"
|
||||
|
||||
#include "hb-font-private.hh"
|
||||
|
||||
#include FT_ADVANCES_H
|
||||
#include FT_MULTIPLE_MASTERS_H
|
||||
#include FT_TRUETYPE_TABLES_H
|
||||
|
||||
|
||||
|
||||
#ifndef HB_DEBUG_FT
|
||||
#define HB_DEBUG_FT (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* 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?
|
||||
*
|
||||
* - 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;
|
||||
int load_flags;
|
||||
bool symbol; /* Whether selected cmap is symbol cmap. */
|
||||
bool unref; /* Whether to destroy ft_face when done. */
|
||||
};
|
||||
|
||||
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));
|
||||
|
||||
if (unlikely (!ft_font))
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
ft_font->ft_face = ft_face;
|
||||
ft_font->symbol = symbol;
|
||||
ft_font->unref = unref;
|
||||
|
||||
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
|
||||
_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)
|
||||
FT_Done_Face (ft_font->ft_face);
|
||||
_hb_ft_face_destroy (ft_font->ft_face);
|
||||
|
||||
free (ft_font);
|
||||
}
|
||||
@ -113,7 +119,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
|
||||
if (font->immutable)
|
||||
return;
|
||||
|
||||
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
|
||||
if (font->destroy != _hb_ft_font_destroy)
|
||||
return;
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
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
|
||||
hb_ft_font_get_face (hb_font_t *font)
|
||||
{
|
||||
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
|
||||
return NULL;
|
||||
if (font->destroy != _hb_ft_font_destroy)
|
||||
return nullptr;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
return true;
|
||||
@ -397,7 +417,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
||||
return true;
|
||||
}
|
||||
|
||||
static hb_font_funcs_t *static_ft_funcs = NULL;
|
||||
static hb_font_funcs_t *static_ft_funcs = nullptr;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
static
|
||||
@ -417,24 +437,24 @@ retry:
|
||||
{
|
||||
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_v_extents_func (funcs, hb_ft_get_font_v_extents, NULL, NULL);
|
||||
hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, NULL, NULL);
|
||||
hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL);
|
||||
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, NULL, NULL);
|
||||
//hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, 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, nullptr, nullptr);
|
||||
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, nullptr, nullptr);
|
||||
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, nullptr, nullptr);
|
||||
//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, nullptr, nullptr);
|
||||
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, nullptr, nullptr);
|
||||
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, nullptr, nullptr);
|
||||
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, nullptr, nullptr);
|
||||
|
||||
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);
|
||||
goto retry;
|
||||
}
|
||||
@ -444,10 +464,12 @@ retry:
|
||||
#endif
|
||||
};
|
||||
|
||||
bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
|
||||
|
||||
hb_font_set_funcs (font,
|
||||
funcs,
|
||||
_hb_ft_font_create (ft_face, unref),
|
||||
(hb_destroy_func_t) _hb_ft_font_destroy);
|
||||
_hb_ft_font_create (ft_face, symbol, unref),
|
||||
_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 */
|
||||
|
||||
error = FT_Load_Sfnt_Table (ft_face, tag, 0, NULL, &length);
|
||||
error = FT_Load_Sfnt_Table (ft_face, tag, 0, nullptr, &length);
|
||||
if (error)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
buffer = (FT_Byte *) malloc (length);
|
||||
if (buffer == NULL)
|
||||
return NULL;
|
||||
if (!buffer)
|
||||
return nullptr;
|
||||
|
||||
error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
|
||||
if (error)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
return hb_blob_create ((const char *) buffer, length,
|
||||
HB_MEMORY_MODE_WRITABLE,
|
||||
@ -494,7 +516,7 @@ hb_ft_face_create (FT_Face ft_face,
|
||||
{
|
||||
hb_face_t *face;
|
||||
|
||||
if (ft_face->stream->read == NULL) {
|
||||
if (!ft_face->stream->read) {
|
||||
hb_blob_t *blob;
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
@ -552,7 +574,7 @@ hb_ft_face_create_cached (FT_Face ft_face)
|
||||
if (ft_face->generic.finalizer)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -581,16 +603,61 @@ hb_ft_font_create (FT_Face ft_face,
|
||||
font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
_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,
|
||||
(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.y_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 + (1u<<15)) >> 16));
|
||||
#if 0 /* hb-ft works in no-hinting model */
|
||||
hb_font_set_ppem (font,
|
||||
ft_face->size->metrics.x_ppem,
|
||||
ft_face->size->metrics.y_ppem);
|
||||
#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)
|
||||
{
|
||||
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. */
|
||||
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);
|
||||
goto retry;
|
||||
}
|
||||
@ -662,7 +729,7 @@ hb_ft_font_set_funcs (hb_font_t *font)
|
||||
if (unlikely (!blob_length))
|
||||
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 (),
|
||||
(const FT_Byte *) blob_data,
|
||||
blob_length,
|
||||
@ -675,7 +742,8 @@ hb_ft_font_set_funcs (hb_font_t *font)
|
||||
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,
|
||||
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,
|
||||
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.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_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_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;
|
||||
}
|
||||
|
||||
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_glib_get_unicode_funcs (void)
|
||||
{
|
||||
static const hb_unicode_funcs_t _hb_glib_unicode_funcs = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
retry:
|
||||
hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_glib_funcs);
|
||||
|
||||
NULL, /* parent */
|
||||
true, /* immutable */
|
||||
{
|
||||
#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_glib_unicode_##name,
|
||||
if (unlikely (!funcs))
|
||||
{
|
||||
funcs = hb_unicode_funcs_create (nullptr);
|
||||
|
||||
#define HB_UNICODE_FUNC_IMPLEMENT(name) \
|
||||
hb_unicode_funcs_set_##name##_func (funcs, hb_glib_unicode_##name, nullptr, nullptr);
|
||||
HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#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,
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
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_glib_get_unicode_funcs (void);
|
||||
|
||||
#if GLIB_CHECK_VERSION(2,31,10)
|
||||
HB_EXTERN hb_blob_t *
|
||||
hb_glib_blob_create (GBytes *gbytes);
|
||||
|
||||
#endif
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
|
@ -42,7 +42,8 @@ HB_BEGIN_DECLS
|
||||
/*** END file-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 ())
|
||||
|
||||
/*** 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) \
|
||||
{ \
|
||||
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; \
|
||||
return c; \
|
||||
} \
|
||||
@ -78,3 +78,6 @@ HB_DEFINE_VALUE_TYPE (glyph_info)
|
||||
HB_DEFINE_VALUE_TYPE (glyph_position)
|
||||
HB_DEFINE_VALUE_TYPE (segment_properties)
|
||||
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