mirror of
https://github.com/harfbuzz/harfbuzz.git
synced 2025-04-13 08:42:59 +00:00
Merge branch 'master' into remove-coretext-96dpi-assumption
This commit is contained in:
commit
37de38adea
555 changed files with 25930 additions and 17603 deletions
17
.ci/build-freetype.sh
Normal file
17
.ci/build-freetype.sh
Normal file
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
set -o errexit -o nounset
|
||||
|
||||
# 22.0.16 is the libtool version of 2.9.0
|
||||
if pkg-config --atleast-version 22.0.16 freetype2; then exit; fi
|
||||
|
||||
pushd $HOME
|
||||
wget http://download.savannah.gnu.org/releases/freetype/freetype-2.9.tar.bz2
|
||||
tar xf freetype-2.9.tar.bz2
|
||||
pushd freetype-2.9
|
||||
./autogen.sh
|
||||
./configure --prefix=$HOME/.local
|
||||
make -j4 install
|
||||
popd
|
||||
popd
|
|
@ -7,7 +7,7 @@ jobs:
|
|||
xcode: "9.2.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel freetype glib cairo
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget autoconf automake libtool pkg-config ragel freetype glib cairo
|
||||
- run: ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo
|
||||
- run: make -j4
|
||||
- run: make check || .ci/fail.sh
|
||||
|
@ -17,49 +17,24 @@ jobs:
|
|||
xcode: "10.1.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel freetype glib cairo
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget autoconf automake libtool pkg-config ragel freetype glib cairo
|
||||
- run: ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo
|
||||
- run: make -j4
|
||||
- run: make check || .ci/fail.sh
|
||||
|
||||
macos-llvm-gcc-4.2:
|
||||
macos-10.14.3-aat-fonts:
|
||||
macos:
|
||||
xcode: "8.3.3"
|
||||
xcode: "10.2.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel freetype glib cairo
|
||||
- run: wget https://packages.macports.org/llvm-gcc42/llvm-gcc42-2336.11_3+universal.darwin_15.i386-x86_64.tbz2 && tar zxvf llvm-gcc42-2336.11_3+universal.darwin_15.i386-x86_64.tbz2
|
||||
- run: CC=$PWD/opt/local/bin/llvm-gcc-4.2 CXX=$PWD/opt/local/bin/llvm-g++-4.2 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo
|
||||
# Ignoring assembler complains, https://stackoverflow.com/a/39867021
|
||||
- run: make 2>&1 | grep -v -e '^/var/folders/*' -e '^[[:space:]]*\.section' -e '^[[:space:]]*\^[[:space:]]*~*'
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget autoconf automake libtool pkg-config ragel freetype glib cairo icu4c graphite2
|
||||
- run: export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" && ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-coretext --with-graphite2
|
||||
- run: make -j4
|
||||
- run: make check || .ci/fail.sh
|
||||
|
||||
macos-notest-apple-gcc-i686-4.2:
|
||||
macos:
|
||||
xcode: "8.3.3"
|
||||
steps:
|
||||
- checkout
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel
|
||||
- run: wget https://packages.macports.org/apple-gcc42/apple-gcc42-5666.3_15+universal.darwin_15.i386-x86_64.tbz2 && tar zxvf apple-gcc42-5666.3_15+universal.darwin_15.i386-x86_64.tbz2
|
||||
- run: CPP=$PWD/opt/local/bin/i686-apple-darwin15-cpp-apple-4.2.1 CC=$PWD/opt/local/bin/i686-apple-darwin15-gcc-apple-4.2.1 CXX=$PWD/opt/local/bin/i686-apple-darwin15-g++-apple-4.2.1 ./autogen.sh
|
||||
# Ignoring assembler complains, https://stackoverflow.com/a/39867021
|
||||
- run: make 2>&1 | grep -v -e '^/var/folders/*' -e '^[[:space:]]*\.section' -e '^[[:space:]]*\^[[:space:]]*~*'
|
||||
|
||||
macos-notest-ios:
|
||||
macos:
|
||||
xcode: "10.0.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake
|
||||
# not needed to be a framework but we like to test that also
|
||||
# TODO: wrong way of targeting iOS as it doesn't point to iOS headers thus building
|
||||
# CoreText support is not possible, after the fix feel free HB_IOS from CMake altogether
|
||||
- run: cmake -DBUILD_FRAMEWORK=ON -H. -Bbuild -GXcode -DHB_HAVE_CORETEXT=OFF -DHB_BUILD_SUBSET=OFF -DHB_BUILD_TESTS=OFF
|
||||
- run: cd build && xcodebuild -sdk iphoneos12.0 -configuration Release build -arch arm64
|
||||
|
||||
distcheck:
|
||||
docker:
|
||||
- image: ubuntu:17.10
|
||||
- image: ubuntu:19.04
|
||||
steps:
|
||||
- checkout
|
||||
- run: apt update && apt install -y ninja-build binutils libtool autoconf automake make cmake gcc g++ pkg-config ragel gtk-doc-tools libfontconfig1-dev libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
|
||||
|
@ -70,37 +45,50 @@ jobs:
|
|||
- 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-NOMMAP:
|
||||
alpine-O3-Os-NOMMAP:
|
||||
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
|
||||
- run: apk update && apk add ragel make pkgconfig libtool autoconf automake gettext gcc g++ glib-dev freetype-dev cairo-dev python
|
||||
# C??FLAGS are not needed for a regular build
|
||||
- run: CFLAGS="-O3" CXXFLAGS="-O3 -DHB_NO_MMAP" ./autogen.sh
|
||||
- run: make -j32
|
||||
- run: make check || .ci/fail.sh
|
||||
- run: make clean
|
||||
- run: CFLAGS="-Os -DHB_OPTIMIZE_SIZE" CXXFLAGS="-Os -DHB_NO_MMAP -DHB_OPTIMIZE_SIZE" ./autogen.sh
|
||||
- run: make -j32
|
||||
- run: make check || .ci/fail.sh
|
||||
|
||||
archlinux-py3-all:
|
||||
docker:
|
||||
- image: base/devel
|
||||
- image: archlinux/base
|
||||
steps:
|
||||
- checkout
|
||||
- run: pacman --noconfirm -Syu freetype2 cairo icu gettext gobject-introspection gcc gcc-libs glib2 graphite pkg-config ragel python python-pip
|
||||
- run: pacman --noconfirm -Syu freetype2 cairo icu gettext gobject-introspection gcc gcc-libs glib2 graphite pkg-config ragel python python-pip make which base-devel
|
||||
- run: pip install flake8 fonttools
|
||||
- run: flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
|
||||
# C??FLAGS are not needed for a regular build
|
||||
- run: CFLAGS="-Wall -Wextra -Wno-cast-function-type" CXXFLAGS="-Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-class-memaccess -Wpedantic -Wno-format -Wno-cast-function-type" ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2
|
||||
- run: ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2
|
||||
- run: make -j32 CPPFLAGS="-Werror"
|
||||
- run: make check CPPFLAGS="-Werror" || .ci/fail.sh
|
||||
|
||||
clang-O3-O0:
|
||||
## Doesn't play well with CircleCI apparently
|
||||
#void-notest:
|
||||
# docker:
|
||||
# - image: voidlinux/voidlinux
|
||||
# steps:
|
||||
# - checkout
|
||||
# - run: xbps-install -Suy freetype gettext gcc glib graphite pkg-config ragel libtool autoconf automake make
|
||||
# - run: ./autogen.sh && make -j32 && make check
|
||||
|
||||
clang-O3-O0-and-nobuildsystem:
|
||||
docker:
|
||||
- image: multiarch/crossbuild
|
||||
- image: ubuntu:18.10
|
||||
steps:
|
||||
- checkout
|
||||
- run: apt update || true
|
||||
- run: apt install -y ragel libfreetype6-dev libfontconfig1-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
|
||||
- run: apt install -y clang wget autoconf automake libtool pkg-config ragel libfreetype6-dev libfontconfig1-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 -j32 && cd ..
|
||||
- run: CFLAGS="-O3" CXXFLAGS="-O3" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-fontconfig --with-glib --with-cairo --with-icu --with-graphite2
|
||||
|
@ -109,6 +97,7 @@ jobs:
|
|||
- run: CFLAGS="-O0" CXXFLAGS="-O0" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-fontconfig --with-glib --with-cairo --with-icu --with-graphite2
|
||||
- run: make -j32
|
||||
- run: LD_LIBRARY_PATH="$PWD/freetype-2.9/objs/.libs" make check || .ci/fail.sh
|
||||
- run: make clean && cd src && clang++ -c hb-*.cc
|
||||
|
||||
gcc-valgrind:
|
||||
docker:
|
||||
|
@ -138,7 +127,7 @@ jobs:
|
|||
- run: apt update || true
|
||||
- run: apt install -y clang lld binutils libtool autoconf automake make pkg-config gtk-doc-tools ragel libfreetype6-dev libfontconfig1-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
|
||||
- run: pip install fonttools
|
||||
- run: CFLAGS="-Weverything -Wno-reserved-id-macro -Wno-conversion -Wno-padded -Wno-sign-conversion -Wno-cast-qual -Wno-documentation -Wno-documentation-unknown-command" CXXFLAGS="-Weverything -Wno-old-style-cast -Wno-documentation -Wno-documentation-unknown-command -Wno-c++98-compat -Wno-cast-qual -Wno-c++98-compat-pedantic -Wno-sign-conversion -Wno-padded -Wno-shorten-64-to-32 -Wno-reserved-id-macro -Wno-float-conversion -Wno-format-pedantic -Wno-shadow -Wno-conversion -Wno-zero-as-null-pointer-constant -Wno-missing-field-initializers -Wno-used-but-marked-unused -Wno-unused-macros -Wno-comma -Wno-float-equal -Wno-disabled-macro-expansion -Wno-weak-vtables -Wno-unused-parameter -Wno-covered-switch-default -Wno-unreachable-code" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2 --with-fontconfig
|
||||
- run: CFLAGS="-Weverything -Wno-reserved-id-macro -Wno-conversion -Wno-padded -Wno-sign-conversion -Wno-cast-qual -Wno-documentation -Wno-documentation-unknown-command" CXXFLAGS="-Weverything -Wno-old-style-cast -Wno-documentation -Wno-documentation-unknown-command -Wno-c++98-compat -Wno-cast-qual -Wno-c++98-compat-pedantic -Wno-sign-conversion -Wno-padded -Wno-shorten-64-to-32 -Wno-reserved-id-macro -Wno-float-conversion -Wno-format-pedantic -Wno-shadow -Wno-conversion -Wno-zero-as-null-pointer-constant -Wno-missing-field-initializers -Wno-used-but-marked-unused -Wno-unused-macros -Wno-comma -Wno-float-equal -Wno-disabled-macro-expansion -Wno-weak-vtables -Wno-unused-parameter -Wno-covered-switch-default -Wno-unreachable-code -Wno-unused-template" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2 --with-fontconfig
|
||||
- run: make -j32 CPPFLAGS="-Werror"
|
||||
- run: make check CPPFLAGS="-Werror" || .ci/fail.sh
|
||||
|
||||
|
@ -208,18 +197,27 @@ jobs:
|
|||
- run: make -j32
|
||||
- run: make check || .ci/fail.sh | asan_symbolize | c++filt
|
||||
|
||||
fedora-O0-debug-outoftreebuild:
|
||||
fedora-O0-debug-outoftreebuild-mingw:
|
||||
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: 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 mingw32-gcc-c++ mingw64-gcc-c++ mingw32-glib2 mingw32-cairo mingw32-freetype mingw64-glib2 mingw64-cairo mingw64-freetype glibc-devel.i686 || true
|
||||
- run: CFLAGS="-O0" CXXFLAGS="-O0" CPPFLAGS="-DHB_DEBUG" 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)
|
||||
- run: mkdir build && cd build && ../configure && make -j32 && (make check || ../.ci/fail.sh)
|
||||
- run: pip install pefile
|
||||
- run: mkdir winbuild32 && cd winbuild32 && ../mingw32.sh && make -j32 && make dist-win && cp harfbuzz-*-win32.zip harfbuzz-win32.zip
|
||||
- run: mkdir winbuild64 && cd winbuild64 && ../mingw64.sh && make -j32 && make dist-win && cp harfbuzz-*-win64.zip harfbuzz-win64.zip
|
||||
- store_artifacts:
|
||||
path: winbuild32/harfbuzz-win32.zip
|
||||
destination: harfbuzz-win32.zip
|
||||
- store_artifacts:
|
||||
path: winbuild64/harfbuzz-win64.zip
|
||||
destination: harfbuzz-win64.zip
|
||||
|
||||
cmake-gcc:
|
||||
docker:
|
||||
- image: ubuntu:17.10
|
||||
- image: ubuntu:19.04
|
||||
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
|
||||
|
@ -229,17 +227,17 @@ jobs:
|
|||
- 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 libnsl || 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_FREETYPE=ON -Bbuild -H.
|
||||
- run: make -Cbuild -j32
|
||||
- run: CTEST_OUTPUT_ON_FAILURE=1 make -Cbuild test
|
||||
- run: make -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 libnsl || 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_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -Bbuild -H.
|
||||
# - run: make -Cbuild -j32
|
||||
# - run: CTEST_OUTPUT_ON_FAILURE=1 make -Cbuild test
|
||||
# - run: make -Cbuild install
|
||||
|
||||
crosscompile-notest-djgpp:
|
||||
docker:
|
||||
|
@ -251,22 +249,13 @@ jobs:
|
|||
- run: CFLAGS="-Wno-attributes" CXXFLAGS="-Wno-attributes" ./autogen.sh --prefix=/usr/local/djgpp --host=i586-pc-msdosdjgpp
|
||||
- run: make -j32
|
||||
|
||||
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 -j32
|
||||
|
||||
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: echo '#!/bin/true' > /usr/bin/ragel && chmod +x /usr/bin/ragel
|
||||
- run: ./autogen.sh --prefix=/usr/local/vitasdk/arm-vita-eabi --host=arm-vita-eabi
|
||||
- run: make -j32
|
||||
|
||||
|
@ -275,17 +264,15 @@ jobs:
|
|||
- image: dockcross/android-arm
|
||||
steps:
|
||||
- checkout
|
||||
- run: apt update && apt install ragel
|
||||
- run: cmake -Bbuild -H. -GNinja
|
||||
- run: cmake -Bbuild -H. -GNinja -DHB_BUILD_TESTS=OFF
|
||||
- run: ninja -Cbuild
|
||||
|
||||
crosscompile-cmake-notest-browser-asmjs:
|
||||
crosscompile-cmake-notest-browser-asmjs-hb_tiny:
|
||||
docker:
|
||||
- image: dockcross/browser-asmjs
|
||||
steps:
|
||||
- checkout
|
||||
- run: apt update && apt install ragel
|
||||
- run: cmake -Bbuild -H. -GNinja
|
||||
- run: cmake -Bbuild -H. -GNinja -DCMAKE_CXX_FLAGS="-DHB_TINY" -DHB_BUILD_TESTS=OFF
|
||||
- run: ninja -Cbuild
|
||||
|
||||
crosscompile-cmake-notest-linux-arm64:
|
||||
|
@ -293,8 +280,7 @@ jobs:
|
|||
- image: dockcross/linux-arm64
|
||||
steps:
|
||||
- checkout
|
||||
- run: apt update && apt install ragel
|
||||
- run: cmake -Bbuild -H. -GNinja
|
||||
- run: cmake -Bbuild -H. -GNinja -DHB_BUILD_TESTS=OFF
|
||||
- run: ninja -Cbuild
|
||||
|
||||
crosscompile-cmake-notest-linux-mips:
|
||||
|
@ -302,8 +288,7 @@ jobs:
|
|||
- image: dockcross/linux-mips
|
||||
steps:
|
||||
- checkout
|
||||
- run: apt update && apt install ragel
|
||||
- run: cmake -Bbuild -H. -GNinja
|
||||
- run: cmake -Bbuild -H. -GNinja -DHB_BUILD_TESTS=OFF
|
||||
- run: ninja -Cbuild
|
||||
|
||||
#crosscompile-cmake-notest-windows-x64:
|
||||
|
@ -311,7 +296,6 @@ jobs:
|
|||
# - image: dockcross/windows-x64
|
||||
# steps:
|
||||
# - checkout
|
||||
# - run: apt update && apt install ragel
|
||||
# - run: cmake -Bbuild -H. -GNinja
|
||||
# - run: ninja -Cbuild
|
||||
|
||||
|
@ -322,39 +306,37 @@ workflows:
|
|||
# macOS
|
||||
- macos-10.12.6-aat-fonts
|
||||
- macos-10.13.6-aat-fonts
|
||||
- macos-llvm-gcc-4.2
|
||||
- macos-notest-apple-gcc-i686-4.2
|
||||
- macos-notest-ios
|
||||
- macos-10.14.3-aat-fonts
|
||||
|
||||
# both autotools and cmake
|
||||
- distcheck
|
||||
|
||||
# autotools based builds
|
||||
- alpine-O3-NOMMAP
|
||||
- alpine-O3-Os-NOMMAP
|
||||
- archlinux-py3-all
|
||||
#- void-notest
|
||||
- gcc-valgrind
|
||||
- clang-O3-O0
|
||||
- clang-O3-O0-and-nobuildsystem
|
||||
- clang-everything
|
||||
- clang-asan
|
||||
- clang-msan
|
||||
- clang-tsan
|
||||
- clang-ubsan
|
||||
- fedora-O0-debug-outoftreebuild
|
||||
- fedora-O0-debug-outoftreebuild-mingw
|
||||
|
||||
# cmake based builds
|
||||
- cmake-gcc
|
||||
- cmake-oracledeveloperstudio
|
||||
#- 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-browser-asmjs-hb_tiny
|
||||
- crosscompile-cmake-notest-linux-arm64
|
||||
- crosscompile-cmake-notest-linux-mips
|
||||
#- crosscompile-cmake-notest-windows-x64
|
||||
|
|
|
@ -8,11 +8,8 @@ insert_final_newline = true
|
|||
|
||||
[*.{c,cc,h,hh}]
|
||||
tab_width = 8
|
||||
indent_style = tab
|
||||
# This should be the following but as VSCode and Atom don't support it, disabled for now
|
||||
# https://github.com/Microsoft/vscode/issues/44438
|
||||
# indent_size = 2
|
||||
# indent_style = space
|
||||
indent_size = 2
|
||||
indent_style = tab # should be space
|
||||
|
||||
[*.{py,sh}]
|
||||
indent_style = tab
|
||||
|
|
36
.travis.yml
36
.travis.yml
|
@ -6,8 +6,6 @@ language: cpp
|
|||
env:
|
||||
global:
|
||||
- CPPFLAGS=""
|
||||
- CFLAGS="-Werror -Werror=unused -Werror=unused-function"
|
||||
- CXXFLAGS="-Werror -Werror=unused -Werror=unused-function -Wno-deprecated-register" # glib uses register and clang raises a warning
|
||||
- CONFIGURE_OPTS="--with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2"
|
||||
- NOCONFIGURE=1
|
||||
# COVERITY_SCAN_TOKEN
|
||||
|
@ -18,9 +16,10 @@ matrix:
|
|||
- 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"
|
||||
# Remove the following three lines when Travis updates its distro
|
||||
- export PKG_CONFIG_PATH="$HOME/.local/lib/pkgconfig"
|
||||
- export LD_LIBRARY_PATH="$HOME/.local/lib"
|
||||
- bash .ci/build-freetype.sh
|
||||
|
||||
- ./autogen.sh
|
||||
- ./configure $CONFIGURE_OPTS --enable-gtk-doc --enable-code-coverage
|
||||
|
@ -36,35 +35,24 @@ matrix:
|
|||
- 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"
|
||||
# Remove the following three lines when Travis updates its distro
|
||||
- export PKG_CONFIG_PATH="$HOME/.local/lib/pkgconfig"
|
||||
- export LD_LIBRARY_PATH="$HOME/.local/lib"
|
||||
- bash .ci/build-freetype.sh
|
||||
|
||||
- ./autogen.sh
|
||||
- ./configure $CONFIGURE_OPTS
|
||||
- make
|
||||
- make check || .ci/fail.sh
|
||||
|
||||
- os: osx
|
||||
compiler: clang
|
||||
install:
|
||||
- brew update;
|
||||
# Workaround Travis/brew bug
|
||||
- brew uninstall libtool && brew install libtool
|
||||
- brew install ragel freetype glib gobject-introspection cairo graphite2 || true
|
||||
- brew upgrade icu4c || true
|
||||
- export PATH="/usr/local/opt/icu4c/sbin:/usr/local/opt/icu4c/bin:$PATH"
|
||||
- export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig"
|
||||
script:
|
||||
- ./autogen.sh
|
||||
- ./configure $CONFIGURE_OPTS --with-coretext
|
||||
- make
|
||||
- make check || .ci/fail.sh
|
||||
|
||||
notifications:
|
||||
irc: "irc.freenode.org#harfbuzz"
|
||||
email: harfbuzz-bots-chatter@googlegroups.com
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- /home/travis/.local
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
|
|
3
AUTHORS
3
AUTHORS
|
@ -1,11 +1,14 @@
|
|||
Behdad Esfahbod
|
||||
David Corbett
|
||||
David Turner
|
||||
Ebrahim Byagowi
|
||||
Garret Rieger
|
||||
Jonathan Kew
|
||||
Khaled Hosny
|
||||
Lars Knoll
|
||||
Martin Hosken
|
||||
Owen Taylor
|
||||
Roderick Sheeter
|
||||
Roozbeh Pournader
|
||||
Simon Hausmann
|
||||
Werner Lemberg
|
||||
|
|
120
CMakeLists.txt
120
CMakeLists.txt
|
@ -35,7 +35,6 @@ 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)
|
||||
|
@ -44,6 +43,7 @@ if (APPLE)
|
|||
endif ()
|
||||
if (WIN32)
|
||||
option(HB_HAVE_UNISCRIBE "Enable Uniscribe shaper backend on Windows" OFF)
|
||||
option(HB_HAVE_GDI "Enable GDI integration helpers 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)
|
||||
|
@ -70,7 +70,6 @@ option(HB_CHECK OFF "Do a configuration suitable for testing (shared library and
|
|||
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)
|
||||
|
@ -79,6 +78,7 @@ if (HB_CHECK)
|
|||
set (HB_HAVE_GRAPHITE2 ON)
|
||||
if (WIN32)
|
||||
set (HB_HAVE_UNISCRIBE ON)
|
||||
set (HB_HAVE_GDI ON)
|
||||
set (HB_HAVE_DIRECTWRITE ON)
|
||||
elseif (APPLE)
|
||||
set (HB_HAVE_CORETEXT ON)
|
||||
|
@ -90,8 +90,6 @@ include_directories(AFTER
|
|||
${PROJECT_BINARY_DIR}/src
|
||||
)
|
||||
|
||||
add_definitions(-DHAVE_FALLBACK)
|
||||
|
||||
# We need PYTHON_EXECUTABLE to be set for running the tests...
|
||||
include (FindPythonInterp)
|
||||
|
||||
|
@ -110,7 +108,7 @@ endmacro ()
|
|||
if (UNIX)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES m)
|
||||
endif ()
|
||||
check_funcs(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l round)
|
||||
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)
|
||||
|
@ -144,8 +142,8 @@ 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})
|
||||
string(REGEX MATCH "${variable} = ([^$]+)\\$" temp "${makefile_source}")
|
||||
string(REGEX MATCHALL "[^ \n\t\\]+" listVar "${CMAKE_MATCH_1}")
|
||||
set (${variable} ${listVar} PARENT_SCOPE)
|
||||
endfunction ()
|
||||
|
||||
|
@ -160,14 +158,9 @@ 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_SUBSET_sources ${SRCSOURCES})
|
||||
add_prefix_to_list(HB_SUBSET_sources "${PROJECT_SOURCE_DIR}/src/")
|
||||
|
@ -191,9 +184,6 @@ 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})
|
||||
|
@ -202,61 +192,12 @@ 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)
|
||||
# foreach (ragel_output IN ITEMS ${HB_BASE_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}
|
||||
)
|
||||
|
||||
set (subset_project_sources
|
||||
${HB_SUBSET_sources}
|
||||
)
|
||||
|
||||
set (project_sources ${PROJECT_SOURCE_DIR}/src/harfbuzz.cc) # use amalgam source
|
||||
set (subset_project_sources ${HB_SUBSET_sources})
|
||||
set (project_extra_sources)
|
||||
|
||||
set (project_headers
|
||||
#${HB_VERSION_H}
|
||||
|
||||
${HB_BASE_headers}
|
||||
)
|
||||
|
||||
set (subset_project_headers
|
||||
${HB_SUBSET_headers}
|
||||
)
|
||||
|
||||
set (project_headers ${HB_BASE_headers})
|
||||
set (subset_project_headers ${HB_SUBSET_headers})
|
||||
|
||||
## Find and include needed header folders and libraries
|
||||
if (HB_HAVE_FREETYPE)
|
||||
|
@ -269,7 +210,6 @@ if (HB_HAVE_FREETYPE)
|
|||
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
|
||||
|
@ -287,7 +227,6 @@ if (HB_HAVE_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})
|
||||
|
@ -295,14 +234,6 @@ if (HB_HAVE_GRAPHITE2)
|
|||
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)
|
||||
|
||||
|
@ -316,7 +247,6 @@ if (HB_HAVE_GLIB)
|
|||
|
||||
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})
|
||||
|
@ -336,7 +266,6 @@ if (HB_HAVE_ICU)
|
|||
|
||||
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})
|
||||
|
@ -348,7 +277,6 @@ 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)
|
||||
|
||||
if (HB_IOS)
|
||||
|
@ -379,21 +307,21 @@ if (APPLE AND HB_HAVE_CORETEXT)
|
|||
endif ()
|
||||
endif ()
|
||||
|
||||
if (WIN32 AND HB_HAVE_GDI)
|
||||
add_definitions(-DHAVE_GDI)
|
||||
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-gdi.h)
|
||||
list(APPEND THIRD_PARTY_LIBS gdi32)
|
||||
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 ()
|
||||
|
||||
|
@ -501,7 +429,6 @@ if (HB_HAVE_GOBJECT)
|
|||
)
|
||||
endif ()
|
||||
|
||||
|
||||
## Atomic ops availability detection
|
||||
file(WRITE "${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c"
|
||||
" void memory_barrier (void) { __sync_synchronize (); }
|
||||
|
@ -610,7 +537,6 @@ if (WIN32)
|
|||
endif ()
|
||||
|
||||
if (HB_HAVE_INTROSPECTION)
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_GI QUIET gobject-introspection-1.0)
|
||||
|
||||
|
@ -842,21 +768,9 @@ if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
|
|||
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 ()
|
||||
|
||||
|
||||
if (HB_BUILD_TESTS)
|
||||
## src/ executables
|
||||
foreach (prog main test test-would-substitute test-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges)
|
||||
foreach (prog main test test-gsub-would-substitute test-gpos-size-params test-buffer-serialize test-unicode-ranges) # hb-ot-tag
|
||||
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
|
||||
|
@ -865,7 +779,7 @@ if (HB_BUILD_TESTS)
|
|||
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")
|
||||
# set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN")
|
||||
|
||||
## Tests
|
||||
if (UNIX OR MINGW)
|
||||
|
|
151
CONFIG.md
Normal file
151
CONFIG.md
Normal file
|
@ -0,0 +1,151 @@
|
|||
# Configuring HarfBuzz
|
||||
|
||||
Most of the time you will not need any custom configuration. The configuration
|
||||
options provided by `configure` or `cmake` should be enough. In particular,
|
||||
if you just want HarfBuzz library plus hb-shape / hb-view utilities, make sure
|
||||
FreeType and Cairo are available and found during configuration.
|
||||
|
||||
If you are building for distribution, you should more carefully consider whether
|
||||
you need Glib, ICU, Graphite2, as well as CoreText / Uniscribe / DWrite. Make
|
||||
sure the relevant ones are enabled.
|
||||
|
||||
If you are building for custom environment (embedded, downloadable app, etc)
|
||||
where you mostly just want to call `hb_shape()` and the binary size of the
|
||||
resulting library is very important to you, the rest of this file guides you
|
||||
through your options to disable features you may not need, in exchange for
|
||||
binary size savings.
|
||||
|
||||
## Compiler Options
|
||||
|
||||
Make sure you build with your compiler's "optimize for size" option. On `gcc`
|
||||
this is `-Os`, and can be enabled by passing `CXXFLAGS=-Os` either to `configure`
|
||||
(sticky) or to `make` (non-sticky). On clang there is an even more extreme flag,
|
||||
`-Oz`.
|
||||
|
||||
HarfBuzz heavily uses inline functions and the optimize-size flag can make the
|
||||
library smaller by 20% or more. Moreover, sometimes, based on the target CPU,
|
||||
the optimize-size builds perform *faster* as well, thanks to lower code
|
||||
footprint and caching effects. So, definitely try that even if size is not
|
||||
extremely tight but you have a huge application. For example, Chrome does
|
||||
that. Note that this configuration also automatically enables certain internal
|
||||
optimizations. Search for `HB_OPTIMIZE_SIZE` for details, if you are using
|
||||
other compilers, or continue reading.
|
||||
|
||||
Another compiler option to consider is "link-time optimization", also known as
|
||||
'lto'. To enable that, with `gcc` or `clang`, add `-flto` to both `CXXFLAGS`
|
||||
and `LDFLAGS`, either on `configure` invocation (sticky) or on `make` (non-sticky).
|
||||
This, also, can have a huge impact on the final size, 20% or more.
|
||||
|
||||
Finally, if you are making a static library build or otherwise linking the
|
||||
library into your app, make sure your linker removes unused functions. This
|
||||
can be tricky and differ from environment to environment, but you definitely
|
||||
want to make sure this happens. Otherwise, every unused public function will
|
||||
be adding unneeded bytes to your binary. The following pointers might come
|
||||
handy:
|
||||
|
||||
* https://lwn.net/Articles/741494/ (all of the four-part series)
|
||||
* https://elinux.org/images/2/2d/ELC2010-gc-sections_Denys_Vlasenko.pdf
|
||||
|
||||
Combining the above three build options should already shrink your library a lot.
|
||||
The rest of this file shows you ways to shrink the library even further at the
|
||||
expense of removing functionality (that may not be needed). The remaining
|
||||
options are all enabled by defining pre-processor macros, which can be done
|
||||
via `CXXFLAGS` or `CPPFLAGS` similarly.
|
||||
|
||||
|
||||
## Unicode-functions
|
||||
|
||||
Access to Unicode data can be configured at compile time as well as run-time.
|
||||
By default, HarfBuzz ships with its own compact subset of properties from
|
||||
Unicode Character Database that it needs. This is a highly-optimized
|
||||
implementation that depending on compile settings (optimize-size or not)
|
||||
takes around ~40kb or ~60kb. Using this implementation (default) is highly
|
||||
recommended, as HarfBuzz always ships with data from latest version of Unicode.
|
||||
This implementation can be disabled by defining `HB_NO_UCD`.
|
||||
|
||||
For example, if you are enabling ICU as a built-in option, or GLib, those
|
||||
can provide Unicode data as well, so defining `HB_NO_UCD` might save you
|
||||
space without reducing functionality (to the extent that the Unicode version
|
||||
of those implementations is recent.)
|
||||
|
||||
If, however, you provide your own Unicode data to HarfBuzz at run-time by
|
||||
calling `hb_buffer_set_unicode_funcs` on every buffer you create, and you do
|
||||
not rely on `hb_unicode_funcs_get_default()` results, you can disable the
|
||||
internal implementation by defining both `HB_NO_UCD` and `HB_NO_UNICODE_FUNCS`.
|
||||
The latter is needed to guard against accidentally building a library without
|
||||
any default Unicode implementations.
|
||||
|
||||
|
||||
## Font-functions
|
||||
|
||||
Access to certain font functionalities can also be configured at run-time. By
|
||||
default, HarfBuzz uses an efficient internal implementation of OpenType
|
||||
functionality for this. This internal implementation is called `hb-ot-font`.
|
||||
All newly-created `hb_font_t` objects by default use `hb-ot-font`. Using this
|
||||
is highly recommended, and is what fonts use by default when they are created.
|
||||
|
||||
Most embedded uses will probably use HarfBuzz with FreeType using `hb-ft.h`.
|
||||
In that case, or if you otherwise provide those functions by calling
|
||||
`hb_font_set_funcs()` on every font you create, you can disable `hb-ot-font`
|
||||
without loss of functionality by defining `HB_NO_OT_FONT`.
|
||||
|
||||
|
||||
## Shapers
|
||||
|
||||
Most HarfBuzz clients use it for the main shaper, called "ot". However, it
|
||||
is legitimate to want to compile HarfBuzz with only another backend, eg.
|
||||
CoreText, for example for an iOS app. For that, you want `HB_NO_OT_SHAPE`.
|
||||
If you are going down that route, check if you want `HB_NO_OT`.
|
||||
|
||||
This is very rarely what you need. Make sure you understand exactly what you
|
||||
are doing.
|
||||
|
||||
Defining `HB_NO_FALLBACK_SHAPE` however is pretty harmless. That removes the
|
||||
(unused) "fallback" shaper.
|
||||
|
||||
|
||||
## Thread-safety
|
||||
|
||||
By default HarfBuzz builds as a thread-safe library. The exception is that
|
||||
the `HB_TINY` predefined configuring (more below) disables thread-safety.
|
||||
|
||||
If you do /not/ need thread-safety in the library (eg. you always call into
|
||||
HarfBuzz from the same thread), you can disable thread-safety by defining
|
||||
`HB_NO_MT`. As noted already, this is enabled by `HB_TINY`.
|
||||
|
||||
|
||||
## Pre-defined configurations
|
||||
|
||||
The [`hb-config.hh`](src/hb-config.hh) internal header supports three
|
||||
pre-defined configurations as well grouping of various configuration options.
|
||||
The pre-defined configurations are:
|
||||
|
||||
* `HB_MINI`: Disables shaping of AAT as well as legacy fonts. Ie. it produces
|
||||
a capable OpenType shaper only.
|
||||
|
||||
* `HB_LEAN`: Disables various non-shaping functionality in the library, as well
|
||||
as esoteric or rarely-used shaping features. See the definition for details.
|
||||
|
||||
* `HB_TINY`: Enables both `HB_MINI` and `HB_LEAN` configurations, as well as
|
||||
disabling thread-safety and debugging, and use even more size-optimized data
|
||||
tables.
|
||||
|
||||
|
||||
## Tailoring configuration
|
||||
|
||||
Most of the time, one of the pre-defined configuration is exactly what one needs.
|
||||
Sometimes, however, the pre-defined configuration cuts out features that might
|
||||
be desired in the library. Unfortunately there is no quick way to undo those
|
||||
configurations from the command-line. But one can add a header file called
|
||||
`config-override.h` to undefine certain `HB_NO_*` symbols as desired. Then
|
||||
define `HAVE_CONFIG_OVERRIDE_H` to make `hb-config.hh` include your configuration
|
||||
overrides at the end.
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
Note that the config option `HB_NO_CFF`, which is enabled by `HB_LEAN` and
|
||||
`HB_TINY` does /not/ mean that the resulting library won't work with CFF fonts.
|
||||
The library can shape valid CFF fonts just fine, with or without this option.
|
||||
This option disables (among other things) the code to calculate glyph exntents
|
||||
for CFF fonts.
|
3
COPYING
3
COPYING
|
@ -2,7 +2,8 @@ HarfBuzz is licensed under the so-called "Old MIT" license. Details follow.
|
|||
For parts of HarfBuzz that are licensed under different licenses see individual
|
||||
files names COPYING in subdirectories where applicable.
|
||||
|
||||
Copyright © 2010,2011,2012 Google, Inc.
|
||||
Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019 Google, Inc.
|
||||
Copyright © 2019 Facebook, Inc.
|
||||
Copyright © 2012 Mozilla Foundation
|
||||
Copyright © 2011 Codethink Limited
|
||||
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
||||
|
|
29
Makefile.am
29
Makefile.am
|
@ -9,12 +9,19 @@ SUBDIRS = src util test docs
|
|||
EXTRA_DIST = \
|
||||
autogen.sh \
|
||||
harfbuzz.doap \
|
||||
README.md \
|
||||
README.mingw.md \
|
||||
README.python.md \
|
||||
README.wine.md \
|
||||
BUILD.md \
|
||||
CONFIG.md \
|
||||
RELEASING.md \
|
||||
TESTING.md \
|
||||
CMakeLists.txt \
|
||||
replace-enum-strings.cmake \
|
||||
mingw-configure.sh \
|
||||
mingw-ldd.py \
|
||||
mingw32.sh \
|
||||
mingw64.sh \
|
||||
$(NULL)
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
|
@ -36,7 +43,7 @@ ChangeLog: $(srcdir)/ChangeLog
|
|||
$(srcdir)/ChangeLog:
|
||||
$(AM_V_GEN) if test -d "$(top_srcdir)/.git"; then \
|
||||
(GIT_DIR=$(top_srcdir)/.git \
|
||||
$(GIT) log $(CHANGELOG_RANGE) --stat) | fmt --split-only > $@.tmp \
|
||||
$(GIT) log $(CHANGELOG_RANGE) --stat) > $@.tmp \
|
||||
&& mv -f $@.tmp "$(srcdir)/ChangeLog" \
|
||||
|| ($(RM) $@.tmp; \
|
||||
echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
|
||||
|
@ -60,8 +67,6 @@ DISTCHECK_CONFIGURE_FLAGS = \
|
|||
--enable-introspection \
|
||||
$(NULL)
|
||||
|
||||
# TODO: Copy infrastructure from cairo
|
||||
|
||||
# TAR_OPTIONS is not set as env var for 'make dist'. How to fix that?
|
||||
TAR_OPTIONS = --owner=0 --group=0
|
||||
|
||||
|
@ -70,8 +75,7 @@ dist-hook: dist-clear-sticky-bits
|
|||
dist-clear-sticky-bits:
|
||||
chmod -R a-s $(distdir)
|
||||
|
||||
|
||||
tar_file = $(PACKAGE_TARNAME)-$(VERSION).tar.bz2
|
||||
tar_file = $(PACKAGE_TARNAME)-$(VERSION).tar.xz
|
||||
sha256_file = $(tar_file).sha256
|
||||
gpg_file = $(sha256_file).asc
|
||||
$(sha256_file): $(tar_file)
|
||||
|
@ -82,5 +86,18 @@ $(gpg_file): $(sha256_file)
|
|||
|
||||
release-files: $(tar_file) $(sha256_file) $(gpg_file)
|
||||
|
||||
dist-win:
|
||||
@case $(host_triplet) in *-w64-mingw32) ;; *) echo "Error: Requires mingw build. See README.mingw.md.">&2; exit 1 ;; esac
|
||||
@DIR=$(PACKAGE_TARNAME)-$(VERSION)-win`case $(host_triplet) in i686-*) echo 32 ;; x86_64-*) echo 64 ;; esac`; \
|
||||
$(RM) -r $$DIR; $(MKDIR_P) $$DIR || exit 1; \
|
||||
cp util/.libs/hb-{shape,view,subset}.exe $$DIR && \
|
||||
$(top_srcdir)/mingw-ldd.py $$DIR/hb-view.exe | grep -v 'not found' | cut -d '>' -f 2 | xargs cp -t $$DIR && \
|
||||
cp src/.libs/libharfbuzz{,-subset}-0.dll $$DIR && \
|
||||
chmod a+x $$DIR/*.{exe,dll} && \
|
||||
$(STRIP) $$DIR/*.{exe,dll} && \
|
||||
zip -r $$DIR.zip $$DIR && \
|
||||
$(RM) -r $$DIR && \
|
||||
echo "$$DIR.zip is ready."
|
||||
|
||||
|
||||
-include $(top_srcdir)/git.mk
|
||||
|
|
85
NEWS
85
NEWS
|
@ -1,3 +1,88 @@
|
|||
Overview of changes leading to 2.6.0
|
||||
Tuesday, August 13, 2019
|
||||
====================================
|
||||
- New OpenType metrics, baseline, and metadata table access APIs.
|
||||
- New API to set font variations to a named-instance.
|
||||
- New hb-gdi.h header and API for creating hb_face_t from HFONT.
|
||||
- Amalgam: Provide a single-file harfbuzz.cc file for easier alternate building.
|
||||
- More size-reduction configurable options, enabled by HB_TINY.
|
||||
- New API:
|
||||
+hb_font_set_var_named_instance()
|
||||
+hb_gdi_face_create()
|
||||
+hb_ot_layout_baseline_tag_t
|
||||
+hb_ot_layout_get_baseline()
|
||||
+hb_ot_meta_tag_t
|
||||
+hb_ot_meta_get_entry_tags()
|
||||
+hb_ot_meta_reference_entry()
|
||||
+hb_ot_metrics_tag_t
|
||||
+hb_ot_metrics_get_position()
|
||||
+hb_ot_metrics_get_variation()
|
||||
+hb_ot_metrics_get_x_variation()
|
||||
+hb_ot_metrics_get_y_variation()
|
||||
|
||||
|
||||
Overview of changes leading to 2.5.3
|
||||
Wednesday, June 26, 2019
|
||||
====================================
|
||||
- Fix UCD script data for Unicode 10+ scripts. This was broken since 2.5.0.
|
||||
- More optimizations for HB_TINY.
|
||||
|
||||
|
||||
Overview of changes leading to 2.5.2
|
||||
Thursday, June 20, 2019
|
||||
====================================
|
||||
- More hb-config.hh facilities to shrink library size, namely when built as
|
||||
HB_TINY.
|
||||
- New documentation of custom configurations in CONFIG.md.
|
||||
- Fix build on gcc 4.8. That's supported again.
|
||||
- Universal Shaping Engine improvements thanks to David Corbett.
|
||||
- API Changes: Undeprecate some horizontal-kerning API and re-enable in hb-ft,
|
||||
such that Type1 fonts will continue kerning.
|
||||
|
||||
|
||||
Overview of changes leading to 2.5.1
|
||||
Friday, May 31, 2019
|
||||
====================================
|
||||
- Fix build with various versions of Visual Studio.
|
||||
- Improved documentation, thanks to Nathan Willis.
|
||||
- Bugfix in subsetting glyf table.
|
||||
- Improved scripts for cross-compiling for Windows using mingw.
|
||||
- Rename HB_MATH_GLYPH_PART_FLAG_EXTENDER to HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER.
|
||||
A deprecated macro is added for backwards-compatibility.
|
||||
|
||||
|
||||
Overview of changes leading to 2.5.0
|
||||
Friday, May 24, 2019
|
||||
====================================
|
||||
- This release does not include much functional changes, but includes major internal
|
||||
code-base changes. We now require C++11. Support for gcc 4.8 and earlier has been
|
||||
dropped.
|
||||
- New hb-config.hh facility for compiling smaller library for embedded and web usecases.
|
||||
- New Unicode Character Databse implementation that is half the size of previously-used
|
||||
UCDN.
|
||||
- Subsetter improvements.
|
||||
- Improved documentation, thanks to Nathan Willis.
|
||||
- Misc shaping fixes.
|
||||
|
||||
|
||||
Overview of changes leading to 2.4.0
|
||||
Monday, March 25, 2019
|
||||
====================================
|
||||
- Unicode 12.
|
||||
- Misc fixes.
|
||||
- Subsetter improvements.
|
||||
- New API:
|
||||
HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE
|
||||
hb_directwrite_face_create()
|
||||
|
||||
|
||||
Overview of changes leading to 2.3.1
|
||||
Wednesday, January 30, 2019
|
||||
====================================
|
||||
- AAT bug fixes.
|
||||
- Misc internal housekeeping cleanup.
|
||||
|
||||
|
||||
Overview of changes leading to 2.3.0
|
||||
Thursday, December 20, 2018
|
||||
====================================
|
||||
|
|
18
README
18
README
|
@ -1,18 +0,0 @@
|
|||
[](https://travis-ci.org/harfbuzz/harfbuzz)
|
||||
[](https://ci.appveyor.com/project/harfbuzz/harfbuzz)
|
||||
[](https://circleci.com/gh/harfbuzz/harfbuzz)
|
||||
[](https://scan.coverity.com/projects/behdad-harfbuzz)
|
||||
[](https://app.codacy.com/app/behdad/harfbuzz)
|
||||
[](https://codecov.io/gh/harfbuzz/harfbuzz)
|
||||
[](https://coveralls.io/r/harfbuzz/harfbuzz)
|
||||
[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
|
||||
|
||||
This is HarfBuzz, a text shaping library.
|
||||
|
||||
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
|
1
README
Symbolic link
1
README
Symbolic link
|
@ -0,0 +1 @@
|
|||
README.md
|
|
@ -1 +0,0 @@
|
|||
README
|
24
README.md
Normal file
24
README.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
[](https://travis-ci.org/harfbuzz/harfbuzz)
|
||||
[](https://ci.appveyor.com/project/harfbuzz/harfbuzz)
|
||||
[](https://circleci.com/gh/harfbuzz/harfbuzz/tree/master)
|
||||
[](https://scan.coverity.com/projects/behdad-harfbuzz)
|
||||
[](https://app.codacy.com/app/behdad/harfbuzz)
|
||||
[](https://codecov.io/gh/harfbuzz/harfbuzz)
|
||||
[](https://coveralls.io/r/harfbuzz/harfbuzz)
|
||||
[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
|
||||
|
||||
This is HarfBuzz, a text shaping library.
|
||||
|
||||
For bug reports, mailing list, and other information please visit:
|
||||
|
||||
http://harfbuzz.org/
|
||||
|
||||
For license information, see [COPYING](COPYING).
|
||||
|
||||
For build information, see [BUILD.md](BUILD.md).
|
||||
|
||||
For custom configurations, see [CONFIG.md](CONFIG.md).
|
||||
|
||||
For test execution, see [TESTING.md](TESTING.md).
|
||||
|
||||
Documentation: https://harfbuzz.github.io
|
48
README.mingw.md
Normal file
48
README.mingw.md
Normal file
|
@ -0,0 +1,48 @@
|
|||
For the development of HarfBuzz, the Microsoft shaping technology, Uniscribe,
|
||||
as a widely used and tested shaper is used as more-or-less OpenType reference
|
||||
implementation and that specially is important where OpenType specification
|
||||
is or wasn't that clear. For having access to Uniscribe on Linux/macOS these
|
||||
steps are recommended:
|
||||
|
||||
1. Install Wine from your favorite package manager. On Fedora that's `dnf install wine`.
|
||||
|
||||
2. And `mingw-w64` compiler.
|
||||
With `brew` on macOS, you can have it like `brew install mingw-w64`.
|
||||
On Fedora, with `dnf install mingw32-gcc-c++`, or `dnf install mingw64-gcc-c++` for the
|
||||
64-bit Windows.
|
||||
|
||||
3. Install cross-compiled dependency packages. Alternatively see [^1] below.
|
||||
On Fedora that would be `dnf install mingw32-glib2 mingw32-cairo mingw32-freetype`
|
||||
for 32-bit, or `dnf install mingw64-glib2 mingw64-cairo mingw64-freetype` for 64-bit.
|
||||
|
||||
5. `NOCONFIGURE=1 ./autogen.sh && mkdir winbuild && cd winbuild`
|
||||
|
||||
6. Run `../mingw32.sh` for 32-bit build, or `../mingw64.sh` for 64-bit. This configures
|
||||
HarfBuzz for cross-compiling. It enables Uniscribe backend as well.
|
||||
|
||||
7. `make`
|
||||
|
||||
Now you can use hb-shape using `wine util/hb-shape.exe` but if you like to shape with
|
||||
the Microsoft Uniscribe,
|
||||
|
||||
8. Bring a 32bit version of `usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your
|
||||
Windows installation (assuming you have a 64-bit installation, otherwise
|
||||
`C:\Windows\System32\usp10.dll`) that it is not a DirectWrite proxy
|
||||
([for more info](https://en.wikipedia.org/wiki/Uniscribe)).
|
||||
Rule of thumb, your `usp10.dll` should have a size more than 500kb, otherwise
|
||||
it is designed to work with DirectWrite which Wine can't work with its original one.
|
||||
You want a Uniscribe from Windows 7 or older.
|
||||
|
||||
Put the DLL in the folder you are going to run the next command,
|
||||
|
||||
9. `WINEDLLOVERRIDES="usp10=n" wine util/hb-shape.exe fontname.ttf -u 0061,0062,0063 --shaper=uniscribe`
|
||||
|
||||
(`0061,0062,0063` means `abc`, use test/shaping/hb-unicode-decode to generate ones you need)
|
||||
|
||||
|
||||
[^1] Download and put [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ)
|
||||
in your `~/.local/i686-w64-mingw32`. Then replace all the instances of
|
||||
`/home/behdad/.local/i586-mingw32msvc` and `/home/behdad/.local/i686-w64-mingw32`
|
||||
with `<$HOME>/.local/i686-w64-mingw32` on that folder.
|
||||
(`<$HOME>` replace it with `/home/XXX` or `/Users/XXX` on macOS)
|
||||
You shouldn't replace the instances of those inside binary files.
|
|
@ -6,21 +6,21 @@ you can install that this way:
|
|||
sudo apt-get install libgirepository1.0-dev
|
||||
```
|
||||
|
||||
And then run autogen.sh (if building from git), and then:
|
||||
And then run `autogen.sh` (if building from git), and then:
|
||||
|
||||
```bash
|
||||
./configure --with-gobject --enable-introspection
|
||||
```
|
||||
|
||||
Make sure that gobject-introspection is enabled then in the final report.
|
||||
Make sure that gobject-introspection is reported enabled then in the `configure` script output.
|
||||
|
||||
Compile and install.
|
||||
|
||||
Make sure you have the installation lib dir in LD_LIBRARY_PATH, as needed
|
||||
Make sure you have the installation lib dir in `LD_LIBRARY_PATH`, as needed
|
||||
for the linker to find the library.
|
||||
|
||||
Then make sure you also have GI_TYPELIB_PATH pointing to the resulting
|
||||
$prefix/lib/girepository-* directory.
|
||||
Then make sure you also have `GI_TYPELIB_PATH` pointing to the resulting
|
||||
`$prefix/lib/girepository-*` directory.
|
||||
|
||||
Make sure you have pygobject installed. Then check that the following
|
||||
import works in your Python interpreter:
|
||||
|
@ -30,7 +30,7 @@ from gi.repository import HarfBuzz
|
|||
```
|
||||
|
||||
If it does, you are ready to call HarfBuzz from Python! Congratulations.
|
||||
See src/sample.py.
|
||||
See [`src/sample.py`](src/sample.py).
|
||||
|
||||
The Python API will change. Let us know on the mailing list if you are
|
||||
using it, and send lots of feedback.
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
For the development of HarfBuzz, the Microsoft shaping technology, Uniscribe,
|
||||
as a widely used and tested shaper is used as more-or-less OpenType reference
|
||||
implementation and that specially is important where OpenType specification
|
||||
is or wasn't that clear. For having access to Uniscribe on Linux/macOS these
|
||||
steps are recommended:
|
||||
|
||||
1. Install Wine from your favorite package manager.
|
||||
|
||||
2. And `mingw-w64` compiler.
|
||||
With `brew` on macOS, you can have it like `brew install mingw-w64`
|
||||
|
||||
3. Download and put [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ)
|
||||
on your `~/.local/i686-w64-mingw32`.
|
||||
|
||||
4. Replace all the instances of `/home/behdad/.local/i586-mingw32msvc`
|
||||
and `/home/behdad/.local/i686-w64-mingw32` with `<$HOME>/.local/i686-w64-mingw32`
|
||||
on that folder. (`<$HOME>` replace it with `/home/XXX` or `/Users/XXX` on macOS)
|
||||
|
||||
Probably you shouldn't replace the ones are inside binaries.
|
||||
|
||||
5. `NOCONFIGURE=1 ./autogen.sh && mkdir winbuild && cd winbuild`
|
||||
|
||||
6. `../mingw32.sh --with-uniscribe && cd ..`
|
||||
|
||||
7. `make -Cwinbuild`
|
||||
|
||||
Now you can use hb-shape using `wine winbuild/util/hb-shape.exe` but if you like to
|
||||
to use the original Uniscribe,
|
||||
|
||||
8. Bring a 32bit version of `usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your
|
||||
Windows installation (assuming you have a 64-bit installation, otherwise `C:\Windows\System32\usp10.dll`)
|
||||
that it is not a DirectWrite proxy ([for more info](https://en.wikipedia.org/wiki/Uniscribe)).
|
||||
Rule of thumb, your `usp10.dll` should have a size more than 500kb, otherwise
|
||||
it is designed to work with DirectWrite which Wine can't work with its original one.
|
||||
|
||||
Put the dll on the folder you are going to run the next command,
|
||||
|
||||
9. `WINEDLLOVERRIDES="usp10=n" wine winbuild/util/hb-shape.exe fontname.ttf -u 0061,0062,0063 --shaper=uniscribe`
|
||||
|
||||
(`0061,0062,0063` means `abc`, use test/shaping/hb-unicode-decode to generate ones you need)
|
63
RELEASING.md
63
RELEASING.md
|
@ -33,39 +33,34 @@ HarfBuzz release walk-through checklist:
|
|||
That's what happened to 2.0.0 going out with 1.8.0 hb-version.h... So, that's
|
||||
a clue.
|
||||
|
||||
7. "make release-files". Enter your GPG password. This creates a sha256 hash
|
||||
and signs it.
|
||||
|
||||
8. Now that you have release files, commit NEWS, configure.ac, and src/hb-version.h,
|
||||
7. Now that you have release files, commit NEWS, configure.ac, and src/hb-version.h,
|
||||
as well as any REPLACEME changes you made. The commit message is simply the
|
||||
release number. Eg. "1.4.7"
|
||||
|
||||
8. "make dist" again to get a tarball with your new commit in the ChangeLog. Then
|
||||
"make release-files". Enter your GPG password. This creates a sha256 hash
|
||||
and signs it. Check the size of the three resulting files.
|
||||
|
||||
9. Tag the release and sign it: Eg. "git tag -s 1.4.7 -m 1.4.7". Enter your
|
||||
GPG password again.
|
||||
|
||||
10. Build win32 bundle.
|
||||
|
||||
a. Put contents of [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ) on your `~/.local/i686-w64-mingw32`,
|
||||
a. Build Win32 binaries. See [README.mingw.md](README.mingw.md).
|
||||
|
||||
b. Run `../mingw32.sh --with-uniscribe` script 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.
|
||||
b. Run "make dist-win" to build Win32 bundle.
|
||||
|
||||
11. 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 1592693 Jul 18 11:25 harfbuzz-1.4.7.tar.xz
|
||||
-rw-r--r-- 1 behdad eng 89 Jul 18 11:34 harfbuzz-1.4.7.tar.xz.sha256
|
||||
-rw-r--r-- 1 behdad eng 339 Jul 18 11:34 harfbuzz-1.4.7.tar.xz.sha256.asc
|
||||
-rw-r--r-- 1 behdad eng 2895619 Jul 18 11:34 harfbuzz-1.4.7-win32.zip
|
||||
```
|
||||
|
||||
12. While doing that, quickly double-check the size of the .tar.bz2 and .zip
|
||||
12. While doing that, quickly double-check the size of the .tar.xz 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.
|
||||
|
@ -75,39 +70,3 @@ HarfBuzz release walk-through checklist:
|
|||
|
||||
14. 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
|
||||
```
|
||||
|
|
75
TESTING.md
Normal file
75
TESTING.md
Normal file
|
@ -0,0 +1,75 @@
|
|||
## Build & Run
|
||||
|
||||
Depending on what area you are working in change or add `HB_DEBUG_<whatever>`.
|
||||
Values defined in `hb-debug.hh`.
|
||||
|
||||
```shell
|
||||
# quick sanity check
|
||||
time (make -j4 CPPFLAGS='-DHB_DEBUG_SUBSET=100' \
|
||||
&& (make -j4 -C test/api check || cat test/api/test-suite.log))
|
||||
|
||||
# slower sanity check
|
||||
time (make -j4 CPPFLAGS='-DHB_DEBUG_SUBSET=100' \
|
||||
&& make -j4 -C src check \
|
||||
&& make -j4 -C test/api check \
|
||||
&& make -j4 -C test/subset check)
|
||||
|
||||
# confirm you didn't break anything else
|
||||
time (make -j4 CPPFLAGS='-DHB_DEBUG_SUBSET=100' \
|
||||
&& make -j4 check)
|
||||
|
||||
# often catches files you didn't add, e.g. test fonts to EXTRA_DIST
|
||||
make distcheck
|
||||
```
|
||||
|
||||
### Run tests with asan
|
||||
|
||||
**NOTE**: this sometimes yields harder to read results than the full fuzzer
|
||||
|
||||
```shell
|
||||
# For nice symbols tell asan how to symoblize. Note that it doesn't like versioned copies like llvm-symbolizer-3.8
|
||||
# export ASAN_SYMBOLIZER_PATH=path to version-less llvm-symbolizer
|
||||
# ex
|
||||
export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-3.8/bin/llvm-symbolizer
|
||||
|
||||
./configure CC=clang CXX=clang++ CPPFLAGS=-fsanitize=address LDFLAGS=-fsanitize=address
|
||||
# make/run tests as usual
|
||||
```
|
||||
|
||||
### Debug with GDB
|
||||
|
||||
```
|
||||
cd ./util
|
||||
../libtool --mode=execute gdb --args ./hb-subset ...
|
||||
```
|
||||
|
||||
### Enable Debug Logging
|
||||
|
||||
```shell
|
||||
# make clean if you previously build w/o debug logging
|
||||
make CPPFLAGS=-DHB_DEBUG_SUBSET=100
|
||||
```
|
||||
|
||||
## Build and Test via CMake
|
||||
|
||||
Note: You'll need to first install ninja-build via apt-get.
|
||||
|
||||
```shell
|
||||
cd harfbuzz
|
||||
mkdir buid
|
||||
cmake -DHB_CHECK=ON -Bbuild -H. -GNinja && ninja -Cbuild && CTEST_OUTPUT_ON_FAILURE=1 ninja -Cbuild test
|
||||
```
|
||||
## Test with the Fuzzer
|
||||
|
||||
```shell
|
||||
# push your changs to a branch on googlefonts/harfbuzz
|
||||
# In a local copy of oss-fuzz, edit projects/harfbuzz/Dockerfile
|
||||
# Change the git clone to pull your branch
|
||||
|
||||
# Do this periodically
|
||||
sudo python infra/helper.py build_image harfbuzz
|
||||
|
||||
# Do these to update/run
|
||||
sudo python infra/helper.py build_fuzzers --sanitizer address harfbuzz
|
||||
sudo python infra/helper.py run_fuzzer harfbuzz hb-subset-fuzzer
|
||||
```
|
2
THANKS
2
THANKS
|
@ -1,6 +1,6 @@
|
|||
Bradley Grainger
|
||||
Khaled Hosny
|
||||
Kenichi Ishibashi
|
||||
Ivan Kuckir <https://photopea.com/>
|
||||
Ryan Lortie
|
||||
Jeff Muizelaar
|
||||
suzuki toshiya
|
||||
|
|
69
appveyor.yml
69
appveyor.yml
|
@ -2,16 +2,18 @@ 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
|
||||
# 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
|
||||
|
@ -19,10 +21,35 @@ environment:
|
|||
configuration: Debug
|
||||
|
||||
|
||||
# Build only
|
||||
|
||||
#- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
# compiler: msvc2
|
||||
# generator: Visual Studio 12
|
||||
# platform: Win32
|
||||
# configuration: Release
|
||||
# triplet: x86-windows
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
compiler: msvc2
|
||||
generator: Visual Studio 15
|
||||
platform: Win32
|
||||
configuration: Release
|
||||
triplet: x86-windows
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
compiler: msvc2
|
||||
generator: Visual Studio 16
|
||||
platform: Win32
|
||||
configuration: Release
|
||||
triplet: x86-windows
|
||||
|
||||
|
||||
- compiler: msys2
|
||||
MINGW_PREFIX: /mingw64
|
||||
MINGW_CHOST: x86_64-w64-mingw32
|
||||
MSYS2_ARCH: x86_64
|
||||
|
||||
- compiler: msys2
|
||||
MINGW_PREFIX: /mingw32
|
||||
MINGW_CHOST: i686-w64-mingw32
|
||||
|
@ -30,30 +57,26 @@ environment:
|
|||
|
||||
|
||||
install:
|
||||
# - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -Sy && pacman --noconfirm --force -S pacman-mirrors && pacman --force -Syu --noconfirm"'
|
||||
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -S --needed mingw-w64-$MSYS2_ARCH-{gcc,freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2}"'
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel"
|
||||
- set PATH=%PATH%;C:\msys64\mingw64\bin # msys2 is added just for having "ragel" on PATH
|
||||
- 'if "%compiler%"=="cygwin" %CYGWIN_PREFIX%\setup-%CYGWIN_ARCH%.exe -g -q -P cygwin-devel,libfreetype-devel,libcairo-devel,libicu-devel,gcc,gcc-g++,gobject-introspection,libglib2.0-devel,libgraphite2-devel,pkg-config,python2'
|
||||
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -S --needed mingw-w64-$MSYS2_ARCH-{gcc,freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2,ragel}"'
|
||||
- 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" vcpkg install glib:%triplet% freetype:%triplet% cairo:%triplet%'
|
||||
|
||||
build_script:
|
||||
- 'if "%compiler%"=="msvc" md build'
|
||||
- 'if "%compiler%"=="msvc" cd build'
|
||||
- 'if "%compiler%"=="msvc" if "%platform%"=="ARM" cmake -Bbuild -H. -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -G "%generator%"'
|
||||
- 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" cmake -Bbuild -H. -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -DHB_BUILD_UTILS=ON -G "%generator%" -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake'
|
||||
|
||||
- 'if "%compiler%"=="msvc" set PATH=%PATH%;C:\Program Files (x86)\MSBuild\14.0\Bin'
|
||||
|
||||
- 'if "%compiler%"=="msvc" if "%platform%"=="ARM" cmake -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -G "%generator%" ../'
|
||||
- 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" cmake -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -DHB_BUILD_UTILS=ON -G "%generator%" -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake ../'
|
||||
|
||||
- 'if "%compiler%"=="msvc" cd build'
|
||||
- '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%"=="msvc2" cmake -G "%generator%" -Bbuild -H.'
|
||||
- 'if "%compiler%"=="msvc2" cmake --build build --config %configuration%'
|
||||
|
||||
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "curl https://raw.githubusercontent.com/mirror/mingw-w64/023eb04c396d4e8d8fcf604cfababc53dae13398/mingw-w64-headers/include/dwrite_1.h > %MINGW_PREFIX%/%MINGW_CHOST%/include/dwrite_1.h"'
|
||||
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make -j3 check || .ci/fail.sh"'
|
||||
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --with-gdi --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make -j3 check || .ci/fail.sh"'
|
||||
|
||||
cache:
|
||||
- c:\tools\vcpkg\installed\
|
||||
- '%CYGWIN_PREFIX%\var\cache\setup'
|
||||
|
||||
notifications:
|
||||
- provider: Email
|
||||
|
|
77
configure.ac
77
configure.ac
|
@ -1,6 +1,6 @@
|
|||
AC_PREREQ([2.64])
|
||||
AC_INIT([HarfBuzz],
|
||||
[2.3.0],
|
||||
[2.6.0],
|
||||
[https://github.com/harfbuzz/harfbuzz/issues/new],
|
||||
[harfbuzz],
|
||||
[http://harfbuzz.org/])
|
||||
|
@ -9,7 +9,7 @@ AC_CONFIG_MACRO_DIR([m4])
|
|||
AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.13.0 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
|
||||
AM_INIT_AUTOMAKE([1.13.0 gnits tar-ustar dist-xz no-dist-gzip -Wall no-define color-tests -Wno-portability])
|
||||
AM_SILENT_RULES([yes])
|
||||
AX_CODE_COVERAGE
|
||||
|
||||
|
@ -23,7 +23,7 @@ AC_PROG_CC
|
|||
AC_PROG_CC_C99
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_CXX
|
||||
dnl AX_CXX_COMPILE_STDCXX(11, noext, optional)
|
||||
AX_CXX_COMPILE_STDCXX(11,, optional)
|
||||
AC_SYS_LARGEFILE
|
||||
PKG_PROG_PKG_CONFIG([0.20])
|
||||
AM_MISSING_PROG([RAGEL], [ragel])
|
||||
|
@ -77,13 +77,7 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
|
|||
])
|
||||
|
||||
# Functions and headers
|
||||
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l posix_memalign)
|
||||
|
||||
save_libs="$LIBS"
|
||||
LIBS="$LIBS -lm"
|
||||
AC_CHECK_FUNCS([round], ,[AC_CHECK_DECLS([round], , ,[#include <math.h>])])
|
||||
LIBS="$save_libs"
|
||||
|
||||
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l)
|
||||
AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h stdbool.h)
|
||||
|
||||
# Compiler flags
|
||||
|
@ -102,9 +96,6 @@ if test "x$GCC" = "xyes"; then
|
|||
# by overriding CXXFLAGS.
|
||||
CXXFLAGS="-fno-rtti $CXXFLAGS -fno-exceptions -fno-threadsafe-statics"
|
||||
|
||||
# Assorted warnings
|
||||
CXXFLAGS="$CXXFLAGS -Wcast-align"
|
||||
|
||||
case "$host" in
|
||||
*-*-mingw*)
|
||||
;;
|
||||
|
@ -137,9 +128,7 @@ AC_MSG_RESULT([$hb_os_win32])
|
|||
AM_CONDITIONAL(OS_WIN32, test "$hb_os_win32" = "yes")
|
||||
|
||||
have_pthread=false
|
||||
if test "$hb_os_win32" = no; then
|
||||
AX_PTHREAD([have_pthread=true])
|
||||
fi
|
||||
AX_PTHREAD([have_pthread=true])
|
||||
if $have_pthread; then
|
||||
AC_DEFINE(HAVE_PTHREAD, 1, [Have POSIX threads])
|
||||
fi
|
||||
|
@ -147,14 +136,6 @@ AM_CONDITIONAL(HAVE_PTHREAD, $have_pthread)
|
|||
|
||||
dnl ==========================================================================
|
||||
|
||||
have_fallback=true
|
||||
if $have_fallback; then
|
||||
AC_DEFINE(HAVE_FALLBACK, 1, [Have simple TrueType Layout backend])
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_FALLBACK, $have_fallback)
|
||||
|
||||
dnl ===========================================================================
|
||||
|
||||
AC_ARG_WITH(glib,
|
||||
[AS_HELP_STRING([--with-glib=@<:@yes/no/auto@:>@],
|
||||
[Use glib @<:@default=auto@:>@])],,
|
||||
|
@ -303,21 +284,6 @@ AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin")
|
|||
|
||||
dnl ===========================================================================
|
||||
|
||||
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])
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_UCDN, $have_ucdn)
|
||||
|
||||
dnl ==========================================================================
|
||||
|
||||
AC_ARG_WITH(graphite2,
|
||||
[AS_HELP_STRING([--with-graphite2=@<:@yes/no/auto@:>@],
|
||||
[Use the graphite2 library @<:@default=no@:>@])],,
|
||||
|
@ -395,6 +361,28 @@ AM_CONDITIONAL(HAVE_UNISCRIBE, $have_uniscribe)
|
|||
|
||||
dnl ===========================================================================
|
||||
|
||||
AC_ARG_WITH(gdi,
|
||||
[AS_HELP_STRING([--with-gdi=@<:@yes/no/auto@:>@],
|
||||
[Provide GDI integration helpers @<:@default=no@:>@])],,
|
||||
[with_gdi=no])
|
||||
have_gdi=false
|
||||
if test "x$with_gdi" = "xyes" -o "x$with_gdi" = "xauto"; then
|
||||
AC_CHECK_HEADERS(windows.h, have_gdi=true)
|
||||
fi
|
||||
if test "x$with_gdi" = "xyes" -a "x$have_gdi" != "xtrue"; then
|
||||
AC_MSG_ERROR([gdi support requested but not found])
|
||||
fi
|
||||
if $have_gdi; then
|
||||
GDI_CFLAGS=
|
||||
GDI_LIBS="-lgdi32"
|
||||
AC_SUBST(GDI_CFLAGS)
|
||||
AC_SUBST(GDI_LIBS)
|
||||
AC_DEFINE(HAVE_GDI, 1, [Have GDI library])
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_GDI, $have_gdi)
|
||||
|
||||
dnl ===========================================================================
|
||||
|
||||
AC_ARG_WITH(directwrite,
|
||||
[AS_HELP_STRING([--with-directwrite=@<:@yes/no/auto@:>@],
|
||||
[Use the DirectWrite library (experimental) @<:@default=no@:>@])],,
|
||||
|
@ -410,7 +398,7 @@ if test "x$with_directwrite" = "xyes" -a "x$have_directwrite" != "xtrue"; then
|
|||
fi
|
||||
if $have_directwrite; then
|
||||
DIRECTWRITE_CXXFLAGS=
|
||||
DIRECTWRITE_LIBS="-ldwrite"
|
||||
DIRECTWRITE_LIBS=
|
||||
AC_SUBST(DIRECTWRITE_CXXFLAGS)
|
||||
AC_SUBST(DIRECTWRITE_LIBS)
|
||||
AC_DEFINE(HAVE_DIRECTWRITE, 1, [Have DirectWrite library])
|
||||
|
@ -500,7 +488,6 @@ AC_CONFIG_FILES([
|
|||
Makefile
|
||||
src/Makefile
|
||||
src/harfbuzz-config.cmake
|
||||
src/hb-ucdn/Makefile
|
||||
util/Makefile
|
||||
test/Makefile
|
||||
test/api/Makefile
|
||||
|
@ -518,12 +505,17 @@ docs/version.xml
|
|||
|
||||
AC_OUTPUT
|
||||
|
||||
echo
|
||||
echo "C++ compiler version:"
|
||||
$CXX --version
|
||||
echo
|
||||
|
||||
AC_MSG_NOTICE([
|
||||
|
||||
Build configuration:
|
||||
|
||||
Unicode callbacks (you want at least one):
|
||||
Builtin (UCDN): ${have_ucdn}
|
||||
Builtin true
|
||||
Glib: ${have_glib}
|
||||
ICU: ${have_icu}
|
||||
|
||||
|
@ -540,6 +532,7 @@ Additional shapers (the more the merrier):
|
|||
Platform shapers (not normally needed):
|
||||
CoreText: ${have_coretext}
|
||||
DirectWrite: ${have_directwrite}
|
||||
GDI: ${have_gdi}
|
||||
Uniscribe: ${have_uniscribe}
|
||||
|
||||
Other features:
|
||||
|
|
|
@ -33,7 +33,7 @@ SCAN_OPTIONS=--rebuild-types --deprecated-guards="HB_DISABLE_DEPRECATED" \
|
|||
|
||||
# Header files or dirs to ignore when scanning. Use base file/dir names
|
||||
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
|
||||
IGNORE_HFILES=`cd $(top_srcdir)/src; find . -path './hb-*/*.h' | sed 's@^.*/@@'`
|
||||
IGNORE_HFILES=`cd $(top_srcdir)/src; find . -path './*/*.h' | sed 's@^.*/@@'`
|
||||
if HAVE_GOBJECT
|
||||
else
|
||||
IGNORE_HFILES+=hb-gobject.h hb-gobject-enums.h hb-gobject-structs.h
|
||||
|
@ -75,12 +75,14 @@ content_files= \
|
|||
usermanual-what-is-harfbuzz.xml \
|
||||
usermanual-install-harfbuzz.xml \
|
||||
usermanual-getting-started.xml \
|
||||
usermanual-glyph-information.xml \
|
||||
usermanual-shaping-concepts.xml \
|
||||
usermanual-object-model.xml \
|
||||
usermanual-buffers-language-script-and-direction.xml \
|
||||
usermanual-fonts-and-faces.xml \
|
||||
usermanual-clusters.xml \
|
||||
usermanual-opentype-features.xml \
|
||||
usermanual-glyph-information.xml \
|
||||
usermanual-clusters.xml \
|
||||
usermanual-utilities.xml \
|
||||
version.xml
|
||||
|
||||
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
|
||||
|
|
|
@ -20,11 +20,7 @@
|
|||
|
||||
<para>
|
||||
The canonical source-code tree is available at
|
||||
<ulink
|
||||
url="https://github.com/harfbuzz/harfbuzz">github.com/harfbuzz/harfbuzz</ulink>
|
||||
and is also available at
|
||||
<ulink
|
||||
url="http://cgit.freedesktop.org/harfbuzz/">cgit.freedesktop.org/harfbuzz</ulink>.
|
||||
<ulink url="https://github.com/harfbuzz/harfbuzz">github.com/harfbuzz/harfbuzz</ulink>.
|
||||
See <xref linkend="download" endterm="download.title"/> for
|
||||
release tarballs.
|
||||
</para>
|
||||
|
@ -37,11 +33,12 @@
|
|||
<xi:include href="usermanual-install-harfbuzz.xml"/>
|
||||
<xi:include href="usermanual-getting-started.xml"/>
|
||||
<xi:include href="usermanual-shaping-concepts.xml"/>
|
||||
<xi:include href="usermanual-object-model.xml"/>
|
||||
<xi:include href="usermanual-buffers-language-script-and-direction.xml"/>
|
||||
<xi:include href="usermanual-fonts-and-faces.xml"/>
|
||||
<xi:include href="usermanual-clusters.xml"/>
|
||||
<xi:include href="usermanual-opentype-features.xml"/>
|
||||
<xi:include href="usermanual-glyph-information.xml"/>
|
||||
<xi:include href="usermanual-clusters.xml"/>
|
||||
<xi:include href="usermanual-utilities.xml"/>
|
||||
</part>
|
||||
|
||||
<part>
|
||||
|
@ -136,6 +133,11 @@
|
|||
<index id="api-index-full"><title>API Index</title><xi:include href="xml/api-index-full.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></index>
|
||||
|
||||
<index id="api-index-2-6-0" role="2.6.0"><title>Index of new symbols in 2.6.0</title><xi:include href="xml/api-index-2.6.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-5-0" role="2.5.0"><title>Index of new symbols in 2.5.0</title><xi:include href="xml/api-index-2.5.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-4-0" role="2.4.0"><title>Index of new symbols in 2.4.0</title><xi:include href="xml/api-index-2.4.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-3-0" role="2.3.0"><title>Index of new symbols in 2.3.0</title><xi:include href="xml/api-index-2.3.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-2-0" role="2.2.0"><title>Index of new symbols in 2.2.0</title><xi:include href="xml/api-index-2.2.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-1-0" role="2.1.0"><title>Index of new symbols in 2.1.0</title><xi:include href="xml/api-index-2.1.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-0-0" role="2.0.0"><title>Index of new symbols in 2.0.0</title><xi:include href="xml/api-index-2.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-9-0" role="1.9.0"><title>Index of new symbols in 1.9.0</title><xi:include href="xml/api-index-1.9.0.xml"><xi:fallback /></xi:include></index>
|
||||
|
@ -149,7 +151,6 @@
|
|||
<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-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-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-0" role="1.4.0"><title>Index of new symbols in 1.4.0</title><xi:include href="xml/api-index-1.4.0.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-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-1-3" role="1.1.3"><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>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<SUBSECTION Private>
|
||||
HB_H_IN
|
||||
HB_OT_H_IN
|
||||
HB_AAT_H_IN
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -124,11 +125,17 @@ hb_script_get_horizontal_direction
|
|||
hb_language_from_string
|
||||
hb_language_to_string
|
||||
hb_language_get_default
|
||||
hb_feature_from_string
|
||||
hb_feature_to_string
|
||||
hb_variation_from_string
|
||||
hb_variation_to_string
|
||||
hb_bool_t
|
||||
hb_codepoint_t
|
||||
hb_destroy_func_t
|
||||
hb_direction_t
|
||||
hb_language_t
|
||||
hb_feature_t
|
||||
hb_variation_t
|
||||
hb_mask_t
|
||||
hb_position_t
|
||||
hb_tag_t
|
||||
|
@ -147,6 +154,8 @@ HB_DIRECTION_IS_HORIZONTAL
|
|||
HB_DIRECTION_IS_VALID
|
||||
HB_DIRECTION_IS_VERTICAL
|
||||
HB_LANGUAGE_INVALID
|
||||
HB_FEATURE_GLOBAL_END
|
||||
HB_FEATURE_GLOBAL_START
|
||||
<SUBSECTION Private>
|
||||
HB_BEGIN_DECLS
|
||||
HB_END_DECLS
|
||||
|
@ -171,6 +180,7 @@ HB_BUFFER_SERIALIZE_FLAGS_DEFAULT
|
|||
HB_SCRIPT_CANADIAN_ABORIGINAL
|
||||
hb_font_funcs_set_glyph_func
|
||||
hb_font_get_glyph_func_t
|
||||
HB_MATH_GLYPH_PART_FLAG_EXTENDER
|
||||
hb_ot_layout_table_choose_script
|
||||
hb_ot_layout_table_find_script
|
||||
hb_ot_tag_from_language
|
||||
|
@ -187,12 +197,7 @@ HB_UNICODE_MAX_DECOMPOSITION_LEN
|
|||
hb_unicode_decompose_compatibility_func_t
|
||||
hb_unicode_decompose_compatibility
|
||||
hb_unicode_funcs_set_decompose_compatibility_func
|
||||
hb_font_funcs_set_glyph_h_kerning_func
|
||||
hb_font_funcs_set_glyph_v_kerning_func
|
||||
hb_font_get_glyph_h_kerning
|
||||
hb_font_get_glyph_h_kerning_func_t
|
||||
hb_font_get_glyph_kerning_for_direction
|
||||
hb_font_get_glyph_kerning_func_t
|
||||
hb_font_get_glyph_v_kerning
|
||||
hb_font_get_glyph_v_kerning_func_t
|
||||
</SECTION>
|
||||
|
@ -208,6 +213,14 @@ hb_coretext_face_get_cg_font
|
|||
hb_coretext_font_get_ct_font
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-directwrite</FILE>
|
||||
hb_directwrite_face_create
|
||||
hb_directwrite_face_get_font_face
|
||||
<SUBSECTION Private>
|
||||
hb_directwrite_shape_experimental_width
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-face</FILE>
|
||||
hb_face_count
|
||||
|
@ -255,6 +268,7 @@ hb_font_funcs_set_glyph_extents_func
|
|||
hb_font_funcs_set_glyph_from_name_func
|
||||
hb_font_funcs_set_glyph_h_advance_func
|
||||
hb_font_funcs_set_glyph_h_advances_func
|
||||
hb_font_funcs_set_glyph_h_kerning_func
|
||||
hb_font_funcs_set_glyph_h_origin_func
|
||||
hb_font_funcs_set_glyph_name_func
|
||||
hb_font_funcs_set_glyph_v_advance_func
|
||||
|
@ -284,8 +298,12 @@ hb_font_get_glyph_h_advance
|
|||
hb_font_get_glyph_h_advance_func_t
|
||||
hb_font_get_glyph_h_advances
|
||||
hb_font_get_glyph_h_advances_func_t
|
||||
hb_font_get_glyph_h_kerning
|
||||
hb_font_get_glyph_h_kerning_func_t
|
||||
hb_font_get_glyph_h_origin
|
||||
hb_font_get_glyph_h_origin_func_t
|
||||
hb_font_get_glyph_kerning_for_direction
|
||||
hb_font_get_glyph_kerning_func_t
|
||||
hb_font_get_glyph_name
|
||||
hb_font_get_glyph_name_func_t
|
||||
hb_font_get_glyph_origin_for_direction
|
||||
|
@ -321,12 +339,10 @@ 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_set_var_named_instance
|
||||
hb_font_subtract_glyph_origin_for_direction
|
||||
hb_font_t
|
||||
hb_reference_table_func_t
|
||||
|
@ -354,6 +370,11 @@ hb_ft_font_get_load_flags
|
|||
hb_ft_font_set_funcs
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-gdi</FILE>
|
||||
hb_gdi_face_create
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-glib</FILE>
|
||||
hb_glib_get_unicode_funcs
|
||||
|
@ -527,6 +548,7 @@ HB_OT_TAG_GDEF
|
|||
HB_OT_TAG_GPOS
|
||||
HB_OT_TAG_GSUB
|
||||
HB_OT_TAG_JSTF
|
||||
hb_ot_layout_baseline_tag_t
|
||||
hb_ot_layout_collect_lookups
|
||||
hb_ot_layout_collect_features
|
||||
hb_ot_layout_feature_get_characters
|
||||
|
@ -534,6 +556,7 @@ hb_ot_layout_feature_get_lookups
|
|||
hb_ot_layout_feature_get_name_ids
|
||||
hb_ot_layout_feature_with_variations_get_lookups
|
||||
hb_ot_layout_get_attach_points
|
||||
hb_ot_layout_get_baseline
|
||||
hb_ot_layout_get_glyph_class
|
||||
hb_ot_layout_get_glyphs_in_class
|
||||
hb_ot_layout_get_ligature_carets
|
||||
|
@ -587,6 +610,22 @@ hb_ot_math_get_min_connector_overlap
|
|||
hb_ot_math_get_glyph_assembly
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-ot-meta</FILE>
|
||||
hb_ot_meta_t
|
||||
hb_ot_meta_get_entry_tags
|
||||
hb_ot_meta_reference_entry
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-ot-metrics</FILE>
|
||||
hb_ot_metrics_t
|
||||
hb_ot_metrics_get_position
|
||||
hb_ot_metrics_get_variation
|
||||
hb_ot_metrics_get_x_variation
|
||||
hb_ot_metrics_get_y_variation
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-ot-shape</FILE>
|
||||
hb_ot_shape_glyphs_closure
|
||||
|
@ -649,11 +688,6 @@ hb_set_union
|
|||
|
||||
<SECTION>
|
||||
<FILE>hb-shape</FILE>
|
||||
HB_FEATURE_GLOBAL_END
|
||||
HB_FEATURE_GLOBAL_START
|
||||
hb_feature_t
|
||||
hb_feature_from_string
|
||||
hb_feature_to_string
|
||||
hb_shape
|
||||
hb_shape_full
|
||||
hb_shape_list_shapers
|
||||
|
@ -715,8 +749,6 @@ 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>
|
||||
|
|
|
@ -7,30 +7,38 @@
|
|||
<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 the HarfBuzz shaper 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.
|
||||
the text that we want and how to customize the properties of the
|
||||
buffer. We'll also look at a piece of lower-level machinery that
|
||||
you will need to understand before proceeding: the functions that
|
||||
HarfBuzz uses to retrieve Unicode information.
|
||||
</para>
|
||||
<para>
|
||||
After shaping is complete, HarfBuzz puts its output back
|
||||
into the buffer. But getting that output requires setting up a
|
||||
face and a font first, so we will look at that in the next chapter
|
||||
instead of here.
|
||||
</para>
|
||||
<section id="creating-and-destroying-buffers">
|
||||
<title>Creating and destroying buffers</title>
|
||||
<para>
|
||||
As we saw in our <emphasis>Getting Started</emphasis> example, a
|
||||
buffer is created and
|
||||
initialized with <literal>hb_buffer_create()</literal>. This
|
||||
initialized with <function>hb_buffer_create()</function>. This
|
||||
produces a new, empty buffer object, instantiated with some
|
||||
default values and ready to accept your Unicode strings.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz manages the memory of objects (such as buffers) that it
|
||||
creates, so you don't have to. When you have finished working on
|
||||
a buffer, you can call <literal>hb_buffer_destroy()</literal>:
|
||||
a buffer, you can call <function>hb_buffer_destroy()</function>:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_buffer_t *buffer = hb_buffer_create();
|
||||
...
|
||||
hb_buffer_destroy(buffer);
|
||||
</programlisting>
|
||||
hb_buffer_t *buf = hb_buffer_create();
|
||||
...
|
||||
hb_buffer_destroy(buf);
|
||||
</programlisting>
|
||||
<para>
|
||||
This will destroy the object and free its associated memory -
|
||||
unless some other part of the program holds a reference to this
|
||||
|
@ -39,46 +47,364 @@
|
|||
else destroying it, you should increase its reference count:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
void somefunc(hb_buffer_t *buffer) {
|
||||
buffer = hb_buffer_reference(buffer);
|
||||
...
|
||||
</programlisting>
|
||||
void somefunc(hb_buffer_t *buf) {
|
||||
buf = hb_buffer_reference(buf);
|
||||
...
|
||||
</programlisting>
|
||||
<para>
|
||||
And then decrease it once you're done with it:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_buffer_destroy(buffer);
|
||||
}
|
||||
</programlisting>
|
||||
hb_buffer_destroy(buf);
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
While we are on the subject of reference-counting buffers, it is
|
||||
worth noting that an individual buffer can only meaningfully be
|
||||
used by one thread at a time.
|
||||
</para>
|
||||
<para>
|
||||
To throw away all the data in your buffer and start from scratch,
|
||||
call <literal>hb_buffer_reset(buffer)</literal>. If you want to
|
||||
call <function>hb_buffer_reset(buf)</function>. If you want to
|
||||
throw away the string in the buffer but keep the options, you can
|
||||
instead call <literal>hb_buffer_clear_contents(buffer)</literal>.
|
||||
instead call <function>hb_buffer_clear_contents(buf)</function>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<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
|
||||
of Unicode codepoints, but your input string is probably in one of
|
||||
the standard Unicode character encodings (UTF-8, UTF-16, UTF-32)
|
||||
of Unicode code points, but your input string is probably in one of
|
||||
the standard Unicode character encodings (UTF-8, UTF-16, or
|
||||
UTF-32). HarfBuzz provides convenience functions that accept
|
||||
each of these encodings:
|
||||
<function>hb_buffer_add_utf8()</function>,
|
||||
<function>hb_buffer_add_utf16()</function>, and
|
||||
<function>hb_buffer_add_utf32()</function>. Other than the
|
||||
character encoding they accept, they function identically.
|
||||
</para>
|
||||
<para>
|
||||
You can add UTF-8 text to a buffer by passing in the text array,
|
||||
the array's length, an offset into the array for the first
|
||||
character to add, and the length of the segment to add:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_buffer_add_utf8 (hb_buffer_t *buf,
|
||||
const char *text,
|
||||
int text_length,
|
||||
unsigned int item_offset,
|
||||
int item_length)
|
||||
</programlisting>
|
||||
<para>
|
||||
So, in practice, you can say:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text));
|
||||
</programlisting>
|
||||
<para>
|
||||
This will append your new characters to
|
||||
<parameter>buf</parameter>, not replace its existing
|
||||
contents. Also, note that you can use <literal>-1</literal> in
|
||||
place of the first instance of <function>strlen(text)</function>
|
||||
if your text array is NULL-terminated. Similarly, you can also use
|
||||
<literal>-1</literal> as the final argument want to add its full
|
||||
contents.
|
||||
</para>
|
||||
<para>
|
||||
Whatever start <parameter>item_offset</parameter> and
|
||||
<parameter>item_length</parameter> you provide, HarfBuzz will also
|
||||
attempt to grab the five characters <emphasis>before</emphasis>
|
||||
the offset point and the five characters
|
||||
<emphasis>after</emphasis> the designated end. These are the
|
||||
before and after "context" segments, which are used internally
|
||||
for HarfBuzz to make shaping decisions. They will not be part of
|
||||
the final output, but they ensure that HarfBuzz's
|
||||
script-specific shaping operations are correct. If there are
|
||||
fewer than five characters available for the before or after
|
||||
contexts, HarfBuzz will just grab what is there.
|
||||
</para>
|
||||
<para>
|
||||
For longer text runs, such as full paragraphs, it might be
|
||||
tempting to only add smaller sub-segments to a buffer and
|
||||
shape them in piecemeal fashion. Generally, this is not a good
|
||||
idea, however, because a lot of shaping decisions are
|
||||
dependent on this context information. For example, in Arabic
|
||||
and other connected scripts, HarfBuzz needs to know the code
|
||||
points before and after each character in order to correctly
|
||||
determine which glyph to return.
|
||||
</para>
|
||||
<para>
|
||||
The safest approach is to add all of the text available, then
|
||||
use <parameter>item_offset</parameter> and
|
||||
<parameter>item_length</parameter> to indicate which characters you
|
||||
want shaped, so that HarfBuzz has access to any context.
|
||||
</para>
|
||||
<para>
|
||||
You can also add Unicode code points directly with
|
||||
<function>hb_buffer_add_codepoints()</function>. The arguments
|
||||
to this function are the same as those for the UTF
|
||||
encodings. But it is particularly important to note that
|
||||
HarfBuzz does not do validity checking on the text that is added
|
||||
to a buffer. Invalid code points will be replaced, but it is up
|
||||
to you to do any deep-sanity checking necessary.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="setting-buffer-properties">
|
||||
<title>Setting buffer properties</title>
|
||||
<para>
|
||||
Buffers containing input characters still need several
|
||||
properties set before HarfBuzz can shape their text correctly.
|
||||
</para>
|
||||
</section>
|
||||
<section id="what-about-the-other-scripts">
|
||||
<title>What about the other scripts?</title>
|
||||
<para>
|
||||
Initially, all buffers are set to the
|
||||
<literal>HB_BUFFER_CONTENT_TYPE_INVALID</literal> content
|
||||
type. After adding text, the buffer should be set to
|
||||
<literal>HB_BUFFER_CONTENT_TYPE_UNICODE</literal> instead, which
|
||||
indicates that it contains un-shaped input
|
||||
characters. After shaping, the buffer will have the
|
||||
<literal>HB_BUFFER_CONTENT_TYPE_GLYPHS</literal> content type.
|
||||
</para>
|
||||
<para>
|
||||
<function>hb_buffer_add_utf8()</function> and the
|
||||
other UTF functions set the content type of their buffer
|
||||
automatically. But if you are reusing a buffer you may want to
|
||||
check its state with
|
||||
<function>hb_buffer_get_content_type(buffer)</function>. If
|
||||
necessary you can set the content type with
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_buffer_set_content_type(buf, HB_BUFFER_CONTENT_TYPE_UNICODE);
|
||||
</programlisting>
|
||||
<para>
|
||||
to prepare for shaping.
|
||||
</para>
|
||||
<para>
|
||||
Buffers also need to carry information about the script,
|
||||
language, and text direction of their contents. You can set
|
||||
these properties individually:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_buffer_set_direction(buf, HB_DIRECTION_LTR);
|
||||
hb_buffer_set_script(buf, HB_SCRIPT_LATIN);
|
||||
hb_buffer_set_language(buf, hb_language_from_string("en", -1));
|
||||
</programlisting>
|
||||
<para>
|
||||
However, since these properties are often the repeated for
|
||||
multiple text runs, you can also save them in a
|
||||
<literal>hb_segment_properties_t</literal> for reuse:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_segment_properties_t *savedprops;
|
||||
hb_buffer_get_segment_properties (buf, savedprops);
|
||||
...
|
||||
hb_buffer_set_segment_properties (buf2, savedprops);
|
||||
</programlisting>
|
||||
<para>
|
||||
HarfBuzz also provides getter functions to retrieve a buffer's
|
||||
direction, script, and language properties individually.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz recognizes four text directions in
|
||||
<type>hb_direction_t</type>: left-to-right
|
||||
(<literal>HB_DIRECTION_LTR</literal>), right-to-left (<literal>HB_DIRECTION_RTL</literal>),
|
||||
top-to-bottom (<literal>HB_DIRECTION_TTB</literal>), and
|
||||
bottom-to-top (<literal>HB_DIRECTION_BTT</literal>). For the
|
||||
script property, HarfBuzz uses identifiers based on the
|
||||
<ulink
|
||||
url="https://unicode.org/iso15924/">ISO 15924
|
||||
standard</ulink>. For languages, HarfBuzz uses tags based on the
|
||||
<ulink url="https://tools.ietf.org/html/bcp47">IETF BCP 47</ulink> standard.
|
||||
</para>
|
||||
<para>
|
||||
Helper functions are provided to convert character strings into
|
||||
the necessary script and language tag types.
|
||||
</para>
|
||||
<para>
|
||||
Two additional buffer properties to be aware of are the
|
||||
"invisible glyph" and the replacement code point. The
|
||||
replacement code point is inserted into buffer output in place of
|
||||
any invalid code points encountered in the input. By default, it
|
||||
is the Unicode <literal>REPLACEMENT CHARACTER</literal> code
|
||||
point, <literal>U+FFFD</literal> "�". You can change this with
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_buffer_set_replacement_codepoint(buf, replacement);
|
||||
</programlisting>
|
||||
<para>
|
||||
passing in the replacement Unicode code point as the
|
||||
<parameter>replacement</parameter> parameter.
|
||||
</para>
|
||||
<para>
|
||||
The invisible glyph is used to replace all output glyphs that
|
||||
are invisible. By default, the standard space character
|
||||
<literal>U+0020</literal> is used; you can replace this (for
|
||||
example, when using a font that provides script-specific
|
||||
spaces) with
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_buffer_set_invisible_glyph(buf, replacement_glyph);
|
||||
</programlisting>
|
||||
<para>
|
||||
Do note that in the <parameter>replacement_glyph</parameter>
|
||||
parameter, you must provide the glyph ID of the replacement you
|
||||
wish to use, not the Unicode code point.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz supports a few additional flags you might want to set
|
||||
on your buffer under certain circumstances. The
|
||||
<literal>HB_BUFFER_FLAG_BOT</literal> and
|
||||
<literal>HB_BUFFER_FLAG_EOT</literal> flags tell HarfBuzz
|
||||
that the buffer represents the beginning or end (respectively)
|
||||
of a text element (such as a paragraph or other block). Knowing
|
||||
this allows HarfBuzz to apply certain contextual font features
|
||||
when shaping, such as initial or final variants in connected
|
||||
scripts.
|
||||
</para>
|
||||
<para>
|
||||
<literal>HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES</literal>
|
||||
tells HarfBuzz not to hide glyphs with the
|
||||
<literal>Default_Ignorable</literal> property in Unicode. This
|
||||
property designates control characters and other non-printing
|
||||
code points, such as joiners and variation selectors. Normally
|
||||
HarfBuzz replaces them in the output buffer with zero-width
|
||||
space glyphs (using the "invisible glyph" property discussed
|
||||
above); setting this flag causes them to be printed, which can
|
||||
be helpful for troubleshooting.
|
||||
</para>
|
||||
<para>
|
||||
Conversely, setting the
|
||||
<literal>HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES</literal> flag
|
||||
tells HarfBuzz to remove <literal>Default_Ignorable</literal>
|
||||
glyphs from the output buffer entirely. Finally, setting the
|
||||
<literal>HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE</literal>
|
||||
flag tells HarfBuzz not to insert the dotted-circle glyph
|
||||
(<literal>U+25CC</literal>, "◌"), which is normally
|
||||
inserted into buffer output when broken character sequences are
|
||||
encountered (such as combining marks that are not attached to a
|
||||
base character).
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="customizing-unicode-functions">
|
||||
<title>Customizing Unicode functions</title>
|
||||
<para>
|
||||
HarfBuzz requires some simple functions for accessing
|
||||
information from the Unicode Character Database (such as the
|
||||
<literal>General_Category</literal> (gc) and
|
||||
<literal>Script</literal> (sc) properties) that is useful
|
||||
for shaping, as well as some useful operations like composing and
|
||||
decomposing code points.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz includes its own internal, lightweight set of Unicode
|
||||
functions. At build time, it is also possible to compile support
|
||||
for some other options, such as the Unicode functions provided
|
||||
by GLib or the International Components for Unicode (ICU)
|
||||
library. Generally, this option is only of interest for client
|
||||
programs that have specific integration requirements or that do
|
||||
a significant amount of customization.
|
||||
</para>
|
||||
<para>
|
||||
If your program has access to other Unicode functions, however,
|
||||
such as through a system library or application framework, you
|
||||
might prefer to use those instead of the built-in
|
||||
options. HarfBuzz supports this by implementing its Unicode
|
||||
functions as a set of virtual methods that you can replace —
|
||||
without otherwise affecting HarfBuzz's functionality.
|
||||
</para>
|
||||
<para>
|
||||
The Unicode functions are specified in a structure called
|
||||
<literal>unicode_funcs</literal> which is attached to each
|
||||
buffer. But even though <literal>unicode_funcs</literal> is
|
||||
associated with a <type>hb_buffer_t</type>, the functions
|
||||
themselves are called by other HarfBuzz APIs that access
|
||||
buffers, so it would be unwise for you to hook different
|
||||
functions into different buffers.
|
||||
</para>
|
||||
<para>
|
||||
In addition, you can mark your <literal>unicode_funcs</literal>
|
||||
as immutable by calling
|
||||
<function>hb_unicode_funcs_make_immutable (ufuncs)</function>.
|
||||
This is especially useful if your code is a
|
||||
library or framework that will have its own client programs. By
|
||||
marking your Unicode function choices as immutable, you prevent
|
||||
your own client programs from changing the
|
||||
<literal>unicode_funcs</literal> configuration and introducing
|
||||
inconsistencies and errors downstream.
|
||||
</para>
|
||||
<para>
|
||||
You can retrieve the Unicode-functions configuration for
|
||||
your buffer by calling <function>hb_buffer_get_unicode_funcs()</function>:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_unicode_funcs_t *ufunctions;
|
||||
ufunctions = hb_buffer_get_unicode_funcs(buf);
|
||||
</programlisting>
|
||||
<para>
|
||||
The current version of <literal>unicode_funcs</literal> uses six functions:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_unicode_combining_class_func_t</function>:
|
||||
returns the Canonical Combining Class of a code point.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_unicode_general_category_func_t</function>:
|
||||
returns the General Category (gc) of a code point.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_unicode_mirroring_func_t</function>: returns
|
||||
the Mirroring Glyph code point (for bi-directional
|
||||
replacement) of a code point.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_unicode_script_func_t</function>: returns the
|
||||
Script (sc) property of a code point.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_unicode_compose_func_t</function>: returns the
|
||||
canonical composition of a sequence of two code points.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_unicode_decompose_func_t</function>: returns
|
||||
the canonical decomposition of a code point.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
Note, however, that future HarfBuzz releases may alter this set.
|
||||
</para>
|
||||
<para>
|
||||
Each Unicode function has a corresponding setter, with which you
|
||||
can assign a callback to your replacement function. For example,
|
||||
to replace
|
||||
<function>hb_unicode_general_category_func_t</function>, you can call
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_unicode_funcs_set_general_category_func (*ufuncs, func, *user_data, destroy)
|
||||
</programlisting>
|
||||
<para>
|
||||
Virtualizing this set of Unicode functions is primarily intended
|
||||
to improve portability. There is no need for every client
|
||||
program to make the effort to replace the default options, so if
|
||||
you are unsure, do not feel any pressure to customize
|
||||
<literal>unicode_funcs</literal>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
|
|
|
@ -156,18 +156,20 @@
|
|||
order.
|
||||
</para>
|
||||
<para>
|
||||
For left-to-right scripts (LTR) and top-to-bottom scripts (TTB),
|
||||
For buffers in the left-to-right (LTR)
|
||||
or top-to-bottom (TTB) text flow direction,
|
||||
HarfBuzz will preserve the monotonic property: client programs
|
||||
are guaranteed that monotonically increasing initial clulster
|
||||
are guaranteed that monotonically increasing initial cluster
|
||||
values will be returned as monotonically increasing final
|
||||
cluster values.
|
||||
</para>
|
||||
<para>
|
||||
For right-to-left scripts (RTL) and bottom-to-top scripts (BTT),
|
||||
For buffers in the right-to-left (RTL)
|
||||
or bottom-to-top (BTT) text flow direction,
|
||||
the directionality of the buffer itself is reversed for final
|
||||
output as a matter of design. Therefore, HarfBuzz inverts the
|
||||
monotonic property: client programs are guaranteed that
|
||||
monotonically increasing initial clulster values will be
|
||||
monotonically increasing initial cluster values will be
|
||||
returned as monotonically <emphasis>decreasing</emphasis> final
|
||||
cluster values.
|
||||
</para>
|
||||
|
@ -492,7 +494,7 @@
|
|||
</para>
|
||||
<para>
|
||||
But this initial cluster-merging behavior makes it impossible
|
||||
client programs to implement some features (such as to
|
||||
for client programs to implement some features (such as to
|
||||
color diacritic marks differently from their base
|
||||
characters). That is why, in level 1, HarfBuzz does not perform
|
||||
the initial merging step.
|
||||
|
@ -684,7 +686,7 @@
|
|||
<para>
|
||||
There may be other problems encountered with ligatures under
|
||||
level 2, such as if the direction of the text is forced to
|
||||
opposite of its natural direction (for example, Arabic text
|
||||
the opposite of its natural direction (for example, Arabic text
|
||||
that is forced into left-to-right directionality). But,
|
||||
generally speaking, these other scenarios are minor corner
|
||||
cases that are too obscure for most client programs to need to
|
||||
|
|
|
@ -5,20 +5,449 @@
|
|||
<!ENTITY version SYSTEM "version.xml">
|
||||
]>
|
||||
<chapter id="fonts-and-faces">
|
||||
<title>Fonts and faces</title>
|
||||
<section id="using-freetype">
|
||||
<title>Fonts, faces, and output</title>
|
||||
<para>
|
||||
In the previous chapter, we saw how to set up a buffer and fill
|
||||
it with text as Unicode code points. In order to shape this
|
||||
buffer text with HarfBuzz, you will need also need a font
|
||||
object.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz provides abstractions to help you cache and reuse the
|
||||
heavier parts of working with binary fonts, so we will look at
|
||||
how to do that. We will also look at how to work with the
|
||||
FreeType font-rendering library and at how you can customize
|
||||
HarfBuzz to work with other libraries.
|
||||
</para>
|
||||
<para>
|
||||
Finally, we will look at how to work with OpenType variable
|
||||
fonts, the latest update to the OpenType font format, and at
|
||||
some other recent additions to OpenType.
|
||||
</para>
|
||||
|
||||
<section id="fonts-and-faces-objects">
|
||||
<title>Font and face objects</title>
|
||||
<para>
|
||||
The outcome of shaping a run of text depends on the contents of
|
||||
a specific font file (such as the substitutions and positioning
|
||||
moves in the 'GSUB' and 'GPOS' tables), so HarfBuzz makes
|
||||
accessing those internals fast.
|
||||
</para>
|
||||
<para>
|
||||
An <type>hb_face_t</type> represents a <emphasis>face</emphasis>
|
||||
in HarfBuzz. This data type is a wrapper around an
|
||||
<type>hb_blob_t</type> blob that holds the contents of a binary
|
||||
font file. Since HarfBuzz supports TrueType Collections and
|
||||
OpenType Collections (each of which can include multiple
|
||||
typefaces), a HarfBuzz face also requires an index number
|
||||
specifying which typeface in the file you want to use. Most of
|
||||
the font files you will encounter in the wild include just a
|
||||
single face, however, so most of the time you would pass in
|
||||
<literal>0</literal> as the index when you create a face:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_blob_t* blob = hb_blob_create_from_file(file);
|
||||
...
|
||||
hb_face_t* face = hb_face_create(blob, 0);
|
||||
</programlisting>
|
||||
<para>
|
||||
On its own, a face object is not quite ready to use for
|
||||
shaping. The typeface must be set to a specific point size in
|
||||
order for some details (such as hinting) to work. In addition,
|
||||
if the font file in question is an OpenType Variable Font, then
|
||||
you may need to specify one or variation-axis settings (or a
|
||||
named instance) in order to get the output you need.
|
||||
</para>
|
||||
<para>
|
||||
In HarfBuzz, you do this by creating a <emphasis>font</emphasis>
|
||||
object from your face.
|
||||
</para>
|
||||
<para>
|
||||
Font objects also have the advantage of being considerably
|
||||
lighter-weight than face objects (remember that a face contains
|
||||
the contents of a binary font file mapped into memory). As a
|
||||
result, you can cache and reuse a font object, but you could
|
||||
also create a new one for each additional size you needed.
|
||||
Creating new fonts incurs some additional overhead, of course,
|
||||
but whether or not it is excessive is your call in the end. In
|
||||
contrast, face objects are substantially larger, and you really
|
||||
should cache them and reuse them whenever possible.
|
||||
</para>
|
||||
<para>
|
||||
You can create a font object from a face object:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_font_t* hb_font = hb_font_create(hb_face);
|
||||
</programlisting>
|
||||
<para>
|
||||
After creating a font, there are a few properties you should
|
||||
set. Many fonts enable and disable hints based on the size it
|
||||
is used at, so setting this is important for font
|
||||
objects. <function>hb_font_set_ppem(font, x_ppem,
|
||||
y_ppem)</function> sets the pixels-per-EM value of the font. You
|
||||
can also set the point size of the font with
|
||||
<function>hb_font_set_ptem(font, ptem)</function>. HarfBuzz uses the
|
||||
industry standard 72 points per inch.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz lets you specify the degree subpixel precision you want
|
||||
through a scaling factor. You can set horizontal and
|
||||
vertical scaling factors on the
|
||||
font by calling <function>hb_font_set_scale(font, x_scale,
|
||||
y_scale)</function>.
|
||||
</para>
|
||||
<para>
|
||||
There may be times when you are handed a font object and need to
|
||||
access the face object that it comes from. For that, you can call
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_face = hb_font_get_face(hb_font);
|
||||
</programlisting>
|
||||
<para>
|
||||
You can also create a font object from an existing font object
|
||||
using the <function>hb_font_create_sub_font()</function>
|
||||
function. This creates a child font object that is initiated
|
||||
with the same attributes as its parent; it can be used to
|
||||
quickly set up a new font for the purpose of overriding a specific
|
||||
font-functions method.
|
||||
</para>
|
||||
<para>
|
||||
All face objects and font objects are lifecycle-managed by
|
||||
HarfBuzz. After creating a face, you increase its reference
|
||||
count with <function>hb_face_reference(face)</function> and
|
||||
decrease it with
|
||||
<function>hb_face_destroy(face)</function>. Likewise, you
|
||||
increase the reference count on a font with
|
||||
<function>hb_font_reference(font)</function> and decrease it
|
||||
with <function>hb_font_destroy(font)</function>.
|
||||
</para>
|
||||
<para>
|
||||
You can also attach user data to face objects and font objects.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="fonts-and-faces-custom-functions">
|
||||
<title>Customizing font functions</title>
|
||||
<para>
|
||||
During shaping, HarfBuzz frequently needs to query font objects
|
||||
to get at the contents and parameters of the glyphs in a font
|
||||
file. It includes a built-in set of functions that is tailored
|
||||
to working with OpenType fonts. However, as was the case with
|
||||
Unicode functions in the buffers chapter, HarfBuzz also wants to
|
||||
make it easy for you to assign a substitute set of font
|
||||
functions if you are developing a program to work with a library
|
||||
or platform that provides its own font functions.
|
||||
</para>
|
||||
<para>
|
||||
Therefore, the HarfBuzz API defines a set of virtual
|
||||
methods for accessing font-object properties, and you can
|
||||
replace the defaults with your own selections without
|
||||
interfering with the shaping process. Each font object in
|
||||
HarfBuzz includes a structure called
|
||||
<literal>font_funcs</literal> that serves as a vtable for the
|
||||
font object. The virtual methods in
|
||||
<literal>font_funcs</literal> are:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_font_h_extents_func_t</function>: returns
|
||||
the extents of the font for horizontal text.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_font_v_extents_func_t</function>: returns
|
||||
the extents of the font for vertical text.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_nominal_glyph_func_t</function>: returns
|
||||
the font's nominal glyph for a given code point.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_variation_glyph_func_t</function>: returns
|
||||
the font's glyph for a given code point when it is followed by a
|
||||
given Variation Selector.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_nominal_glyphs_func_t</function>: returns
|
||||
the font's nominal glyphs for a series of code points.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_advance_func_t</function>: returns
|
||||
the advance for a glyph.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_h_advance_func_t</function>: returns
|
||||
the advance for a glyph for horizontal text.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_v_advance_func_t</function>:returns
|
||||
the advance for a glyph for vertical text.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_advances_func_t</function>: returns
|
||||
the advances for a series of glyphs.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_h_advances_func_t</function>: returns
|
||||
the advances for a series of glyphs for horizontal text .
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_v_advances_func_t</function>: returns
|
||||
the advances for a series of glyphs for vertical text.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_origin_func_t</function>: returns
|
||||
the origin coordinates of a glyph.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_h_origin_func_t</function>: returns
|
||||
the origin coordinates of a glyph for horizontal text.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_v_origin_func_t</function>: returns
|
||||
the origin coordinates of a glyph for vertical text.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_extents_func_t</function>: returns
|
||||
the extents for a glyph.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_contour_point_func_t</function>:
|
||||
returns the coordinates of a specific contour point from a glyph.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_name_func_t</function>: returns the
|
||||
name of a glyph (from its glyph index).
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_get_glyph_from_name_func_t</function>: returns
|
||||
the glyph index that corresponds to a given glyph name.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
You can fetch the font-functions configuration for a font object
|
||||
by calling <function>hb_font_get_font_funcs()</function>:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_font_funcs_t *ffunctions;
|
||||
ffunctions = hb_font_get_font_funcs (font);
|
||||
</programlisting>
|
||||
<para>
|
||||
The individual methods can each be replaced with their own setter
|
||||
function, such as
|
||||
<function>hb_font_funcs_set_nominal_glyph_func(*ffunctions,
|
||||
func, *user_data, destroy)</function>.
|
||||
</para>
|
||||
<para>
|
||||
Font-functions structures can be reused for multiple font
|
||||
objects, and can be reference counted with
|
||||
<function>hb_font_funcs_reference()</function> and
|
||||
<function>hb_font_funcs_destroy()</function>. Just like other
|
||||
objects in HarfBuzz, you can set user-data for each
|
||||
font-functions structure and assign a destroy callback for
|
||||
it.
|
||||
</para>
|
||||
<para>
|
||||
You can also mark a font-functions structure as immutable,
|
||||
with <function>hb_font_funcs_make_immutable()</function>. This
|
||||
is especially useful if your code is a library or framework that
|
||||
will have its own client programs. By marking your
|
||||
font-functions structures as immutable, you prevent your client
|
||||
programs from changing the configuration and introducing
|
||||
inconsistencies and errors downstream.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="fonts-and-faces-native-opentype">
|
||||
<title>Font objects and HarfBuzz's native OpenType implementation</title>
|
||||
<para>
|
||||
By default, whenever HarfBuzz creates a font object, it will
|
||||
configure the font to use a built-in set of font functions that
|
||||
supports contemporary OpenType font internals. If you want to
|
||||
work with OpenType or TrueType fonts, you should be able to use
|
||||
these functions without difficulty.
|
||||
</para>
|
||||
<para>
|
||||
Many of the methods in the font-functions structure deal with
|
||||
the fundamental properties of glyphs that are required for
|
||||
shaping text: extents (the maximums and minimums on each axis),
|
||||
origins (the <literal>(0,0)</literal> coordinate point which
|
||||
glyphs are drawn in reference to), and advances (the amount that
|
||||
the cursor needs to be moved after drawing each glyph, including
|
||||
any empty space for the glyph's side bearings).
|
||||
</para>
|
||||
<para>
|
||||
As you can see in the list of functions, there are separate "horizontal"
|
||||
and "vertical" variants depending on whether the text is set in
|
||||
the horizontal or vertical direction. For some scripts, fonts
|
||||
that are designed to support text set horizontally or vertically (for
|
||||
example, in Japanese) may include metrics for both text
|
||||
directions. When fonts don't include this information, HarfBuzz
|
||||
does its best to transform what the font provides.
|
||||
</para>
|
||||
<para>
|
||||
In addition to the direction-specific functions, HarfBuzz
|
||||
provides some higher-level functions for fetching information
|
||||
like extents and advances for a glyph. If you call
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_font_get_glyph_advance_for_direction(font, direction, extents);
|
||||
</programlisting>
|
||||
<para>
|
||||
then you can provide any <type>hb_direction_t</type> as the
|
||||
<parameter>direction</parameter> parameter, and HarfBuzz will
|
||||
use the correct function variant for the text direction. There
|
||||
are similar higher-level versions of the functions for fetching
|
||||
extents, origin coordinates, and contour-point
|
||||
coordinates. There are also addition and subtraction functions
|
||||
for moving points with respect to the origin.
|
||||
</para>
|
||||
<para>
|
||||
There are also methods for fetching the glyph ID that
|
||||
corresponds to a Unicode code point (possibly when followed by a
|
||||
variation-selector code point), fetching the glyph name from the
|
||||
font, and fetching the glyph ID that corresponds to a glyph name
|
||||
you already have.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz also provides functions for converting between glyph
|
||||
names and string
|
||||
variables. <function>hb_font_glyph_to_string(font, glyph, s,
|
||||
size)</function> retrieves the name for the glyph ID
|
||||
<parameter>glyph</parameter> from the font object. It generates a
|
||||
generic name of the form <literal>gidDDD</literal> (where DDD is
|
||||
the glyph index) if there is no name for the glyph in the
|
||||
font. The <function>hb_font_glyph_from_string(font, s, len,
|
||||
glyph)</function> takes an input string <parameter>s</parameter>
|
||||
and looks for a glyph with that name in the font, returning its
|
||||
glyph ID in the <parameter>glyph</parameter>
|
||||
output parameter. It automatically parses
|
||||
<literal>gidDDD</literal> and <literal>uniUUUU</literal> strings.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
<!-- Commenting out FreeType integration section-holder for now. May move
|
||||
to the full-blown Integration Chapter. -->
|
||||
|
||||
<!-- <section id="fonts-and-faces-freetype">
|
||||
<title>Using FreeType</title>
|
||||
<para>
|
||||
|
||||
</para>
|
||||
</section>
|
||||
<section id="using-harfbuzzs-native-opentype-implementation">
|
||||
<title>Using HarfBuzz's native OpenType implementation</title>
|
||||
<para>
|
||||
|
||||
</para>
|
||||
</section>
|
||||
<section id="using-your-own-font-functions">
|
||||
<title>Using your own font functions</title>
|
||||
</section> -->
|
||||
|
||||
<section id="fonts-and-faces-variable">
|
||||
<title>Working with OpenType Variable Fonts</title>
|
||||
<para>
|
||||
If you are working with OpenType Variable Fonts, there are a few
|
||||
additional functions you should use to specify the
|
||||
variation-axis settings of your font object. Without doing so,
|
||||
your variable font's font object can still be used, but only at
|
||||
the default setting for every axis (which, of course, is
|
||||
sometimes what you want, but does not cover general usage).
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz manages variation settings in the
|
||||
<type>hb_variation_t</type> data type, which holds a <property>tag</property> for the
|
||||
variation-axis identifier tag and a <property>value</property> for its
|
||||
setting. You can retrieve the list of variation axes in a font
|
||||
binary from the face object (not from a font object, notably) by
|
||||
calling <function>hb_ot_var_get_axis_count(face)</function> to
|
||||
find the number of axes, then using
|
||||
<function>hb_ot_var_get_axis_infos()</function> to collect the
|
||||
axis structures:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
axes = hb_ot_var_get_axis_count(face);
|
||||
...
|
||||
hb_ot_var_get_axis_infos(face, 0, axes, axes_array);
|
||||
</programlisting>
|
||||
<para>
|
||||
For each axis returned in the array, you can can access the
|
||||
identifier in its <property>tag</property>. HarfBuzz also has
|
||||
tag definitions predefined for the five standard axes specified
|
||||
in OpenType (<literal>ital</literal> for italic,
|
||||
<literal>opsz</literal> for optical size,
|
||||
<literal>slnt</literal> for slant, <literal>wdth</literal> for
|
||||
width, and <literal>wght</literal> for weight). Each axis also
|
||||
has a <property>min_value</property>, a
|
||||
<property>default_value</property>, and a <property>max_value</property>.
|
||||
</para>
|
||||
<para>
|
||||
To set your font object's variation settings, you call the
|
||||
<function>hb_font_set_variations()</function> function with an
|
||||
array of <type>hb_variation_t</type> variation settings. Let's
|
||||
say our font has weight and width axes. We need to specify each
|
||||
of the axes by tag and assign a value on the axis:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
unsigned int variation_count = 2;
|
||||
hb_variation_t variation_data[variation_count];
|
||||
variation_data[0].tag = HB_OT_TAG_VAR_AXIS_WIDTH;
|
||||
variation_data[1].tag = HB_OT_TAG_VAR_AXIS_WEIGHT;
|
||||
variation_data[0].value = 80;
|
||||
variation_data[1].value = 750;
|
||||
...
|
||||
hb_font_set_variations(font, variation_data, variation_count);
|
||||
</programlisting>
|
||||
<para>
|
||||
That should give us a slightly condensed font ("normal" on the
|
||||
<literal>wdth</literal> axis is 100) at a noticeably bolder
|
||||
weight ("regular" is 400 on the <literal>wght</literal> axis).
|
||||
</para>
|
||||
<para>
|
||||
In practice, though, you should always check that the value you
|
||||
want to set on the axis is within the
|
||||
[<property>min_value</property>,<property>max_value</property>]
|
||||
range actually implemented in the font's variation axis. After
|
||||
all, a font might only provide lighter-than-regular weights, and
|
||||
setting a heavier value on the <literal>wght</literal> axis will
|
||||
not change that.
|
||||
</para>
|
||||
<para>
|
||||
Once your variation settings are specified on your font object,
|
||||
however, shaping with a variable font is just like shaping a
|
||||
static font.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
</chapter>
|
||||
|
|
|
@ -223,7 +223,7 @@
|
|||
<orderedlist numeration="arabic">
|
||||
<listitem override="2">
|
||||
<para>
|
||||
Guess the script, language and direction of the buffer.
|
||||
Set the script, language and direction of the buffer.
|
||||
</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
@ -275,14 +275,14 @@
|
|||
</orderedlist>
|
||||
<programlisting language="C">
|
||||
for (i = 0; i < glyph_count; ++i) {
|
||||
glyphid = glyph_info[i].codepoint;
|
||||
x_offset = glyph_pos[i].x_offset / 64.0;
|
||||
y_offset = glyph_pos[i].y_offset / 64.0;
|
||||
x_advance = glyph_pos[i].x_advance / 64.0;
|
||||
y_advance = glyph_pos[i].y_advance / 64.0;
|
||||
draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset);
|
||||
cursor_x += x_advance;
|
||||
cursor_y += y_advance;
|
||||
glyphid = glyph_info[i].codepoint;
|
||||
x_offset = glyph_pos[i].x_offset / 64.0;
|
||||
y_offset = glyph_pos[i].y_offset / 64.0;
|
||||
x_advance = glyph_pos[i].x_advance / 64.0;
|
||||
y_advance = glyph_pos[i].y_advance / 64.0;
|
||||
draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset);
|
||||
cursor_x += x_advance;
|
||||
cursor_y += y_advance;
|
||||
}
|
||||
</programlisting>
|
||||
<orderedlist numeration="arabic">
|
||||
|
|
|
@ -246,7 +246,7 @@
|
|||
<listitem>
|
||||
<para>
|
||||
Use <ulink url="https://developer.gnome.org/glib/">GLib</ulink>. <emphasis>(Default = auto)</emphasis>
|
||||
</para>
|
||||
</para>
|
||||
<para>
|
||||
This option enables or disables usage of the GLib
|
||||
library. The default setting is to check for the
|
||||
|
@ -297,7 +297,7 @@
|
|||
<listitem>
|
||||
<para>
|
||||
Use <ulink url="https://www.freedesktop.org/wiki/Software/fontconfig/">Fontconfig</ulink>. <emphasis>(Default = auto)</emphasis>
|
||||
</para>
|
||||
</para>
|
||||
<para>
|
||||
This option enables or disables usage of the Fontconfig
|
||||
library, which provides font-matching functions and
|
||||
|
@ -317,7 +317,7 @@
|
|||
<listitem>
|
||||
<para>
|
||||
Use the <ulink url="http://site.icu-project.org/home">ICU</ulink> library. <emphasis>(Default = auto)</emphasis>
|
||||
</para>
|
||||
</para>
|
||||
<para>
|
||||
This option enables or disables usage of the
|
||||
<emphasis>International Components for
|
||||
|
@ -330,30 +330,12 @@
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>--with-ucdn</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Use HarfBuzz's <ulink url="https://github.com/harfbuzz/harfbuzz/tree/master/src/hb-ucdn">built-in UCDN library</ulink>. <emphasis>(Default = auto)</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
The HarfBuzz source tree includes a <emphasis>Unicode
|
||||
Database and Normalization</emphasis> (UCDN) library
|
||||
that provides access to basic character properties in
|
||||
the Unicode Character Database (UCD) as well as low-level
|
||||
normalization functions. HarfBuzz can be built without
|
||||
this UCDN support if the usage of a different UCDN
|
||||
library is desired.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>--with-graphite2</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Use the <ulink url="http://graphite.sil.org/">Graphite2</ulink> library. <emphasis>(Default = no)</emphasis>
|
||||
</para>
|
||||
</para>
|
||||
<para>
|
||||
This option enables or disables usage of the Graphite2
|
||||
library, which provides support for the Graphite shaping
|
||||
|
@ -367,7 +349,7 @@
|
|||
<listitem>
|
||||
<para>
|
||||
Use the <ulink url="https://www.freetype.org/">FreeType</ulink> library. <emphasis>(Default = auto)</emphasis>
|
||||
</para>
|
||||
</para>
|
||||
<para>
|
||||
This option enables or disables usage of the FreeType
|
||||
font-rendering library. The default setting is to check for the
|
||||
|
@ -384,7 +366,7 @@
|
|||
Use the <ulink
|
||||
url="https://docs.microsoft.com/en-us/windows/desktop/intl/uniscribe">Uniscribe</ulink>
|
||||
library (experimental). <emphasis>(Default = no)</emphasis>
|
||||
</para>
|
||||
</para>
|
||||
<para>
|
||||
This option enables or disables usage of the Uniscribe
|
||||
font-rendering library. Uniscribe is available on
|
||||
|
@ -400,7 +382,7 @@
|
|||
<listitem>
|
||||
<para>
|
||||
Use the <ulink url="https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal">DirectWrite</ulink> library (experimental). <emphasis>(Default = no)</emphasis>
|
||||
</para>
|
||||
</para>
|
||||
<para>
|
||||
This option enables or disables usage of the DirectWrite
|
||||
font-rendering library. DirectWrite is available on
|
||||
|
@ -416,13 +398,25 @@
|
|||
<listitem>
|
||||
<para>
|
||||
Use the <ulink url="https://developer.apple.com/documentation/coretext">CoreText</ulink> library. <emphasis>(Default = no)</emphasis>
|
||||
</para>
|
||||
</para>
|
||||
<para>
|
||||
This option enables or disables usage of the CoreText
|
||||
library. CoreText is available on macOS and iOS systems.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>--enable-gtk-doc</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Use <ulink url="https://www.gtk.org/gtk-doc/">GTK-Doc</ulink>. <emphasis>(Default = no)</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
This option enables the building of the documentation.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</section>
|
||||
|
||||
|
|
258
docs/usermanual-object-model.xml
Normal file
258
docs/usermanual-object-model.xml
Normal file
|
@ -0,0 +1,258 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
|
||||
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
|
||||
<!ENTITY version SYSTEM "version.xml">
|
||||
]>
|
||||
<chapter id="object-model">
|
||||
<title>The HarfBuzz object model</title>
|
||||
<section id="object-model-intro">
|
||||
<title>An overview of data types in HarfBuzz</title>
|
||||
<para>
|
||||
HarfBuzz features two kinds of data types: non-opaque,
|
||||
pass-by-value types and opaque, heap-allocated types. This kind
|
||||
of separation is common in C libraries that have to provide
|
||||
API/ABI compatibility (almost) indefinitely.
|
||||
</para>
|
||||
<para>
|
||||
<emphasis>Value types:</emphasis> The non-opaque, pass-by-value
|
||||
types include integer types, enums, and small structs. Exposing
|
||||
a struct in the public API makes it impossible to expand the
|
||||
struct in the future. As such, exposing structs is reserved for
|
||||
cases where it’s extremely inefficient to do otherwise.
|
||||
</para>
|
||||
<para>
|
||||
In HarfBuzz, several structs, like <literal>hb_glyph_info_t</literal> and
|
||||
<literal>hb_glyph_position_t</literal>, fall into that efficiency-sensitive
|
||||
category and are non-opaque.
|
||||
</para>
|
||||
<para>
|
||||
For all non-opaque structs where future extensibility may be
|
||||
necessary, reserved members are included to hold space for
|
||||
possible future members. As such, it’s important to provide
|
||||
<function>equal()</function>, and <function>hash()</function>
|
||||
methods for such structs, allowing users of the API do
|
||||
effectively deal with the type without having to
|
||||
adapt their code to future changes.
|
||||
</para>
|
||||
<para>
|
||||
Important value types provided by HarfBuzz include the structs
|
||||
for working with Unicode code points, glyphs, and tags for font
|
||||
tables and features, as well as the enums for many Unicode and
|
||||
OpenType properties.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="object-model-object-types">
|
||||
<title>Objects in HarfBuzz</title>
|
||||
<para>
|
||||
<emphasis>Object types:</emphasis> Opaque struct types are used
|
||||
for what HarfBuzz loosely calls "objects." This doesn’t have
|
||||
much to do with the terminology from object-oriented programming
|
||||
(OOP), although some of the concepts are similar.
|
||||
</para>
|
||||
<para>
|
||||
In HarfBuzz, all object types provide certain
|
||||
lifecycle-management APIs. Objects are reference-counted, and
|
||||
constructed with various <function>create()</function> methods, referenced via
|
||||
<function>reference()</function> and dereferenced using
|
||||
<function>destroy()</function>.
|
||||
</para>
|
||||
<para>
|
||||
For example,
|
||||
the <literal>hb_buffer_t</literal> object has
|
||||
<function>hb_buffer_create()</function> as its constructor,
|
||||
<function>hb_buffer_reference()</function> to reference, and
|
||||
<function>hb_buffer_destroy()</function> to dereference.
|
||||
</para>
|
||||
<para>
|
||||
After construction, each object's properties are accessible only
|
||||
through the setter and getter functions described in the API
|
||||
Reference manual.
|
||||
</para>
|
||||
<para>
|
||||
Key object types provided by HarfBuzz include:
|
||||
</para>
|
||||
<itemizedlist spacing="compact">
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>blobs</emphasis>, which act as low-level wrappers around binary
|
||||
data. Blobs are typically used to hold the contents of a
|
||||
binary font file.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>faces</emphasis>, which represent typefaces from a
|
||||
font file, but without specific parameters (such as size) set.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>fonts</emphasis>, which represent instances of a
|
||||
face with all of their parameters specified.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>buffers</emphasis>, which hold Unicode code points
|
||||
for characters (before shaping) and the shaped glyph output
|
||||
(after shaping).
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>shape plans</emphasis>, which store the settings
|
||||
that HarfBuzz will use when shaping a particular text
|
||||
segment. Shape plans are not generally used by client
|
||||
programs directly, but as we will see in a later chapter,
|
||||
they are still valuable to understand.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<section id="object-model-lifecycle">
|
||||
<title>Object lifecycle management</title>
|
||||
<para>
|
||||
Each object type in HarfBuzz provides a
|
||||
<function>create()</function> method. Some object types provide
|
||||
additional variants of <function>create()</function> to handle
|
||||
special cases or to speed up common tasks; those variants are
|
||||
documented in the API reference. For example,
|
||||
<function>hb_blob_create_from_file()</function> constructs a new
|
||||
blob directly from the contents of a file.
|
||||
</para>
|
||||
<para>
|
||||
All objects are created with an initial reference count of
|
||||
<literal>1</literal>. Client programs can increase the reference
|
||||
count on an object by calling its
|
||||
<function>reference()</function> method. Whenever a client
|
||||
program is finished with an object, it should call its
|
||||
corresponding <function>destroy()</function> method. The destroy
|
||||
method will decrease the reference count on the object and,
|
||||
whenever the reference count reaches zero, it will also destroy
|
||||
the object and free all of the associated memory.
|
||||
</para>
|
||||
<para>
|
||||
All of HarfBuzz's object-lifecycle-management APIs are
|
||||
thread-safe (unless you compiled HarfBuzz from source with the
|
||||
<literal>HB_NO_MT</literal> configuration flag), even when the
|
||||
object as a whole is not thread-safe.
|
||||
It is also permissible to <function>reference()</function> or to
|
||||
<function>destroy()</function> the <literal>NULL</literal>
|
||||
value.
|
||||
</para>
|
||||
<para>
|
||||
Some objects are thread-safe after they have been constructed
|
||||
and set up. The general pattern is to
|
||||
<function>create()</function> the object, make a few
|
||||
<function>set_*()</function> calls to set up the
|
||||
object, and then use it without further modification.
|
||||
</para>
|
||||
<para>
|
||||
To ensure that such an object is not modified, client programs
|
||||
can explicitly mark an object as immutable. HarfBuzz provides
|
||||
<function>make_immutable()</function> methods to mark an object
|
||||
as immutable and <function>is_immutable()</function> methods to
|
||||
test whether or not an object is immutable. Attempts to use
|
||||
setter functions on immutable objects will fail silently; see the API
|
||||
Reference manual for specifics.
|
||||
</para>
|
||||
<para>
|
||||
Note also that there are no "make mutable" methods. If client
|
||||
programs need to alter an object previously marked as immutable,
|
||||
they will need to make a duplicate of the original.
|
||||
</para>
|
||||
<para>
|
||||
Finally, object constructors (and, indeed, as much of the
|
||||
shaping API as possible) will never return
|
||||
<literal>NULL</literal>. Instead, if there is an allocation
|
||||
error, each constructor will return an “empty” object
|
||||
singleton.
|
||||
</para>
|
||||
<para>
|
||||
These empty-object singletons are inert and safe (although
|
||||
typically useless) to pass around. This design choice avoids
|
||||
having to check for <literal>NULL</literal> pointers all
|
||||
throughout the code.
|
||||
</para>
|
||||
<para>
|
||||
In addition, this “empty” object singleton can also be accessed
|
||||
using the <function>get_empty()</function> method of the object
|
||||
type in question.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="object-model-user-data">
|
||||
<title>User data</title>
|
||||
<para>
|
||||
To better integrate with client programs, HarfBuzz's objects
|
||||
offer a "user data" mechanism that can be used to attach
|
||||
arbitrary data to the object. User-data attachment can be
|
||||
useful for tying the lifecycles of various pieces of data
|
||||
together, or for creating language bindings.
|
||||
</para>
|
||||
<para>
|
||||
Each object type has a <function>set_user_data()</function>
|
||||
method and a <function>get_user_data()</function> method. The
|
||||
<function>set_user_data()</function> methods take a client-provided
|
||||
<literal>key</literal> and a pointer,
|
||||
<literal>user_data</literal>, pointing to the data itself. Once
|
||||
the key-data pair has been attached to the object, the
|
||||
<function>get_user_data()</function> method can be called with
|
||||
the key, returning the <function>user_data</function> pointer.
|
||||
</para>
|
||||
<para>
|
||||
The <function>set_user_data()</function> methods also support an
|
||||
optional <function>destroy</function> callback. Client programs
|
||||
can set the <function>destroy</function> callback and receive
|
||||
notification from HarfBuzz whenever the object is destructed.
|
||||
</para>
|
||||
<para>
|
||||
Finally, each <function>set_user_data()</function> method allows
|
||||
the client program to set a <literal>replace</literal> Boolean
|
||||
indicating whether or not the function call should replace any
|
||||
existing <literal>user_data</literal>
|
||||
associated with the specified key.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<section id="object-model-blobs">
|
||||
<title>Blobs</title>
|
||||
<para>
|
||||
While most of HarfBuzz's object types are specific to the
|
||||
shaping process, <emphasis>blobs</emphasis> are somewhat
|
||||
different.
|
||||
</para>
|
||||
<para>
|
||||
Blobs are an abstraction desgined to negotiate lifecycle and
|
||||
permissions for raw pieces of data. For example, when you load
|
||||
the raw font data into memory and want to pass it to HarfBuzz,
|
||||
you do so in a <literal>hb_blob_t</literal> wrapper.
|
||||
</para>
|
||||
<para>
|
||||
This allows you to take advantage of HarffBuzz's
|
||||
reference-counting and <function>destroy</function>
|
||||
callbacks. If you allocated the memory for the data using
|
||||
<function>malloc()</function>, you would create the blob using
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_blob_create (data, length, HB_MEMORY_MODE_WRITABLE, NULL, free)
|
||||
</programlisting>
|
||||
<para>
|
||||
That way, HarfBuzz will call <function>free()</function> on the
|
||||
allocated memory whenever the blob drops its last reference and
|
||||
is deconstructed. Consequently, the user code can stop worrying
|
||||
about freeing memory and let the reference-counting machinery
|
||||
take care of that.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
|
@ -6,14 +6,299 @@
|
|||
]>
|
||||
<chapter id="shaping-and-shape-plans">
|
||||
<title>Shaping and shape plans</title>
|
||||
<section id="opentype-features">
|
||||
<para>
|
||||
Once you have your face and font objects configured as desired and
|
||||
your input buffer is filled with the characters you need to shape,
|
||||
all you need to do is call <function>hb_shape()</function>.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz will return the shaped version of the text in the same
|
||||
buffer that you provided, but it will be in output mode. At that
|
||||
point, you can iterate through the glyphs in the buffer, drawing
|
||||
each one at the specified position or handing them off to the
|
||||
appropriate graphics library.
|
||||
</para>
|
||||
<para>
|
||||
For the most part, HarfBuzz's shaping step is straightforward from
|
||||
the outside. But that doesn't mean there will never be cases where
|
||||
you want to look under the hood and see what is happening on the
|
||||
inside. HarfBuzz provides facilities for doing that, too.
|
||||
</para>
|
||||
|
||||
<section id="shaping-buffer-output">
|
||||
<title>Shaping and buffer output</title>
|
||||
<para>
|
||||
The <function>hb_shape()</function> function call takes four arguments: the font
|
||||
object to use, the buffer of characters to shape, an array of
|
||||
user-specified features to apply, and the length of that feature
|
||||
array. The feature array can be NULL, so for the sake of
|
||||
simplicity we will start with that case.
|
||||
</para>
|
||||
<para>
|
||||
Internally, HarfBuzz looks at the tables of the font file to
|
||||
determine where glyph classes, substitutions, and positioning
|
||||
are defined, using that information to decide which
|
||||
<emphasis>shaper</emphasis> to use (<literal>ot</literal> for
|
||||
OpenType fonts, <literal>aat</literal> for Apple Advanced
|
||||
Typography fonts, and so on). It also looks at the direction,
|
||||
script, and language properties of the segment to figure out
|
||||
which script-specific shaping model is needed (at least, in
|
||||
shapers that support multiple options).
|
||||
</para>
|
||||
<para>
|
||||
If a font has a GDEF table, then that is used for
|
||||
glyph classes; if not, HarfBuzz will fall back to Unicode
|
||||
categorization by code point. If a font has an AAT "morx" table,
|
||||
then it is used for substitutions; if not, but there is a GSUB
|
||||
table, then the GSUB table is used. If the font has an AAT
|
||||
"kerx" table, then it is used for positioning; if not, but
|
||||
there is a GPOS table, then the GPOS table is used. If neither
|
||||
table is found, but there is a "kern" table, then HarfBuzz will
|
||||
use the "kern" table. If there is no "kerx", no GPOS, and no
|
||||
"kern", HarfBuzz will fall back to positioning marks itself.
|
||||
</para>
|
||||
<para>
|
||||
With a well-behaved OpenType font, you expect GDEF, GSUB, and
|
||||
GPOS tables to all be applied. HarfBuzz implements the
|
||||
script-specific shaping models in internal functions, rather
|
||||
than in the public API.
|
||||
</para>
|
||||
<para>
|
||||
The algorithms
|
||||
used for complex scripts can be quite involved; HarfBuzz tries
|
||||
to be compatible with the OpenType Layout specification
|
||||
and, wherever there is any ambiguity, HarfBuzz attempts to replicate the
|
||||
output of Microsoft's Uniscribe engine. See the <ulink
|
||||
url="https://docs.microsoft.com/en-us/typography/script-development/standard">Microsoft
|
||||
Typography pages</ulink> for more detail.
|
||||
</para>
|
||||
<para>
|
||||
In general, though, all that you need to know is that
|
||||
<function>hb_shape()</function> returns the results of shaping
|
||||
in the same buffer that you provided. The buffer's content type
|
||||
will now be set to
|
||||
<literal>HB_BUFFER_CONTENT_TYPE_GLYPHS</literal>, indicating
|
||||
that it contains shaped output, rather than input text. You can
|
||||
now extract the glyph information and positioning arrays:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count);
|
||||
hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count);
|
||||
</programlisting>
|
||||
<para>
|
||||
The glyph information array holds a <type>hb_glyph_info_t</type>
|
||||
for each output glyph, which has two fields:
|
||||
<parameter>codepoint</parameter> and
|
||||
<parameter>cluster</parameter>. Whereas, in the input buffer,
|
||||
the <parameter>codepoint</parameter> field contained the Unicode
|
||||
code point, it now contains the glyph ID of the corresponding
|
||||
glyph in the font. The <parameter>cluster</parameter> field is
|
||||
an integer that you can use to help identify when shaping has
|
||||
reordered, split, or combined code points; we will say more
|
||||
about that in the next chapter.
|
||||
</para>
|
||||
<para>
|
||||
The glyph positions array holds a corresponding
|
||||
<type>hb_glyph_position_t</type> for each output glyph,
|
||||
containing four fields: <parameter>x_advance</parameter>,
|
||||
<parameter>y_advance</parameter>,
|
||||
<parameter>x_offset</parameter>, and
|
||||
<parameter>y_offset</parameter>. The advances tell you how far
|
||||
you need to move the drawing point after drawing this glyph,
|
||||
depending on whether you are setting horizontal text (in which
|
||||
case you will have x advances) or vertical text (for which you
|
||||
will have y advances). The x and y offsets tell you where to
|
||||
move to start drawing the glyph; usually you will have both and
|
||||
x and a y offset, regardless of the text direction.
|
||||
</para>
|
||||
<para>
|
||||
Most of the time, you will rely on a font-rendering library or
|
||||
other graphics library to do the actual drawing of glyphs, so
|
||||
you will need to iterate through the glyphs in the buffer and
|
||||
pass the corresponding values off.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="shaping-opentype-features">
|
||||
<title>OpenType features</title>
|
||||
<para>
|
||||
OpenType features enable fonts to include smart behavior,
|
||||
implemented as "lookup" rules stored in the GSUB and GPOS
|
||||
tables. The OpenType specification defines a long list of
|
||||
standard features that fonts can use for these behaviors; each
|
||||
feature has a four-character reserved name and a well-defined
|
||||
semantic meaning.
|
||||
</para>
|
||||
<para>
|
||||
Some OpenType features are defined for the purpose of supporting
|
||||
complex-script shaping, and are automatically activated, but
|
||||
only when a buffer's script property is set to a script that the
|
||||
feature supports.
|
||||
</para>
|
||||
<para>
|
||||
Other features are more generic and can apply to several (or
|
||||
any) script, and shaping engines are expected to implement
|
||||
them. By default, HarfBuzz activates several of these features
|
||||
on every text run. They include <literal>ccmp</literal>,
|
||||
<literal>locl</literal>, <literal>mark</literal>,
|
||||
<literal>mkmk</literal>, and <literal>rlig</literal>.
|
||||
</para>
|
||||
<para>
|
||||
In addition, if the text direction is horizontal, HarfBuzz
|
||||
also applies the <literal>calt</literal>,
|
||||
<literal>clig</literal>, <literal>curs</literal>,
|
||||
<literal>kern</literal>, <literal>liga</literal>,
|
||||
<literal>rclt</literal>, and <literal>frac</literal> features.
|
||||
</para>
|
||||
<para>
|
||||
If the text direction is vertical, HarfBuzz applies
|
||||
the <literal>vert</literal> feature by default.
|
||||
</para>
|
||||
<para>
|
||||
Still other features are designed to be purely optional and left
|
||||
up to the application or the end user to enable or disable as desired.
|
||||
</para>
|
||||
<para>
|
||||
You can adjust the set of features that HarfBuzz applies to a
|
||||
buffer by supplying an array of <type>hb_feature_t</type>
|
||||
features as the third argument to
|
||||
<function>hb_shape()</function>. For a simple case, let's just
|
||||
enable the <literal>dlig</literal> feature, which turns on any
|
||||
"discretionary" ligatures in the font:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_feature_t userfeatures[1];
|
||||
userfeatures[0].tag = HB_TAG('d','l','i','g');
|
||||
userfeatures[0].value = 1;
|
||||
userfeatures[0].start = HB_FEATURE_GLOBAL_START;
|
||||
userfeatures[0].end = HB_FEATURE_GLOBAL_END;
|
||||
</programlisting>
|
||||
<para>
|
||||
<literal>HB_FEATURE_GLOBAL_END</literal> and
|
||||
<literal>HB_FEATURE_GLOBAL_END</literal> are macros we can use
|
||||
to indicate that the features will be applied to the entire
|
||||
buffer. We could also have used a literal <literal>0</literal>
|
||||
for the start and a <literal>-1</literal> to indicate the end of
|
||||
the buffer (or have selected other start and end positions, if needed).
|
||||
</para>
|
||||
<para>
|
||||
When we pass the <varname>userfeatures</varname> array to
|
||||
<function>hb_shape()</function>, any discretionary ligature
|
||||
substitutions from our font that match the text in our buffer
|
||||
will get performed:
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
hb_shape(font, buf, userfeatures, num_features);
|
||||
</programlisting>
|
||||
<para>
|
||||
Just like we enabled the <literal>dlig</literal> feature by
|
||||
setting its <parameter>value</parameter> to
|
||||
<literal>1</literal>, you would disable a feature by setting its
|
||||
<parameter>value</parameter> to <literal>0</literal>. Some
|
||||
features can take other <parameter>value</parameter> settings;
|
||||
be sure you read the full specification of each feature tag to
|
||||
understand what it does and how to control it.
|
||||
</para>
|
||||
</section>
|
||||
<section id="plans-and-caching">
|
||||
|
||||
<section id="shaping-shaper-selection">
|
||||
<title>Shaper selection</title>
|
||||
<para>
|
||||
The basic version of <function>hb_shape()</function> determines
|
||||
its shaping strategy based on examining the capabilities of the
|
||||
font file. OpenType font tables cause HarfBuzz to try the
|
||||
<literal>ot</literal> shaper, while AAT font tables cause HarfBuzz to try the
|
||||
<literal>aat</literal> shaper.
|
||||
</para>
|
||||
<para>
|
||||
In the real world, however, a font might include some unusual
|
||||
mix of tables, or one of the tables might simply be broken for
|
||||
the script you need to shape. So, sometimes, you might not
|
||||
want to rely on HarfBuzz's process for deciding what to do, and
|
||||
just tell <function>hb_shape()</function> what you want it to try.
|
||||
</para>
|
||||
<para>
|
||||
<function>hb_shape_full()</function> is an alternate shaping
|
||||
function that lets you supply a list of shapers for HarfBuzz to
|
||||
try, in order, when shaping your buffer. For example, if you
|
||||
have determined that HarfBuzz's attempts to work around broken
|
||||
tables gives you better results than the AAT shaper itself does,
|
||||
you might move the AAT shaper to the end of your list of
|
||||
preferences and call <function>hb_shape_full()</function>
|
||||
</para>
|
||||
<programlisting language="C">
|
||||
char *shaperprefs[3] = {"ot", "default", "aat"};
|
||||
...
|
||||
hb_shape_full(font, buf, userfeatures, num_features, shaperprefs);
|
||||
</programlisting>
|
||||
<para>
|
||||
to get results you are happier with.
|
||||
</para>
|
||||
<para>
|
||||
You may also want to call
|
||||
<function>hb_shape_list_shapers()</function> to get a list of
|
||||
the shapers that were built at compile time in your copy of HarfBuzz.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="shaping-plans-and-caching">
|
||||
<title>Plans and caching</title>
|
||||
<para>
|
||||
Internally, HarfBuzz uses a structure called a shape plan to
|
||||
track its decisions about how to shape the contents of a
|
||||
buffer. The <function>hb_shape()</function> function builds up the shape plan by
|
||||
examining segment properties and by inspecting the contents of
|
||||
the font.
|
||||
</para>
|
||||
<para>
|
||||
This process can involve some decision-making and
|
||||
trade-offs — for example, HarfBuzz inspects the GSUB and GPOS
|
||||
lookups for the script and language tags set on the segment
|
||||
properties, but it falls back on the lookups under the
|
||||
<literal>DFLT</literal> tag (and sometimes other common tags)
|
||||
if there are actually no lookups for the tag requested.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz also includes some work-arounds for
|
||||
handling well-known older font conventions that do not follow
|
||||
OpenType or Unicode specifications, for buggy system fonts, and for
|
||||
peculiarities of Microsoft Uniscribe. All of that means that a
|
||||
shape plan, while not something that you should edit directly in
|
||||
client code, still might be an object that you want to
|
||||
inspect. Furthermore, if resources are tight, you might want to
|
||||
cache the shape plan that HarfBuzz builds for your buffer and
|
||||
font, so that you do not have to rebuild it for every shaping call.
|
||||
</para>
|
||||
<para>
|
||||
You can create a cacheable shape plan with
|
||||
<function>hb_shape_plan_create_cached(face, props,
|
||||
user_features, num_user_features, shaper_list)</function>, where
|
||||
<parameter>face</parameter> is a face object (not a font object,
|
||||
notably), <parameter>props</parameter> is an
|
||||
<type>hb_segment_properties_t</type>,
|
||||
<parameter>user_features</parameter> is an array of
|
||||
<type>hb_feature_t</type>s (with length
|
||||
<parameter>num_user_features</parameter>), and
|
||||
<parameter>shaper_list</parameter> is a list of shapers to try.
|
||||
</para>
|
||||
<para>
|
||||
Shape plans are objects in HarfBuzz, so there are
|
||||
reference-counting functions and user-data attachment functions
|
||||
you can
|
||||
use. <function>hb_shape_plan_reference(shape_plan)</function>
|
||||
increases the reference count on a shape plan, while
|
||||
<function>hb_shape_plan_destroy(shape_plan)</function> decreases
|
||||
the reference count, destroying the shape plan when the last
|
||||
reference is dropped.
|
||||
</para>
|
||||
<para>
|
||||
You can attach user data to a shaper (with a key) using the
|
||||
<function>hb_shape_plan_set_user_data(shape_plan,key,data,destroy,replace)</function>
|
||||
function, optionally supplying a <function>destroy</function>
|
||||
callback to use. You can then fetch the user data attached to a
|
||||
shape plan with
|
||||
<function>hb_shape_plan_get_user_data(shape_plan, key)</function>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
|
|
244
docs/usermanual-utilities.xml
Normal file
244
docs/usermanual-utilities.xml
Normal file
|
@ -0,0 +1,244 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
|
||||
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
|
||||
<!ENTITY version SYSTEM "version.xml">
|
||||
]>
|
||||
<chapter id="utilities">
|
||||
<title>Utilities</title>
|
||||
<para>
|
||||
HarfBuzz includes several auxiliary components in addition to the
|
||||
main APIs. These include a set of command-line tools, a set of
|
||||
lower-level APIs for common data types that may be of interest to
|
||||
client programs, and an embedded library for working with
|
||||
Unicode Character Database (UCD) data.
|
||||
</para>
|
||||
|
||||
<section id="utilities-command-line-tools">
|
||||
<title>Command-line tools</title>
|
||||
<para>
|
||||
HarfBuzz include three command-line tools:
|
||||
<program>hb-shape</program>, <program>hb-view</program>, and
|
||||
<program>hb-subset</program>. They can be used to examine
|
||||
HarfBuzz's functionality, debug font binaries, or explore the
|
||||
various shaping models and features from a terminal.
|
||||
</para>
|
||||
|
||||
<section id="utilities-command-line-hbshape">
|
||||
<title>hb-shape</title>
|
||||
<para>
|
||||
<emphasis><program>hb-shape</program></emphasis> allows you to run HarfBuzz's
|
||||
<function>hb_shape()</function> function on an input string and
|
||||
to examine the outcome, in human-readable form, as terminal
|
||||
output. <program>hb-shape</program> does
|
||||
<emphasis>not</emphasis> render the results of the shaping call
|
||||
into rendered text (you can use <program>hb-view</program>, below, for
|
||||
that). Instead, it prints out the final glyph indices and
|
||||
positions, taking all shaping operations into account, as if the
|
||||
input string were a HarfBuzz input buffer.
|
||||
</para>
|
||||
<para>
|
||||
You can specify the font to be used for shaping and, with
|
||||
command-line options, you can add various aspects of the
|
||||
internal state to the output that is sent to the terminal. The
|
||||
general format is
|
||||
</para>
|
||||
<programlisting>
|
||||
<command>hb-shape</command> <optional>[OPTIONS]</optional>
|
||||
<parameter>path/to/font/file.ttf</parameter>
|
||||
<parameter>yourinputtext</parameter>
|
||||
</programlisting>
|
||||
<para>
|
||||
The default output format is plain text (although JSON output
|
||||
can be selected instead by specifying the option
|
||||
<optional>--output-format=json</optional>). The default output
|
||||
syntax reports each glyph name (or glyph index if there is no
|
||||
name) followed by its cluster value, its horizontal and vertical
|
||||
position displacement, and its horizontal and vertical advances.
|
||||
</para>
|
||||
<para>
|
||||
Output options exist to skip any of these elements in the
|
||||
output, and to include additional data, such as Unicode
|
||||
code-point values, glyph extents, glyph flags, or interim
|
||||
shaping results.
|
||||
</para>
|
||||
<para>
|
||||
Output can also be redirected to a file, or input read from a
|
||||
file. Additional options enable you to enable or disable
|
||||
specific font features, to set variation-font axis values, to
|
||||
alter the language, script, direction, and clustering settings
|
||||
used, to enable sanity checks, or to change which shaping engine is used.
|
||||
</para>
|
||||
<para>
|
||||
For a complete explanation of the options available, run
|
||||
</para>
|
||||
<programlisting>
|
||||
<command>hb-shape</command> <parameter>--help</parameter>
|
||||
</programlisting>
|
||||
</section>
|
||||
|
||||
<section id="utilities-command-line-hbview">
|
||||
<title>hb-view</title>
|
||||
<para>
|
||||
<emphasis><program>hb-view</program></emphasis> allows you to
|
||||
see the shaped output of an input string in rendered
|
||||
form. Like <program>hb-shape</program>,
|
||||
<program>hb-view</program> takes a font file and a text string
|
||||
as its arguments:
|
||||
</para>
|
||||
<programlisting>
|
||||
<command>hb-view</command> <optional>[OPTIONS]</optional>
|
||||
<parameter>path/to/font/file.ttf</parameter>
|
||||
<parameter>yourinputtext</parameter>
|
||||
</programlisting>
|
||||
<para>
|
||||
By default, <program>hb-view</program> renders the shaped
|
||||
text in ASCII block-character images as terminal output. By
|
||||
appending the
|
||||
<command>--output-file=<optional>filename</optional></command>
|
||||
switch, you can write the output to a PNG, SVG, or PDF file
|
||||
(among other formats).
|
||||
</para>
|
||||
<para>
|
||||
As with <program>hb-shape</program>, a lengthy set of options
|
||||
is available, with which you can enable or disable
|
||||
specific font features, set variation-font axis values,
|
||||
alter the language, script, direction, and clustering settings
|
||||
used, enable sanity checks, or change which shaping engine is
|
||||
used.
|
||||
</para>
|
||||
<para>
|
||||
You can also set the foreground and background colors used for
|
||||
the output, independently control the width of all four
|
||||
margins, alter the line spacing, and annotate the output image
|
||||
with
|
||||
</para>
|
||||
<para>
|
||||
In general, <program>hb-view</program> is a quick way to
|
||||
verify that the output of HarfBuzz's shaping operation looks
|
||||
correct for a given text-and-font combination, but you may
|
||||
want to use <program>hb-shape</program> to figure out exactly
|
||||
why something does not appear as expected.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="utilities-command-line-hbsubset">
|
||||
<title>hb-subset</title>
|
||||
<para>
|
||||
<emphasis><program>hb-subset</program></emphasis> allows you
|
||||
to generate a subset of a given font, with a limited set of
|
||||
supported characters, features, and variation settings.
|
||||
</para>
|
||||
<para>
|
||||
By default, you provide an input font and an input text string
|
||||
as the arguments to <program>hb-subset</program>, and it will
|
||||
generate a font that covers the input text exactly like the
|
||||
input font does, but includes no other characters or features.
|
||||
</para>
|
||||
<programlisting>
|
||||
<command>hb-subset</command> <optional>[OPTIONS]</optional>
|
||||
<parameter>path/to/font/file.ttf</parameter>
|
||||
<parameter>yourinputtext</parameter>
|
||||
</programlisting>
|
||||
<para>
|
||||
For example, to create a subset of Noto Serif that just includes the
|
||||
numerals and the lowercase Latin alphabet, you could run
|
||||
</para>
|
||||
<programlisting>
|
||||
<command>hb-subset</command> <optional>[OPTIONS]</optional>
|
||||
<parameter>NotoSerif-Regular.ttf</parameter>
|
||||
<parameter>0123456789abcdefghijklmnopqrstuvwxyz</parameter>
|
||||
</programlisting>
|
||||
<para>
|
||||
There are options available to remove hinting from the
|
||||
subsetted font and to specify a list of variation-axis settings.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="utilities-common-types-apis">
|
||||
<title>Common data types and APIs</title>
|
||||
<para>
|
||||
HarfBuzz includes several APIs for working with general-purpose
|
||||
data that you may find convenient to leverage in your own
|
||||
software. They include set operations and integer-to-integer
|
||||
mapping operations.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz uses set operations for internal bookkeeping, such as
|
||||
when it collects all of the glyph IDs covered by a particular
|
||||
font feature. You can also use the set API to build sets, add
|
||||
and remove elements, test whether or not sets contain particular
|
||||
elements, or compute the unions, intersections, or differences
|
||||
between sets.
|
||||
</para>
|
||||
<para>
|
||||
All set elements are integers (specifically,
|
||||
<type>hb_codepoint_t</type> 32-bit unsigned ints), and there are
|
||||
functions for fetching the minimum and maximum element from a
|
||||
set. The set API also includes some functions that might not
|
||||
be part of a generic set facility, such as the ability to add a
|
||||
contiguous range of integer elements to a set in bulk, and the
|
||||
ability to fetch the next-smallest or next-largest element.
|
||||
</para>
|
||||
<para>
|
||||
The HarfBuzz set API includes some conveniences as well. All
|
||||
sets are lifecycle-managed, just like other HarfBuzz
|
||||
objects. You increase the reference count on a set with
|
||||
<function>hb_set_reference()</function> and decrease it with
|
||||
<function>hb_set_destroy()</function>. You can also attach
|
||||
user data to a set, just like you can to blobs, buffers, faces,
|
||||
fonts, and other objects, and set destroy callbacks.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz also provides an API for keeping track of
|
||||
integer-to-integer mappings. As with the set API, each integer is
|
||||
stored as an unsigned 32-bit <type>hb_codepoint_t</type>
|
||||
element. Maps, like other objects, are reference counted with
|
||||
reference and destroy functions, and you can attach user data to
|
||||
them. The mapping operations include adding and deleting
|
||||
integer-to-integer key:value pairs to the map, testing for the
|
||||
presence of a key, fetching the population of the map, and so on.
|
||||
</para>
|
||||
<para>
|
||||
There are several other internal HarfBuzz facilities that are
|
||||
exposed publicly and which you may want to take advantage of
|
||||
while processing text. HarfBuzz uses a common
|
||||
<type>hb_tag_t</type> for a variety of OpenType tag identifiers (for
|
||||
scripts, languages, font features, table names, variation-axis
|
||||
names, and more), and provides functions for converting strings
|
||||
to tags and vice-versa.
|
||||
</para>
|
||||
<para>
|
||||
Finally, HarfBuzz also includes data type for Booleans, bit
|
||||
masks, and other simple types.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="utilities-ucdn">
|
||||
<title>UCDN</title>
|
||||
<para>
|
||||
HarfBuzz includes a copy of the <ulink
|
||||
url="https://github.com/grigorig/ucdn">UCDN</ulink> (Unicode
|
||||
Database and Normalization) library, which provides functions
|
||||
for accessing basic Unicode character properties, performing
|
||||
canonical composition, and performing both canonical and
|
||||
compatibility decomposition.
|
||||
</para>
|
||||
<para>
|
||||
Currently, UCDN supports direct queries for several more character
|
||||
properties than HarfBuzz's built-in set of Unicode functions
|
||||
does, such as the BiDirectional Class, East Asian Width, Paired
|
||||
Bracket and Resolved Linebreak properties. If you need to access
|
||||
more properties than HarfBuzz's internal implementation
|
||||
provides, using the built-in UCDN functions may be a useful solution.
|
||||
</para>
|
||||
<para>
|
||||
The built-in UCDN functions are compiled by default when
|
||||
building HarfBuzz from source, but this can be disabled with a
|
||||
compile-time switch.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
|
@ -151,9 +151,9 @@
|
|||
</para>
|
||||
<para>
|
||||
For example, in Tamil, when the letter "TTA" (ட)
|
||||
letter is followed by "U" (உ), the pair
|
||||
letter is followed by the vowel sign "U" (ு), the pair
|
||||
must be replaced by the single glyph "டு". The
|
||||
sequence of Unicode characters "டஉ" needs to be
|
||||
sequence of Unicode characters "ட,ு" needs to be
|
||||
substituted with a single "டு" glyph from the
|
||||
font.
|
||||
</para>
|
||||
|
|
28
mingw-configure.sh
Executable file
28
mingw-configure.sh
Executable file
|
@ -0,0 +1,28 @@
|
|||
#!/bin/sh
|
||||
|
||||
case $1 in
|
||||
i686 | x86_64) ;;
|
||||
*) echo "Usage: $0 i686|x86_64" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
target=$1-w64-mingw32
|
||||
shift
|
||||
|
||||
exec "$(dirname "$0")"/configure \
|
||||
--build=`../config.guess` \
|
||||
--host=$target \
|
||||
--prefix=$HOME/.local/$target \
|
||||
CC= \
|
||||
CXX= \
|
||||
CPP= \
|
||||
LD= \
|
||||
CFLAGS="-static-libgcc" \
|
||||
CXXFLAGS="-static-libgcc -static-libstdc++" \
|
||||
CPPFLAGS="-I$HOME/.local/$target/include" \
|
||||
LDFLAGS=-L$HOME/.local/$target/lib \
|
||||
PKG_CONFIG_LIBDIR=$HOME/.local/$target/lib/pkgconfig:/usr/$target/sys-root/mingw/lib/pkgconfig/ \
|
||||
PKG_CONFIG_PATH=$HOME/.local/$target/share/pkgconfig:/usr/$target/sys-root/mingw/share/pkgconfig/ \
|
||||
PATH=$HOME/.local/$target/bin:/usr/$target/sys-root/mingw/bin:/usr/$target/bin:$PATH \
|
||||
--without-icu \
|
||||
--with-uniscribe \
|
||||
"$@"
|
58
mingw-ldd.py
Executable file
58
mingw-ldd.py
Executable file
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Copied from https://github.com/xantares/mingw-ldd/blob/master/mingw-ldd.py
|
||||
# Modified to point to right prefix location on Fedora.
|
||||
|
||||
# WTFPL - Do What the Fuck You Want to Public License
|
||||
from __future__ import print_function
|
||||
import pefile
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def get_dependency(filename):
|
||||
deps = []
|
||||
pe = pefile.PE(filename)
|
||||
for imp in pe.DIRECTORY_ENTRY_IMPORT:
|
||||
deps.append(imp.dll.decode())
|
||||
return deps
|
||||
|
||||
|
||||
def dep_tree(root, prefix=None):
|
||||
if not prefix:
|
||||
arch = get_arch(root)
|
||||
#print('Arch =', arch)
|
||||
prefix = '/usr/'+arch+'-w64-mingw32/sys-root/mingw/bin'
|
||||
#print('Using default prefix', prefix)
|
||||
dep_dlls = dict()
|
||||
|
||||
def dep_tree_impl(root, prefix):
|
||||
for dll in get_dependency(root):
|
||||
if dll in dep_dlls:
|
||||
continue
|
||||
full_path = os.path.join(prefix, dll)
|
||||
if os.path.exists(full_path):
|
||||
dep_dlls[dll] = full_path
|
||||
dep_tree_impl(full_path, prefix=prefix)
|
||||
else:
|
||||
dep_dlls[dll] = 'not found'
|
||||
|
||||
dep_tree_impl(root, prefix)
|
||||
return (dep_dlls)
|
||||
|
||||
|
||||
def get_arch(filename):
|
||||
type2arch= {pefile.OPTIONAL_HEADER_MAGIC_PE: 'i686',
|
||||
pefile.OPTIONAL_HEADER_MAGIC_PE_PLUS: 'x86_64'}
|
||||
pe = pefile.PE(filename)
|
||||
try:
|
||||
return type2arch[pe.PE_TYPE]
|
||||
except KeyError:
|
||||
sys.stderr.write('Error: unknown architecture')
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
filename = sys.argv[1]
|
||||
for dll, full_path in dep_tree(filename).items():
|
||||
print(' ' * 7, dll, '=>', full_path)
|
||||
|
24
mingw32.sh
24
mingw32.sh
|
@ -1,22 +1,2 @@
|
|||
#!/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 "$@"
|
||||
#!/bin/sh
|
||||
exec "$(dirname "$0")"/mingw-configure.sh i686 "$@"
|
||||
|
|
24
mingw64.sh
24
mingw64.sh
|
@ -1,22 +1,2 @@
|
|||
#!/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 "$@"
|
||||
#!/bin/sh
|
||||
exec "$(dirname "$0")"/mingw-configure.sh x86_64 "$@"
|
||||
|
|
112
src/Makefile.am
112
src/Makefile.am
|
@ -12,9 +12,15 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
|
|||
TESTS =
|
||||
check_PROGRAMS =
|
||||
|
||||
EXTRA_DIST += harfbuzz.cc
|
||||
|
||||
# Convenience targets:
|
||||
lib: $(BUILT_SOURCES) libharfbuzz.la
|
||||
libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES)
|
||||
tiny:
|
||||
$(MAKE) $(AM_MAKEFLAGS) CPPFLAGS="-Os -DHB_TINY $(CPPFLAGS)" libs
|
||||
tinyz:
|
||||
$(MAKE) $(AM_MAKEFLAGS) CPPFLAGS="-Oz -DHB_TINY $(CPPFLAGS)" libs
|
||||
|
||||
lib_LTLIBRARIES = libharfbuzz.la
|
||||
|
||||
|
@ -28,10 +34,6 @@ HBSOURCES = $(HB_BASE_sources)
|
|||
HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
|
||||
HBHEADERS = $(HB_BASE_headers)
|
||||
|
||||
if HAVE_FALLBACK
|
||||
HBSOURCES += $(HB_FALLBACK_sources)
|
||||
endif
|
||||
|
||||
if HAVE_PTHREAD
|
||||
HBCFLAGS += $(PTHREAD_CFLAGS)
|
||||
HBNONPCLIBS += $(PTHREAD_LIBS)
|
||||
|
@ -80,6 +82,13 @@ HBSOURCES += $(HB_DIRECTWRITE_sources)
|
|||
HBHEADERS += $(HB_DIRECTWRITE_headers)
|
||||
endif
|
||||
|
||||
if HAVE_GDI
|
||||
HBCFLAGS += $(GDI_CXXFLAGS)
|
||||
HBNONPCLIBS += $(GDI_LIBS)
|
||||
HBSOURCES += $(HB_GDI_sources)
|
||||
HBHEADERS += $(HB_GDI_headers)
|
||||
endif
|
||||
|
||||
if HAVE_CORETEXT
|
||||
HBCFLAGS += $(CORETEXT_CFLAGS)
|
||||
HBNONPCLIBS += $(CORETEXT_LIBS)
|
||||
|
@ -87,17 +96,6 @@ HBSOURCES += $(HB_CORETEXT_sources)
|
|||
HBHEADERS += $(HB_CORETEXT_headers)
|
||||
endif
|
||||
|
||||
if HAVE_UCDN
|
||||
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
|
||||
|
||||
|
||||
BUILT_SOURCES += \
|
||||
hb-version.h
|
||||
|
@ -258,36 +256,44 @@ GENERATORS = \
|
|||
gen-indic-table.py \
|
||||
gen-os2-unicode-ranges.py \
|
||||
gen-tag-table.py \
|
||||
gen-ucd-table.py \
|
||||
gen-use-table.py \
|
||||
gen-vowel-constraints.py \
|
||||
$(NULL)
|
||||
EXTRA_DIST += $(GENERATORS)
|
||||
|
||||
unicode-tables: arabic-table indic-table tag-table use-table emoji-table
|
||||
unicode-tables: \
|
||||
arabic-table \
|
||||
emoji-table \
|
||||
indic-table \
|
||||
tag-table \
|
||||
ucd-table \
|
||||
use-table \
|
||||
emoji-table \
|
||||
$(NULL)
|
||||
|
||||
arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-arabic-table.hh \
|
||||
|| ($(RM) $(srcdir)/hb-ot-shape-complex-arabic-table.hh; false)
|
||||
|
||||
emoji-table: gen-emoji-table.py emoji-data.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \
|
||||
|| ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false)
|
||||
indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-indic-table.cc \
|
||||
|| ($(RM) $(srcdir)/hb-ot-shape-complex-indic-table.cc; false)
|
||||
|
||||
tag-table: gen-tag-table.py languagetags language-subtag-registry
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-tag-table.hh \
|
||||
|| ($(RM) $(srcdir)/hb-ot-tag-table.hh; false)
|
||||
|
||||
ucd-table: gen-ucd-table.py ucd.nounihan.grouped.zip hb-common.h
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ucd-table.hh \
|
||||
|| ($(RM) $(srcdir)/hb-ucd-table.hh; false)
|
||||
use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-use-table.cc \
|
||||
|| ($(RM) $(srcdir)/hb-ot-shape-complex-use-table.cc; false)
|
||||
|
||||
vowel-constraints: gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc \
|
||||
|| ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc; false)
|
||||
|
||||
emoji-table: gen-emoji-table.py emoji-data.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \
|
||||
|| ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false)
|
||||
|
||||
built-sources: $(BUILT_SOURCES)
|
||||
|
||||
|
@ -306,13 +312,30 @@ $(srcdir)/%.hh: $(srcdir)/%.rl
|
|||
$(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \
|
||||
|| ($(RM) "$@"; false)
|
||||
|
||||
harfbuzz.cc: Makefile.sources
|
||||
$(AM_V_GEN) \
|
||||
for f in \
|
||||
$(HB_BASE_sources) \
|
||||
$(HB_GLIB_sources) \
|
||||
$(HB_FT_sources) \
|
||||
$(HB_GRAPHITE2_sources) \
|
||||
$(HB_UNISCRIBE_sources) \
|
||||
$(HB_GDI_sources) \
|
||||
$(HB_DIRECTWRITE_sources) \
|
||||
$(HB_CORETEXT_sources) \
|
||||
; do echo '#include "'$$f'"'; done | \
|
||||
grep '[.]cc"' > $(srcdir)/harfbuzz.cc \
|
||||
|| ($(RM) $(srcdir)/harfbuzz.cc; false)
|
||||
BUILT_SOURCES += harfbuzz.cc
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
main \
|
||||
test \
|
||||
test-buffer-serialize \
|
||||
test-name-table \
|
||||
test-size-params \
|
||||
test-would-substitute \
|
||||
test-ot-meta \
|
||||
test-ot-name \
|
||||
test-gpos-size-params \
|
||||
test-gsub-would-substitute \
|
||||
$(NULL)
|
||||
bin_PROGRAMS =
|
||||
|
||||
|
@ -328,17 +351,21 @@ test_buffer_serialize_SOURCES = test-buffer-serialize.cc
|
|||
test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
|
||||
test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_name_table_SOURCES = test-name-table.cc
|
||||
test_name_table_CPPFLAGS = $(HBCFLAGS)
|
||||
test_name_table_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
test_ot_meta_SOURCES = test-ot-meta.cc
|
||||
test_ot_meta_CPPFLAGS = $(HBCFLAGS)
|
||||
test_ot_meta_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_size_params_SOURCES = test-size-params.cc
|
||||
test_size_params_CPPFLAGS = $(HBCFLAGS)
|
||||
test_size_params_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
test_ot_name_SOURCES = test-ot-name.cc
|
||||
test_ot_name_CPPFLAGS = $(HBCFLAGS)
|
||||
test_ot_name_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_would_substitute_SOURCES = test-would-substitute.cc
|
||||
test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
|
||||
test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
||||
test_gpos_size_params_SOURCES = test-gpos-size-params.cc
|
||||
test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
|
||||
test_gpos_size_params_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc
|
||||
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
|
||||
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
||||
|
||||
if HAVE_FREETYPE
|
||||
if HAVE_CAIRO_FT
|
||||
|
@ -384,16 +411,24 @@ 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)
|
||||
|
||||
COMPILED_TESTS = test-iter test-ot-tag test-unicode-ranges
|
||||
COMPILED_TESTS = test-algs test-iter test-meta test-ot-tag test-unicode-ranges test-bimap
|
||||
COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
|
||||
COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
check_PROGRAMS += $(COMPILED_TESTS)
|
||||
TESTS += $(COMPILED_TESTS)
|
||||
|
||||
test_algs_SOURCES = test-algs.cc hb-static.cc
|
||||
test_algs_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_algs_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
||||
test_iter_SOURCES = test-iter.cc hb-static.cc
|
||||
test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_iter_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
||||
test_meta_SOURCES = test-meta.cc hb-static.cc
|
||||
test_meta_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_meta_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
||||
test_ot_tag_SOURCES = hb-ot-tag.cc
|
||||
test_ot_tag_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_ot_tag_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
@ -402,6 +437,10 @@ test_unicode_ranges_SOURCES = test-unicode-ranges.cc
|
|||
test_unicode_ranges_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_unicode_ranges_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
||||
test_bimap_SOURCES = test-bimap.cc hb-static.cc
|
||||
test_bimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_bimap_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
||||
TESTS_ENVIRONMENT = \
|
||||
srcdir="$(srcdir)" \
|
||||
MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
|
||||
|
@ -430,6 +469,7 @@ HarfBuzz_0_0_gir_CFLAGS = \
|
|||
-DHB_AAT_H_IN \
|
||||
-DHB_GOBJECT_H \
|
||||
-DHB_GOBJECT_H_IN \
|
||||
-DHAVE_GOBJECT \
|
||||
-DHB_EXTERN= \
|
||||
$(NULL)
|
||||
HarfBuzz_0_0_gir_LIBS = \
|
||||
|
|
|
@ -10,12 +10,14 @@ HB_BASE_sources = \
|
|||
hb-aat-layout-kerx-table.hh \
|
||||
hb-aat-layout-lcar-table.hh \
|
||||
hb-aat-layout-morx-table.hh \
|
||||
hb-aat-layout-opbd-table.hh \
|
||||
hb-aat-layout-trak-table.hh \
|
||||
hb-aat-layout.cc \
|
||||
hb-aat-layout.hh \
|
||||
hb-aat-ltag-table.hh \
|
||||
hb-aat-map.cc \
|
||||
hb-aat-map.hh \
|
||||
hb-algs.hh \
|
||||
hb-array.hh \
|
||||
hb-atomic.hh \
|
||||
hb-blob.cc \
|
||||
|
@ -30,10 +32,12 @@ HB_BASE_sources = \
|
|||
hb-cff1-interp-cs.hh \
|
||||
hb-cff2-interp-cs.hh \
|
||||
hb-common.cc \
|
||||
hb-config.hh \
|
||||
hb-debug.hh \
|
||||
hb-dsalgs.hh \
|
||||
hb-dispatch.hh \
|
||||
hb-face.cc \
|
||||
hb-face.hh \
|
||||
hb-fallback-shape.cc \
|
||||
hb-font.cc \
|
||||
hb-font.hh \
|
||||
hb-iter.hh \
|
||||
|
@ -41,6 +45,8 @@ HB_BASE_sources = \
|
|||
hb-machinery.hh \
|
||||
hb-map.cc \
|
||||
hb-map.hh \
|
||||
hb-bimap.hh \
|
||||
hb-meta.hh \
|
||||
hb-mutex.hh \
|
||||
hb-null.hh \
|
||||
hb-object.hh \
|
||||
|
@ -60,6 +66,7 @@ HB_BASE_sources = \
|
|||
hb-ot-color.cc \
|
||||
hb-ot-face.cc \
|
||||
hb-ot-face.hh \
|
||||
hb-ot-face-table-list.hh \
|
||||
hb-ot-font.cc \
|
||||
hb-ot-gasp-table.hh \
|
||||
hb-ot-glyf-table.hh \
|
||||
|
@ -82,7 +89,11 @@ HB_BASE_sources = \
|
|||
hb-ot-math-table.hh \
|
||||
hb-ot-math.cc \
|
||||
hb-ot-maxp-table.hh \
|
||||
hb-ot-name-language.cc \
|
||||
hb-ot-meta-table.hh \
|
||||
hb-ot-meta.cc \
|
||||
hb-ot-metrics.cc \
|
||||
hb-ot-metrics.hh \
|
||||
hb-ot-name-language-static.hh \
|
||||
hb-ot-name-language.hh \
|
||||
hb-ot-name-table.hh \
|
||||
hb-ot-name.cc \
|
||||
|
@ -127,6 +138,9 @@ HB_BASE_sources = \
|
|||
hb-ot-var-mvar-table.hh \
|
||||
hb-ot-var.cc \
|
||||
hb-ot-vorg-table.hh \
|
||||
hb-pool.hh \
|
||||
hb-sanitize.hh \
|
||||
hb-serialize.hh \
|
||||
hb-set-digest.hh \
|
||||
hb-set.cc \
|
||||
hb-set.hh \
|
||||
|
@ -139,6 +153,8 @@ HB_BASE_sources = \
|
|||
hb-shaper.hh \
|
||||
hb-static.cc \
|
||||
hb-string-array.hh \
|
||||
hb-ucd-table.hh \
|
||||
hb-ucd.cc \
|
||||
hb-unicode-emoji-table.hh \
|
||||
hb-unicode.cc \
|
||||
hb-unicode.hh \
|
||||
|
@ -180,6 +196,8 @@ HB_BASE_headers = \
|
|||
hb-ot-font.h \
|
||||
hb-ot-layout.h \
|
||||
hb-ot-math.h \
|
||||
hb-ot-meta.h \
|
||||
hb-ot-metrics.h \
|
||||
hb-ot-name.h \
|
||||
hb-ot-shape.h \
|
||||
hb-ot-var.h \
|
||||
|
@ -192,10 +210,6 @@ HB_BASE_headers = \
|
|||
hb.h \
|
||||
$(NULL)
|
||||
|
||||
HB_FALLBACK_sources = \
|
||||
hb-fallback-shape.cc \
|
||||
$(NULL)
|
||||
|
||||
# Optional Sources and Headers with external deps
|
||||
|
||||
HB_FT_sources = hb-ft.cc
|
||||
|
@ -215,12 +229,12 @@ HB_CORETEXT_headers = hb-coretext.h
|
|||
HB_DIRECTWRITE_sources = hb-directwrite.cc
|
||||
HB_DIRECTWRITE_headers = hb-directwrite.h
|
||||
|
||||
HB_GDI_sources = hb-gdi.cc
|
||||
HB_GDI_headers = hb-gdi.h
|
||||
|
||||
HB_UNISCRIBE_sources = hb-uniscribe.cc
|
||||
HB_UNISCRIBE_headers = hb-uniscribe.h
|
||||
|
||||
# Additional supplemental sources
|
||||
HB_UCDN_sources = hb-ucdn.cc
|
||||
|
||||
# Sources for libharfbuzz-gobject and libharfbuzz-icu
|
||||
HB_ICU_sources = hb-icu.cc
|
||||
HB_ICU_headers = hb-icu.h
|
||||
|
@ -236,9 +250,6 @@ HB_SUBSET_sources = \
|
|||
hb-subset-cff1.hh \
|
||||
hb-subset-cff2.cc \
|
||||
hb-subset-cff2.hh \
|
||||
hb-subset-glyf.cc \
|
||||
hb-subset-glyf.hh \
|
||||
hb-subset-glyf.hh \
|
||||
hb-subset-input.cc \
|
||||
hb-subset-input.hh \
|
||||
hb-subset-plan.cc \
|
||||
|
|
|
@ -7,7 +7,7 @@ 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_.*'
|
||||
IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_.*\|llvm_.*'
|
||||
|
||||
if which nm 2>/dev/null >/dev/null; then
|
||||
:
|
||||
|
@ -26,7 +26,7 @@ for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do
|
|||
symprefix=
|
||||
if test $suffix = dylib; then symprefix=_; fi
|
||||
|
||||
EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRST] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`"
|
||||
EXPORTED_SYMBOLS=`nm "$so" | grep ' [BCDGINRST] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`
|
||||
|
||||
prefix=$symprefix`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'`
|
||||
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Suggested setup to use the script:
|
||||
# (on the root of the project)
|
||||
# $ NOCONFIGURE=1 ./autogen.sh && mkdir build && cd build
|
||||
# $ ../configure --with-freetype --with-glib --with-gobject --with-cairo
|
||||
# $ 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 want to open the result rendering using a GUI app,
|
||||
# $ src/dev-run.sh open [FONT-FILE] [TEXT]
|
||||
#
|
||||
# And if you are using iTerm2, you can use 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 = "open" ] && openimg=1 && shift
|
||||
OPEN=xdg-open
|
||||
[ "$(uname)" == "Darwin" ] && OPEN=open
|
||||
|
||||
|
||||
[ $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=tmp.png
|
||||
[ -f 'build/build.ninja' ] && CMAKENINJA=TRUE
|
||||
# or "fswatch -0 . -e build/ -e .git"
|
||||
find src/ | entr printf '\0' | while read -d ""; do
|
||||
clear
|
||||
yes = | head -n`tput cols` | tr -d '\n'
|
||||
if [[ $CMAKENINJA ]]; then
|
||||
ninja -Cbuild hb-shape hb-view && {
|
||||
build/hb-shape $@
|
||||
if [ $openimg ]; then
|
||||
build/hb-view $@ -O png -o $tmp
|
||||
$OPEN $tmp
|
||||
elif [ $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 [ $openimg ]; then
|
||||
build/util/hb-view $@ -O png -o $tmp
|
||||
$OPEN $tmp
|
||||
elif [ $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
|
|
@ -4,6 +4,7 @@ from __future__ import print_function, division, absolute_import
|
|||
import sys
|
||||
import os.path
|
||||
from collections import OrderedDict
|
||||
import packTab
|
||||
|
||||
if len (sys.argv) != 2:
|
||||
print("usage: ./gen-emoji-table.py emoji-data.txt", file=sys.stderr)
|
||||
|
@ -52,14 +53,19 @@ print ()
|
|||
print ('#include "hb-unicode.hh"')
|
||||
print ()
|
||||
|
||||
for typ,s in ranges.items():
|
||||
for typ, s in ranges.items():
|
||||
if typ != "Extended_Pictographic": continue
|
||||
|
||||
arr = dict()
|
||||
for start,end in s:
|
||||
for i in range(start,end):
|
||||
arr[i] = 1
|
||||
|
||||
sol = packTab.pack_table(arr, 0, compression=3)
|
||||
code = packTab.Code('_hb_emoji')
|
||||
sol.genCode(code, 'is_'+typ)
|
||||
code.print_c(linkage='static inline')
|
||||
print()
|
||||
print("static const struct hb_unicode_range_t _hb_unicode_emoji_%s_table[] =" % typ)
|
||||
print("{")
|
||||
for pair in sorted(s):
|
||||
print(" {0x%04X, 0x%04X}," % pair)
|
||||
print("};")
|
||||
|
||||
print ()
|
||||
print ("#endif /* HB_UNICODE_EMOJI_TABLE_HH */")
|
||||
|
|
|
@ -79,10 +79,6 @@ data = combined
|
|||
del combined
|
||||
num = len (data)
|
||||
|
||||
for u in [0x17CD, 0x17CE, 0x17CF, 0x17D0, 0x17D3]:
|
||||
if data[u][0] == 'Other':
|
||||
data[u][0] = "Vowel_Dependent"
|
||||
|
||||
# Move the outliers NO-BREAK SPACE and DOTTED CIRCLE out
|
||||
singles = {}
|
||||
for u in ALLOWED_SINGLES:
|
||||
|
@ -102,6 +98,10 @@ for h in headers:
|
|||
print (" * %s" % (l.strip()))
|
||||
print (" */")
|
||||
print ()
|
||||
print ('#include "hb.hh"')
|
||||
print ()
|
||||
print ('#ifndef HB_NO_OT_SHAPE')
|
||||
print ()
|
||||
print ('#include "hb-ot-shape-complex-indic.hh"')
|
||||
print ()
|
||||
|
||||
|
@ -131,6 +131,8 @@ for i in range (2):
|
|||
|
||||
what = ["INDIC_SYLLABIC_CATEGORY", "INDIC_MATRA_CATEGORY"]
|
||||
what_short = ["ISC", "IMC"]
|
||||
print ('#pragma GCC diagnostic push')
|
||||
print ('#pragma GCC diagnostic ignored "-Wunused-macros"')
|
||||
for i in range (2):
|
||||
print ()
|
||||
vv = sorted (values[i].keys ())
|
||||
|
@ -148,6 +150,7 @@ for i in range (2):
|
|||
(what_short[i], s, what[i], v.upper (),
|
||||
' '* ((48-1 - len (what[i]) - 1 - len (v)) // 8),
|
||||
values[i][v], v))
|
||||
print ('#pragma GCC diagnostic pop')
|
||||
print ()
|
||||
print ("#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)")
|
||||
print ()
|
||||
|
@ -252,6 +255,8 @@ for i in range (2):
|
|||
print ("#undef %s_%s" %
|
||||
(what_short[i], short[i][v]))
|
||||
print ()
|
||||
print ()
|
||||
print ('#endif')
|
||||
print ("/* == End of generated table == */")
|
||||
|
||||
# Maintain at least 30% occupancy in the table */
|
||||
|
|
4
src/gen-os2-unicode-ranges.py
Normal file → Executable file
4
src/gen-os2-unicode-ranges.py
Normal file → Executable file
|
@ -1,8 +1,10 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# -*- 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).
|
||||
# (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur).
|
||||
|
||||
from __future__ import print_function, division, absolute_import
|
||||
|
||||
|
|
|
@ -895,20 +895,18 @@ def language_name_intersection (a, b):
|
|||
def get_matching_language_name (intersection, candidates):
|
||||
return next (iter (c for c in candidates if not intersection.isdisjoint (get_variant_set (c))))
|
||||
|
||||
maximum_tags = 0
|
||||
def same_tag (bcp_47_tag, ot_tags):
|
||||
return len (bcp_47_tag) == 3 and len (ot_tags) == 1 and bcp_47_tag == ot_tags[0].lower ()
|
||||
|
||||
for language, tags in sorted (ot.from_bcp_47.items ()):
|
||||
if language == '' or '-' in language:
|
||||
continue
|
||||
print (' {\"%s\",\t{' % language, end='')
|
||||
maximum_tags = max (maximum_tags, len (tags))
|
||||
tag_count = len (tags)
|
||||
commented_out = same_tag (language, tags)
|
||||
for i, tag in enumerate (tags, start=1):
|
||||
if i > 1:
|
||||
print ('\t\t ', end='')
|
||||
print (hb_tag (tag), end='')
|
||||
if i == tag_count:
|
||||
print ('}}', end='')
|
||||
print (',\t/* ', end='')
|
||||
print ('%s{\"%s\",\t%s},' % ('/*' if commented_out else ' ', language, hb_tag (tag)), end='')
|
||||
if commented_out:
|
||||
print ('*/', end='')
|
||||
print ('\t/* ', end='')
|
||||
bcp_47_name = bcp_47.names.get (language, '')
|
||||
bcp_47_name_candidates = bcp_47_name.split ('\n')
|
||||
intersection = language_name_intersection (bcp_47_name, ot.names[tag])
|
||||
|
@ -923,8 +921,6 @@ for language, tags in sorted (ot.from_bcp_47.items ()):
|
|||
|
||||
print ('};')
|
||||
print ()
|
||||
print ('static_assert (HB_OT_MAX_TAGS_PER_LANGUAGE == %iu, "");' % maximum_tags)
|
||||
print ()
|
||||
|
||||
print ('/**')
|
||||
print (' * hb_ot_tags_from_complex_language:')
|
||||
|
@ -1051,7 +1047,8 @@ print (' * @tag: A language tag.')
|
|||
print (' *')
|
||||
print (' * Converts @tag to a BCP 47 language tag if it is ambiguous (it corresponds to')
|
||||
print (' * many language tags) and the best tag is not the alphabetically first, or if')
|
||||
print (' * the best tag consists of multiple subtags.')
|
||||
print (' * the best tag consists of multiple subtags, or if the best tag does not appear')
|
||||
print (' * in #ot_languages.')
|
||||
print (' *')
|
||||
print (' * Return value: The #hb_language_t corresponding to the BCP 47 language tag,')
|
||||
print (' * or #HB_LANGUAGE_INVALID if @tag is not ambiguous.')
|
||||
|
@ -1102,7 +1099,8 @@ def verify_disambiguation_dict ():
|
|||
'%s is not a valid disambiguation for %s' % (disambiguation[ot_tag], ot_tag))
|
||||
elif ot_tag not in disambiguation:
|
||||
disambiguation[ot_tag] = macrolanguages[0]
|
||||
if disambiguation[ot_tag] == sorted (primary_tags)[0] and '-' not in disambiguation[ot_tag]:
|
||||
different_primary_tags = sorted (t for t in primary_tags if not same_tag (t, ot.from_bcp_47.get (t)))
|
||||
if different_primary_tags and disambiguation[ot_tag] == different_primary_tags[0] and '-' not in disambiguation[ot_tag]:
|
||||
del disambiguation[ot_tag]
|
||||
for ot_tag in disambiguation.keys ():
|
||||
expect (ot_tag in ot.to_bcp_47, 'unknown OT tag: %s' % ot_tag)
|
||||
|
|
164
src/gen-ucd-table.py
Executable file
164
src/gen-ucd-table.py
Executable file
|
@ -0,0 +1,164 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function, division, absolute_import
|
||||
|
||||
import io, os.path, sys, re
|
||||
import logging
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
|
||||
|
||||
if len (sys.argv) not in (2, 3):
|
||||
print("usage: ./gen-ucd-table ucd.nounihan.grouped.xml [/path/to/hb-common.h]", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# https://github.com/harfbuzz/packtab
|
||||
import packTab
|
||||
import packTab.ucdxml
|
||||
|
||||
logging.info('Loading UCDXML...')
|
||||
ucdxml = packTab.ucdxml.load_ucdxml(sys.argv[1])
|
||||
ucd = packTab.ucdxml.ucdxml_get_repertoire(ucdxml)
|
||||
|
||||
hb_common_h = 'hb-common.h' if len (sys.argv) < 3 else sys.argv[2]
|
||||
|
||||
logging.info('Preparing data tables...')
|
||||
|
||||
gc = [u['gc'] for u in ucd]
|
||||
ccc = [int(u['ccc']) for u in ucd]
|
||||
bmg = [int(v, 16) - int(u) if v else 0 for u,v in enumerate(u['bmg'] for u in ucd)]
|
||||
#gc_ccc_non0 = set((cat,klass) for cat,klass in zip(gc,ccc) if klass)
|
||||
#gc_bmg_non0 = set((cat,mirr) for cat,mirr in zip(gc, bmg) if mirr)
|
||||
|
||||
sc = [u['sc'] for u in ucd]
|
||||
|
||||
dm = {i:tuple(int(v, 16) for v in u['dm'].split()) for i,u in enumerate(ucd)
|
||||
if u['dm'] != '#' and u['dt'] == 'can' and not (0xAC00 <= i < 0xAC00+11172)}
|
||||
ce = {i for i,u in enumerate(ucd) if u['Comp_Ex'] == 'Y'}
|
||||
|
||||
assert not any(v for v in dm.values() if len(v) not in (1,2))
|
||||
dm1 = sorted(set(v for v in dm.values() if len(v) == 1))
|
||||
assert all((v[0] >> 16) in (0,2) for v in dm1)
|
||||
dm1_p0_array = ['0x%04Xu' % (v[0] & 0xFFFF) for v in dm1 if (v[0] >> 16) == 0]
|
||||
dm1_p2_array = ['0x%04Xu' % (v[0] & 0xFFFF) for v in dm1 if (v[0] >> 16) == 2]
|
||||
dm1_order = {v:i+1 for i,v in enumerate(dm1)}
|
||||
|
||||
dm2 = sorted((v+(i if i not in ce and not ccc[i] else 0,), v)
|
||||
for i,v in dm.items() if len(v) == 2)
|
||||
|
||||
filt = lambda v: ((v[0] & 0xFFFFF800) == 0x0000 and
|
||||
(v[1] & 0xFFFFFF80) == 0x0300 and
|
||||
(v[2] & 0xFFF0C000) == 0x0000)
|
||||
dm2_u32_array = [v for v in dm2 if filt(v[0])]
|
||||
dm2_u64_array = [v for v in dm2 if not filt(v[0])]
|
||||
assert dm2_u32_array + dm2_u64_array == dm2
|
||||
dm2_u32_array = ["HB_CODEPOINT_ENCODE3_11_7_14 (0x%04Xu, 0x%04Xu, 0x%04Xu)" % v[0] for v in dm2_u32_array]
|
||||
dm2_u64_array = ["HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" % v[0] for v in dm2_u64_array]
|
||||
|
||||
l = 1 + len(dm1_p0_array) + len(dm1_p2_array)
|
||||
dm2_order = {v[1]:i+l for i,v in enumerate(dm2)}
|
||||
|
||||
dm_order = {None: 0}
|
||||
dm_order.update(dm1_order)
|
||||
dm_order.update(dm2_order)
|
||||
|
||||
gc_order = dict()
|
||||
for i,v in enumerate(('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu',
|
||||
'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf',
|
||||
'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs',)):
|
||||
gc_order[i] = v
|
||||
gc_order[v] = i
|
||||
|
||||
sc_order = dict()
|
||||
sc_array = []
|
||||
sc_re = re.compile(r"\b(HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]")
|
||||
for line in open(hb_common_h):
|
||||
m = sc_re.search (line)
|
||||
if not m: continue
|
||||
name = m.group(1)
|
||||
tag = ''.join(m.group(i) for i in range(2, 6))
|
||||
i = len(sc_array)
|
||||
sc_order[tag] = i
|
||||
sc_order[i] = tag
|
||||
sc_array.append(name)
|
||||
|
||||
DEFAULT = 1
|
||||
COMPACT = 3
|
||||
SLOPPY = 5
|
||||
|
||||
|
||||
logging.info('Generating output...')
|
||||
print("/* == Start of generated table == */")
|
||||
print("/*")
|
||||
print(" * The following table is generated by running:")
|
||||
print(" *")
|
||||
print(" * ./gen-ucd-table.py ucd.nounihan.grouped.xml")
|
||||
print(" *")
|
||||
print(" * on file with this description:", ucdxml.description)
|
||||
print(" */")
|
||||
print()
|
||||
print("#ifndef HB_UCD_TABLE_HH")
|
||||
print("#define HB_UCD_TABLE_HH")
|
||||
print()
|
||||
print('#include "hb.hh"')
|
||||
print()
|
||||
|
||||
code = packTab.Code('_hb_ucd')
|
||||
sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array)
|
||||
dm1_p0_array, _ = code.addArray('uint16_t', 'dm1_p0_map', dm1_p0_array)
|
||||
dm1_p2_array, _ = code.addArray('uint16_t', 'dm1_p2_map', dm1_p2_array)
|
||||
dm2_u32_array, _ = code.addArray('uint32_t', 'dm2_u32_map', dm2_u32_array)
|
||||
dm2_u64_array, _ = code.addArray('uint64_t', 'dm2_u64_map', dm2_u64_array)
|
||||
code.print_c(linkage='static inline')
|
||||
|
||||
datasets = [
|
||||
('gc', gc, 'Cn', gc_order),
|
||||
('ccc', ccc, 0, None),
|
||||
('bmg', bmg, 0, None),
|
||||
('sc', sc, 'Zzzz', sc_order),
|
||||
('dm', dm, None, dm_order),
|
||||
]
|
||||
|
||||
for compression in (DEFAULT, COMPACT, SLOPPY):
|
||||
logging.info(' Compression=%d:' % compression)
|
||||
print()
|
||||
if compression == DEFAULT:
|
||||
print('#ifndef HB_OPTIMIZE_SIZE')
|
||||
elif compression == COMPACT:
|
||||
print('#elif !defined(HB_NO_UCD_UNASSIGNED)')
|
||||
else:
|
||||
print('#else')
|
||||
print()
|
||||
|
||||
if compression == SLOPPY:
|
||||
for i in range(len(gc)):
|
||||
if (i % 128) and gc[i] == 'Cn':
|
||||
gc[i] = gc[i - 1]
|
||||
for i in range(len(gc) - 2, -1, -1):
|
||||
if ((i + 1) % 128) and gc[i] == 'Cn':
|
||||
gc[i] = gc[i + 1]
|
||||
for i in range(len(sc)):
|
||||
if (i % 128) and sc[i] == 'Zzzz':
|
||||
sc[i] = sc[i - 1]
|
||||
for i in range(len(sc) - 2, -1, -1):
|
||||
if ((i + 1) % 128) and sc[i] == 'Zzzz':
|
||||
sc[i] = sc[i + 1]
|
||||
|
||||
|
||||
code = packTab.Code('_hb_ucd')
|
||||
|
||||
for name,data,default,mapping in datasets:
|
||||
sol = packTab.pack_table(data, default, mapping=mapping, compression=compression)
|
||||
logging.info(' Dataset=%-8s FullCost=%d' % (name, sol.fullCost))
|
||||
sol.genCode(code, name)
|
||||
|
||||
code.print_c(linkage='static inline')
|
||||
|
||||
print()
|
||||
|
||||
print('#endif')
|
||||
print()
|
||||
|
||||
print()
|
||||
print("#endif /* HB_UCD_TABLE_HH */")
|
||||
print()
|
||||
print("/* == End of generated table == */")
|
||||
logging.info('Done.')
|
|
@ -47,9 +47,22 @@ 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][0x1B61] = defaults[0]
|
||||
data[0][0x1B63] = defaults[0]
|
||||
data[0][0x1B64] = defaults[0]
|
||||
data[0][0x1B65] = defaults[0]
|
||||
data[0][0x1B66] = defaults[0]
|
||||
data[0][0x1B67] = defaults[0]
|
||||
data[0][0x1B69] = defaults[0]
|
||||
data[0][0x1B6A] = defaults[0]
|
||||
data[0][0x2060] = defaults[0]
|
||||
data[0][0x20F0] = defaults[0]
|
||||
# TODO https://github.com/roozbehp/unicode-data/issues/9
|
||||
# TODO https://github.com/harfbuzz/harfbuzz/pull/1685
|
||||
data[0][0x1B5B] = 'Consonant_Placeholder'
|
||||
data[0][0x1B5C] = 'Consonant_Placeholder'
|
||||
data[0][0x1B5F] = 'Consonant_Placeholder'
|
||||
data[0][0x1B62] = 'Consonant_Placeholder'
|
||||
data[0][0x1B68] = 'Consonant_Placeholder'
|
||||
# TODO https://github.com/harfbuzz/harfbuzz/issues/1035
|
||||
data[0][0x11C44] = 'Consonant_Placeholder'
|
||||
data[0][0x11C45] = 'Consonant_Placeholder'
|
||||
# TODO https://github.com/harfbuzz/harfbuzz/pull/1399
|
||||
|
@ -172,7 +185,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 [0x104B, 0x104E, 0x2022, 0x111C8, 0x11A3F, 0x11A45, 0x11C44, 0x11C45]) or
|
||||
(UGC == Po and not U in [0x104B, 0x104E, 0x1B5B, 0x1B5C, 0x1B5F, 0x2022, 0x111C8, 0x11A3F, 0x11A45, 0x11C44, 0x11C45]) or
|
||||
False # SPEC-DRAFT-OUTDATED! U == 0x002D
|
||||
)
|
||||
def is_BASE_NUM(U, UISC, UGC):
|
||||
|
@ -184,15 +197,15 @@ def is_BASE_OTHER(U, UISC, UGC):
|
|||
def is_CGJ(U, UISC, UGC):
|
||||
return U == 0x034F
|
||||
def is_CONS_FINAL(U, UISC, UGC):
|
||||
# Consonant_Initial_Postfixed is new in Unicode 11; not in the spec.
|
||||
return ((UISC == Consonant_Final and UGC != Lo) or
|
||||
UISC == Consonant_Initial_Postfixed or
|
||||
UISC == Consonant_Succeeding_Repha)
|
||||
def is_CONS_FINAL_MOD(U, UISC, UGC):
|
||||
#SPEC-DRAFT return UISC in [Consonant_Final_Modifier, Syllable_Modifier]
|
||||
return UISC == Syllable_Modifier
|
||||
def is_CONS_MED(U, UISC, UGC):
|
||||
return UISC == Consonant_Medial and UGC != Lo
|
||||
# Consonant_Initial_Postfixed is new in Unicode 11; not in the spec.
|
||||
return (UISC == Consonant_Medial and UGC != Lo or
|
||||
UISC == Consonant_Initial_Postfixed)
|
||||
def is_CONS_MOD(U, UISC, UGC):
|
||||
return UISC in [Nukta, Gemination_Mark, Consonant_Killer]
|
||||
def is_CONS_SUB(U, UISC, UGC):
|
||||
|
@ -201,7 +214,9 @@ def is_CONS_SUB(U, UISC, UGC):
|
|||
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] and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC)
|
||||
return (UISC in [Virama, Invisible_Stacker]
|
||||
and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC)
|
||||
and not is_SAKOT(U, UISC, UGC))
|
||||
def is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC):
|
||||
# https://github.com/harfbuzz/harfbuzz/issues/1102
|
||||
# https://github.com/harfbuzz/harfbuzz/issues/1379
|
||||
|
@ -217,6 +232,7 @@ def is_Word_Joiner(U, UISC, UGC):
|
|||
def is_OTHER(U, UISC, UGC):
|
||||
#SPEC-OUTDATED return UGC == Zs # or any other SCRIPT_COMMON characters
|
||||
return (UISC == Other
|
||||
and not is_SYM(U, UISC, UGC)
|
||||
and not is_SYM_MOD(U, UISC, UGC)
|
||||
and not is_CGJ(U, UISC, UGC)
|
||||
and not is_Word_Joiner(U, UISC, UGC)
|
||||
|
@ -226,20 +242,22 @@ def is_Reserved(U, UISC, UGC):
|
|||
return UGC == 'Cn'
|
||||
def is_REPHA(U, UISC, UGC):
|
||||
return UISC in [Consonant_Preceding_Repha, Consonant_Prefixed]
|
||||
def is_SAKOT(U, UISC, UGC):
|
||||
return U == 0x1A60
|
||||
def is_SYM(U, UISC, UGC):
|
||||
if U == 0x25CC: return False #SPEC-DRAFT
|
||||
#SPEC-DRAFT return UGC in [So, Sc] or UISC == Symbol_Letter
|
||||
return UGC in [So, Sc]
|
||||
return UGC in [So, Sc] and U not in [0x1B62, 0x1B68]
|
||||
def is_SYM_MOD(U, UISC, UGC):
|
||||
return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73]
|
||||
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
|
||||
# https://github.com/harfbuzz/harfbuzz/issues/376
|
||||
return (UISC == Pure_Killer or
|
||||
(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
|
||||
# https://github.com/harfbuzz/harfbuzz/issues/376
|
||||
return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or
|
||||
(UGC != Lo and (UISC == Bindu or U in [0xAA29])))
|
||||
|
||||
|
@ -265,6 +283,7 @@ use_mapping = {
|
|||
'Rsv': is_Reserved,
|
||||
'R': is_REPHA,
|
||||
'S': is_SYM,
|
||||
'Sk': is_SAKOT,
|
||||
'SM': is_SYM_MOD,
|
||||
'VS': is_VARIATION_SELECTOR,
|
||||
'V': is_VOWEL,
|
||||
|
@ -306,7 +325,11 @@ use_positions = {
|
|||
'H': None,
|
||||
'HVM': None,
|
||||
'B': None,
|
||||
'FM': None,
|
||||
'FM': {
|
||||
'Abv': [Top],
|
||||
'Blw': [Bottom],
|
||||
'Pst': [Not_Applicable],
|
||||
},
|
||||
'SUB': None,
|
||||
}
|
||||
|
||||
|
@ -317,12 +340,11 @@ def map_to_use(data):
|
|||
|
||||
# Resolve Indic_Syllabic_Category
|
||||
|
||||
# TODO: These don't have UISC assigned in Unicode 8.0, but have UIPC
|
||||
if U == 0x17DD: UISC = Vowel_Dependent
|
||||
# TODO: These don't have UISC assigned in Unicode 12.0, but have UIPC
|
||||
if 0x1CE2 <= U <= 0x1CE8: UISC = Cantillation_Mark
|
||||
|
||||
# Tibetan:
|
||||
# TODO: These don't have UISC assigned in Unicode 11.0, but have UIPC
|
||||
# TODO: These don't have UISC assigned in Unicode 12.0, but have UIPC
|
||||
if 0x0F18 <= U <= 0x0F19 or 0x0F3E <= U <= 0x0F3F: UISC = Vowel_Dependent
|
||||
if 0x0F86 <= U <= 0x0F87: UISC = Tone_Mark
|
||||
# Overrides to allow NFC order matching syllable
|
||||
|
@ -346,48 +368,28 @@ def map_to_use(data):
|
|||
# the nasalization marks, maybe only for U+1CE9..U+1CF1.
|
||||
if U == 0x1CED: UISC = Tone_Mark
|
||||
|
||||
# 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
|
||||
|
||||
# TODO: https://github.com/harfbuzz/harfbuzz/issues/1105
|
||||
if U == 0x11134: UISC = Gemination_Mark
|
||||
|
||||
# TODO: https://github.com/harfbuzz/harfbuzz/pull/1399
|
||||
if U == 0x111C9: UISC = Consonant_Final
|
||||
|
||||
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]
|
||||
|
||||
# Resolve Indic_Positional_Category
|
||||
|
||||
# TODO: Not in Unicode 8.0 yet, but in spec.
|
||||
if U == 0x1B6C: UIPC = Bottom
|
||||
|
||||
# TODO: These should die, but have UIPC in Unicode 8.0
|
||||
# TODO: These should die, but have UIPC in Unicode 12.0
|
||||
if U in [0x953, 0x954]: UIPC = Not_Applicable
|
||||
|
||||
# TODO: In USE's override list but not in Unicode 11.0
|
||||
# TODO: In USE's override list but not in Unicode 12.0
|
||||
if U == 0x103C: UIPC = Left
|
||||
|
||||
# TODO: These are not in USE's override list that we have, nor are they in Unicode 11.0
|
||||
# TODO: These are not in USE's override list that we have, nor are they in Unicode 12.0
|
||||
if 0xA926 <= U <= 0xA92A: UIPC = Top
|
||||
if U == 0x111CA: UIPC = Bottom
|
||||
if U == 0x11300: UIPC = Top
|
||||
# TODO: https://github.com/harfbuzz/harfbuzz/pull/1037
|
||||
if U == 0x11302: UIPC = Top
|
||||
if U == 0x1133C: UIPC = Bottom
|
||||
if U == 0x1171E: UIPC = Left # Correct?!
|
||||
if 0x1CF2 <= U <= 0x1CF3: UIPC = Right
|
||||
# and https://github.com/harfbuzz/harfbuzz/issues/1631
|
||||
if U in [0x11302, 0x11303, 0x114C1]: UIPC = Top
|
||||
if U == 0x1171E: UIPC = Left
|
||||
if 0x1CF8 <= U <= 0x1CF9: UIPC = Top
|
||||
# https://github.com/roozbehp/unicode-data/issues/8
|
||||
if U == 0x0A51: UIPC = Bottom
|
||||
|
||||
assert (UIPC in [Not_Applicable, Visual_Order_Left] or
|
||||
USE in use_positions), "%s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UGC)
|
||||
|
@ -417,6 +419,10 @@ for h in headers:
|
|||
print (" * %s" % (l.strip()))
|
||||
print (" */")
|
||||
print ()
|
||||
print ('#include "hb.hh"')
|
||||
print ()
|
||||
print ('#ifndef HB_NO_OT_SHAPE')
|
||||
print ()
|
||||
print ('#include "hb-ot-shape-complex-use.hh"')
|
||||
print ()
|
||||
|
||||
|
@ -455,6 +461,8 @@ num = 0
|
|||
offset = 0
|
||||
starts = []
|
||||
ends = []
|
||||
print ('#pragma GCC diagnostic push')
|
||||
print ('#pragma GCC diagnostic ignored "-Wunused-macros"')
|
||||
for k,v in sorted(use_mapping.items()):
|
||||
if k in use_positions and use_positions[k]: continue
|
||||
print ("#define %s USE_%s /* %s */" % (k, k, v.__name__[3:]))
|
||||
|
@ -463,6 +471,7 @@ for k,v in sorted(use_positions.items()):
|
|||
for suf in v.keys():
|
||||
tag = k + suf
|
||||
print ("#define %s USE_%s" % (tag, tag))
|
||||
print ('#pragma GCC diagnostic pop')
|
||||
print ("")
|
||||
print ("static const USE_TABLE_ELEMENT_TYPE use_table[] = {")
|
||||
for u in uu:
|
||||
|
@ -528,6 +537,8 @@ for k,v in sorted(use_positions.items()):
|
|||
tag = k + suf
|
||||
print ("#undef %s" % tag)
|
||||
print ()
|
||||
print ()
|
||||
print ('#endif')
|
||||
print ("/* == End of generated table == */")
|
||||
|
||||
# Maintain at least 50% occupancy in the table */
|
||||
|
|
|
@ -157,6 +157,11 @@ print (' *')
|
|||
for line in scripts_header:
|
||||
print (' * %s' % line.strip ())
|
||||
print (' */')
|
||||
|
||||
print ()
|
||||
print ('#include "hb.hh"')
|
||||
print ()
|
||||
print ('#ifndef HB_NO_OT_SHAPE')
|
||||
print ()
|
||||
print ('#include "hb-ot-shape-complex-vowel-constraints.hh"')
|
||||
print ()
|
||||
|
@ -180,6 +185,12 @@ print ('_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB
|
|||
print ('\t\t\t\t hb_buffer_t *buffer,')
|
||||
print ('\t\t\t\t hb_font_t *font HB_UNUSED)')
|
||||
print ('{')
|
||||
print ('#if defined(HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS)')
|
||||
print (' return;')
|
||||
print ('#endif')
|
||||
print (' if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)')
|
||||
print (' return;')
|
||||
print ()
|
||||
print (' /* UGLY UGLY UGLY business of adding dotted-circle in the middle of')
|
||||
print (' * vowel-sequences that look like another vowel. Data for each script')
|
||||
print (' * collected from the USE script development spec.')
|
||||
|
@ -212,8 +223,11 @@ print (' if (processed)')
|
|||
print (' {')
|
||||
print (' if (buffer->idx < count)')
|
||||
print (' buffer->next_glyph ();')
|
||||
print (' buffer->swap_buffers ();')
|
||||
print (' }')
|
||||
print ('}')
|
||||
|
||||
print ()
|
||||
print ()
|
||||
print ('#endif')
|
||||
print ('/* == End of generated functions == */')
|
||||
|
|
53
src/harfbuzz.cc
Normal file
53
src/harfbuzz.cc
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include "hb-aat-layout.cc"
|
||||
#include "hb-aat-map.cc"
|
||||
#include "hb-blob.cc"
|
||||
#include "hb-buffer-serialize.cc"
|
||||
#include "hb-buffer.cc"
|
||||
#include "hb-common.cc"
|
||||
#include "hb-face.cc"
|
||||
#include "hb-fallback-shape.cc"
|
||||
#include "hb-font.cc"
|
||||
#include "hb-map.cc"
|
||||
#include "hb-ot-cff1-table.cc"
|
||||
#include "hb-ot-cff2-table.cc"
|
||||
#include "hb-ot-color.cc"
|
||||
#include "hb-ot-face.cc"
|
||||
#include "hb-ot-font.cc"
|
||||
#include "hb-ot-layout.cc"
|
||||
#include "hb-ot-map.cc"
|
||||
#include "hb-ot-math.cc"
|
||||
#include "hb-ot-meta.cc"
|
||||
#include "hb-ot-metrics.cc"
|
||||
#include "hb-ot-name.cc"
|
||||
#include "hb-ot-shape-complex-arabic.cc"
|
||||
#include "hb-ot-shape-complex-default.cc"
|
||||
#include "hb-ot-shape-complex-hangul.cc"
|
||||
#include "hb-ot-shape-complex-hebrew.cc"
|
||||
#include "hb-ot-shape-complex-indic-table.cc"
|
||||
#include "hb-ot-shape-complex-indic.cc"
|
||||
#include "hb-ot-shape-complex-khmer.cc"
|
||||
#include "hb-ot-shape-complex-myanmar.cc"
|
||||
#include "hb-ot-shape-complex-thai.cc"
|
||||
#include "hb-ot-shape-complex-use-table.cc"
|
||||
#include "hb-ot-shape-complex-use.cc"
|
||||
#include "hb-ot-shape-complex-vowel-constraints.cc"
|
||||
#include "hb-ot-shape-fallback.cc"
|
||||
#include "hb-ot-shape-normalize.cc"
|
||||
#include "hb-ot-shape.cc"
|
||||
#include "hb-ot-tag.cc"
|
||||
#include "hb-ot-var.cc"
|
||||
#include "hb-set.cc"
|
||||
#include "hb-shape-plan.cc"
|
||||
#include "hb-shape.cc"
|
||||
#include "hb-shaper.cc"
|
||||
#include "hb-static.cc"
|
||||
#include "hb-ucd.cc"
|
||||
#include "hb-unicode.cc"
|
||||
#include "hb-warning.cc"
|
||||
#include "hb-glib.cc"
|
||||
#include "hb-ft.cc"
|
||||
#include "hb-graphite2.cc"
|
||||
#include "hb-uniscribe.cc"
|
||||
#include "hb-gdi.cc"
|
||||
#include "hb-directwrite.cc"
|
||||
#include "hb-coretext.cc"
|
|
@ -74,7 +74,7 @@ struct FontDescriptor
|
|||
|
||||
struct fdsc
|
||||
{
|
||||
enum { tableTag = HB_AAT_TAG_fdsc };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_fdsc;
|
||||
|
||||
enum {
|
||||
Weight = HB_TAG ('w','g','h','t'),
|
||||
|
|
|
@ -58,20 +58,16 @@ typedef LArrayOf<Anchor> GlyphAnchors;
|
|||
|
||||
struct ankr
|
||||
{
|
||||
enum { tableTag = HB_AAT_TAG_ankr };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_ankr;
|
||||
|
||||
const Anchor &get_anchor (hb_codepoint_t glyph_id,
|
||||
unsigned int i,
|
||||
unsigned int num_glyphs,
|
||||
const char *end) const
|
||||
unsigned int num_glyphs) const
|
||||
{
|
||||
const Offset<HBUINT16, false> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
|
||||
const NNOffsetTo<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
|
||||
if (!offset)
|
||||
return Null(Anchor);
|
||||
const GlyphAnchors &anchors = StructAtOffset<GlyphAnchors> (&(this+anchorData), *offset);
|
||||
if (unlikely (end - (const char *) &anchors < anchors.len.static_size ||
|
||||
end - (const char *) &anchors < anchors.get_size ()))
|
||||
return Null(Anchor);
|
||||
const GlyphAnchors &anchors = &(this+anchorData) + *offset;
|
||||
return anchors[i];
|
||||
}
|
||||
|
||||
|
@ -80,16 +76,16 @@ struct ankr
|
|||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
version == 0 &&
|
||||
lookupTable.sanitize (c, this) &&
|
||||
anchorData.sanitize (c, this) /* Just one byte. */));
|
||||
c->check_range (this, anchorData) &&
|
||||
lookupTable.sanitize (c, this, &(this+anchorData))));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Version number (set to zero) */
|
||||
HBUINT16 flags; /* Flags (currently unused; set to zero) */
|
||||
LOffsetTo<Lookup<Offset<HBUINT16, false> >, false>
|
||||
LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors>>>
|
||||
lookupTable; /* Offset to the table's lookup table */
|
||||
LOffsetTo<HBUINT8, false>
|
||||
LNNOffsetTo<HBUINT8>
|
||||
anchorData; /* Offset to the glyph data table */
|
||||
|
||||
public:
|
||||
|
|
|
@ -116,7 +116,7 @@ struct BaselineTableFormat3Part
|
|||
|
||||
struct bsln
|
||||
{
|
||||
enum { tableTag = HB_AAT_TAG_bsln };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_bsln;
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
|
|
@ -77,7 +77,7 @@ struct LookupFormat0
|
|||
template <typename T>
|
||||
struct LookupSegmentSingle
|
||||
{
|
||||
enum { TerminationWordCount = 2 };
|
||||
static constexpr unsigned TerminationWordCount = 2u;
|
||||
|
||||
int cmp (hb_codepoint_t g) const
|
||||
{ return g < first ? -1 : g <= last ? 0 : +1 ; }
|
||||
|
@ -125,7 +125,7 @@ struct LookupFormat2
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
VarSizedBinSearchArrayOf<LookupSegmentSingle<T> >
|
||||
VarSizedBinSearchArrayOf<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). */
|
||||
|
@ -136,7 +136,7 @@ struct LookupFormat2
|
|||
template <typename T>
|
||||
struct LookupSegmentArray
|
||||
{
|
||||
enum { TerminationWordCount = 2 };
|
||||
static constexpr unsigned TerminationWordCount = 2u;
|
||||
|
||||
const T* get_value (hb_codepoint_t glyph_id, const void *base) const
|
||||
{
|
||||
|
@ -153,18 +153,18 @@ struct LookupSegmentArray
|
|||
first <= last &&
|
||||
valuesZ.sanitize (c, base, last - first + 1));
|
||||
}
|
||||
template <typename T2>
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base, T2 user_data) const
|
||||
template <typename ...Ts>
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
first <= last &&
|
||||
valuesZ.sanitize (c, base, last - first + 1, user_data));
|
||||
valuesZ.sanitize (c, base, last - first + 1, hb_forward<Ts> (ds)...));
|
||||
}
|
||||
|
||||
GlyphID last; /* Last GlyphID in this segment */
|
||||
GlyphID first; /* First GlyphID in this segment */
|
||||
OffsetTo<UnsizedArrayOf<T>, HBUINT16, false>
|
||||
NNOffsetTo<UnsizedArrayOf<T>>
|
||||
valuesZ; /* A 16-bit offset from the start of
|
||||
* the table to the data. */
|
||||
public:
|
||||
|
@ -196,7 +196,7 @@ struct LookupFormat4
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 4 */
|
||||
VarSizedBinSearchArrayOf<LookupSegmentArray<T> >
|
||||
VarSizedBinSearchArrayOf<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). */
|
||||
|
@ -207,7 +207,7 @@ struct LookupFormat4
|
|||
template <typename T>
|
||||
struct LookupSingle
|
||||
{
|
||||
enum { TerminationWordCount = 1 };
|
||||
static constexpr unsigned TerminationWordCount = 1u;
|
||||
|
||||
int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
|
||||
|
||||
|
@ -253,7 +253,7 @@ struct LookupFormat6
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 6 */
|
||||
VarSizedBinSearchArrayOf<LookupSingle<T> >
|
||||
VarSizedBinSearchArrayOf<LookupSingle<T>>
|
||||
entries; /* The actual entries, sorted by glyph index. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, entries);
|
||||
|
@ -394,7 +394,7 @@ struct Lookup
|
|||
case 4: return_trace (u.format4.sanitize (c, base));
|
||||
case 6: return_trace (u.format6.sanitize (c, base));
|
||||
case 8: return_trace (u.format8.sanitize (c, base));
|
||||
case 10: return_trace (false); /* No need to support format10 apparently */
|
||||
case 10: return_trace (false); /* We don't support format10 here currently. */
|
||||
default:return_trace (true);
|
||||
}
|
||||
}
|
||||
|
@ -418,15 +418,11 @@ struct Lookup
|
|||
} /* Close namespace. */
|
||||
/* Ugly hand-coded null objects for template Lookup<> :(. */
|
||||
extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
|
||||
template <>
|
||||
/*static*/ inline const AAT::Lookup<OT::HBUINT16>& Null<AAT::Lookup<OT::HBUINT16> > ()
|
||||
{ return *reinterpret_cast<const AAT::Lookup<OT::HBUINT16> *> (_hb_Null_AAT_Lookup); }
|
||||
template <>
|
||||
/*static*/ inline const AAT::Lookup<OT::HBUINT32>& Null<AAT::Lookup<OT::HBUINT32> > ()
|
||||
{ return *reinterpret_cast<const AAT::Lookup<OT::HBUINT32> *> (_hb_Null_AAT_Lookup); }
|
||||
template <>
|
||||
/*static*/ inline const AAT::Lookup<OT::Offset<OT::HBUINT16, false> >& Null<AAT::Lookup<OT::Offset<OT::HBUINT16, false> > > ()
|
||||
{ return *reinterpret_cast<const AAT::Lookup<OT::Offset<OT::HBUINT16, false> > *> (_hb_Null_AAT_Lookup); }
|
||||
template <typename T>
|
||||
struct Null<AAT::Lookup<T>> {
|
||||
static AAT::Lookup<T> const & get_null ()
|
||||
{ return *reinterpret_cast<const AAT::Lookup<T> *> (_hb_Null_AAT_Lookup); }
|
||||
};
|
||||
namespace AAT {
|
||||
|
||||
enum { DELETED_GLYPH = 0xFFFF };
|
||||
|
@ -511,9 +507,10 @@ struct StateTable
|
|||
const Entry<Extra> *get_entries () const
|
||||
{ return (this+entryTable).arrayZ; }
|
||||
|
||||
const Entry<Extra> *get_entryZ (int state, unsigned int klass) const
|
||||
const Entry<Extra> &get_entry (int state, unsigned int klass) const
|
||||
{
|
||||
if (unlikely (klass >= nClasses)) return nullptr;
|
||||
if (unlikely (klass >= nClasses))
|
||||
klass = StateTable<Types, Entry<Extra>>::CLASS_OUT_OF_BOUNDS;
|
||||
|
||||
const HBUSHORT *states = (this+stateArrayTable).arrayZ;
|
||||
const Entry<Extra> *entries = (this+entryTable).arrayZ;
|
||||
|
@ -521,7 +518,7 @@ struct StateTable
|
|||
unsigned int entry = states[state * nClasses + klass];
|
||||
DEBUG_MSG (APPLY, nullptr, "e%u", entry);
|
||||
|
||||
return &entries[entry];
|
||||
return entries[entry];
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c,
|
||||
|
@ -529,6 +526,7 @@ struct StateTable
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!(c->check_struct (this) &&
|
||||
nClasses >= 4 /* Ensure pre-defined classes fit. */ &&
|
||||
classTable.sanitize (c, this)))) return_trace (false);
|
||||
|
||||
const HBUSHORT *states = (this+stateArrayTable).arrayZ;
|
||||
|
@ -571,14 +569,14 @@ struct StateTable
|
|||
-min_state,
|
||||
row_stride)))
|
||||
return_trace (false);
|
||||
if ((c->max_ops -= state_neg - min_state) < 0)
|
||||
if ((c->max_ops -= state_neg - min_state) <= 0)
|
||||
return_trace (false);
|
||||
{ /* Sweep new states. */
|
||||
const HBUSHORT *stop = &states[min_state * num_classes];
|
||||
if (unlikely (stop > states))
|
||||
return_trace (false);
|
||||
for (const HBUSHORT *p = states; stop < p; p--)
|
||||
num_entries = MAX<unsigned int> (num_entries, *(p - 1) + 1);
|
||||
num_entries = hb_max (num_entries, *(p - 1) + 1);
|
||||
state_neg = min_state;
|
||||
}
|
||||
}
|
||||
|
@ -590,7 +588,7 @@ struct StateTable
|
|||
max_state + 1,
|
||||
row_stride)))
|
||||
return_trace (false);
|
||||
if ((c->max_ops -= max_state - state_pos + 1) < 0)
|
||||
if ((c->max_ops -= max_state - state_pos + 1) <= 0)
|
||||
return_trace (false);
|
||||
{ /* Sweep new states. */
|
||||
if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
|
||||
|
@ -599,22 +597,22 @@ struct StateTable
|
|||
if (unlikely (stop < states))
|
||||
return_trace (false);
|
||||
for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
|
||||
num_entries = MAX<unsigned int> (num_entries, *p + 1);
|
||||
num_entries = hb_max (num_entries, *p + 1);
|
||||
state_pos = max_state + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely (!c->check_array (entries, num_entries)))
|
||||
return_trace (false);
|
||||
if ((c->max_ops -= num_entries - entry) < 0)
|
||||
if ((c->max_ops -= num_entries - entry) <= 0)
|
||||
return_trace (false);
|
||||
{ /* Sweep new entries. */
|
||||
const Entry<Extra> *stop = &entries[num_entries];
|
||||
for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
|
||||
{
|
||||
int newState = new_state (p->newState);
|
||||
min_state = MIN (min_state, newState);
|
||||
max_state = MAX (max_state, newState);
|
||||
min_state = hb_min (min_state, newState);
|
||||
max_state = hb_max (max_state, newState);
|
||||
}
|
||||
entry = num_entries;
|
||||
}
|
||||
|
@ -629,11 +627,11 @@ struct StateTable
|
|||
protected:
|
||||
HBUINT nClasses; /* Number of classes, which is the number of indices
|
||||
* in a single line in the state array. */
|
||||
OffsetTo<ClassType, HBUINT, false>
|
||||
NNOffsetTo<ClassType, HBUINT>
|
||||
classTable; /* Offset to the class table. */
|
||||
OffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT, false>
|
||||
NNOffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT>
|
||||
stateArrayTable;/* Offset to the state array. */
|
||||
OffsetTo<UnsizedArrayOf<Entry<Extra> >, HBUINT, false>
|
||||
NNOffsetTo<UnsizedArrayOf<Entry<Extra>>, HBUINT>
|
||||
entryTable; /* Offset to the entry array. */
|
||||
|
||||
public:
|
||||
|
@ -669,7 +667,7 @@ struct ClassTable
|
|||
|
||||
struct ObsoleteTypes
|
||||
{
|
||||
enum { extended = false };
|
||||
static constexpr bool extended = false;
|
||||
typedef HBUINT16 HBUINT;
|
||||
typedef HBUINT8 HBUSHORT;
|
||||
typedef ClassTable<HBUINT8> ClassTypeNarrow;
|
||||
|
@ -699,7 +697,7 @@ struct ObsoleteTypes
|
|||
};
|
||||
struct ExtendedTypes
|
||||
{
|
||||
enum { extended = true };
|
||||
static constexpr bool extended = true;
|
||||
typedef HBUINT32 HBUINT;
|
||||
typedef HBUINT16 HBUSHORT;
|
||||
typedef Lookup<HBUINT16> ClassTypeNarrow;
|
||||
|
@ -745,16 +743,13 @@ struct StateTableDriver
|
|||
buffer->clear_output ();
|
||||
|
||||
int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT;
|
||||
bool last_was_dont_advance = false;
|
||||
for (buffer->idx = 0; buffer->successful;)
|
||||
{
|
||||
unsigned int klass = buffer->idx < buffer->len ?
|
||||
machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
|
||||
(unsigned) StateTable<Types, EntryData>::CLASS_END_OF_TEXT;
|
||||
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
|
||||
const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
|
||||
if (unlikely (!entry))
|
||||
break;
|
||||
const Entry<EntryData> &entry = machine.get_entry (state, klass);
|
||||
|
||||
/* Unsafe-to-break before this if not in state 0, as things might
|
||||
* go differently if we start from state 0 here.
|
||||
|
@ -765,31 +760,28 @@ struct StateTableDriver
|
|||
/* 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 == StateTable<Types, EntryData>::STATE_START_OF_TEXT &&
|
||||
entry->flags == context_t::DontAdvance))
|
||||
!(entry.newState == StateTable<Types, EntryData>::STATE_START_OF_TEXT &&
|
||||
entry.flags == context_t::DontAdvance))
|
||||
buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 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);
|
||||
const Entry<EntryData> &end_entry = machine.get_entry (state, StateTable<Types, EntryData>::CLASS_END_OF_TEXT);
|
||||
if (c->is_actionable (this, end_entry))
|
||||
buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
|
||||
}
|
||||
|
||||
if (unlikely (!c->transition (this, entry)))
|
||||
break;
|
||||
c->transition (this, entry);
|
||||
|
||||
last_was_dont_advance = (entry->flags & context_t::DontAdvance) && buffer->max_ops-- > 0;
|
||||
|
||||
state = machine.new_state (entry->newState);
|
||||
state = machine.new_state (entry.newState);
|
||||
DEBUG_MSG (APPLY, nullptr, "s%d", state);
|
||||
|
||||
if (buffer->idx == buffer->len)
|
||||
break;
|
||||
|
||||
if (!last_was_dont_advance)
|
||||
if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
|
||||
buffer->next_glyph ();
|
||||
}
|
||||
|
||||
|
@ -825,7 +817,6 @@ struct hb_aat_apply_context_t :
|
|||
hb_buffer_t *buffer;
|
||||
hb_sanitize_context_t sanitizer;
|
||||
const ankr *ankr_table;
|
||||
const char *ankr_end;
|
||||
|
||||
/* Unused. For debug tracing only. */
|
||||
unsigned int lookup_index;
|
||||
|
@ -838,7 +829,7 @@ struct hb_aat_apply_context_t :
|
|||
|
||||
HB_INTERNAL ~hb_aat_apply_context_t ();
|
||||
|
||||
HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_, const char *ankr_end_);
|
||||
HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
|
||||
|
||||
void set_lookup_index (unsigned int i) { lookup_index = i; }
|
||||
};
|
||||
|
|
|
@ -47,17 +47,16 @@ struct SettingName
|
|||
hb_aat_layout_feature_selector_t get_selector () const
|
||||
{ return (hb_aat_layout_feature_selector_t) (unsigned) setting; }
|
||||
|
||||
void get_info (hb_aat_layout_feature_selector_info_t *s,
|
||||
hb_aat_layout_feature_selector_t default_selector) const
|
||||
hb_aat_layout_feature_selector_info_t get_info (hb_aat_layout_feature_selector_t default_selector) const
|
||||
{
|
||||
s->name_id = nameIndex;
|
||||
|
||||
s->enable = (hb_aat_layout_feature_selector_t) (unsigned int) setting;
|
||||
s->disable = default_selector == HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID ?
|
||||
(hb_aat_layout_feature_selector_t) (s->enable + 1) :
|
||||
default_selector;
|
||||
|
||||
s->reserved = 0;
|
||||
return {
|
||||
nameIndex,
|
||||
(hb_aat_layout_feature_selector_t) (unsigned int) setting,
|
||||
default_selector == HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID
|
||||
? (hb_aat_layout_feature_selector_t) (setting + 1)
|
||||
: default_selector,
|
||||
0
|
||||
};
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -117,9 +116,10 @@ struct FeatureName
|
|||
|
||||
if (selectors_count)
|
||||
{
|
||||
hb_array_t<const SettingName> arr = settings_table.sub_array (start_offset, selectors_count);
|
||||
for (unsigned int i = 0; i < arr.length; i++)
|
||||
settings_table[start_offset + i].get_info (&selectors[i], default_selector);
|
||||
+ settings_table.sub_array (start_offset, selectors_count)
|
||||
| hb_map ([=] (const SettingName& setting) { return setting.get_info (default_selector); })
|
||||
| hb_sink (hb_array (selectors, *selectors_count))
|
||||
;
|
||||
}
|
||||
return settings_table.length;
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ struct FeatureName
|
|||
|
||||
struct feat
|
||||
{
|
||||
enum { tableTag = HB_AAT_TAG_feat };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_feat;
|
||||
|
||||
bool has_data () const { return version.to_int (); }
|
||||
|
||||
|
@ -162,21 +162,18 @@ struct feat
|
|||
unsigned int *count,
|
||||
hb_aat_layout_feature_type_t *features) const
|
||||
{
|
||||
unsigned int feature_count = featureNameCount;
|
||||
if (count && *count)
|
||||
if (count)
|
||||
{
|
||||
unsigned int len = MIN (feature_count - start_offset, *count);
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
features[i] = namesZ[i + start_offset].get_feature_type ();
|
||||
*count = len;
|
||||
+ namesZ.as_array (featureNameCount).sub_array (start_offset, count)
|
||||
| hb_map (&FeatureName::get_feature_type)
|
||||
| hb_sink (hb_array (features, *count))
|
||||
;
|
||||
}
|
||||
return featureNameCount;
|
||||
}
|
||||
|
||||
const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
|
||||
{
|
||||
return namesZ.bsearch (featureNameCount, feature_type);
|
||||
}
|
||||
{ return namesZ.bsearch (featureNameCount, feature_type); }
|
||||
|
||||
hb_ot_name_id_t get_feature_name_id (hb_aat_layout_feature_type_t feature) const
|
||||
{ return get_feature (feature).get_feature_name_id (); }
|
||||
|
|
|
@ -309,7 +309,7 @@ struct WidthDeltaPair
|
|||
public:
|
||||
DEFINE_SIZE_STATIC (24);
|
||||
};
|
||||
|
||||
|
||||
typedef OT::LArrayOf<WidthDeltaPair> WidthDeltaCluster;
|
||||
|
||||
struct JustificationCategory
|
||||
|
@ -371,7 +371,7 @@ struct JustificationHeader
|
|||
* of postcompensation subtable (set to zero if none).
|
||||
*
|
||||
* The postcompensation subtable, if present in the font. */
|
||||
Lookup<OffsetTo<WidthDeltaCluster> >
|
||||
Lookup<OffsetTo<WidthDeltaCluster>>
|
||||
lookupTable; /* Lookup table associating glyphs with width delta
|
||||
* clusters. See the description of Width Delta Clusters
|
||||
* table for details on how to interpret the lookup values. */
|
||||
|
@ -382,7 +382,7 @@ struct JustificationHeader
|
|||
|
||||
struct just
|
||||
{
|
||||
enum { tableTag = HB_AAT_TAG_just };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_just;
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
|
|
@ -170,11 +170,11 @@ struct Format1Entry<true>
|
|||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
static bool performAction (const Entry<EntryData> *entry)
|
||||
{ return entry->data.kernActionIndex != 0xFFFF; }
|
||||
static bool performAction (const Entry<EntryData> &entry)
|
||||
{ return entry.data.kernActionIndex != 0xFFFF; }
|
||||
|
||||
static unsigned int kernActionIndex (const Entry<EntryData> *entry)
|
||||
{ return entry->data.kernActionIndex; }
|
||||
static unsigned int kernActionIndex (const Entry<EntryData> &entry)
|
||||
{ return entry.data.kernActionIndex; }
|
||||
};
|
||||
template <>
|
||||
struct Format1Entry<false>
|
||||
|
@ -192,11 +192,11 @@ struct Format1Entry<false>
|
|||
|
||||
typedef void EntryData;
|
||||
|
||||
static bool performAction (const Entry<EntryData> *entry)
|
||||
{ return entry->flags & Offset; }
|
||||
static bool performAction (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & Offset; }
|
||||
|
||||
static unsigned int kernActionIndex (const Entry<EntryData> *entry)
|
||||
{ return entry->flags & Offset; }
|
||||
static unsigned int kernActionIndex (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & Offset; }
|
||||
};
|
||||
|
||||
template <typename KernSubTableHeader>
|
||||
|
@ -210,7 +210,7 @@ struct KerxSubTableFormat1
|
|||
|
||||
struct driver_context_t
|
||||
{
|
||||
enum { in_place = true };
|
||||
static constexpr bool in_place = true;
|
||||
enum
|
||||
{
|
||||
DontAdvance = Format1EntryT::DontAdvance,
|
||||
|
@ -228,15 +228,15 @@ struct KerxSubTableFormat1
|
|||
crossStream (table->header.coverage & table->header.CrossStream) {}
|
||||
|
||||
bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
|
||||
const Entry<EntryData> *entry)
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
return Format1EntryT::performAction (entry);
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> *entry)
|
||||
void transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
unsigned int flags = entry->flags;
|
||||
unsigned int flags = entry.flags;
|
||||
|
||||
if (flags & Format1EntryT::Reset)
|
||||
depth = 0;
|
||||
|
@ -251,7 +251,7 @@ struct KerxSubTableFormat1
|
|||
|
||||
if (Format1EntryT::performAction (entry) && depth)
|
||||
{
|
||||
unsigned int tuple_count = MAX (1u, table->header.tuple_count ());
|
||||
unsigned int tuple_count = hb_max (1u, table->header.tuple_count ());
|
||||
|
||||
unsigned int kern_idx = Format1EntryT::kernActionIndex (entry);
|
||||
kern_idx = Types::byteOffsetToIndex (kern_idx, &table->machine, kernAction.arrayZ);
|
||||
|
@ -259,7 +259,7 @@ struct KerxSubTableFormat1
|
|||
if (!c->sanitizer.check_array (actions, depth, tuple_count))
|
||||
{
|
||||
depth = 0;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
hb_mask_t kern_mask = c->plan->kern_mask;
|
||||
|
@ -334,8 +334,6 @@ struct KerxSubTableFormat1
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -374,7 +372,7 @@ struct KerxSubTableFormat1
|
|||
protected:
|
||||
KernSubTableHeader header;
|
||||
StateTable<Types, EntryData> machine;
|
||||
OffsetTo<UnsizedArrayOf<FWORD>, HBUINT, false>kernAction;
|
||||
NNOffsetTo<UnsizedArrayOf<FWORD>, HBUINT> kernAction;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 5 * sizeof (HBUINT));
|
||||
};
|
||||
|
@ -443,13 +441,13 @@ struct KerxSubTableFormat2
|
|||
protected:
|
||||
KernSubTableHeader header;
|
||||
HBUINT rowWidth; /* The width, in bytes, of a row in the table. */
|
||||
OffsetTo<typename Types::ClassTypeWide, HBUINT, false>
|
||||
NNOffsetTo<typename Types::ClassTypeWide, HBUINT>
|
||||
leftClassTable; /* Offset from beginning of this subtable to
|
||||
* left-hand class table. */
|
||||
OffsetTo<typename Types::ClassTypeWide, HBUINT, false>
|
||||
NNOffsetTo<typename Types::ClassTypeWide, HBUINT>
|
||||
rightClassTable;/* Offset from beginning of this subtable to
|
||||
* right-hand class table. */
|
||||
OffsetTo<UnsizedArrayOf<FWORD>, HBUINT, false>
|
||||
NNOffsetTo<UnsizedArrayOf<FWORD>, HBUINT>
|
||||
array; /* Offset from beginning of this subtable to
|
||||
* the start of the kerning array. */
|
||||
public:
|
||||
|
@ -471,7 +469,7 @@ struct KerxSubTableFormat4
|
|||
|
||||
struct driver_context_t
|
||||
{
|
||||
enum { in_place = true };
|
||||
static constexpr bool in_place = true;
|
||||
enum Flags
|
||||
{
|
||||
Mark = 0x8000, /* If set, remember this glyph as the marked glyph. */
|
||||
|
@ -498,16 +496,16 @@ struct KerxSubTableFormat4
|
|||
mark (0) {}
|
||||
|
||||
bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
|
||||
const Entry<EntryData> *entry)
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
return entry->data.ankrActionIndex != 0xFFFF;
|
||||
return entry.data.ankrActionIndex != 0xFFFF;
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> *entry)
|
||||
void transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
|
||||
if (mark_set && entry->data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len)
|
||||
if (mark_set && entry.data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len)
|
||||
{
|
||||
hb_glyph_position_t &o = buffer->cur_pos();
|
||||
switch (action_type)
|
||||
|
@ -515,9 +513,8 @@ struct KerxSubTableFormat4
|
|||
case 0: /* Control Point Actions.*/
|
||||
{
|
||||
/* indexed into glyph outline. */
|
||||
const HBUINT16 *data = &ankrData[entry->data.ankrActionIndex];
|
||||
if (!c->sanitizer.check_array (data, 2))
|
||||
return false;
|
||||
const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
|
||||
if (!c->sanitizer.check_array (data, 2)) return;
|
||||
HB_UNUSED unsigned int markControlPoint = *data++;
|
||||
HB_UNUSED unsigned int currControlPoint = *data++;
|
||||
hb_position_t markX = 0;
|
||||
|
@ -532,7 +529,7 @@ struct KerxSubTableFormat4
|
|||
currControlPoint,
|
||||
HB_DIRECTION_LTR /*XXX*/,
|
||||
&currX, &currY))
|
||||
return true; /* True, such that the machine continues. */
|
||||
return;
|
||||
|
||||
o.x_offset = markX - currX;
|
||||
o.y_offset = markY - currY;
|
||||
|
@ -542,19 +539,16 @@ struct KerxSubTableFormat4
|
|||
case 1: /* Anchor Point Actions. */
|
||||
{
|
||||
/* Indexed into 'ankr' table. */
|
||||
const HBUINT16 *data = &ankrData[entry->data.ankrActionIndex];
|
||||
if (!c->sanitizer.check_array (data, 2))
|
||||
return false;
|
||||
const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
|
||||
if (!c->sanitizer.check_array (data, 2)) return;
|
||||
unsigned int markAnchorPoint = *data++;
|
||||
unsigned int currAnchorPoint = *data++;
|
||||
const Anchor markAnchor = c->ankr_table->get_anchor (c->buffer->info[mark].codepoint,
|
||||
markAnchorPoint,
|
||||
c->sanitizer.get_num_glyphs (),
|
||||
c->ankr_end);
|
||||
const Anchor currAnchor = c->ankr_table->get_anchor (c->buffer->cur ().codepoint,
|
||||
currAnchorPoint,
|
||||
c->sanitizer.get_num_glyphs (),
|
||||
c->ankr_end);
|
||||
const Anchor &markAnchor = c->ankr_table->get_anchor (c->buffer->info[mark].codepoint,
|
||||
markAnchorPoint,
|
||||
c->sanitizer.get_num_glyphs ());
|
||||
const Anchor &currAnchor = c->ankr_table->get_anchor (c->buffer->cur ().codepoint,
|
||||
currAnchorPoint,
|
||||
c->sanitizer.get_num_glyphs ());
|
||||
|
||||
o.x_offset = c->font->em_scale_x (markAnchor.xCoordinate) - c->font->em_scale_x (currAnchor.xCoordinate);
|
||||
o.y_offset = c->font->em_scale_y (markAnchor.yCoordinate) - c->font->em_scale_y (currAnchor.yCoordinate);
|
||||
|
@ -563,9 +557,8 @@ struct KerxSubTableFormat4
|
|||
|
||||
case 2: /* Control Point Coordinate Actions. */
|
||||
{
|
||||
const FWORD *data = (const FWORD *) &ankrData[entry->data.ankrActionIndex];
|
||||
if (!c->sanitizer.check_array (data, 4))
|
||||
return false;
|
||||
const FWORD *data = (const FWORD *) &ankrData[entry.data.ankrActionIndex];
|
||||
if (!c->sanitizer.check_array (data, 4)) return;
|
||||
int markX = *data++;
|
||||
int markY = *data++;
|
||||
int currX = *data++;
|
||||
|
@ -581,13 +574,11 @@ struct KerxSubTableFormat4
|
|||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
|
||||
}
|
||||
|
||||
if (entry->flags & Mark)
|
||||
if (entry.flags & Mark)
|
||||
{
|
||||
mark_set = true;
|
||||
mark = buffer->idx;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -721,18 +712,18 @@ struct KerxSubTableFormat6
|
|||
{
|
||||
struct Long
|
||||
{
|
||||
LOffsetTo<Lookup<HBUINT32>, false> rowIndexTable;
|
||||
LOffsetTo<Lookup<HBUINT32>, false> columnIndexTable;
|
||||
LOffsetTo<UnsizedArrayOf<FWORD32>, false> array;
|
||||
LNNOffsetTo<Lookup<HBUINT32>> rowIndexTable;
|
||||
LNNOffsetTo<Lookup<HBUINT32>> columnIndexTable;
|
||||
LNNOffsetTo<UnsizedArrayOf<FWORD32>> array;
|
||||
} l;
|
||||
struct Short
|
||||
{
|
||||
LOffsetTo<Lookup<HBUINT16>, false> rowIndexTable;
|
||||
LOffsetTo<Lookup<HBUINT16>, false> columnIndexTable;
|
||||
LOffsetTo<UnsizedArrayOf<FWORD>, false> array;
|
||||
LNNOffsetTo<Lookup<HBUINT16>> rowIndexTable;
|
||||
LNNOffsetTo<Lookup<HBUINT16>> columnIndexTable;
|
||||
LNNOffsetTo<UnsizedArrayOf<FWORD>> array;
|
||||
} s;
|
||||
} u;
|
||||
LOffsetTo<UnsizedArrayOf<FWORD>, false> vector;
|
||||
LNNOffsetTo<UnsizedArrayOf<FWORD>> vector;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24);
|
||||
};
|
||||
|
@ -780,17 +771,17 @@ struct KerxSubTable
|
|||
unsigned int get_size () const { return u.header.length; }
|
||||
unsigned int get_type () const { return u.header.coverage & u.header.SubtableType; }
|
||||
|
||||
template <typename context_t>
|
||||
typename context_t::return_t dispatch (context_t *c) const
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
unsigned int subtable_type = get_type ();
|
||||
TRACE_DISPATCH (this, subtable_type);
|
||||
switch (subtable_type) {
|
||||
case 0: return_trace (c->dispatch (u.format0));
|
||||
case 1: return_trace (c->dispatch (u.format1));
|
||||
case 2: return_trace (c->dispatch (u.format2));
|
||||
case 4: return_trace (c->dispatch (u.format4));
|
||||
case 6: return_trace (c->dispatch (u.format6));
|
||||
case 0: return_trace (c->dispatch (u.format0, hb_forward<Ts> (ds)...));
|
||||
case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
|
||||
case 4: return_trace (c->dispatch (u.format4, hb_forward<Ts> (ds)...));
|
||||
case 6: return_trace (c->dispatch (u.format6, hb_forward<Ts> (ds)...));
|
||||
default: return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
@ -981,8 +972,8 @@ struct kerx : KerxTable<kerx>
|
|||
{
|
||||
friend struct KerxTable<kerx>;
|
||||
|
||||
enum { tableTag = HB_AAT_TAG_kerx };
|
||||
enum { minVersion = 2u };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_kerx;
|
||||
static constexpr unsigned minVersion = 2u;
|
||||
|
||||
typedef KerxSubTableHeader SubTableHeader;
|
||||
typedef SubTableHeader::Types Types;
|
||||
|
|
|
@ -38,9 +38,83 @@ namespace AAT {
|
|||
|
||||
typedef ArrayOf<HBINT16> LigCaretClassEntry;
|
||||
|
||||
struct lcarFormat0
|
||||
{
|
||||
unsigned int get_lig_carets (hb_font_t *font,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t glyph,
|
||||
unsigned int start_offset,
|
||||
unsigned int *caret_count /* IN/OUT */,
|
||||
hb_position_t *caret_array /* OUT */,
|
||||
const void *base) const
|
||||
{
|
||||
const OffsetTo<LigCaretClassEntry>* entry_offset = lookupTable.get_value (glyph,
|
||||
font->face->get_num_glyphs ());
|
||||
const LigCaretClassEntry& array = entry_offset ? base+*entry_offset : Null (LigCaretClassEntry);
|
||||
if (caret_count)
|
||||
{
|
||||
hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
|
||||
for (unsigned int i = 0; i < arr.length; ++i)
|
||||
caret_array[i] = font->em_scale_dir (arr[i], direction);
|
||||
}
|
||||
return array.len;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
|
||||
}
|
||||
|
||||
protected:
|
||||
Lookup<OffsetTo<LigCaretClassEntry>>
|
||||
lookupTable; /* data Lookup table associating glyphs */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (2);
|
||||
};
|
||||
|
||||
struct lcarFormat1
|
||||
{
|
||||
unsigned int get_lig_carets (hb_font_t *font,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t glyph,
|
||||
unsigned int start_offset,
|
||||
unsigned int *caret_count /* IN/OUT */,
|
||||
hb_position_t *caret_array /* OUT */,
|
||||
const void *base) const
|
||||
{
|
||||
const OffsetTo<LigCaretClassEntry>* entry_offset = lookupTable.get_value (glyph,
|
||||
font->face->get_num_glyphs ());
|
||||
const LigCaretClassEntry& array = entry_offset ? base+*entry_offset : Null (LigCaretClassEntry);
|
||||
if (caret_count)
|
||||
{
|
||||
hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
|
||||
for (unsigned int i = 0; i < arr.length; ++i)
|
||||
{
|
||||
hb_position_t x = 0, y = 0;
|
||||
font->get_glyph_contour_point_for_origin (glyph, arr[i], direction, &x, &y);
|
||||
caret_array[i] = HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
|
||||
}
|
||||
}
|
||||
return array.len;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
|
||||
}
|
||||
|
||||
protected:
|
||||
Lookup<OffsetTo<LigCaretClassEntry>>
|
||||
lookupTable; /* data Lookup table associating glyphs */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (2);
|
||||
};
|
||||
|
||||
struct lcar
|
||||
{
|
||||
enum { tableTag = HB_AAT_TAG_lcar };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_lcar;
|
||||
|
||||
unsigned int get_lig_carets (hb_font_t *font,
|
||||
hb_direction_t direction,
|
||||
|
@ -49,41 +123,36 @@ struct lcar
|
|||
unsigned int *caret_count /* IN/OUT */,
|
||||
hb_position_t *caret_array /* OUT */) const
|
||||
{
|
||||
const OffsetTo<LigCaretClassEntry>* entry_offset = lookup.get_value (glyph,
|
||||
font->face->get_num_glyphs ());
|
||||
const LigCaretClassEntry& array = entry_offset ? this+*entry_offset : Null (LigCaretClassEntry);
|
||||
if (caret_count)
|
||||
switch (format)
|
||||
{
|
||||
hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
|
||||
unsigned int count = arr.length;
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
switch (format)
|
||||
{
|
||||
case 0: caret_array[i] = font->em_scale_dir (arr[i], direction); break;
|
||||
case 1:
|
||||
hb_position_t x, y;
|
||||
font->get_glyph_contour_point_for_origin (glyph, arr[i], direction, &x, &y);
|
||||
caret_array[i] = HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
|
||||
break;
|
||||
}
|
||||
case 0: return u.format0.get_lig_carets (font, direction, glyph, start_offset,
|
||||
caret_count, caret_array, this);
|
||||
case 1: return u.format1.get_lig_carets (font, direction, glyph, start_offset,
|
||||
caret_count, caret_array, this);
|
||||
default:if (caret_count) *caret_count = 0; return 0;
|
||||
}
|
||||
return array.len;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
version.major == 1 &&
|
||||
lookup.sanitize (c, this)));
|
||||
if (unlikely (!c->check_struct (this) || version.major != 1))
|
||||
return_trace (false);
|
||||
|
||||
switch (format) {
|
||||
case 0: return_trace (u.format0.sanitize (c, this));
|
||||
case 1: return_trace (u.format1.sanitize (c, this));
|
||||
default:return_trace (true);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version number of the ligature caret table */
|
||||
HBUINT16 format; /* Format of the ligature caret table. */
|
||||
Lookup<OffsetTo<LigCaretClassEntry> >
|
||||
lookup; /* data Lookup table associating glyphs */
|
||||
|
||||
union {
|
||||
lcarFormat0 format0;
|
||||
lcarFormat0 format1;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_MIN (8);
|
||||
};
|
||||
|
|
|
@ -54,7 +54,7 @@ struct RearrangementSubtable
|
|||
|
||||
struct driver_context_t
|
||||
{
|
||||
enum { in_place = true };
|
||||
static constexpr bool in_place = true;
|
||||
enum Flags
|
||||
{
|
||||
MarkFirst = 0x8000, /* If set, make the current glyph the first
|
||||
|
@ -74,21 +74,21 @@ struct RearrangementSubtable
|
|||
start (0), end (0) {}
|
||||
|
||||
bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
|
||||
const Entry<EntryData> *entry)
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
return (entry->flags & Verb) && start < end;
|
||||
return (entry.flags & Verb) && start < end;
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> *entry)
|
||||
void transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
unsigned int flags = entry->flags;
|
||||
unsigned int flags = entry.flags;
|
||||
|
||||
if (flags & MarkFirst)
|
||||
start = buffer->idx;
|
||||
|
||||
if (flags & MarkLast)
|
||||
end = MIN (buffer->idx + 1, buffer->len);
|
||||
end = hb_min (buffer->idx + 1, buffer->len);
|
||||
|
||||
if ((flags & Verb) && start < end)
|
||||
{
|
||||
|
@ -117,14 +117,14 @@ struct RearrangementSubtable
|
|||
};
|
||||
|
||||
unsigned int m = map[flags & Verb];
|
||||
unsigned int l = MIN<unsigned int> (2, m >> 4);
|
||||
unsigned int r = MIN<unsigned int> (2, m & 0x0F);
|
||||
unsigned int l = hb_min (2u, m >> 4);
|
||||
unsigned int r = hb_min (2u, 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, hb_min (buffer->idx + 1, buffer->len));
|
||||
buffer->merge_clusters (start, end);
|
||||
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
@ -152,8 +152,6 @@ struct RearrangementSubtable
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -204,7 +202,7 @@ struct ContextualSubtable
|
|||
|
||||
struct driver_context_t
|
||||
{
|
||||
enum { in_place = true };
|
||||
static constexpr bool in_place = true;
|
||||
enum Flags
|
||||
{
|
||||
SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */
|
||||
|
@ -223,39 +221,39 @@ struct ContextualSubtable
|
|||
subs (table+table->substitutionTables) {}
|
||||
|
||||
bool is_actionable (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> *entry)
|
||||
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;
|
||||
return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> *entry)
|
||||
void transition (StateTableDriver<Types, 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;
|
||||
return;
|
||||
|
||||
const GlyphID *replacement;
|
||||
|
||||
replacement = nullptr;
|
||||
if (Types::extended)
|
||||
{
|
||||
if (entry->data.markIndex != 0xFFFF)
|
||||
if (entry.data.markIndex != 0xFFFF)
|
||||
{
|
||||
const Lookup<GlyphID> &lookup = subs[entry->data.markIndex];
|
||||
const Lookup<GlyphID> &lookup = subs[entry.data.markIndex];
|
||||
replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int offset = entry->data.markIndex + buffer->info[mark].codepoint;
|
||||
unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint;
|
||||
const UnsizedArrayOf<GlyphID> &subs_old = (const UnsizedArrayOf<GlyphID> &) subs;
|
||||
replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
|
||||
if (!replacement->sanitize (&c->sanitizer) || !*replacement)
|
||||
|
@ -263,24 +261,24 @@ struct ContextualSubtable
|
|||
}
|
||||
if (replacement)
|
||||
{
|
||||
buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
|
||||
buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
|
||||
buffer->info[mark].codepoint = *replacement;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
replacement = nullptr;
|
||||
unsigned int idx = MIN (buffer->idx, buffer->len - 1);
|
||||
unsigned int idx = hb_min (buffer->idx, buffer->len - 1);
|
||||
if (Types::extended)
|
||||
{
|
||||
if (entry->data.currentIndex != 0xFFFF)
|
||||
if (entry.data.currentIndex != 0xFFFF)
|
||||
{
|
||||
const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex];
|
||||
const Lookup<GlyphID> &lookup = subs[entry.data.currentIndex];
|
||||
replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int offset = entry->data.currentIndex + buffer->info[idx].codepoint;
|
||||
unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint;
|
||||
const UnsizedArrayOf<GlyphID> &subs_old = (const UnsizedArrayOf<GlyphID> &) subs;
|
||||
replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
|
||||
if (!replacement->sanitize (&c->sanitizer) || !*replacement)
|
||||
|
@ -292,13 +290,11 @@ struct ContextualSubtable
|
|||
ret = true;
|
||||
}
|
||||
|
||||
if (entry->flags & SetMark)
|
||||
if (entry.flags & SetMark)
|
||||
{
|
||||
mark_set = true;
|
||||
mark = buffer->idx;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -341,9 +337,9 @@ struct ContextualSubtable
|
|||
const EntryData &data = entries[i].data;
|
||||
|
||||
if (data.markIndex != 0xFFFF)
|
||||
num_lookups = MAX<unsigned int> (num_lookups, 1 + data.markIndex);
|
||||
num_lookups = hb_max (num_lookups, 1 + data.markIndex);
|
||||
if (data.currentIndex != 0xFFFF)
|
||||
num_lookups = MAX<unsigned int> (num_lookups, 1 + data.currentIndex);
|
||||
num_lookups = hb_max (num_lookups, 1 + data.currentIndex);
|
||||
}
|
||||
|
||||
return_trace (substitutionTables.sanitize (c, this, num_lookups));
|
||||
|
@ -352,7 +348,7 @@ struct ContextualSubtable
|
|||
protected:
|
||||
StateTable<Types, EntryData>
|
||||
machine;
|
||||
OffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false>, HBUINT, false>
|
||||
NNOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false>, HBUINT>
|
||||
substitutionTables;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (20);
|
||||
|
@ -385,11 +381,11 @@ struct LigatureEntry<true>
|
|||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
static bool performAction (const Entry<EntryData> *entry)
|
||||
{ return entry->flags & PerformAction; }
|
||||
static bool performAction (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & PerformAction; }
|
||||
|
||||
static unsigned int ligActionIndex (const Entry<EntryData> *entry)
|
||||
{ return entry->data.ligActionIndex; }
|
||||
static unsigned int ligActionIndex (const Entry<EntryData> &entry)
|
||||
{ return entry.data.ligActionIndex; }
|
||||
};
|
||||
template <>
|
||||
struct LigatureEntry<false>
|
||||
|
@ -407,11 +403,11 @@ struct LigatureEntry<false>
|
|||
|
||||
typedef void EntryData;
|
||||
|
||||
static bool performAction (const Entry<EntryData> *entry)
|
||||
{ return entry->flags & Offset; }
|
||||
static bool performAction (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & Offset; }
|
||||
|
||||
static unsigned int ligActionIndex (const Entry<EntryData> *entry)
|
||||
{ return entry->flags & Offset; }
|
||||
static unsigned int ligActionIndex (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & Offset; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -425,7 +421,7 @@ struct LigatureSubtable
|
|||
|
||||
struct driver_context_t
|
||||
{
|
||||
enum { in_place = false };
|
||||
static constexpr bool in_place = false;
|
||||
enum
|
||||
{
|
||||
DontAdvance = LigatureEntryT::DontAdvance,
|
||||
|
@ -453,26 +449,23 @@ struct LigatureSubtable
|
|||
match_length (0) {}
|
||||
|
||||
bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
|
||||
const Entry<EntryData> *entry)
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
return LigatureEntryT::performAction (entry);
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> *entry)
|
||||
void transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
|
||||
DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx);
|
||||
if (entry->flags & LigatureEntryT::SetComponent)
|
||||
if (entry.flags & LigatureEntryT::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)
|
||||
if (match_length && match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] == buffer->out_len)
|
||||
match_length--;
|
||||
|
||||
match_positions[match_length++] = buffer->out_len;
|
||||
match_positions[match_length++ % ARRAY_LENGTH (match_positions)] = buffer->out_len;
|
||||
DEBUG_MSG (APPLY, nullptr, "Set component at %u", buffer->out_len);
|
||||
}
|
||||
|
||||
|
@ -482,10 +475,10 @@ struct LigatureSubtable
|
|||
unsigned int end = buffer->out_len;
|
||||
|
||||
if (unlikely (!match_length))
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (buffer->idx >= buffer->len)
|
||||
return false; // TODO Work on previous instead?
|
||||
return; /* TODO Work on previous instead? */
|
||||
|
||||
unsigned int cursor = match_length;
|
||||
|
||||
|
@ -506,9 +499,9 @@ struct LigatureSubtable
|
|||
}
|
||||
|
||||
DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1);
|
||||
buffer->move_to (match_positions[--cursor]);
|
||||
buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]);
|
||||
|
||||
if (unlikely (!actionData->sanitize (&c->sanitizer))) return false;
|
||||
if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
|
||||
action = *actionData;
|
||||
|
||||
uint32_t uoffset = action & LigActionOffset;
|
||||
|
@ -518,7 +511,7 @@ struct LigatureSubtable
|
|||
unsigned int component_idx = buffer->cur().codepoint + offset;
|
||||
component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ);
|
||||
const HBUINT16 &componentData = component[component_idx];
|
||||
if (unlikely (!componentData.sanitize (&c->sanitizer))) return false;
|
||||
if (unlikely (!componentData.sanitize (&c->sanitizer))) break;
|
||||
ligature_idx += componentData;
|
||||
|
||||
DEBUG_MSG (APPLY, nullptr, "Action store %u last %u",
|
||||
|
@ -528,23 +521,23 @@ struct LigatureSubtable
|
|||
{
|
||||
ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
|
||||
const GlyphID &ligatureData = ligature[ligature_idx];
|
||||
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false;
|
||||
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break;
|
||||
hb_codepoint_t lig = ligatureData;
|
||||
|
||||
DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
|
||||
buffer->replace_glyph (lig);
|
||||
|
||||
unsigned int lig_end = match_positions[match_length - 1] + 1;
|
||||
unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u;
|
||||
/* Now go and delete all subsequent components. */
|
||||
while (match_length - 1 > cursor)
|
||||
while (match_length - 1u > cursor)
|
||||
{
|
||||
DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
|
||||
buffer->move_to (match_positions[--match_length]);
|
||||
buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]);
|
||||
buffer->replace_glyph (DELETED_GLYPH);
|
||||
}
|
||||
|
||||
buffer->move_to (lig_end);
|
||||
buffer->merge_out_clusters (match_positions[cursor], buffer->out_len);
|
||||
buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len);
|
||||
}
|
||||
|
||||
actionData++;
|
||||
|
@ -552,8 +545,6 @@ struct LigatureSubtable
|
|||
while (!(action & LigActionLast));
|
||||
buffer->move_to (end);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -591,11 +582,11 @@ struct LigatureSubtable
|
|||
protected:
|
||||
StateTable<Types, EntryData>
|
||||
machine;
|
||||
OffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT, false>
|
||||
NNOffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT>
|
||||
ligAction; /* Offset to the ligature action table. */
|
||||
OffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT, false>
|
||||
NNOffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT>
|
||||
component; /* Offset to the component table. */
|
||||
OffsetTo<UnsizedArrayOf<GlyphID>, HBUINT, false>
|
||||
NNOffsetTo<UnsizedArrayOf<GlyphID>, HBUINT>
|
||||
ligature; /* Offset to the actual ligature lists. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (28);
|
||||
|
@ -661,7 +652,7 @@ struct InsertionSubtable
|
|||
|
||||
struct driver_context_t
|
||||
{
|
||||
enum { in_place = false };
|
||||
static constexpr bool in_place = false;
|
||||
enum Flags
|
||||
{
|
||||
SetMark = 0x8000, /* If set, mark the current glyph. */
|
||||
|
@ -714,28 +705,29 @@ struct InsertionSubtable
|
|||
hb_aat_apply_context_t *c_) :
|
||||
ret (false),
|
||||
c (c_),
|
||||
mark_set (false),
|
||||
mark (0),
|
||||
insertionAction (table+table->insertionAction) {}
|
||||
|
||||
bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
|
||||
const Entry<EntryData> *entry)
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
return (entry->flags & (CurrentInsertCount | MarkedInsertCount)) &&
|
||||
(entry->data.currentInsertIndex != 0xFFFF ||entry->data.markedInsertIndex != 0xFFFF);
|
||||
return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
|
||||
(entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> *entry)
|
||||
void transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
unsigned int flags = entry->flags;
|
||||
unsigned int flags = entry.flags;
|
||||
|
||||
if (entry->data.markedInsertIndex != 0xFFFF && mark_set)
|
||||
unsigned mark_loc = buffer->out_len;
|
||||
|
||||
if (entry.data.markedInsertIndex != 0xFFFF)
|
||||
{
|
||||
unsigned int count = (flags & MarkedInsertCount);
|
||||
unsigned int start = entry->data.markedInsertIndex;
|
||||
unsigned int start = entry.data.markedInsertIndex;
|
||||
const GlyphID *glyphs = &insertionAction[start];
|
||||
if (unlikely (!c->sanitizer.check_array (glyphs, count))) return false;
|
||||
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
|
||||
|
||||
bool before = flags & MarkedInsertBefore;
|
||||
|
||||
|
@ -752,15 +744,18 @@ struct InsertionSubtable
|
|||
|
||||
buffer->move_to (end + count);
|
||||
|
||||
buffer->unsafe_to_break_from_outbuffer (mark, MIN (buffer->idx + 1, buffer->len));
|
||||
buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len));
|
||||
}
|
||||
|
||||
if (entry->data.currentInsertIndex != 0xFFFF)
|
||||
if (flags & SetMark)
|
||||
mark = mark_loc;
|
||||
|
||||
if (entry.data.currentInsertIndex != 0xFFFF)
|
||||
{
|
||||
unsigned int count = (flags & CurrentInsertCount) >> 5;
|
||||
unsigned int start = entry->data.currentInsertIndex;
|
||||
unsigned int start = entry.data.currentInsertIndex;
|
||||
const GlyphID *glyphs = &insertionAction[start];
|
||||
if (unlikely (!c->sanitizer.check_array (glyphs, count))) return false;
|
||||
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
|
||||
|
||||
bool before = flags & CurrentInsertBefore;
|
||||
|
||||
|
@ -791,21 +786,12 @@ struct InsertionSubtable
|
|||
*/
|
||||
buffer->move_to ((flags & DontAdvance) ? end : end + count);
|
||||
}
|
||||
|
||||
if (flags & SetMark)
|
||||
{
|
||||
mark_set = true;
|
||||
mark = buffer->out_len;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
bool ret;
|
||||
private:
|
||||
hb_aat_apply_context_t *c;
|
||||
bool mark_set;
|
||||
unsigned int mark;
|
||||
const UnsizedArrayOf<GlyphID> &insertionAction;
|
||||
};
|
||||
|
@ -833,7 +819,7 @@ struct InsertionSubtable
|
|||
protected:
|
||||
StateTable<Types, EntryData>
|
||||
machine;
|
||||
OffsetTo<UnsizedArrayOf<GlyphID>, HBUINT, false>
|
||||
NNOffsetTo<UnsizedArrayOf<GlyphID>, HBUINT>
|
||||
insertionAction; /* Byte offset from stateHeader to the start of
|
||||
* the insertion glyph table. */
|
||||
public:
|
||||
|
@ -897,17 +883,17 @@ struct ChainSubtable
|
|||
Insertion = 5
|
||||
};
|
||||
|
||||
template <typename context_t>
|
||||
typename context_t::return_t dispatch (context_t *c) const
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) 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));
|
||||
case Rearrangement: return_trace (c->dispatch (u.rearrangement, hb_forward<Ts> (ds)...));
|
||||
case Contextual: return_trace (c->dispatch (u.contextual, hb_forward<Ts> (ds)...));
|
||||
case Ligature: return_trace (c->dispatch (u.ligature, hb_forward<Ts> (ds)...));
|
||||
case Noncontextual: return_trace (c->dispatch (u.noncontextual, hb_forward<Ts> (ds)...));
|
||||
case Insertion: return_trace (c->dispatch (u.insertion, hb_forward<Ts> (ds)...));
|
||||
default: return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
@ -983,7 +969,7 @@ struct Chain
|
|||
void apply (hb_aat_apply_context_t *c,
|
||||
hb_mask_t flags) const
|
||||
{
|
||||
const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
|
||||
const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
|
||||
unsigned int count = subtableCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
|
@ -1045,7 +1031,7 @@ struct Chain
|
|||
if (unlikely (!c->buffer->successful)) return;
|
||||
|
||||
skip:
|
||||
subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
|
||||
subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
|
||||
c->set_lookup_index (c->lookup_index + 1);
|
||||
}
|
||||
}
|
||||
|
@ -1063,13 +1049,13 @@ struct Chain
|
|||
if (!c->check_array (featureZ.arrayZ, featureCount))
|
||||
return_trace (false);
|
||||
|
||||
const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
|
||||
const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
|
||||
unsigned int count = subtableCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (!subtable->sanitize (c))
|
||||
return_trace (false);
|
||||
subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
|
||||
subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
|
@ -1097,7 +1083,7 @@ struct Chain
|
|||
template <typename Types>
|
||||
struct mortmorx
|
||||
{
|
||||
enum { tableTag = HB_AAT_TAG_morx };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_morx;
|
||||
|
||||
bool has_data () const { return version != 0; }
|
||||
|
||||
|
@ -1109,7 +1095,7 @@ struct mortmorx
|
|||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
map->chain_flags.push (chain->compile_flags (mapper));
|
||||
chain = &StructAfter<Chain<Types> > (*chain);
|
||||
chain = &StructAfter<Chain<Types>> (*chain);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1123,7 +1109,7 @@ struct mortmorx
|
|||
{
|
||||
chain->apply (c, c->plan->aat_map.chain_flags[i]);
|
||||
if (unlikely (!c->buffer->successful)) return;
|
||||
chain = &StructAfter<Chain<Types> > (*chain);
|
||||
chain = &StructAfter<Chain<Types>> (*chain);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1139,7 +1125,7 @@ struct mortmorx
|
|||
{
|
||||
if (!chain->sanitize (c, version))
|
||||
return_trace (false);
|
||||
chain = &StructAfter<Chain<Types> > (*chain);
|
||||
chain = &StructAfter<Chain<Types>> (*chain);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
|
@ -1159,11 +1145,11 @@ struct mortmorx
|
|||
|
||||
struct morx : mortmorx<ExtendedTypes>
|
||||
{
|
||||
enum { tableTag = HB_AAT_TAG_morx };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_morx;
|
||||
};
|
||||
struct mort : mortmorx<ObsoleteTypes>
|
||||
{
|
||||
enum { tableTag = HB_AAT_TAG_mort };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_mort;
|
||||
};
|
||||
|
||||
|
||||
|
|
173
src/hb-aat-layout-opbd-table.hh
Normal file
173
src/hb-aat-layout-opbd-table.hh
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright © 2019 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_OPBD_TABLE_HH
|
||||
#define HB_AAT_LAYOUT_OPBD_TABLE_HH
|
||||
|
||||
#include "hb-aat-layout-common.hh"
|
||||
#include "hb-open-type.hh"
|
||||
|
||||
/*
|
||||
* opbd -- Optical Bounds
|
||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6opbd.html
|
||||
*/
|
||||
#define HB_AAT_TAG_opbd HB_TAG('o','p','b','d')
|
||||
|
||||
|
||||
namespace AAT {
|
||||
|
||||
struct OpticalBounds
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this)));
|
||||
}
|
||||
|
||||
FWORD leftSide;
|
||||
FWORD topSide;
|
||||
FWORD rightSide;
|
||||
FWORD bottomSide;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
};
|
||||
|
||||
struct opbdFormat0
|
||||
{
|
||||
bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
|
||||
hb_glyph_extents_t *extents, const void *base) const
|
||||
{
|
||||
const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
|
||||
if (!bounds_offset) return false;
|
||||
const OpticalBounds &bounds = base+*bounds_offset;
|
||||
|
||||
if (extents)
|
||||
*extents = {
|
||||
font->em_scale_x (bounds.leftSide),
|
||||
font->em_scale_y (bounds.topSide),
|
||||
font->em_scale_x (bounds.rightSide),
|
||||
font->em_scale_y (bounds.bottomSide)
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
|
||||
}
|
||||
|
||||
protected:
|
||||
Lookup<OffsetTo<OpticalBounds>>
|
||||
lookupTable; /* Lookup table associating glyphs with the four
|
||||
* int16 values for the left-side, top-side,
|
||||
* right-side, and bottom-side optical bounds. */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (2);
|
||||
};
|
||||
|
||||
struct opbdFormat1
|
||||
{
|
||||
bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
|
||||
hb_glyph_extents_t *extents, const void *base) const
|
||||
{
|
||||
const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
|
||||
if (!bounds_offset) return false;
|
||||
const OpticalBounds &bounds = base+*bounds_offset;
|
||||
|
||||
hb_position_t left = 0, top = 0, right = 0, bottom = 0, ignore;
|
||||
if (font->get_glyph_contour_point (glyph_id, bounds.leftSide, &left, &ignore) ||
|
||||
font->get_glyph_contour_point (glyph_id, bounds.topSide, &ignore, &top) ||
|
||||
font->get_glyph_contour_point (glyph_id, bounds.rightSide, &right, &ignore) ||
|
||||
font->get_glyph_contour_point (glyph_id, bounds.bottomSide, &ignore, &bottom))
|
||||
{
|
||||
if (extents)
|
||||
*extents = {left, top, right, bottom};
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) && lookupTable.sanitize (c, base)));
|
||||
}
|
||||
|
||||
protected:
|
||||
Lookup<OffsetTo<OpticalBounds>>
|
||||
lookupTable; /* Lookup table associating glyphs with the four
|
||||
* int16 values for the left-side, top-side,
|
||||
* right-side, and bottom-side optical bounds. */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (2);
|
||||
};
|
||||
|
||||
struct opbd
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_opbd;
|
||||
|
||||
bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 0: return u.format0.get_bounds (font, glyph_id, extents, this);
|
||||
case 1: return u.format1.get_bounds (font, glyph_id, extents, this);
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this) || version.major != 1))
|
||||
return_trace (false);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case 0: return_trace (u.format0.sanitize (c, this));
|
||||
case 1: return_trace (u.format1.sanitize (c, this));
|
||||
default:return_trace (true);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version number of the optical bounds
|
||||
* table (0x00010000 for the current version). */
|
||||
HBUINT16 format; /* Format of the optical bounds table.
|
||||
* Format 0 indicates distance and Format 1 indicates
|
||||
* control point. */
|
||||
union {
|
||||
opbdFormat0 format0;
|
||||
opbdFormat1 format1;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_MIN (8);
|
||||
};
|
||||
|
||||
} /* namespace AAT */
|
||||
|
||||
|
||||
#endif /* HB_AAT_LAYOUT_OPBD_TABLE_HH */
|
|
@ -66,7 +66,7 @@ struct TrackTableEntry
|
|||
NameID trackNameID; /* The 'name' table index for this track.
|
||||
* (a short word or phrase like "loose"
|
||||
* or "very tight") */
|
||||
OffsetTo<UnsizedArrayOf<FWORD>, HBUINT16, false>
|
||||
NNOffsetTo<UnsizedArrayOf<FWORD>>
|
||||
valuesZ; /* Offset from start of tracking table to
|
||||
* per-size tracking values for this track. */
|
||||
|
||||
|
@ -153,7 +153,7 @@ struct TrackData
|
|||
|
||||
struct trak
|
||||
{
|
||||
enum { tableTag = HB_AAT_TAG_trak };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_trak;
|
||||
|
||||
bool has_data () const { return version.to_int (); }
|
||||
|
||||
|
|
|
@ -25,9 +25,8 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-ot-face.hh"
|
||||
#include "hb-aat-layout.hh"
|
||||
#include "hb-aat-fdsc-table.hh" // Just so we compile it; unused otherwise.
|
||||
#include "hb-aat-layout-ankr-table.hh"
|
||||
|
@ -40,6 +39,42 @@
|
|||
#include "hb-aat-ltag-table.hh"
|
||||
|
||||
|
||||
/*
|
||||
* hb_aat_apply_context_t
|
||||
*/
|
||||
|
||||
/* Note: This context is used for kerning, even without AAT, hence the condition. */
|
||||
#if !defined(HB_NO_AAT) || !defined(HB_NO_OT_KERN)
|
||||
|
||||
AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
|
||||
hb_font_t *font_,
|
||||
hb_buffer_t *buffer_,
|
||||
hb_blob_t *blob) :
|
||||
plan (plan_),
|
||||
font (font_),
|
||||
face (font->face),
|
||||
buffer (buffer_),
|
||||
sanitizer (),
|
||||
ankr_table (&Null(AAT::ankr)),
|
||||
lookup_index (0),
|
||||
debug_depth (0)
|
||||
{
|
||||
sanitizer.init (blob);
|
||||
sanitizer.set_num_glyphs (face->get_num_glyphs ());
|
||||
sanitizer.start_processing ();
|
||||
sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX);
|
||||
}
|
||||
|
||||
AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t ()
|
||||
{ sanitizer.end_processing (); }
|
||||
|
||||
void
|
||||
AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_)
|
||||
{ ankr_table = ankr_table_; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hb-aat-layout
|
||||
* @title: hb-aat-layout
|
||||
|
@ -50,6 +85,8 @@
|
|||
**/
|
||||
|
||||
|
||||
#if !defined(HB_NO_AAT) || defined(HAVE_CORETEXT)
|
||||
|
||||
/* Table data courtesy of Apple. Converted from mnemonics to integers
|
||||
* when moving to this file. */
|
||||
static const hb_aat_feature_mapping_t feature_mappings[] =
|
||||
|
@ -135,49 +172,16 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
|
|||
const hb_aat_feature_mapping_t *
|
||||
hb_aat_layout_find_feature_mapping (hb_tag_t tag)
|
||||
{
|
||||
return (const hb_aat_feature_mapping_t *) bsearch (&tag,
|
||||
feature_mappings,
|
||||
ARRAY_LENGTH (feature_mappings),
|
||||
sizeof (feature_mappings[0]),
|
||||
hb_aat_feature_mapping_t::cmp);
|
||||
return (const hb_aat_feature_mapping_t *) hb_bsearch (&tag,
|
||||
feature_mappings,
|
||||
ARRAY_LENGTH (feature_mappings),
|
||||
sizeof (feature_mappings[0]),
|
||||
hb_aat_feature_mapping_t::cmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* hb_aat_apply_context_t
|
||||
*/
|
||||
|
||||
AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
|
||||
hb_font_t *font_,
|
||||
hb_buffer_t *buffer_,
|
||||
hb_blob_t *blob) :
|
||||
plan (plan_),
|
||||
font (font_),
|
||||
face (font->face),
|
||||
buffer (buffer_),
|
||||
sanitizer (),
|
||||
ankr_table (&Null(AAT::ankr)),
|
||||
ankr_end (nullptr),
|
||||
lookup_index (0),
|
||||
debug_depth (0)
|
||||
{
|
||||
sanitizer.init (blob);
|
||||
sanitizer.set_num_glyphs (face->get_num_glyphs ());
|
||||
sanitizer.start_processing ();
|
||||
sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX);
|
||||
}
|
||||
|
||||
AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t ()
|
||||
{ sanitizer.end_processing (); }
|
||||
|
||||
void
|
||||
AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_,
|
||||
const char *ankr_end_)
|
||||
{
|
||||
ankr_table = ankr_table_;
|
||||
ankr_end = ankr_end_;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
|
||||
/*
|
||||
* mort/morx/kerx/trak
|
||||
|
@ -286,11 +290,8 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
|
|||
hb_blob_t *kerx_blob = font->face->table.kerx.get_blob ();
|
||||
const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
|
||||
|
||||
hb_blob_t *ankr_blob = font->face->table.ankr.get_blob ();;
|
||||
const AAT::ankr& ankr = *font->face->table.ankr;
|
||||
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
|
||||
c.set_ankr_table (&ankr, ankr_blob->data + ankr_blob->length);
|
||||
c.set_ankr_table (font->face->table.ankr.get ());
|
||||
kerx.apply (&c);
|
||||
}
|
||||
|
||||
|
@ -319,14 +320,6 @@ hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
|
|||
trak.apply (&c);
|
||||
}
|
||||
|
||||
|
||||
hb_language_t
|
||||
_hb_aat_language_get (hb_face_t *face,
|
||||
unsigned int i)
|
||||
{
|
||||
return face->table.ltag->get_language (i);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_aat_layout_get_feature_types:
|
||||
* @face: a face object
|
||||
|
@ -390,3 +383,6 @@ hb_aat_layout_feature_type_get_selector_infos (hb_face_t
|
|||
{
|
||||
return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -85,7 +85,7 @@ typedef enum
|
|||
HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE = 39,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE = 103,
|
||||
|
||||
_HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
|
||||
_HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
} hb_aat_layout_feature_type_t;
|
||||
|
||||
/**
|
||||
|
@ -424,7 +424,7 @@ typedef enum
|
|||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_CJK_ROMAN = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_CJK_ROMAN = 3,
|
||||
|
||||
_HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
|
||||
_HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
} hb_aat_layout_feature_selector_t;
|
||||
|
||||
HB_EXTERN unsigned int
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "hb.hh"
|
||||
|
||||
#include "hb-ot-shape.hh"
|
||||
|
||||
#include "hb-aat-ltag-table.hh"
|
||||
|
||||
struct hb_aat_feature_mapping_t
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ struct hb_aat_feature_mapping_t
|
|||
hb_aat_layout_feature_selector_t selectorToEnable;
|
||||
hb_aat_layout_feature_selector_t selectorToDisable;
|
||||
|
||||
static int cmp (const void *key_, const void *entry_)
|
||||
HB_INTERNAL static int cmp (const void *key_, const void *entry_)
|
||||
{
|
||||
hb_tag_t key = * (unsigned int *) key_;
|
||||
const hb_aat_feature_mapping_t * entry = (const hb_aat_feature_mapping_t *) entry_;
|
||||
|
@ -77,9 +77,5 @@ hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
|
|||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
HB_INTERNAL hb_language_t
|
||||
_hb_aat_language_get (hb_face_t *face,
|
||||
unsigned int i);
|
||||
|
||||
|
||||
#endif /* HB_AAT_LAYOUT_HH */
|
||||
|
|
|
@ -50,7 +50,7 @@ struct FTStringRange
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<UnsizedArrayOf<HBUINT8>, HBUINT16, false>
|
||||
NNOffsetTo<UnsizedArrayOf<HBUINT8>>
|
||||
tag; /* Offset from the start of the table to
|
||||
* the beginning of the string */
|
||||
HBUINT16 length; /* String length (in bytes) */
|
||||
|
@ -60,7 +60,7 @@ struct FTStringRange
|
|||
|
||||
struct ltag
|
||||
{
|
||||
enum { tableTag = HB_AAT_TAG_ltag };
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_ltag;
|
||||
|
||||
hb_language_t get_language (unsigned int i) const
|
||||
{
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
|
||||
#include "hb-aat-map.hh"
|
||||
|
||||
#include "hb-aat-layout.hh"
|
||||
|
@ -66,3 +70,6 @@ hb_aat_map_builder_t::compile (hb_aat_map_t &m)
|
|||
|
||||
hb_aat_layout_compile_map (this, &m);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -66,7 +66,7 @@ struct hb_aat_map_builder_t
|
|||
hb_aat_layout_feature_selector_t setting;
|
||||
unsigned seq; /* For stable sorting only. */
|
||||
|
||||
static int cmp (const void *pa, const void *pb)
|
||||
HB_INTERNAL static int cmp (const void *pa, const void *pb)
|
||||
{
|
||||
const feature_info_t *a = (const feature_info_t *) pa;
|
||||
const feature_info_t *b = (const feature_info_t *) pb;
|
||||
|
@ -84,7 +84,7 @@ struct hb_aat_map_builder_t
|
|||
hb_face_t *face;
|
||||
|
||||
public:
|
||||
hb_vector_t<feature_info_t> features;
|
||||
hb_sorted_vector_t<feature_info_t> features;
|
||||
};
|
||||
|
||||
|
||||
|
|
1042
src/hb-algs.hh
Normal file
1042
src/hb-algs.hh
Normal file
File diff suppressed because it is too large
Load diff
119
src/hb-array.hh
119
src/hb-array.hh
|
@ -28,7 +28,7 @@
|
|||
#define HB_ARRAY_HH
|
||||
|
||||
#include "hb.hh"
|
||||
#include "hb-dsalgs.hh"
|
||||
#include "hb-algs.hh"
|
||||
#include "hb-iter.hh"
|
||||
#include "hb-null.hh"
|
||||
|
||||
|
@ -37,22 +37,31 @@ template <typename Type>
|
|||
struct hb_sorted_array_t;
|
||||
|
||||
template <typename Type>
|
||||
struct hb_array_t :
|
||||
hb_iter_t<hb_array_t<Type>, Type>,
|
||||
hb_iter_mixin_t<hb_array_t<Type>, Type>
|
||||
struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
||||
{
|
||||
/*
|
||||
* Constructors.
|
||||
*/
|
||||
hb_array_t () : arrayZ (nullptr), length (0) {}
|
||||
hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
|
||||
template <unsigned int length_> hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_) {}
|
||||
hb_array_t () : arrayZ (nullptr), length (0), backwards_length (0) {}
|
||||
hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_), backwards_length (0) {}
|
||||
template <unsigned int length_>
|
||||
hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_), backwards_length (0) {}
|
||||
|
||||
template <typename U,
|
||||
hb_enable_if (hb_is_cr_convertible(U, Type))>
|
||||
hb_array_t (const hb_array_t<U> &o) :
|
||||
hb_iter_with_fallback_t<hb_array_t<Type>, Type&> (),
|
||||
arrayZ (o.arrayZ), length (o.length), backwards_length (o.backwards_length) {}
|
||||
template <typename U,
|
||||
hb_enable_if (hb_is_cr_convertible(U, Type))>
|
||||
hb_array_t& operator = (const hb_array_t<U> &o)
|
||||
{ arrayZ = o.arrayZ; length = o.length; backwards_length = o.backwards_length; return *this; }
|
||||
|
||||
/*
|
||||
* Iterator implementation.
|
||||
*/
|
||||
typedef Type __item_type__;
|
||||
typedef Type& __item_t__;
|
||||
static constexpr bool is_random_access_iterator = true;
|
||||
Type& __item_at__ (unsigned i) const
|
||||
{
|
||||
if (unlikely (i >= length)) return CrapOrNull (Type);
|
||||
|
@ -63,16 +72,25 @@ struct hb_array_t :
|
|||
if (unlikely (n > length))
|
||||
n = length;
|
||||
length -= n;
|
||||
backwards_length += n;
|
||||
arrayZ += n;
|
||||
}
|
||||
void __rewind__ (unsigned n)
|
||||
{
|
||||
if (unlikely (n > length))
|
||||
n = length;
|
||||
length -= n;
|
||||
if (unlikely (n > backwards_length))
|
||||
n = backwards_length;
|
||||
length += n;
|
||||
backwards_length -= n;
|
||||
arrayZ -= n;
|
||||
}
|
||||
unsigned __len__ () const { return length; }
|
||||
bool __random_access__ () const { return true; }
|
||||
/* Ouch. The operator== compares the contents of the array. For range-based for loops,
|
||||
* it's best if we can just compare arrayZ, though comparing contents is still fast,
|
||||
* but also would require that Type has operator==. As such, we optimize this operator
|
||||
* for range-based for loop and just compare arrayZ. No need to compare length, as we
|
||||
* assume we're only compared to .end(). */
|
||||
bool operator != (const hb_array_t& o) const
|
||||
{ return arrayZ != o.arrayZ; }
|
||||
|
||||
/* Extra operators.
|
||||
*/
|
||||
|
@ -80,6 +98,9 @@ struct hb_array_t :
|
|||
operator hb_array_t<const Type> () { return hb_array_t<const Type> (arrayZ, length); }
|
||||
template <typename T> operator T * () const { return arrayZ; }
|
||||
|
||||
HB_INTERNAL bool operator == (const hb_array_t &o) const;
|
||||
HB_INTERNAL uint32_t hash () const;
|
||||
|
||||
/*
|
||||
* Compare, Sort, and Search.
|
||||
*/
|
||||
|
@ -91,7 +112,7 @@ struct hb_array_t :
|
|||
return (int) a.length - (int) length;
|
||||
return hb_memcmp (a.arrayZ, arrayZ, get_size ());
|
||||
}
|
||||
static int cmp (const void *pa, const void *pb)
|
||||
HB_INTERNAL static int cmp (const void *pa, const void *pb)
|
||||
{
|
||||
hb_array_t<Type> *a = (hb_array_t<Type> *) pa;
|
||||
hb_array_t<Type> *b = (hb_array_t<Type> *) pb;
|
||||
|
@ -120,21 +141,21 @@ struct hb_array_t :
|
|||
hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
|
||||
{
|
||||
if (likely (length))
|
||||
::qsort (arrayZ, length, this->item_size, cmp_);
|
||||
hb_qsort (arrayZ, length, this->item_size, cmp_);
|
||||
return hb_sorted_array_t<Type> (*this);
|
||||
}
|
||||
hb_sorted_array_t<Type> qsort ()
|
||||
{
|
||||
if (likely (length))
|
||||
::qsort (arrayZ, length, this->item_size, Type::cmp);
|
||||
hb_qsort (arrayZ, length, this->item_size, Type::cmp);
|
||||
return hb_sorted_array_t<Type> (*this);
|
||||
}
|
||||
void qsort (unsigned int start, unsigned int end)
|
||||
{
|
||||
end = MIN (end, length);
|
||||
end = hb_min (end, length);
|
||||
assert (start <= end);
|
||||
if (likely (start < end))
|
||||
::qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
|
||||
hb_qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -154,7 +175,7 @@ struct hb_array_t :
|
|||
else
|
||||
count -= start_offset;
|
||||
if (seg_count)
|
||||
count = *seg_count = MIN (count, *seg_count);
|
||||
count = *seg_count = hb_min (count, *seg_count);
|
||||
return hb_array_t<Type> (arrayZ + start_offset, count);
|
||||
}
|
||||
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
|
||||
|
@ -164,6 +185,17 @@ struct hb_array_t :
|
|||
void free ()
|
||||
{ ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
|
||||
|
||||
template <typename hb_serialize_context_t>
|
||||
hb_array_t copy (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto* out = c->start_embed (arrayZ);
|
||||
if (unlikely (!c->extend_size (out, get_size ()))) return_trace (hb_array_t ());
|
||||
for (unsigned i = 0; i < length; i++)
|
||||
out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */
|
||||
return_trace (hb_array_t (out, length));
|
||||
}
|
||||
|
||||
template <typename hb_sanitize_context_t>
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{ return c->check_array (arrayZ, length); }
|
||||
|
@ -175,6 +207,7 @@ struct hb_array_t :
|
|||
public:
|
||||
Type *arrayZ;
|
||||
unsigned int length;
|
||||
unsigned int backwards_length;
|
||||
};
|
||||
template <typename T> inline hb_array_t<T>
|
||||
hb_array (T *array, unsigned int length)
|
||||
|
@ -183,7 +216,6 @@ template <typename T, unsigned int length_> inline hb_array_t<T>
|
|||
hb_array (T (&array_)[length_])
|
||||
{ return hb_array_t<T> (array_); }
|
||||
|
||||
|
||||
enum hb_bfind_not_found_t
|
||||
{
|
||||
HB_BFIND_NOT_FOUND_DONT_STORE,
|
||||
|
@ -193,14 +225,32 @@ enum hb_bfind_not_found_t
|
|||
|
||||
template <typename Type>
|
||||
struct hb_sorted_array_t :
|
||||
hb_sorted_iter_t<hb_sorted_array_t<Type>, Type>,
|
||||
hb_array_t<Type>,
|
||||
hb_iter_mixin_t<hb_sorted_array_t<Type>, Type>
|
||||
hb_iter_t<hb_sorted_array_t<Type>, Type&>,
|
||||
hb_array_t<Type>
|
||||
{
|
||||
typedef hb_iter_t<hb_sorted_array_t<Type>, Type&> iter_base_t;
|
||||
HB_ITER_USING (iter_base_t);
|
||||
static constexpr bool is_random_access_iterator = true;
|
||||
static constexpr bool is_sorted_iterator = true;
|
||||
|
||||
hb_sorted_array_t () : hb_array_t<Type> () {}
|
||||
hb_sorted_array_t (const hb_array_t<Type> &o) : hb_array_t<Type> (o) {}
|
||||
hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
|
||||
template <unsigned int length_> hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
|
||||
template <unsigned int length_>
|
||||
hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
|
||||
|
||||
template <typename U,
|
||||
hb_enable_if (hb_is_cr_convertible(U, Type))>
|
||||
hb_sorted_array_t (const hb_array_t<U> &o) :
|
||||
hb_iter_t<hb_sorted_array_t<Type>, Type&> (),
|
||||
hb_array_t<Type> (o) {}
|
||||
template <typename U,
|
||||
hb_enable_if (hb_is_cr_convertible(U, Type))>
|
||||
hb_sorted_array_t& operator = (const hb_array_t<U> &o)
|
||||
{ hb_array_t<Type> (*this) = o; return *this; }
|
||||
|
||||
/* Iterator implementation. */
|
||||
bool operator != (const hb_sorted_array_t& o) const
|
||||
{ return this->arrayZ != o.arrayZ || this->length != o.length; }
|
||||
|
||||
hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
|
||||
{ return hb_sorted_array_t<Type> (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
|
||||
|
@ -269,9 +319,30 @@ template <typename T, unsigned int length_> inline hb_sorted_array_t<T>
|
|||
hb_sorted_array (T (&array_)[length_])
|
||||
{ return hb_sorted_array_t<T> (array_); }
|
||||
|
||||
template <typename T>
|
||||
bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
|
||||
{
|
||||
return length == o.length &&
|
||||
+ hb_zip (*this, o)
|
||||
| hb_map ([] (hb_pair_t<T&, T&> &&_) { return _.first == _.second; })
|
||||
| hb_all
|
||||
;
|
||||
}
|
||||
template <typename T>
|
||||
uint32_t hb_array_t<T>::hash () const
|
||||
{
|
||||
return
|
||||
+ hb_iter (*this)
|
||||
| hb_map (hb_hash)
|
||||
| hb_reduce ([] (uint32_t a, uint32_t b) { return a * 31 + b; }, 0)
|
||||
;
|
||||
}
|
||||
|
||||
typedef hb_array_t<const char> hb_bytes_t;
|
||||
typedef hb_array_t<const unsigned char> hb_ubytes_t;
|
||||
|
||||
/* TODO Specialize opeator==/hash() for hb_bytes_t and hb_ubytes_t. */
|
||||
//template <>
|
||||
//uint32_t hb_array_t<const char>::hash () const { return 0; }
|
||||
|
||||
#endif /* HB_ARRAY_HH */
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#define HB_ATOMIC_HH
|
||||
|
||||
#include "hb.hh"
|
||||
#include "hb-meta.hh"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -85,11 +86,11 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
|
|||
#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
|
||||
#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_release))
|
||||
#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<int> *> (AI)->load (std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_get(AI) (reinterpret_cast<std::atomic<int> *> (AI)->load (std::memory_order_acquire))
|
||||
#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<int> const *> (AI)->load (std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_get(AI) (reinterpret_cast<std::atomic<int> const *> (AI)->load (std::memory_order_acquire))
|
||||
|
||||
#define hb_atomic_ptr_impl_set_relaxed(P, V) (reinterpret_cast<std::atomic<void*> *> (P)->store ((V), std::memory_order_relaxed))
|
||||
#define hb_atomic_ptr_impl_get_relaxed(P) (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_relaxed))
|
||||
#define hb_atomic_ptr_impl_get_relaxed(P) (reinterpret_cast<std::atomic<void*> const *> (P)->load (std::memory_order_relaxed))
|
||||
#define hb_atomic_ptr_impl_get(P) (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_acquire))
|
||||
static inline bool
|
||||
_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
|
||||
|
@ -106,7 +107,7 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
|
|||
|
||||
static inline void _hb_memory_barrier ()
|
||||
{
|
||||
#if !defined(MemoryBarrier)
|
||||
#if !defined(MemoryBarrier) && !defined(__MINGW32_VERSION)
|
||||
/* MinGW has a convoluted history of supporting MemoryBarrier. */
|
||||
LONG dummy = 0;
|
||||
InterlockedExchange (&dummy, 1);
|
||||
|
@ -184,7 +185,7 @@ static inline bool _hb_compare_and_swap_ptr (void **P, void *O, void *N)
|
|||
#endif
|
||||
|
||||
|
||||
#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__)
|
||||
#elif !defined(HB_NO_MT) && defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__))
|
||||
|
||||
#include <builtins.h>
|
||||
|
||||
|
@ -215,7 +216,7 @@ static_assert ((sizeof (long) == sizeof (void *)), "");
|
|||
|
||||
#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
|
||||
|
||||
#define _hb_memory_barrier()
|
||||
#define _hb_memory_barrier() do {} while (0)
|
||||
|
||||
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
|
||||
|
||||
|
@ -226,7 +227,7 @@ static_assert ((sizeof (long) == sizeof (void *)), "");
|
|||
|
||||
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
|
||||
|
||||
#define _hb_memory_barrier()
|
||||
#define _hb_memory_barrier() do {} while (0)
|
||||
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
|
||||
|
||||
|
@ -282,7 +283,7 @@ struct hb_atomic_int_t
|
|||
template <typename P>
|
||||
struct hb_atomic_ptr_t
|
||||
{
|
||||
typedef typename hb_remove_pointer (P) T;
|
||||
typedef hb_remove_pointer<P> T;
|
||||
|
||||
void init (T* v_ = nullptr) { set_relaxed (v_); }
|
||||
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
|
||||
|
|
143
src/hb-bimap.hh
Normal file
143
src/hb-bimap.hh
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright © 2019 Adobe 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.
|
||||
*
|
||||
* Adobe Author(s): Michiharu Ariza
|
||||
*/
|
||||
|
||||
#ifndef HB_BIMAP_HH
|
||||
#define HB_BIMAP_HH
|
||||
|
||||
#include "hb.hh"
|
||||
#include "hb-map.hh"
|
||||
|
||||
/* Bi-directional map */
|
||||
struct hb_bimap_t
|
||||
{
|
||||
hb_bimap_t () { init (); }
|
||||
~hb_bimap_t () { fini (); }
|
||||
|
||||
void init ()
|
||||
{
|
||||
forw_map.init ();
|
||||
back_map.init ();
|
||||
}
|
||||
|
||||
void fini ()
|
||||
{
|
||||
forw_map.fini ();
|
||||
back_map.fini ();
|
||||
}
|
||||
|
||||
void reset ()
|
||||
{
|
||||
forw_map.reset ();
|
||||
back_map.reset ();
|
||||
}
|
||||
|
||||
bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
|
||||
|
||||
void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
|
||||
{
|
||||
if (unlikely (lhs == HB_MAP_VALUE_INVALID)) return;
|
||||
if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; }
|
||||
forw_map.set (lhs, rhs);
|
||||
back_map.set (rhs, lhs);
|
||||
}
|
||||
|
||||
hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
|
||||
hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map.get (rhs); }
|
||||
|
||||
hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); }
|
||||
bool has (hb_codepoint_t lhs, hb_codepoint_t *vp = nullptr) const { return forw_map.has (lhs, vp); }
|
||||
|
||||
void del (hb_codepoint_t lhs)
|
||||
{
|
||||
back_map.del (get (lhs));
|
||||
forw_map.del (lhs);
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
forw_map.clear ();
|
||||
back_map.clear ();
|
||||
}
|
||||
|
||||
bool is_empty () const { return get_population () == 0; }
|
||||
|
||||
unsigned int get_population () const { return forw_map.get_population (); }
|
||||
|
||||
protected:
|
||||
hb_map_t forw_map;
|
||||
hb_map_t back_map;
|
||||
};
|
||||
|
||||
/* Inremental bimap: only lhs is given, rhs is incrementally assigned */
|
||||
struct hb_inc_bimap_t : hb_bimap_t
|
||||
{
|
||||
/* Add a mapping from lhs to rhs with a unique value if lhs is unknown.
|
||||
* Return the rhs value as the result.
|
||||
*/
|
||||
hb_codepoint_t add (hb_codepoint_t lhs)
|
||||
{
|
||||
hb_codepoint_t rhs = forw_map[lhs];
|
||||
if (rhs == HB_MAP_VALUE_INVALID)
|
||||
{
|
||||
rhs = get_population ();
|
||||
set (lhs, rhs);
|
||||
}
|
||||
return rhs;
|
||||
}
|
||||
|
||||
/* Create an identity map. */
|
||||
bool identity (unsigned int size)
|
||||
{
|
||||
clear ();
|
||||
for (hb_codepoint_t i = 0; i < size; i++) set (i, i);
|
||||
return !in_error ();
|
||||
}
|
||||
|
||||
protected:
|
||||
static int cmp_id (const void* a, const void* b)
|
||||
{ return (int)*(const hb_codepoint_t *)a - (int)*(const hb_codepoint_t *)b; }
|
||||
|
||||
public:
|
||||
/* Optional: after finished adding all mappings in a random order,
|
||||
* reassign rhs to lhs so that they are in the same order. */
|
||||
void sort ()
|
||||
{
|
||||
hb_codepoint_t count = get_population ();
|
||||
hb_vector_t <hb_codepoint_t> work;
|
||||
work.resize (count);
|
||||
|
||||
for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
|
||||
work[rhs] = back_map[rhs];
|
||||
|
||||
work.qsort (cmp_id);
|
||||
|
||||
clear ();
|
||||
for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
|
||||
set (work[rhs], rhs);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* HB_BIMAP_HH */
|
|
@ -30,8 +30,11 @@
|
|||
* http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
|
||||
* https://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html
|
||||
*/
|
||||
#ifndef _POSIX_C_SOURCE
|
||||
#if !defined(_POSIX_C_SOURCE) && !defined(_MSC_VER) && !defined(__NetBSD__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-macros"
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#include "hb.hh"
|
||||
|
@ -152,7 +155,7 @@ hb_blob_create_sub_blob (hb_blob_t *parent,
|
|||
hb_blob_make_immutable (parent);
|
||||
|
||||
blob = hb_blob_create (parent->data + offset,
|
||||
MIN (length, parent->length - offset),
|
||||
hb_min (length, parent->length - offset),
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
hb_blob_reference (parent),
|
||||
_hb_blob_destroy);
|
||||
|
@ -484,6 +487,7 @@ hb_blob_t::try_make_writable ()
|
|||
* Mmap
|
||||
*/
|
||||
|
||||
#ifndef HB_NO_OPEN
|
||||
#ifdef HAVE_MMAP
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
|
@ -673,3 +677,4 @@ fread_fail_without_close:
|
|||
free (data);
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
#endif /* !HB_NO_OPEN */
|
||||
|
|
|
@ -71,6 +71,9 @@ hb_blob_create (const char *data,
|
|||
void *user_data,
|
||||
hb_destroy_func_t destroy);
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
hb_blob_create_from_file (const char *file_name);
|
||||
|
||||
/* Always creates with MEMORY_MODE_READONLY.
|
||||
* Even if the parent blob is writable, we don't
|
||||
* want the user of the sub-blob to be able to
|
||||
|
@ -123,9 +126,6 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length);
|
|||
HB_EXTERN char *
|
||||
hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length);
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
hb_blob_create_from_file (const char *file_name);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_BLOB_H */
|
||||
|
|
|
@ -81,7 +81,7 @@ struct hb_blob_t
|
|||
template <typename P>
|
||||
struct hb_blob_ptr_t
|
||||
{
|
||||
typedef typename hb_remove_pointer (P) T;
|
||||
typedef hb_remove_pointer<P> T;
|
||||
|
||||
hb_blob_ptr_t (hb_blob_t *b_ = nullptr) : b (b_) {}
|
||||
hb_blob_t * operator = (hb_blob_t *b_) { return b = b_; }
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_BUFFER_SERIALIZE
|
||||
|
||||
#include "hb-buffer.hh"
|
||||
|
||||
|
||||
|
@ -85,7 +89,7 @@ hb_buffer_serialize_format_from_string (const char *str, int len)
|
|||
const char *
|
||||
hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
|
||||
{
|
||||
switch (format)
|
||||
switch ((unsigned) format)
|
||||
{
|
||||
case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0];
|
||||
case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1];
|
||||
|
@ -138,34 +142,34 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
|
|||
*p++ = '"';
|
||||
}
|
||||
else
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
|
||||
|
||||
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
|
||||
}
|
||||
|
||||
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
|
||||
{
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
|
||||
p += hb_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",
|
||||
p += hb_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));
|
||||
p += hb_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)
|
||||
{
|
||||
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",
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
|
||||
extents.x_bearing, extents.y_bearing));
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
|
||||
extents.width, extents.height));
|
||||
}
|
||||
|
||||
|
@ -224,37 +228,37 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
|
|||
p += strlen (p);
|
||||
}
|
||||
else
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
|
||||
|
||||
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
|
||||
}
|
||||
|
||||
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
|
||||
{
|
||||
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 += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset));
|
||||
|
||||
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
|
||||
{
|
||||
*p++ = '+';
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
|
||||
p += hb_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));
|
||||
p += hb_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));
|
||||
p += hb_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)
|
||||
{
|
||||
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), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
|
||||
}
|
||||
|
||||
unsigned int l = p - b;
|
||||
|
@ -380,7 +384,7 @@ static hb_bool_t
|
|||
parse_uint (const char *pp, const char *end, uint32_t *pv)
|
||||
{
|
||||
char buf[32];
|
||||
unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
|
||||
unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
|
||||
strncpy (buf, pp, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
|
@ -401,7 +405,7 @@ static hb_bool_t
|
|||
parse_int (const char *pp, const char *end, int32_t *pv)
|
||||
{
|
||||
char buf[32];
|
||||
unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
|
||||
unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
|
||||
strncpy (buf, pp, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
|
@ -484,3 +488,6 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -524,7 +524,7 @@ hb_buffer_t::merge_clusters_impl (unsigned int start,
|
|||
unsigned int cluster = info[start].cluster;
|
||||
|
||||
for (unsigned int i = start + 1; i < end; i++)
|
||||
cluster = MIN<unsigned int> (cluster, info[i].cluster);
|
||||
cluster = hb_min (cluster, info[i].cluster);
|
||||
|
||||
/* Extend end */
|
||||
while (end < len && info[end - 1].cluster == info[end].cluster)
|
||||
|
@ -555,7 +555,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<unsigned int> (cluster, out_info[i].cluster);
|
||||
cluster = hb_min (cluster, out_info[i].cluster);
|
||||
|
||||
/* Extend start */
|
||||
while (start && out_info[start - 1].cluster == out_info[start].cluster)
|
||||
|
@ -1993,6 +1993,7 @@ hb_buffer_diff (hb_buffer_t *buffer,
|
|||
* Debugging.
|
||||
*/
|
||||
|
||||
#ifndef HB_NO_BUFFER_MESSAGE
|
||||
/**
|
||||
* hb_buffer_set_message_func:
|
||||
* @buffer: an #hb_buffer_t.
|
||||
|
@ -2022,11 +2023,11 @@ hb_buffer_set_message_func (hb_buffer_t *buffer,
|
|||
buffer->message_destroy = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
|
||||
{
|
||||
char buf[100];
|
||||
vsnprintf (buf, sizeof (buf), fmt, ap);
|
||||
vsnprintf (buf, sizeof (buf), fmt, ap);
|
||||
return (bool) this->message_func (this, font, buf, this->message_data);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -284,6 +284,10 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
|
|||
* space glyph and zeroing the advance width.)
|
||||
* @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES takes
|
||||
* precedence over this flag. Since: 1.8.0
|
||||
* @HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE:
|
||||
* flag indicating that a dotted circle should
|
||||
* not be inserted in the rendering of incorrect
|
||||
* character sequences (such at <0905 093E>). Since: 2.4
|
||||
*
|
||||
* Since: 0.9.20
|
||||
*/
|
||||
|
@ -292,7 +296,8 @@ typedef enum { /*< flags >*/
|
|||
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_REMOVE_DEFAULT_IGNORABLES = 0x00000008u
|
||||
HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u,
|
||||
HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u
|
||||
} hb_buffer_flags_t;
|
||||
|
||||
HB_EXTERN void
|
||||
|
|
|
@ -119,12 +119,14 @@ struct hb_buffer_t
|
|||
/* Text before / after the main buffer contents.
|
||||
* Always in Unicode, and ordered outward.
|
||||
* Index 0 is for "pre-context", 1 for "post-context". */
|
||||
enum { CONTEXT_LENGTH = 5 };
|
||||
static constexpr unsigned CONTEXT_LENGTH = 5u;
|
||||
hb_codepoint_t context[2][CONTEXT_LENGTH];
|
||||
unsigned int context_len[2];
|
||||
|
||||
/* Debugging API */
|
||||
#ifndef HB_NO_BUFFER_MESSAGE
|
||||
hb_buffer_message_func_t message_func;
|
||||
#endif
|
||||
void *message_data;
|
||||
hb_destroy_func_t message_destroy;
|
||||
|
||||
|
@ -347,9 +349,19 @@ struct hb_buffer_t
|
|||
|
||||
HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
|
||||
|
||||
bool messaging () { return unlikely (message_func); }
|
||||
bool messaging ()
|
||||
{
|
||||
#ifdef HB_NO_BUFFER_MESSAGE
|
||||
return false;
|
||||
#else
|
||||
return unlikely (message_func);
|
||||
#endif
|
||||
}
|
||||
bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
|
||||
{
|
||||
#ifdef HB_NO_BUFFER_MESSAGE
|
||||
return true;
|
||||
#else
|
||||
if (!messaging ())
|
||||
return true;
|
||||
va_list ap;
|
||||
|
@ -357,6 +369,7 @@ struct hb_buffer_t
|
|||
bool ret = message_impl (font, fmt, ap);
|
||||
va_end (ap);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
|
||||
|
||||
|
@ -379,7 +392,7 @@ struct hb_buffer_t
|
|||
unsigned int cluster) const
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
cluster = MIN<unsigned int> (cluster, infos[i].cluster);
|
||||
cluster = hb_min (cluster, infos[i].cluster);
|
||||
return cluster;
|
||||
}
|
||||
void
|
||||
|
|
|
@ -226,7 +226,7 @@ struct number_t
|
|||
void set_fixed (int32_t v) { value = v / 65536.0; }
|
||||
int32_t to_fixed () const { return (int32_t) (value * 65536.0); }
|
||||
|
||||
void set_real (double v) { value = v; }
|
||||
void set_real (double v) { value = v; }
|
||||
double to_real () const { return value; }
|
||||
|
||||
int ceil () const { return (int) ::ceil (value); }
|
||||
|
@ -235,17 +235,10 @@ struct number_t
|
|||
bool in_int_range () const
|
||||
{ return ((double) (int16_t) to_int () == value); }
|
||||
|
||||
bool operator > (const number_t &n) const
|
||||
{ return value > n.to_real (); }
|
||||
|
||||
bool operator < (const number_t &n) const
|
||||
{ return n > *this; }
|
||||
|
||||
bool operator >= (const number_t &n) const
|
||||
{ return !(*this < n); }
|
||||
|
||||
bool operator <= (const number_t &n) const
|
||||
{ return !(*this > n); }
|
||||
bool operator > (const number_t &n) const { return value > n.to_real (); }
|
||||
bool operator < (const number_t &n) const { return n > *this; }
|
||||
bool operator >= (const number_t &n) const { return !(*this < n); }
|
||||
bool operator <= (const number_t &n) const { return !(*this > n); }
|
||||
|
||||
const number_t &operator += (const number_t &n)
|
||||
{
|
||||
|
@ -255,7 +248,7 @@ struct number_t
|
|||
}
|
||||
|
||||
protected:
|
||||
double value;
|
||||
double value;
|
||||
};
|
||||
|
||||
/* byte string */
|
||||
|
@ -272,11 +265,11 @@ struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
|
|||
|
||||
HBUINT8 *p = c->allocate_size<HBUINT8> (1);
|
||||
if (unlikely (p == nullptr)) return_trace (false);
|
||||
p->set (intOp);
|
||||
*p = intOp;
|
||||
|
||||
INTTYPE *ip = c->allocate_size<INTTYPE> (INTTYPE::static_size);
|
||||
if (unlikely (ip == nullptr)) return_trace (false);
|
||||
ip->set ((unsigned int)value);
|
||||
*ip = (unsigned int) value;
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
@ -308,7 +301,7 @@ struct byte_str_t : hb_ubytes_t
|
|||
: hb_ubytes_t (s, l) {}
|
||||
byte_str_t (const hb_ubytes_t &ub) /* conversion from hb_ubytes_t */
|
||||
: hb_ubytes_t (ub) {}
|
||||
|
||||
|
||||
/* sub-string */
|
||||
byte_str_t sub_str (unsigned int offset, unsigned int len_) const
|
||||
{ return byte_str_t (hb_ubytes_t::sub_array (offset, len_)); }
|
||||
|
@ -320,8 +313,7 @@ struct byte_str_t : hb_ubytes_t
|
|||
/* A byte string associated with the current offset and an error condition */
|
||||
struct byte_str_ref_t
|
||||
{
|
||||
byte_str_ref_t ()
|
||||
{ init (); }
|
||||
byte_str_ref_t () { init (); }
|
||||
|
||||
void init ()
|
||||
{
|
||||
|
@ -343,13 +335,12 @@ struct byte_str_ref_t
|
|||
}
|
||||
|
||||
const unsigned char& operator [] (int i) {
|
||||
if (unlikely ((unsigned int)(offset + i) >= str.length))
|
||||
if (unlikely ((unsigned int) (offset + i) >= str.length))
|
||||
{
|
||||
set_error ();
|
||||
return Null(unsigned char);
|
||||
return Null (unsigned char);
|
||||
}
|
||||
else
|
||||
return str[offset + i];
|
||||
return str[offset + i];
|
||||
}
|
||||
|
||||
/* Conversion to byte_str_t */
|
||||
|
@ -359,9 +350,7 @@ struct byte_str_ref_t
|
|||
{ return str.sub_str (offset_, len_); }
|
||||
|
||||
bool avail (unsigned int count=1) const
|
||||
{
|
||||
return (!in_error () && str.check_limit (offset, count));
|
||||
}
|
||||
{ return (!in_error () && str.check_limit (offset, count)); }
|
||||
void inc (unsigned int count=1)
|
||||
{
|
||||
if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length)))
|
||||
|
@ -389,7 +378,7 @@ typedef hb_vector_t<byte_str_t> byte_str_array_t;
|
|||
|
||||
/* stack */
|
||||
template <typename ELEM, int LIMIT>
|
||||
struct stack_t
|
||||
struct cff_stack_t
|
||||
{
|
||||
void init ()
|
||||
{
|
||||
|
@ -400,11 +389,7 @@ struct stack_t
|
|||
for (unsigned int i = 0; i < elements.length; i++)
|
||||
elements[i].init ();
|
||||
}
|
||||
|
||||
void fini ()
|
||||
{
|
||||
elements.fini_deep ();
|
||||
}
|
||||
void fini () { elements.fini_deep (); }
|
||||
|
||||
ELEM& operator [] (unsigned int i)
|
||||
{
|
||||
|
@ -419,7 +404,6 @@ struct stack_t
|
|||
else
|
||||
set_error ();
|
||||
}
|
||||
|
||||
ELEM &push ()
|
||||
{
|
||||
if (likely (count < elements.length))
|
||||
|
@ -441,7 +425,6 @@ struct stack_t
|
|||
return Crap(ELEM);
|
||||
}
|
||||
}
|
||||
|
||||
void pop (unsigned int n)
|
||||
{
|
||||
if (likely (count >= n))
|
||||
|
@ -452,13 +435,12 @@ struct stack_t
|
|||
|
||||
const ELEM& peek ()
|
||||
{
|
||||
if (likely (count > 0))
|
||||
return elements[count-1];
|
||||
else
|
||||
if (unlikely (count < 0))
|
||||
{
|
||||
set_error ();
|
||||
return Null(ELEM);
|
||||
}
|
||||
return elements[count - 1];
|
||||
}
|
||||
|
||||
void unpop ()
|
||||
|
@ -475,9 +457,9 @@ struct stack_t
|
|||
void set_error () { error = true; }
|
||||
|
||||
unsigned int get_count () const { return count; }
|
||||
bool is_empty () const { return count == 0; }
|
||||
bool is_empty () const { return !count; }
|
||||
|
||||
static const unsigned int kSizeLimit = LIMIT;
|
||||
static constexpr unsigned kSizeLimit = LIMIT;
|
||||
|
||||
protected:
|
||||
bool error;
|
||||
|
@ -487,7 +469,7 @@ struct stack_t
|
|||
|
||||
/* argument stack */
|
||||
template <typename ARG=number_t>
|
||||
struct arg_stack_t : stack_t<ARG, 513>
|
||||
struct arg_stack_t : cff_stack_t<ARG, 513>
|
||||
{
|
||||
void push_int (int v)
|
||||
{
|
||||
|
@ -519,7 +501,7 @@ struct arg_stack_t : stack_t<ARG, 513>
|
|||
i = 0;
|
||||
S::set_error ();
|
||||
}
|
||||
return (unsigned)i;
|
||||
return (unsigned) i;
|
||||
}
|
||||
|
||||
void push_longint_from_substr (byte_str_ref_t& str_ref)
|
||||
|
@ -538,12 +520,10 @@ struct arg_stack_t : stack_t<ARG, 513>
|
|||
}
|
||||
|
||||
hb_array_t<const ARG> get_subarray (unsigned int start) const
|
||||
{
|
||||
return S::elements.sub_array (start);
|
||||
}
|
||||
{ return S::elements.sub_array (start); }
|
||||
|
||||
private:
|
||||
typedef stack_t<ARG, 513> S;
|
||||
typedef cff_stack_t<ARG, 513> S;
|
||||
};
|
||||
|
||||
/* an operator prefixed by its operands in a byte string */
|
||||
|
@ -605,7 +585,7 @@ struct parsed_values_t
|
|||
}
|
||||
|
||||
unsigned get_count () const { return values.length; }
|
||||
const VAL &get_value (unsigned int i) const { return values[i]; }
|
||||
const VAL &get_value (unsigned int i) const { return values[i]; }
|
||||
const VAL &operator [] (unsigned int i) const { return get_value (i); }
|
||||
|
||||
unsigned int opStart;
|
||||
|
@ -644,30 +624,19 @@ struct interp_env_t
|
|||
return op;
|
||||
}
|
||||
|
||||
const ARG& eval_arg (unsigned int i)
|
||||
{
|
||||
return argStack[i];
|
||||
}
|
||||
const ARG& eval_arg (unsigned int i) { return argStack[i]; }
|
||||
|
||||
ARG& pop_arg ()
|
||||
{
|
||||
return argStack.pop ();
|
||||
}
|
||||
ARG& pop_arg () { return argStack.pop (); }
|
||||
void pop_n_args (unsigned int n) { argStack.pop (n); }
|
||||
|
||||
void pop_n_args (unsigned int n)
|
||||
{
|
||||
argStack.pop (n);
|
||||
}
|
||||
void clear_args () { pop_n_args (argStack.get_count ()); }
|
||||
|
||||
void clear_args ()
|
||||
{
|
||||
pop_n_args (argStack.get_count ());
|
||||
}
|
||||
|
||||
byte_str_ref_t str_ref;
|
||||
arg_stack_t<ARG> argStack;
|
||||
byte_str_ref_t
|
||||
str_ref;
|
||||
arg_stack_t<ARG>
|
||||
argStack;
|
||||
protected:
|
||||
bool error;
|
||||
bool error;
|
||||
};
|
||||
|
||||
typedef interp_env_t<> num_interp_env_t;
|
||||
|
@ -691,7 +660,7 @@ struct opset_t
|
|||
|
||||
case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
|
||||
case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
|
||||
env.argStack.push_int ((int16_t)(-(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108));
|
||||
env.argStack.push_int ((-(int16_t)(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108));
|
||||
env.str_ref.inc ();
|
||||
break;
|
||||
|
||||
|
@ -711,8 +680,8 @@ struct opset_t
|
|||
};
|
||||
|
||||
template <typename ENV>
|
||||
struct interpreter_t {
|
||||
|
||||
struct interpreter_t
|
||||
{
|
||||
~interpreter_t() { fini (); }
|
||||
|
||||
void fini () { env.fini (); }
|
||||
|
|
|
@ -57,14 +57,14 @@ struct call_context_t
|
|||
|
||||
/* call stack */
|
||||
const unsigned int kMaxCallLimit = 10;
|
||||
struct call_stack_t : stack_t<call_context_t, kMaxCallLimit> {};
|
||||
struct call_stack_t : cff_stack_t<call_context_t, kMaxCallLimit> {};
|
||||
|
||||
template <typename SUBRS>
|
||||
struct biased_subrs_t
|
||||
{
|
||||
void init (const SUBRS &subrs_)
|
||||
void init (const SUBRS *subrs_)
|
||||
{
|
||||
subrs = &subrs_;
|
||||
subrs = subrs_;
|
||||
unsigned int nSubrs = get_count ();
|
||||
if (nSubrs < 1240)
|
||||
bias = 107;
|
||||
|
@ -76,8 +76,8 @@ struct biased_subrs_t
|
|||
|
||||
void fini () {}
|
||||
|
||||
unsigned int get_count () const { return (subrs == nullptr)? 0: subrs->count; }
|
||||
unsigned int get_bias () const { return bias; }
|
||||
unsigned int get_count () const { return (subrs == nullptr) ? 0 : subrs->count; }
|
||||
unsigned int get_bias () const { return bias; }
|
||||
|
||||
byte_str_t operator [] (unsigned int index) const
|
||||
{
|
||||
|
@ -118,7 +118,7 @@ struct point_t
|
|||
template <typename ARG, typename SUBRS>
|
||||
struct cs_interp_env_t : interp_env_t<ARG>
|
||||
{
|
||||
void init (const byte_str_t &str, const SUBRS &globalSubrs_, const SUBRS &localSubrs_)
|
||||
void init (const byte_str_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_)
|
||||
{
|
||||
interp_env_t<ARG>::init (str);
|
||||
|
||||
|
@ -127,6 +127,7 @@ struct cs_interp_env_t : interp_env_t<ARG>
|
|||
seen_hintmask = false;
|
||||
hstem_count = 0;
|
||||
vstem_count = 0;
|
||||
hintmask_size = 0;
|
||||
pt.init ();
|
||||
callStack.init ();
|
||||
globalSubrs.init (globalSubrs_);
|
||||
|
@ -146,8 +147,9 @@ struct cs_interp_env_t : interp_env_t<ARG>
|
|||
return callStack.in_error () || SUPER::in_error ();
|
||||
}
|
||||
|
||||
bool popSubrNum (const biased_subrs_t<SUBRS>& biasedSubrs, unsigned int &subr_num)
|
||||
bool pop_subr_num (const biased_subrs_t<SUBRS>& biasedSubrs, unsigned int &subr_num)
|
||||
{
|
||||
subr_num = 0;
|
||||
int n = SUPER::argStack.pop_int ();
|
||||
n += biasedSubrs.get_bias ();
|
||||
if (unlikely ((n < 0) || ((unsigned int)n >= biasedSubrs.get_count ())))
|
||||
|
@ -157,11 +159,11 @@ struct cs_interp_env_t : interp_env_t<ARG>
|
|||
return true;
|
||||
}
|
||||
|
||||
void callSubr (const biased_subrs_t<SUBRS>& biasedSubrs, cs_type_t type)
|
||||
void call_subr (const biased_subrs_t<SUBRS>& biasedSubrs, cs_type_t type)
|
||||
{
|
||||
unsigned int subr_num;
|
||||
unsigned int subr_num = 0;
|
||||
|
||||
if (unlikely (!popSubrNum (biasedSubrs, subr_num)
|
||||
if (unlikely (!pop_subr_num (biasedSubrs, subr_num)
|
||||
|| callStack.get_count () >= kMaxCallLimit))
|
||||
{
|
||||
SUPER::set_error ();
|
||||
|
@ -174,7 +176,7 @@ struct cs_interp_env_t : interp_env_t<ARG>
|
|||
SUPER::str_ref = context.str_ref;
|
||||
}
|
||||
|
||||
void returnFromSubr ()
|
||||
void return_from_subr ()
|
||||
{
|
||||
if (unlikely (SUPER::str_ref.in_error ()))
|
||||
SUPER::set_error ();
|
||||
|
@ -245,7 +247,7 @@ struct path_procs_null_t
|
|||
static void flex1 (ENV &env, PARAM& param) {}
|
||||
};
|
||||
|
||||
template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=path_procs_null_t<ENV, PARAM> >
|
||||
template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=path_procs_null_t<ENV, PARAM>>
|
||||
struct cs_opset_t : opset_t<ARG>
|
||||
{
|
||||
static void process_op (op_code_t op, ENV &env, PARAM& param)
|
||||
|
@ -253,7 +255,7 @@ struct cs_opset_t : opset_t<ARG>
|
|||
switch (op) {
|
||||
|
||||
case OpCode_return:
|
||||
env.returnFromSubr ();
|
||||
env.return_from_subr ();
|
||||
break;
|
||||
case OpCode_endchar:
|
||||
OPSET::check_width (op, env, param);
|
||||
|
@ -266,11 +268,11 @@ struct cs_opset_t : opset_t<ARG>
|
|||
break;
|
||||
|
||||
case OpCode_callsubr:
|
||||
env.callSubr (env.localSubrs, CSType_LocalSubr);
|
||||
env.call_subr (env.localSubrs, CSType_LocalSubr);
|
||||
break;
|
||||
|
||||
case OpCode_callgsubr:
|
||||
env.callSubr (env.globalSubrs, CSType_GlobalSubr);
|
||||
env.call_subr (env.globalSubrs, CSType_GlobalSubr);
|
||||
break;
|
||||
|
||||
case OpCode_hstem:
|
||||
|
|
|
@ -134,10 +134,10 @@ struct dict_opset_t : opset_t<number_t>
|
|||
return value;
|
||||
|
||||
case END:
|
||||
value = (double)(neg? -int_part: int_part);
|
||||
value = (double) (neg ? -int_part : int_part);
|
||||
if (frac_count > 0)
|
||||
{
|
||||
double frac = (frac_part / pow (10.0, (double)frac_count));
|
||||
double frac = (frac_part / pow (10.0, (double) frac_count));
|
||||
if (neg) frac = -frac;
|
||||
value += frac;
|
||||
}
|
||||
|
@ -146,16 +146,16 @@ struct dict_opset_t : opset_t<number_t>
|
|||
if (value == 0.0)
|
||||
return value;
|
||||
if (exp_neg)
|
||||
return neg? -DBL_MIN: DBL_MIN;
|
||||
return neg ? -DBL_MIN : DBL_MIN;
|
||||
else
|
||||
return neg? -DBL_MAX: DBL_MAX;
|
||||
return neg ? -DBL_MAX : DBL_MAX;
|
||||
}
|
||||
if (exp_part != 0)
|
||||
{
|
||||
if (exp_neg)
|
||||
value /= pow (10.0, (double)exp_part);
|
||||
value /= pow (10.0, (double) exp_part);
|
||||
else
|
||||
value *= pow (10.0, (double)exp_part);
|
||||
value *= pow (10.0, (double) exp_part);
|
||||
}
|
||||
return value;
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ struct cff1_cs_interp_env_t : cs_interp_env_t<number_t, CFF1Subrs>
|
|||
template <typename ACC>
|
||||
void init (const byte_str_t &str, ACC &acc, unsigned int fd)
|
||||
{
|
||||
SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
|
||||
SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
|
||||
processed_width = false;
|
||||
has_width = false;
|
||||
arg_start = 0;
|
||||
|
@ -81,7 +81,7 @@ struct cff1_cs_interp_env_t : cs_interp_env_t<number_t, CFF1Subrs>
|
|||
typedef cs_interp_env_t<number_t, CFF1Subrs> SUPER;
|
||||
};
|
||||
|
||||
template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff1_cs_interp_env_t, PARAM> >
|
||||
template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff1_cs_interp_env_t, PARAM>>
|
||||
struct cff1_cs_opset_t : cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM, PATH>
|
||||
{
|
||||
/* PostScript-originated legacy opcodes (OpCode_add etc) are unsupported */
|
||||
|
|
|
@ -82,7 +82,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
|
|||
void init (const byte_str_t &str, ACC &acc, unsigned int fd,
|
||||
const int *coords_=nullptr, unsigned int num_coords_=0)
|
||||
{
|
||||
SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
|
||||
SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
|
||||
|
||||
coords = coords_;
|
||||
num_coords = num_coords_;
|
||||
|
@ -193,7 +193,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
|
|||
|
||||
typedef cs_interp_env_t<blend_arg_t, CFF2Subrs> SUPER;
|
||||
};
|
||||
template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM> >
|
||||
template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM>>
|
||||
struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>
|
||||
{
|
||||
static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param)
|
||||
|
|
135
src/hb-common.cc
135
src/hb-common.cc
|
@ -35,6 +35,9 @@
|
|||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_SETLOCALE
|
||||
#define setlocale(Category, Locale) "C"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION:hb-common
|
||||
|
@ -67,7 +70,7 @@ _hb_options_init ()
|
|||
p = c + strlen (c);
|
||||
|
||||
#define OPTION(name, symbol) \
|
||||
if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) u.opts.symbol = true;
|
||||
if (0 == strncmp (c, name, p - c) && strlen (name) == static_cast<size_t>(p - c)) do { u.opts.symbol = true; } while (0)
|
||||
|
||||
OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
|
||||
OPTION ("aat", aat);
|
||||
|
@ -356,7 +359,7 @@ hb_language_from_string (const char *str, int len)
|
|||
{
|
||||
/* NUL-terminate it. */
|
||||
char strbuf[64];
|
||||
len = MIN (len, (int) sizeof (strbuf) - 1);
|
||||
len = hb_min (len, (int) sizeof (strbuf) - 1);
|
||||
memcpy (strbuf, str, len);
|
||||
strbuf[len] = '\0';
|
||||
item = lang_find_or_insert (strbuf);
|
||||
|
@ -488,7 +491,7 @@ hb_script_from_string (const char *str, int len)
|
|||
|
||||
/**
|
||||
* hb_script_to_iso15924_tag:
|
||||
* @script: an #hb_script_ to convert.
|
||||
* @script: an #hb_script_t to convert.
|
||||
*
|
||||
* See hb_script_from_iso15924_tag().
|
||||
*
|
||||
|
@ -720,7 +723,7 @@ 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));
|
||||
unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
|
||||
strncpy (buf, *pp, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
|
@ -731,7 +734,7 @@ parse_uint (const char **pp, const char *end, unsigned int *pv)
|
|||
/* Intentionally use strtol instead of strtoul, such that
|
||||
* -1 turns into "big number"... */
|
||||
errno = 0;
|
||||
v = strtol (p, &pend, 0);
|
||||
v = strtol (p, &pend, 10);
|
||||
if (errno || p == pend)
|
||||
return false;
|
||||
|
||||
|
@ -744,7 +747,7 @@ 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));
|
||||
unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
|
||||
strncpy (buf, *pp, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
|
@ -755,7 +758,7 @@ parse_uint32 (const char **pp, const char *end, uint32_t *pv)
|
|||
/* Intentionally use strtol instead of strtoul, such that
|
||||
* -1 turns into "big number"... */
|
||||
errno = 0;
|
||||
v = strtol (p, &pend, 0);
|
||||
v = strtol (p, &pend, 10);
|
||||
if (errno || p == pend)
|
||||
return false;
|
||||
|
||||
|
@ -783,7 +786,7 @@ parse_uint32 (const char **pp, const char *end, uint32_t *pv)
|
|||
static void free_static_C_locale ();
|
||||
#endif
|
||||
|
||||
static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (HB_LOCALE_T),
|
||||
static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<HB_LOCALE_T>,
|
||||
hb_C_locale_lazy_loader_t>
|
||||
{
|
||||
static HB_LOCALE_T create ()
|
||||
|
@ -825,7 +828,7 @@ 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));
|
||||
unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
|
||||
strncpy (buf, *pp, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
|
@ -857,9 +860,14 @@ parse_bool (const char **pp, const char *end, uint32_t *pv)
|
|||
(*pp)++;
|
||||
|
||||
/* CSS allows on/off as aliases 1/0. */
|
||||
if (*pp - p == 2 && 0 == strncmp (p, "on", 2))
|
||||
if (*pp - p == 2
|
||||
&& TOLOWER (p[0]) == 'o'
|
||||
&& TOLOWER (p[1]) == 'n')
|
||||
*pv = 1;
|
||||
else if (*pp - p == 3 && 0 == strncmp (p, "off", 3))
|
||||
else if (*pp - p == 3
|
||||
&& TOLOWER (p[0]) == 'o'
|
||||
&& TOLOWER (p[1]) == 'f'
|
||||
&& TOLOWER (p[2]) == 'f')
|
||||
*pv = 0;
|
||||
else
|
||||
return false;
|
||||
|
@ -974,7 +982,41 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
|
|||
*
|
||||
* Parses a string into a #hb_feature_t.
|
||||
*
|
||||
* TODO: document the syntax here.
|
||||
* The format for specifying feature strings follows. All valid CSS
|
||||
* font-feature-settings values other than 'normal' and the global values are
|
||||
* also accepted, though not documented below. CSS string escapes are not
|
||||
* supported.
|
||||
*
|
||||
* The range indices refer to the positions between Unicode characters. The
|
||||
* position before the first character is always 0.
|
||||
*
|
||||
* The format is Python-esque. Here is how it all works:
|
||||
*
|
||||
* <informaltable pgwide='1' align='left' frame='none'>
|
||||
* <tgroup cols='5'>
|
||||
* <thead>
|
||||
* <row><entry>Syntax</entry> <entry>Value</entry> <entry>Start</entry> <entry>End</entry></row>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <row><entry>Setting value:</entry></row>
|
||||
* <row><entry>kern</entry> <entry>1</entry> <entry>0</entry> <entry>∞</entry> <entry>Turn feature on</entry></row>
|
||||
* <row><entry>+kern</entry> <entry>1</entry> <entry>0</entry> <entry>∞</entry> <entry>Turn feature on</entry></row>
|
||||
* <row><entry>-kern</entry> <entry>0</entry> <entry>0</entry> <entry>∞</entry> <entry>Turn feature off</entry></row>
|
||||
* <row><entry>kern=0</entry> <entry>0</entry> <entry>0</entry> <entry>∞</entry> <entry>Turn feature off</entry></row>
|
||||
* <row><entry>kern=1</entry> <entry>1</entry> <entry>0</entry> <entry>∞</entry> <entry>Turn feature on</entry></row>
|
||||
* <row><entry>aalt=2</entry> <entry>2</entry> <entry>0</entry> <entry>∞</entry> <entry>Choose 2nd alternate</entry></row>
|
||||
* <row><entry>Setting index:</entry></row>
|
||||
* <row><entry>kern[]</entry> <entry>1</entry> <entry>0</entry> <entry>∞</entry> <entry>Turn feature on</entry></row>
|
||||
* <row><entry>kern[:]</entry> <entry>1</entry> <entry>0</entry> <entry>∞</entry> <entry>Turn feature on</entry></row>
|
||||
* <row><entry>kern[5:]</entry> <entry>1</entry> <entry>5</entry> <entry>∞</entry> <entry>Turn feature on, partial</entry></row>
|
||||
* <row><entry>kern[:5]</entry> <entry>1</entry> <entry>0</entry> <entry>5</entry> <entry>Turn feature on, partial</entry></row>
|
||||
* <row><entry>kern[3:5]</entry> <entry>1</entry> <entry>3</entry> <entry>5</entry> <entry>Turn feature on, range</entry></row>
|
||||
* <row><entry>kern[3]</entry> <entry>1</entry> <entry>3</entry> <entry>3+1</entry> <entry>Turn feature on, single char</entry></row>
|
||||
* <row><entry>Mixing it all:</entry></row>
|
||||
* <row><entry>aalt[3:5]=2</entry> <entry>2</entry> <entry>3</entry> <entry>5</entry> <entry>Turn 2nd alternate on for range</entry></row>
|
||||
* </tbody>
|
||||
* </tgroup>
|
||||
* </informaltable>
|
||||
*
|
||||
* Return value:
|
||||
* %true if @str is successfully parsed, %false otherwise.
|
||||
|
@ -1032,21 +1074,21 @@ hb_feature_to_string (hb_feature_t *feature,
|
|||
{
|
||||
s[len++] = '[';
|
||||
if (feature->start)
|
||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
|
||||
len += hb_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));
|
||||
len += hb_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));
|
||||
len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
|
||||
}
|
||||
assert (len < ARRAY_LENGTH (s));
|
||||
len = MIN (len, size - 1);
|
||||
len = hb_min (len, size - 1);
|
||||
memcpy (buf, s, len);
|
||||
buf[len] = '\0';
|
||||
}
|
||||
|
@ -1113,14 +1155,71 @@ hb_variation_to_string (hb_variation_t *variation,
|
|||
while (len && s[len - 1] == ' ')
|
||||
len--;
|
||||
s[len++] = '=';
|
||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
|
||||
len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
|
||||
|
||||
assert (len < ARRAY_LENGTH (s));
|
||||
len = MIN (len, size - 1);
|
||||
len = hb_min (len, size - 1);
|
||||
memcpy (buf, s, len);
|
||||
buf[len] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_color_get_alpha:
|
||||
* color: a #hb_color_t we are interested in its channels.
|
||||
*
|
||||
* Return value: Alpha channel value of the given color
|
||||
*
|
||||
* Since: 2.1.0
|
||||
*/
|
||||
uint8_t
|
||||
(hb_color_get_alpha) (hb_color_t color)
|
||||
{
|
||||
return hb_color_get_alpha (color);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_color_get_red:
|
||||
* color: a #hb_color_t we are interested in its channels.
|
||||
*
|
||||
* Return value: Red channel value of the given color
|
||||
*
|
||||
* Since: 2.1.0
|
||||
*/
|
||||
uint8_t
|
||||
(hb_color_get_red) (hb_color_t color)
|
||||
{
|
||||
return hb_color_get_red (color);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_color_get_green:
|
||||
* color: a #hb_color_t we are interested in its channels.
|
||||
*
|
||||
* Return value: Green channel value of the given color
|
||||
*
|
||||
* Since: 2.1.0
|
||||
*/
|
||||
uint8_t
|
||||
(hb_color_get_green) (hb_color_t color)
|
||||
{
|
||||
return hb_color_get_green (color);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_color_get_blue:
|
||||
* color: a #hb_color_t we are interested in its channels.
|
||||
*
|
||||
* Return value: Blue channel value of the given color
|
||||
*
|
||||
* Since: 2.1.0
|
||||
*/
|
||||
uint8_t
|
||||
(hb_color_get_blue) (hb_color_t color)
|
||||
{
|
||||
return hb_color_get_blue (color);
|
||||
}
|
||||
|
||||
|
||||
/* If there is no visibility control, then hb-static.cc will NOT
|
||||
* define anything. Instead, we get it to define one set in here
|
||||
* only, so only libharfbuzz.so defines them, not other libs. */
|
||||
|
|
|
@ -67,7 +67,7 @@ typedef unsigned __int64 uint64_t;
|
|||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
#define HB_DEPRECATED __attribute__((__deprecated__))
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||
#define HB_DEPRECATED __declspec(deprecated)
|
||||
|
@ -75,7 +75,7 @@ typedef unsigned __int64 uint64_t;
|
|||
#define HB_DEPRECATED
|
||||
#endif
|
||||
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
|
||||
#define HB_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead")))
|
||||
#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320)
|
||||
#define HB_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead"))
|
||||
|
@ -108,7 +108,7 @@ typedef union _hb_var_int_t {
|
|||
typedef uint32_t hb_tag_t;
|
||||
|
||||
#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF)))
|
||||
#define HB_UNTAG(tag) (((tag)>>24)&0xFF), (((tag)>>16)&0xFF), (((tag)>>8)&0xFF), ((tag)&0xFF)
|
||||
#define HB_UNTAG(tag) (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&0xFF)
|
||||
|
||||
#define HB_TAG_NONE HB_TAG(0,0,0,0)
|
||||
#define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
|
||||
|
@ -357,6 +357,14 @@ typedef enum
|
|||
/*11.0*/HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'),
|
||||
/*11.0*/HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'),
|
||||
|
||||
/*
|
||||
* Since 2.4.0
|
||||
*/
|
||||
/*12.0*/HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'),
|
||||
/*12.0*/HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'),
|
||||
/*12.0*/HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'),
|
||||
/*12.0*/HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'),
|
||||
|
||||
/* No script set. */
|
||||
HB_SCRIPT_INVALID = HB_TAG_NONE,
|
||||
|
||||
|
@ -459,39 +467,21 @@ typedef uint32_t hb_color_t;
|
|||
|
||||
#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a)))
|
||||
|
||||
/**
|
||||
* hb_color_get_alpha:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 2.1.0
|
||||
*/
|
||||
HB_EXTERN uint8_t
|
||||
hb_color_get_alpha (hb_color_t color);
|
||||
#define hb_color_get_alpha(color) ((color) & 0xFF)
|
||||
/**
|
||||
* hb_color_get_red:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 2.1.0
|
||||
*/
|
||||
#define hb_color_get_red(color) (((color) >> 8) & 0xFF)
|
||||
/**
|
||||
* hb_color_get_green:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 2.1.0
|
||||
*/
|
||||
#define hb_color_get_green(color) (((color) >> 16) & 0xFF)
|
||||
/**
|
||||
* hb_color_get_blue:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 2.1.0
|
||||
*/
|
||||
#define hb_color_get_blue(color) (((color) >> 24) & 0xFF)
|
||||
|
||||
HB_EXTERN uint8_t
|
||||
hb_color_get_red (hb_color_t color);
|
||||
#define hb_color_get_red(color) (((color) >> 8) & 0xFF)
|
||||
|
||||
HB_EXTERN uint8_t
|
||||
hb_color_get_green (hb_color_t color);
|
||||
#define hb_color_get_green(color) (((color) >> 16) & 0xFF)
|
||||
|
||||
HB_EXTERN uint8_t
|
||||
hb_color_get_blue (hb_color_t color);
|
||||
#define hb_color_get_blue(color) (((color) >> 24) & 0xFF)
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
|
|
161
src/hb-config.hh
Normal file
161
src/hb-config.hh
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright © 2019 Facebook, 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.
|
||||
*
|
||||
* Facebook Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_CONFIG_HH
|
||||
#define HB_CONFIG_HH
|
||||
|
||||
#if 0 /* Make test happy. */
|
||||
#include "hb.hh"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HB_TINY
|
||||
#define HB_LEAN
|
||||
#define HB_MINI
|
||||
#define HB_NO_MT
|
||||
#define HB_NO_UCD_UNASSIGNED
|
||||
#ifndef NDEBUG
|
||||
#define NDEBUG
|
||||
#endif
|
||||
#ifndef __OPTIMIZE_SIZE__
|
||||
#define __OPTIMIZE_SIZE__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HB_LEAN
|
||||
#define HB_DISABLE_DEPRECATED
|
||||
#define HB_NDEBUG
|
||||
#define HB_NO_ATEXIT
|
||||
#define HB_NO_BUFFER_MESSAGE
|
||||
#define HB_NO_BUFFER_SERIALIZE
|
||||
#define HB_NO_BITMAP
|
||||
#define HB_NO_CFF
|
||||
#define HB_NO_COLOR
|
||||
#define HB_NO_FACE_COLLECT_UNICODES
|
||||
#define HB_NO_GETENV
|
||||
#define HB_NO_HINTING
|
||||
#define HB_NO_LANGUAGE_PRIVATE_SUBTAG
|
||||
#define HB_NO_LAYOUT_FEATURE_PARAMS
|
||||
#define HB_NO_LAYOUT_COLLECT_GLYPHS
|
||||
#define HB_NO_LAYOUT_UNUSED
|
||||
#define HB_NO_MATH
|
||||
#define HB_NO_META
|
||||
#define HB_NO_METRICS
|
||||
#define HB_NO_MMAP
|
||||
#define HB_NO_NAME
|
||||
#define HB_NO_OPEN
|
||||
#define HB_NO_SETLOCALE
|
||||
#define HB_NO_OT_FONT_GLYPH_NAMES
|
||||
#define HB_NO_OT_SHAPE_FRACTIONS
|
||||
#define HB_NO_STAT
|
||||
#define HB_NO_SUBSET_LAYOUT
|
||||
#define HB_NO_VAR
|
||||
#endif
|
||||
|
||||
#ifdef HB_MINI
|
||||
#define HB_NO_AAT
|
||||
#define HB_NO_LEGACY
|
||||
#endif
|
||||
|
||||
|
||||
/* Closure of options. */
|
||||
|
||||
#ifdef HB_DISABLE_DEPRECATED
|
||||
#define HB_IF_NOT_DEPRECATED(x)
|
||||
#else
|
||||
#define HB_IF_NOT_DEPRECATED(x) x
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_AAT
|
||||
#define HB_NO_OT_NAME_LANGUAGE_AAT
|
||||
#define HB_NO_AAT_SHAPE
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_BITMAP
|
||||
#define HB_NO_OT_FONT_BITMAP
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_CFF
|
||||
#define HB_NO_OT_FONT_CFF
|
||||
#define HB_NO_SUBSET_CFF
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_GETENV
|
||||
#define HB_NO_UNISCRIBE_BUG_COMPATIBLE
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_LEGACY
|
||||
#define HB_NO_CMAP_LEGACY_SUBTABLES
|
||||
#define HB_NO_FALLBACK_SHAPE
|
||||
#define HB_NO_OT_KERN
|
||||
#define HB_NO_OT_LAYOUT_BLACKLIST
|
||||
#define HB_NO_OT_SHAPE_FALLBACK
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_NAME
|
||||
#define HB_NO_OT_NAME_LANGUAGE
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_OT
|
||||
#define HB_NO_OT_FONT
|
||||
#define HB_NO_OT_LAYOUT
|
||||
#define HB_NO_OT_TAG
|
||||
#define HB_NO_OT_SHAPE
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_OT_SHAPE
|
||||
#define HB_NO_AAT_SHAPE
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_OT_SHAPE_FALLBACK
|
||||
#define HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
|
||||
#define HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
|
||||
#define HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK
|
||||
#define HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
#ifndef HB_NDEBUG
|
||||
#define HB_NDEBUG
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __OPTIMIZE_SIZE__
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
#define HB_OPTIMIZE_SIZE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_OVERRIDE_H
|
||||
#include "config-override.h"
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HB_CONFIG_HH */
|
|
@ -27,6 +27,9 @@
|
|||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifdef HAVE_CORETEXT
|
||||
|
||||
#include "hb-shaper-impl.hh"
|
||||
|
||||
#include "hb-coretext.h"
|
||||
|
@ -54,7 +57,7 @@ release_table_data (void *user_data)
|
|||
}
|
||||
|
||||
static hb_blob_t *
|
||||
reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
_hb_cg_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);
|
||||
|
@ -153,7 +156,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
|
|||
if (CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSText")) ||
|
||||
CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSDisplay")))
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
|
||||
#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1080
|
||||
# define kCTFontUIFontSystem kCTFontSystemFontType
|
||||
# define kCTFontUIFontEmphasizedSystem kCTFontEmphasizedSystemFontType
|
||||
#endif
|
||||
|
@ -196,7 +199,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
|
|||
}
|
||||
|
||||
CFURLRef original_url = nullptr;
|
||||
#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
ATSFontRef atsFont;
|
||||
FSRef fsref;
|
||||
OSStatus status;
|
||||
|
@ -226,7 +229,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
|
|||
* process in Blink. This can be detected by the new file URL location
|
||||
* that the newly found font points to. */
|
||||
CFURLRef new_url = nullptr;
|
||||
#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
|
||||
status = ATSFontGetFileReference (atsFont, &fsref);
|
||||
if (status == noErr)
|
||||
|
@ -278,7 +281,7 @@ _hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *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);
|
||||
return hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -393,7 +396,7 @@ struct active_feature_t {
|
|||
feature_record_t rec;
|
||||
unsigned int order;
|
||||
|
||||
static int cmp (const void *pa, const void *pb) {
|
||||
HB_INTERNAL 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 :
|
||||
|
@ -411,7 +414,7 @@ struct feature_event_t {
|
|||
bool start;
|
||||
active_feature_t feature;
|
||||
|
||||
static int cmp (const void *pa, const void *pb) {
|
||||
HB_INTERNAL 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 :
|
||||
|
@ -581,7 +584,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||
} else {
|
||||
active_feature_t *feature = active_features.find (&event->feature);
|
||||
if (feature)
|
||||
active_features.remove (feature - active_features.arrayZ ());
|
||||
active_features.remove (feature - active_features.arrayZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -591,7 +594,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||
|
||||
#define ALLOCATE_ARRAY(Type, name, len, on_no_room) \
|
||||
Type *name = (Type *) scratch; \
|
||||
{ \
|
||||
do { \
|
||||
unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
|
||||
if (unlikely (_consumed > scratch_size)) \
|
||||
{ \
|
||||
|
@ -600,7 +603,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||
} \
|
||||
scratch += _consumed; \
|
||||
scratch_size -= _consumed; \
|
||||
}
|
||||
} while (0)
|
||||
|
||||
ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2, /*nothing*/);
|
||||
unsigned int chars_len = 0;
|
||||
|
@ -632,7 +635,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||
DEBUG_MSG (CORETEXT, nullptr, __VA_ARGS__); \
|
||||
ret = false; \
|
||||
goto fail; \
|
||||
} HB_STMT_END;
|
||||
} HB_STMT_END
|
||||
|
||||
bool ret = true;
|
||||
CFStringRef string_ref = nullptr;
|
||||
|
@ -694,7 +697,7 @@ resize_and_retry:
|
|||
/* What's the iOS equivalent of this check?
|
||||
* The symbols was introduced in iOS 7.0.
|
||||
* At any rate, our fallback is safe and works fine. */
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
|
||||
#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1090
|
||||
# define kCTLanguageAttributeName CFSTR ("NSLanguage")
|
||||
#endif
|
||||
CFStringRef lang = CFStringCreateWithCStringNoCopy (kCFAllocatorDefault,
|
||||
|
@ -754,7 +757,7 @@ resize_and_retry:
|
|||
feature.start < chars_len && feature.start < feature.end)
|
||||
{
|
||||
CFRange feature_range = CFRangeMake (feature.start,
|
||||
MIN (feature.end, chars_len) - feature.start);
|
||||
hb_min (feature.end, chars_len) - feature.start);
|
||||
if (feature.value)
|
||||
CFAttributedStringRemoveAttribute (attr_string, feature_range, kCTKernAttributeName);
|
||||
else
|
||||
|
@ -766,7 +769,7 @@ resize_and_retry:
|
|||
|
||||
int level = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
|
||||
CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &level);
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
extern const CFStringRef kCTTypesetterOptionForcedEmbeddingLevel;
|
||||
#endif
|
||||
CFDictionaryRef options = CFDictionaryCreate (kCFAllocatorDefault,
|
||||
|
@ -960,7 +963,7 @@ resize_and_retry:
|
|||
|
||||
#define SCRATCH_RESTORE() \
|
||||
scratch_size = scratch_size_saved; \
|
||||
scratch = scratch_saved;
|
||||
scratch = scratch_saved
|
||||
|
||||
{ /* Setup glyphs */
|
||||
SCRATCH_SAVE();
|
||||
|
@ -1052,7 +1055,7 @@ resize_and_retry:
|
|||
if (false)
|
||||
{
|
||||
/* Make sure all runs had the expected direction. */
|
||||
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
|
||||
HB_UNUSED bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
|
||||
assert (bool (status_and & kCTRunStatusRightToLeft) == backward);
|
||||
assert (bool (status_or & kCTRunStatusRightToLeft) == backward);
|
||||
}
|
||||
|
@ -1099,7 +1102,7 @@ resize_and_retry:
|
|||
unsigned int cluster = info[count - 1].cluster;
|
||||
for (unsigned int i = count - 1; i > 0; i--)
|
||||
{
|
||||
cluster = MIN (cluster, info[i - 1].cluster);
|
||||
cluster = hb_min (cluster, info[i - 1].cluster);
|
||||
info[i - 1].cluster = cluster;
|
||||
}
|
||||
}
|
||||
|
@ -1108,7 +1111,7 @@ resize_and_retry:
|
|||
unsigned int cluster = info[0].cluster;
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
{
|
||||
cluster = MIN (cluster, info[i].cluster);
|
||||
cluster = hb_min (cluster, info[i].cluster);
|
||||
info[i].cluster = cluster;
|
||||
}
|
||||
}
|
||||
|
@ -1133,57 +1136,4 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* AAT shaper
|
||||
*/
|
||||
|
||||
/*
|
||||
* shaper face data
|
||||
*/
|
||||
|
||||
struct hb_coretext_aat_face_data_t {};
|
||||
|
||||
hb_coretext_aat_face_data_t *
|
||||
_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
|
||||
{
|
||||
return hb_aat_layout_has_substitution (face) || hb_aat_layout_has_positioning (face) ?
|
||||
(hb_coretext_aat_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_face_data_t *data HB_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* shaper font data
|
||||
*/
|
||||
|
||||
struct hb_coretext_aat_font_data_t {};
|
||||
|
||||
hb_coretext_aat_font_data_t *
|
||||
_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
|
||||
{
|
||||
return font->data.coretext ? (hb_coretext_aat_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_font_data_t *data HB_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* shaper
|
||||
*/
|
||||
|
||||
hb_bool_t
|
||||
_hb_coretext_aat_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_coretext_shape (shape_plan, font, buffer, features, num_features);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include "hb.hh"
|
||||
#include "hb-atomic.hh"
|
||||
#include "hb-dsalgs.hh"
|
||||
#include "hb-algs.hh"
|
||||
|
||||
|
||||
#ifndef HB_DEBUG
|
||||
|
@ -63,6 +63,9 @@ extern HB_INTERNAL hb_atomic_int_t _hb_options;
|
|||
static inline hb_options_t
|
||||
hb_options ()
|
||||
{
|
||||
#ifdef HB_NO_GETENV
|
||||
return hb_options_t ();
|
||||
#endif
|
||||
/* Make a local copy, so we can access bitfield threadsafely. */
|
||||
hb_options_union_t u;
|
||||
u.i = _hb_options.get_relaxed ();
|
||||
|
@ -158,7 +161,7 @@ _hb_debug_msg_va (const char *what,
|
|||
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),
|
||||
bars + sizeof (bars) - 1 - hb_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);
|
||||
|
@ -246,8 +249,8 @@ struct hb_printer_t<bool> {
|
|||
};
|
||||
|
||||
template <>
|
||||
struct hb_printer_t<hb_void_t> {
|
||||
const char *print (hb_void_t) { return ""; }
|
||||
struct hb_printer_t<hb_empty_t> {
|
||||
const char *print (hb_empty_t) { return ""; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -263,7 +266,7 @@ static inline void _hb_warn_no_return (bool returned)
|
|||
}
|
||||
}
|
||||
template <>
|
||||
/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
|
||||
/*static*/ inline void _hb_warn_no_return<hb_empty_t> (bool returned HB_UNUSED)
|
||||
{}
|
||||
|
||||
template <int max_level, typename ret_t>
|
||||
|
@ -327,18 +330,20 @@ struct hb_auto_trace_t<0, ret_t>
|
|||
const char *message,
|
||||
...) HB_PRINTF_FUNC(6, 7) {}
|
||||
|
||||
ret_t ret (ret_t v,
|
||||
const char *func HB_UNUSED = nullptr,
|
||||
unsigned int line HB_UNUSED = 0) { return v; }
|
||||
template <typename T>
|
||||
T ret (T&& v,
|
||||
const char *func HB_UNUSED = nullptr,
|
||||
unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); }
|
||||
};
|
||||
|
||||
/* For disabled tracing; optimize out everything.
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/605 */
|
||||
template <typename ret_t>
|
||||
struct hb_no_trace_t {
|
||||
ret_t ret (ret_t v,
|
||||
const char *func HB_UNUSED = "",
|
||||
unsigned int line HB_UNUSED = 0) { return v; }
|
||||
template <typename T>
|
||||
T ret (T&& v,
|
||||
const char *func HB_UNUSED = nullptr,
|
||||
unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); }
|
||||
};
|
||||
|
||||
#define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
|
||||
|
@ -401,30 +406,6 @@ struct hb_no_trace_t {
|
|||
#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
|
||||
|
@ -461,27 +442,12 @@ struct hb_no_trace_t {
|
|||
#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 + \
|
||||
HB_DEBUG_SUBSET + \
|
||||
0)
|
||||
#endif
|
||||
#if HB_DEBUG_DISPATCH
|
||||
|
|
|
@ -63,7 +63,7 @@ typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
|
|||
hb_codepoint_t *glyph,
|
||||
void *user_data);
|
||||
|
||||
HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func or hb_font_funcs_set_variation_glyph_func) void
|
||||
HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func and hb_font_funcs_set_variation_glyph_func) void
|
||||
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);
|
||||
|
@ -165,29 +165,8 @@ hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
|
|||
hb_codepoint_t *decomposed);
|
||||
|
||||
|
||||
typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
|
||||
void *user_data);
|
||||
typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
|
||||
typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_glyph_h_kerning_func:
|
||||
* @ffuncs: font functions.
|
||||
* @func: (closure user_data) (destroy destroy) (scope notified):
|
||||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
* Deprecated: 2.0.0
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_get_glyph_h_kerning_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_glyph_v_kerning_func:
|
||||
* @ffuncs: font functions.
|
||||
|
@ -206,19 +185,9 @@ hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
|
|||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
HB_EXTERN hb_position_t
|
||||
hb_font_get_glyph_h_kerning (hb_font_t *font,
|
||||
hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
|
||||
HB_EXTERN hb_position_t
|
||||
hb_font_get_glyph_v_kerning (hb_font_t *font,
|
||||
hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
|
||||
hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
|
||||
hb_direction_t direction,
|
||||
hb_position_t *x, hb_position_t *y);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
HB_END_DECLS
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2015-2018 Ebrahim Byagowi
|
||||
* Copyright © 2015-2019 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
@ -23,13 +23,23 @@
|
|||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifdef HAVE_DIRECTWRITE
|
||||
|
||||
#include "hb-shaper-impl.hh"
|
||||
|
||||
#include <DWrite_1.h>
|
||||
#include <dwrite_1.h>
|
||||
|
||||
#include "hb-directwrite.h"
|
||||
|
||||
|
||||
/* Declare object creator for dynamic support of DWRITE */
|
||||
typedef HRESULT (* WINAPI t_DWriteCreateFactory)(
|
||||
DWRITE_FACTORY_TYPE factoryType,
|
||||
REFIID iid,
|
||||
IUnknown **factory
|
||||
);
|
||||
|
||||
/*
|
||||
* hb-directwrite uses new/delete syntatically but as we let users
|
||||
* to override malloc/free, we will redefine new/delete so users
|
||||
|
@ -71,6 +81,8 @@ public:
|
|||
*fontFileStream = mFontFileStream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual ~DWriteFontFileLoader() {}
|
||||
};
|
||||
|
||||
class DWriteFontFileStream : public IDWriteFontFileStream
|
||||
|
@ -122,6 +134,8 @@ public:
|
|||
|
||||
virtual HRESULT STDMETHODCALLTYPE
|
||||
GetLastWriteTime (OUT UINT64* lastWriteTime) { return E_NOTIMPL; }
|
||||
|
||||
virtual ~DWriteFontFileStream() {}
|
||||
};
|
||||
|
||||
|
||||
|
@ -131,10 +145,11 @@ public:
|
|||
|
||||
struct hb_directwrite_face_data_t
|
||||
{
|
||||
HMODULE dwrite_dll;
|
||||
IDWriteFactory *dwriteFactory;
|
||||
IDWriteFontFile *fontFile;
|
||||
IDWriteFontFileStream *fontFileStream;
|
||||
IDWriteFontFileLoader *fontFileLoader;
|
||||
DWriteFontFileStream *fontFileStream;
|
||||
DWriteFontFileLoader *fontFileLoader;
|
||||
IDWriteFontFace *fontFace;
|
||||
hb_blob_t *faceBlob;
|
||||
};
|
||||
|
@ -146,12 +161,43 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
|
|||
if (unlikely (!data))
|
||||
return nullptr;
|
||||
|
||||
// TODO: factory and fontFileLoader should be cached separately
|
||||
IDWriteFactory* dwriteFactory;
|
||||
DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
|
||||
(IUnknown**) &dwriteFactory);
|
||||
#define FAIL(...) \
|
||||
HB_STMT_START { \
|
||||
DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
|
||||
return nullptr; \
|
||||
} HB_STMT_END
|
||||
|
||||
data->dwrite_dll = LoadLibrary (TEXT ("DWRITE"));
|
||||
if (unlikely (!data->dwrite_dll))
|
||||
FAIL ("Cannot find DWrite.DLL");
|
||||
|
||||
t_DWriteCreateFactory p_DWriteCreateFactory;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
#endif
|
||||
|
||||
p_DWriteCreateFactory = (t_DWriteCreateFactory)
|
||||
GetProcAddress (data->dwrite_dll, "DWriteCreateFactory");
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
if (unlikely (!p_DWriteCreateFactory))
|
||||
FAIL ("Cannot find DWriteCreateFactory().");
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
// TODO: factory and fontFileLoader should be cached separately
|
||||
IDWriteFactory* dwriteFactory;
|
||||
hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
|
||||
(IUnknown**) &dwriteFactory);
|
||||
|
||||
if (unlikely (hr != S_OK))
|
||||
FAIL ("Failed to run DWriteCreateFactory().");
|
||||
|
||||
hb_blob_t *blob = hb_face_reference_blob (face);
|
||||
DWriteFontFileStream *fontFileStream;
|
||||
fontFileStream = new DWriteFontFileStream ((uint8_t *) hb_blob_get_data (blob, nullptr),
|
||||
|
@ -165,12 +211,6 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
|
|||
hr = dwriteFactory->CreateCustomFontFileReference (&fontFileKey, sizeof (fontFileKey),
|
||||
fontFileLoader, &fontFile);
|
||||
|
||||
#define FAIL(...) \
|
||||
HB_STMT_START { \
|
||||
DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
|
||||
return nullptr; \
|
||||
} HB_STMT_END;
|
||||
|
||||
if (FAILED (hr))
|
||||
FAIL ("Failed to load font file from data!");
|
||||
|
||||
|
@ -217,6 +257,8 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
|
|||
delete data->fontFileStream;
|
||||
if (data->faceBlob)
|
||||
hb_blob_destroy (data->faceBlob);
|
||||
if (data->dwrite_dll)
|
||||
FreeLibrary (data->dwrite_dll);
|
||||
if (data)
|
||||
delete data;
|
||||
}
|
||||
|
@ -281,7 +323,7 @@ public:
|
|||
public:
|
||||
TextAnalysis (const wchar_t* text, uint32_t textLength,
|
||||
const wchar_t* localeName, DWRITE_READING_DIRECTION readingDirection)
|
||||
: mText (text), mTextLength (textLength), mLocaleName (localeName),
|
||||
: mTextLength (textLength), mText (text), mLocaleName (localeName),
|
||||
mReadingDirection (readingDirection), mCurrentRun (nullptr) {}
|
||||
~TextAnalysis ()
|
||||
{
|
||||
|
@ -497,11 +539,6 @@ protected:
|
|||
Run mRunHead;
|
||||
};
|
||||
|
||||
static inline uint16_t hb_uint16_swap (const uint16_t v)
|
||||
{ return (v >> 8) | (v << 8); }
|
||||
static inline uint32_t hb_uint32_swap (const uint32_t v)
|
||||
{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
|
||||
|
||||
/*
|
||||
* shaper
|
||||
*/
|
||||
|
@ -516,7 +553,6 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
|
|||
{
|
||||
hb_face_t *face = font->face;
|
||||
const hb_directwrite_face_data_t *face_data = face->data.directwrite;
|
||||
const hb_directwrite_font_data_t *font_data = font->data.directwrite;
|
||||
IDWriteFactory *dwriteFactory = face_data->dwriteFactory;
|
||||
IDWriteFontFace *fontFace = face_data->fontFace;
|
||||
|
||||
|
@ -527,12 +563,12 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
|
|||
hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
|
||||
#define ALLOCATE_ARRAY(Type, name, len) \
|
||||
Type *name = (Type *) scratch; \
|
||||
{ \
|
||||
do { \
|
||||
unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
|
||||
assert (_consumed <= scratch_size); \
|
||||
scratch += _consumed; \
|
||||
scratch_size -= _consumed; \
|
||||
}
|
||||
} while (0)
|
||||
|
||||
#define utf16_index() var1.u32
|
||||
|
||||
|
@ -655,10 +691,10 @@ retry_getglyphs:
|
|||
* alignment needed after the WORD array. sizeof (WORD) == 2. */
|
||||
unsigned int glyphs_size = (scratch_size * sizeof (int) - 2)
|
||||
/ (sizeof (WORD) +
|
||||
sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES) +
|
||||
sizeof (int) +
|
||||
sizeof (DWRITE_GLYPH_OFFSET) +
|
||||
sizeof (uint32_t));
|
||||
sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES) +
|
||||
sizeof (int) +
|
||||
sizeof (DWRITE_GLYPH_OFFSET) +
|
||||
sizeof (uint32_t));
|
||||
ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
|
||||
|
||||
#undef ALLOCATE_ARRAY
|
||||
|
@ -770,15 +806,15 @@ retry_getglyphs:
|
|||
|
||||
/* Calculate visual-clusters. That's what we ship. */
|
||||
for (unsigned int i = 0; i < glyphCount; i++)
|
||||
vis_clusters[i] = -1;
|
||||
vis_clusters[i] = (uint32_t) -1;
|
||||
for (unsigned int i = 0; i < buffer->len; i++)
|
||||
{
|
||||
uint32_t *p =
|
||||
&vis_clusters[log_clusters[buffer->info[i].utf16_index ()]];
|
||||
*p = MIN (*p, buffer->info[i].cluster);
|
||||
*p = hb_min (*p, buffer->info[i].cluster);
|
||||
}
|
||||
for (unsigned int i = 1; i < glyphCount; i++)
|
||||
if (vis_clusters[i] == -1)
|
||||
if (vis_clusters[i] == (uint32_t) -1)
|
||||
vis_clusters[i] = vis_clusters[i - 1];
|
||||
|
||||
#undef utf16_index
|
||||
|
@ -843,10 +879,23 @@ _hb_directwrite_shape (hb_shape_plan_t *shape_plan,
|
|||
features, num_features, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Public [experimental] API
|
||||
*/
|
||||
|
||||
/**
|
||||
* hb_directwrite_shape_experimental_width:
|
||||
* Experimental API to test DirectWrite's justification algorithm.
|
||||
*
|
||||
* It inserts Kashida at wrong order so don't use the API ever.
|
||||
*
|
||||
* It doesn't work with cygwin/msys due to header bugs so one
|
||||
* should use MSVC toolchain in order to use it for now.
|
||||
*
|
||||
* @font:
|
||||
* @buffer:
|
||||
* @features:
|
||||
* @num_features:
|
||||
* @width:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_directwrite_shape_experimental_width (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
|
@ -865,3 +914,83 @@ hb_directwrite_shape_experimental_width (hb_font_t *font,
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct _hb_directwrite_font_table_context {
|
||||
IDWriteFontFace *face;
|
||||
void *table_context;
|
||||
};
|
||||
|
||||
static void
|
||||
_hb_directwrite_table_data_release (void *data)
|
||||
{
|
||||
_hb_directwrite_font_table_context *context = (_hb_directwrite_font_table_context *) data;
|
||||
context->face->ReleaseFontTable (context->table_context);
|
||||
delete context;
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
_hb_directwrite_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
{
|
||||
IDWriteFontFace *dw_face = ((IDWriteFontFace *) user_data);
|
||||
const void *data;
|
||||
uint32_t length;
|
||||
void *table_context;
|
||||
BOOL exists;
|
||||
if (!dw_face || FAILED (dw_face->TryGetFontTable (hb_uint32_swap (tag), &data,
|
||||
&length, &table_context, &exists)))
|
||||
return nullptr;
|
||||
|
||||
if (!data || !exists || !length)
|
||||
{
|
||||
dw_face->ReleaseFontTable (table_context);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
_hb_directwrite_font_table_context *context = new _hb_directwrite_font_table_context;
|
||||
context->face = dw_face;
|
||||
context->table_context = table_context;
|
||||
|
||||
return hb_blob_create ((const char *) data, length, HB_MEMORY_MODE_READONLY,
|
||||
context, _hb_directwrite_table_data_release);
|
||||
}
|
||||
|
||||
static void
|
||||
_hb_directwrite_font_release (void *data)
|
||||
{
|
||||
if (data)
|
||||
((IDWriteFontFace *) data)->Release ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_directwrite_face_create:
|
||||
* @font_face: a DirectWrite IDWriteFontFace object.
|
||||
*
|
||||
* Return value: #hb_face_t object corresponding to the given input
|
||||
*
|
||||
* Since: 2.4.0
|
||||
**/
|
||||
hb_face_t *
|
||||
hb_directwrite_face_create (IDWriteFontFace *font_face)
|
||||
{
|
||||
if (font_face)
|
||||
font_face->AddRef ();
|
||||
return hb_face_create_for_tables (_hb_directwrite_reference_table, font_face,
|
||||
_hb_directwrite_font_release);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_directwrite_face_get_font_face:
|
||||
* @face: a #hb_face_t object
|
||||
*
|
||||
* Return value: DirectWrite IDWriteFontFace object corresponding to the given input
|
||||
*
|
||||
* Since: 2.5.0
|
||||
**/
|
||||
IDWriteFontFace *
|
||||
hb_directwrite_face_get_font_face (hb_face_t *face)
|
||||
{
|
||||
return face->data.directwrite->fontFace;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2015 Ebrahim Byagowi
|
||||
* Copyright © 2015-2019 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
@ -34,6 +34,12 @@ 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_EXTERN hb_face_t *
|
||||
hb_directwrite_face_create (IDWriteFontFace *font_face);
|
||||
|
||||
HB_EXTERN IDWriteFontFace *
|
||||
hb_directwrite_face_get_font_face (hb_face_t *face);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_DIRECTWRITE_H */
|
||||
|
|
58
src/hb-dispatch.hh
Normal file
58
src/hb-dispatch.hh
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright © 2007,2008,2009,2010 Red Hat, Inc.
|
||||
* Copyright © 2012,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.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_DISPATCH_HH
|
||||
#define HB_DISPATCH_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
/*
|
||||
* Dispatch
|
||||
*/
|
||||
|
||||
template <typename Context, typename Return, unsigned int MaxDebugDepth>
|
||||
struct hb_dispatch_context_t
|
||||
{
|
||||
private:
|
||||
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
|
||||
const Context* thiz () const { return static_cast<const Context *> (this); }
|
||||
Context* thiz () { return static_cast< Context *> (this); }
|
||||
public:
|
||||
static constexpr unsigned max_debug_depth = MaxDebugDepth;
|
||||
typedef Return return_t;
|
||||
template <typename T, typename F>
|
||||
bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; }
|
||||
template <typename T, typename ...Ts>
|
||||
return_t dispatch (const T &obj, Ts&&... ds)
|
||||
{ return obj.dispatch (thiz (), hb_forward<Ts> (ds)...); }
|
||||
static return_t no_dispatch_return_value () { return Context::default_return_value (); }
|
||||
static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; }
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_DISPATCH_HH */
|
638
src/hb-dsalgs.hh
638
src/hb-dsalgs.hh
|
@ -1,638 +0,0 @@
|
|||
/*
|
||||
* 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.hh"
|
||||
#include "hb-null.hh"
|
||||
|
||||
|
||||
/* Void! For when we need a expression-type of void. */
|
||||
typedef const struct _hb_void_t *hb_void_t;
|
||||
#define HB_VOID ((const _hb_void_t *) nullptr)
|
||||
|
||||
|
||||
/*
|
||||
* Bithacks.
|
||||
*/
|
||||
|
||||
/* Return the number of 1 bits in v. */
|
||||
template <typename T>
|
||||
static inline HB_CONST_FUNC unsigned int
|
||||
hb_popcount (T v)
|
||||
{
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
||||
if (sizeof (T) <= sizeof (unsigned int))
|
||||
return __builtin_popcount (v);
|
||||
|
||||
if (sizeof (T) <= sizeof (unsigned long))
|
||||
return __builtin_popcountl (v);
|
||||
|
||||
if (sizeof (T) <= sizeof (unsigned long long))
|
||||
return __builtin_popcountll (v);
|
||||
#endif
|
||||
|
||||
if (sizeof (T) <= 4)
|
||||
{
|
||||
/* "HACKMEM 169" */
|
||||
uint32_t y;
|
||||
y = (v >> 1) &033333333333;
|
||||
y = v - y - ((y >>1) & 033333333333);
|
||||
return (((y + (y >> 3)) & 030707070707) % 077);
|
||||
}
|
||||
|
||||
if (sizeof (T) == 8)
|
||||
{
|
||||
unsigned int shift = 32;
|
||||
return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
|
||||
}
|
||||
|
||||
if (sizeof (T) == 16)
|
||||
{
|
||||
unsigned int shift = 64;
|
||||
return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
|
||||
}
|
||||
|
||||
assert (0);
|
||||
return 0; /* Shut up stupid compiler. */
|
||||
}
|
||||
|
||||
/* Returns the number of bits needed to store number */
|
||||
template <typename T>
|
||||
static inline HB_CONST_FUNC unsigned int
|
||||
hb_bit_storage (T v)
|
||||
{
|
||||
if (unlikely (!v)) return 0;
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
||||
if (sizeof (T) <= sizeof (unsigned int))
|
||||
return sizeof (unsigned int) * 8 - __builtin_clz (v);
|
||||
|
||||
if (sizeof (T) <= sizeof (unsigned long))
|
||||
return sizeof (unsigned long) * 8 - __builtin_clzl (v);
|
||||
|
||||
if (sizeof (T) <= sizeof (unsigned long long))
|
||||
return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
|
||||
if (sizeof (T) <= sizeof (unsigned int))
|
||||
{
|
||||
unsigned long where;
|
||||
_BitScanReverse (&where, v);
|
||||
return 1 + where;
|
||||
}
|
||||
# if _WIN64
|
||||
if (sizeof (T) <= 8)
|
||||
{
|
||||
unsigned long where;
|
||||
_BitScanReverse64 (&where, v);
|
||||
return 1 + where;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (sizeof (T) <= 4)
|
||||
{
|
||||
/* "bithacks" */
|
||||
const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
|
||||
const unsigned int S[] = {1, 2, 4, 8, 16};
|
||||
unsigned int r = 0;
|
||||
for (int i = 4; i >= 0; i--)
|
||||
if (v & b[i])
|
||||
{
|
||||
v >>= S[i];
|
||||
r |= S[i];
|
||||
}
|
||||
return r + 1;
|
||||
}
|
||||
if (sizeof (T) <= 8)
|
||||
{
|
||||
/* "bithacks" */
|
||||
const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
|
||||
const unsigned int S[] = {1, 2, 4, 8, 16, 32};
|
||||
unsigned int r = 0;
|
||||
for (int i = 5; i >= 0; i--)
|
||||
if (v & b[i])
|
||||
{
|
||||
v >>= S[i];
|
||||
r |= S[i];
|
||||
}
|
||||
return r + 1;
|
||||
}
|
||||
if (sizeof (T) == 16)
|
||||
{
|
||||
unsigned int shift = 64;
|
||||
return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
|
||||
hb_bit_storage<uint64_t> ((uint64_t) v);
|
||||
}
|
||||
|
||||
assert (0);
|
||||
return 0; /* Shut up stupid compiler. */
|
||||
}
|
||||
|
||||
/* Returns the number of zero bits in the least significant side of v */
|
||||
template <typename T>
|
||||
static inline HB_CONST_FUNC unsigned int
|
||||
hb_ctz (T v)
|
||||
{
|
||||
if (unlikely (!v)) return 0;
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
||||
if (sizeof (T) <= sizeof (unsigned int))
|
||||
return __builtin_ctz (v);
|
||||
|
||||
if (sizeof (T) <= sizeof (unsigned long))
|
||||
return __builtin_ctzl (v);
|
||||
|
||||
if (sizeof (T) <= sizeof (unsigned long long))
|
||||
return __builtin_ctzll (v);
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
|
||||
if (sizeof (T) <= sizeof (unsigned int))
|
||||
{
|
||||
unsigned long where;
|
||||
_BitScanForward (&where, v);
|
||||
return where;
|
||||
}
|
||||
# if _WIN64
|
||||
if (sizeof (T) <= 8)
|
||||
{
|
||||
unsigned long where;
|
||||
_BitScanForward64 (&where, v);
|
||||
return where;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (sizeof (T) <= 4)
|
||||
{
|
||||
/* "bithacks" */
|
||||
unsigned int c = 32;
|
||||
v &= - (int32_t) v;
|
||||
if (v) c--;
|
||||
if (v & 0x0000FFFF) c -= 16;
|
||||
if (v & 0x00FF00FF) c -= 8;
|
||||
if (v & 0x0F0F0F0F) c -= 4;
|
||||
if (v & 0x33333333) c -= 2;
|
||||
if (v & 0x55555555) c -= 1;
|
||||
return c;
|
||||
}
|
||||
if (sizeof (T) <= 8)
|
||||
{
|
||||
/* "bithacks" */
|
||||
unsigned int c = 64;
|
||||
v &= - (int64_t) (v);
|
||||
if (v) c--;
|
||||
if (v & 0x00000000FFFFFFFFULL) c -= 32;
|
||||
if (v & 0x0000FFFF0000FFFFULL) c -= 16;
|
||||
if (v & 0x00FF00FF00FF00FFULL) c -= 8;
|
||||
if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
|
||||
if (v & 0x3333333333333333ULL) c -= 2;
|
||||
if (v & 0x5555555555555555ULL) c -= 1;
|
||||
return c;
|
||||
}
|
||||
if (sizeof (T) == 16)
|
||||
{
|
||||
unsigned int shift = 64;
|
||||
return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
|
||||
hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
|
||||
}
|
||||
|
||||
assert (0);
|
||||
return 0; /* Shut up stupid compiler. */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Tiny stuff.
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
static inline T* hb_addressof (T& arg)
|
||||
{
|
||||
/* https://en.cppreference.com/w/cpp/memory/addressof */
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(
|
||||
reinterpret_cast<const volatile char&>(arg)));
|
||||
}
|
||||
|
||||
/* ASCII tag/character handling */
|
||||
static inline bool ISALPHA (unsigned char c)
|
||||
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
|
||||
static inline bool ISALNUM (unsigned char c)
|
||||
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
|
||||
static inline bool ISSPACE (unsigned char c)
|
||||
{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
|
||||
static inline unsigned char TOUPPER (unsigned char c)
|
||||
{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
|
||||
static inline unsigned char TOLOWER (unsigned char c)
|
||||
{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
|
||||
|
||||
#undef MIN
|
||||
template <typename Type>
|
||||
static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
|
||||
|
||||
#undef MAX
|
||||
template <typename Type>
|
||||
static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
|
||||
|
||||
static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
|
||||
{ return (a + (b - 1)) / b; }
|
||||
|
||||
|
||||
#undef ARRAY_LENGTH
|
||||
template <typename Type, unsigned int n>
|
||||
static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
|
||||
/* A const version, but does not detect erratically being called on pointers. */
|
||||
#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
|
||||
|
||||
|
||||
static inline int
|
||||
hb_memcmp (const void *a, const void *b, unsigned int len)
|
||||
{
|
||||
/* It's illegal to pass NULL to memcmp(), even if len is zero.
|
||||
* So, wrap it.
|
||||
* https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
|
||||
if (!len) return 0;
|
||||
return memcmp (a, b, len);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
|
||||
{
|
||||
return (size > 0) && (count >= ((unsigned int) -1) / size);
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
hb_ceil_to_4 (unsigned int v)
|
||||
{
|
||||
return ((v - 1) | 3) + 1;
|
||||
}
|
||||
|
||||
template <typename T> struct hb_is_signed;
|
||||
template <> struct hb_is_signed<signed char> { enum { value = true }; };
|
||||
template <> struct hb_is_signed<signed short> { enum { value = true }; };
|
||||
template <> struct hb_is_signed<signed int> { enum { value = true }; };
|
||||
template <> struct hb_is_signed<signed long> { enum { value = true }; };
|
||||
template <> struct hb_is_signed<unsigned char> { enum { value = false }; };
|
||||
template <> struct hb_is_signed<unsigned short> { enum { value = false }; };
|
||||
template <> struct hb_is_signed<unsigned int> { enum { value = false }; };
|
||||
template <> struct hb_is_signed<unsigned long> { enum { value = false }; };
|
||||
/* We need to define hb_is_signed for the typedefs we use on pre-Visual
|
||||
* Studio 2010 for the int8_t type, since __int8/__int64 is not considered
|
||||
* the same as char/long. The previous lines will suffice for the other
|
||||
* types, though. Note that somehow, unsigned __int8 is considered same
|
||||
* as unsigned char.
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/1499
|
||||
*/
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
template <> struct hb_is_signed<__int8> { enum { value = true }; };
|
||||
#endif
|
||||
|
||||
template <typename T> static inline bool
|
||||
hb_in_range (T u, T lo, T hi)
|
||||
{
|
||||
/* The sizeof() is here to force template instantiation.
|
||||
* I'm sure there are better ways to do this but can't think of
|
||||
* one right now. Declaring a variable won't work as HB_UNUSED
|
||||
* is unusable on some platforms and unused types are less likely
|
||||
* to generate a warning than unused variables. */
|
||||
static_assert (!hb_is_signed<T>::value, "");
|
||||
|
||||
/* The casts below are important as if T is smaller than int,
|
||||
* the subtract results will become a signed int! */
|
||||
return (T)(u - lo) <= (T)(hi - lo);
|
||||
}
|
||||
template <typename T> static inline bool
|
||||
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
|
||||
{
|
||||
return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
|
||||
}
|
||||
template <typename T> static inline bool
|
||||
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
|
||||
{
|
||||
return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sort and search.
|
||||
*/
|
||||
|
||||
static inline void *
|
||||
hb_bsearch (const void *key, const void *base,
|
||||
size_t nmemb, size_t size,
|
||||
int (*compar)(const void *_key, const void *_item))
|
||||
{
|
||||
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);
|
||||
if (c < 0)
|
||||
max = mid - 1;
|
||||
else if (c > 0)
|
||||
min = mid + 1;
|
||||
else
|
||||
return (void *) p;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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 = ((unsigned int) min + (unsigned int) 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 nullptr;
|
||||
}
|
||||
|
||||
|
||||
/* From https://github.com/noporpoise/sort_r
|
||||
* With following modifications:
|
||||
*
|
||||
* 10 November 2018:
|
||||
* https://github.com/noporpoise/sort_r/issues/7
|
||||
*/
|
||||
|
||||
/* 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, *pm, *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) {
|
||||
pm = pl+((pr-pl+1)>>1);
|
||||
for(; pl < pm; pl += w) {
|
||||
if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
|
||||
pr -= w; /* pivot now at pl */
|
||||
break;
|
||||
}
|
||||
}
|
||||
pm = pl+((pr-pl)>>1);
|
||||
for(; pm < 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);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename T2> static inline void
|
||||
hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
|
||||
{
|
||||
for (unsigned int i = 1; i < len; i++)
|
||||
{
|
||||
unsigned int j = i;
|
||||
while (j && compar (&array[j - 1], &array[i]) > 0)
|
||||
j--;
|
||||
if (i == j)
|
||||
continue;
|
||||
/* Move item i to occupy place for item j, shift what's in between. */
|
||||
{
|
||||
T t = array[i];
|
||||
memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
|
||||
array[j] = t;
|
||||
}
|
||||
if (array2)
|
||||
{
|
||||
T2 t = array2[i];
|
||||
memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
|
||||
array2[j] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> static inline void
|
||||
hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
|
||||
{
|
||||
hb_stable_sort (array, len, compar, (int *) nullptr);
|
||||
}
|
||||
|
||||
static inline hb_bool_t
|
||||
hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
|
||||
{
|
||||
/* Pain because we don't know whether s is nul-terminated. */
|
||||
char buf[64];
|
||||
len = MIN (ARRAY_LENGTH (buf) - 1, len);
|
||||
strncpy (buf, s, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
char *end;
|
||||
errno = 0;
|
||||
unsigned long v = strtoul (buf, &end, base);
|
||||
if (errno) return false;
|
||||
if (*end) return false;
|
||||
*out = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
struct HbOpOr
|
||||
{
|
||||
enum { passthru_left = true };
|
||||
enum { passthru_right = true };
|
||||
template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
|
||||
};
|
||||
struct HbOpAnd
|
||||
{
|
||||
enum { passthru_left = false };
|
||||
enum { passthru_right = false };
|
||||
template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
|
||||
};
|
||||
struct HbOpMinus
|
||||
{
|
||||
enum { passthru_left = true };
|
||||
enum { passthru_right = false };
|
||||
template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
|
||||
};
|
||||
struct HbOpXor
|
||||
{
|
||||
enum { passthru_left = true };
|
||||
enum { passthru_right = true };
|
||||
template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
|
||||
};
|
||||
|
||||
|
||||
/* Compiler-assisted vectorization. */
|
||||
|
||||
/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
|
||||
* using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128).
|
||||
* Define that to 0 to disable. */
|
||||
template <typename elt_t, unsigned int byte_size>
|
||||
struct hb_vector_size_t
|
||||
{
|
||||
elt_t& operator [] (unsigned int i) { return u.v[i]; }
|
||||
const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
|
||||
|
||||
void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
|
||||
|
||||
template <class Op>
|
||||
hb_vector_size_t process (const hb_vector_size_t &o) const
|
||||
{
|
||||
hb_vector_size_t r;
|
||||
#if HB_VECTOR_SIZE
|
||||
if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
|
||||
Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
|
||||
else
|
||||
#endif
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
|
||||
Op::process (r.u.v[i], u.v[i], o.u.v[i]);
|
||||
return r;
|
||||
}
|
||||
hb_vector_size_t operator | (const hb_vector_size_t &o) const
|
||||
{ return process<HbOpOr> (o); }
|
||||
hb_vector_size_t operator & (const hb_vector_size_t &o) const
|
||||
{ return process<HbOpAnd> (o); }
|
||||
hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
|
||||
{ return process<HbOpXor> (o); }
|
||||
hb_vector_size_t operator ~ () const
|
||||
{
|
||||
hb_vector_size_t r;
|
||||
#if HB_VECTOR_SIZE && 0
|
||||
if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
|
||||
r.u.vec[i] = ~u.vec[i];
|
||||
else
|
||||
#endif
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
|
||||
r.u.v[i] = ~u.v[i];
|
||||
return r;
|
||||
}
|
||||
|
||||
private:
|
||||
static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
|
||||
union {
|
||||
elt_t v[byte_size / sizeof (elt_t)];
|
||||
#if HB_VECTOR_SIZE
|
||||
hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
|
||||
#endif
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_DSALGS_HH */
|
|
@ -531,6 +531,7 @@ hb_face_get_table_tags (const hb_face_t *face,
|
|||
*/
|
||||
|
||||
|
||||
#ifndef HB_NO_FACE_COLLECT_UNICODES
|
||||
/**
|
||||
* hb_face_collect_unicodes:
|
||||
* @face: font face.
|
||||
|
@ -544,7 +545,6 @@ hb_face_collect_unicodes (hb_face_t *face,
|
|||
{
|
||||
face->table.cmap->collect_unicodes (out);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_face_collect_variation_selectors:
|
||||
* @face: font face.
|
||||
|
@ -560,7 +560,6 @@ hb_face_collect_variation_selectors (hb_face_t *face,
|
|||
{
|
||||
face->table.cmap->collect_variation_selectors (out);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_face_collect_variation_unicodes:
|
||||
* @face: font face.
|
||||
|
@ -577,7 +576,7 @@ hb_face_collect_variation_unicodes (hb_face_t *face,
|
|||
{
|
||||
face->table.cmap->collect_variation_unicodes (variation_selector, out);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "hb-shaper-impl.hh"
|
||||
|
||||
#ifndef HB_NO_FALLBACK_SHAPE
|
||||
|
||||
/*
|
||||
* shaper face data
|
||||
|
@ -120,3 +121,5 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
406
src/hb-font.cc
406
src/hb-font.cc
|
@ -139,10 +139,10 @@ hb_font_get_nominal_glyphs_default (hb_font_t *font,
|
|||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (!font->get_nominal_glyph (*first_unicode, first_glyph))
|
||||
return i;
|
||||
return i;
|
||||
|
||||
first_unicode = &StructAtOffset<hb_codepoint_t> (first_unicode, unicode_stride);
|
||||
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -238,8 +238,8 @@ hb_font_get_glyph_h_advances_default (hb_font_t* font,
|
|||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->get_glyph_h_advance (*first_glyph);
|
||||
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ hb_font_get_glyph_h_advances_default (hb_font_t* font,
|
|||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->parent_scale_x_distance (*first_advance);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,8 +270,8 @@ hb_font_get_glyph_v_advances_default (hb_font_t* font,
|
|||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->get_glyph_v_advance (*first_glyph);
|
||||
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ hb_font_get_glyph_v_advances_default (hb_font_t* font,
|
|||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->parent_scale_y_distance (*first_advance);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,6 +355,7 @@ hb_font_get_glyph_h_kerning_default (hb_font_t *font,
|
|||
return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
|
||||
}
|
||||
|
||||
#ifndef HB_DISABLE_DEPRECATED
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
|
@ -373,6 +374,7 @@ hb_font_get_glyph_v_kerning_default (hb_font_t *font,
|
|||
{
|
||||
return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
|
||||
|
@ -516,9 +518,9 @@ static const hb_font_funcs_t _hb_font_funcs_default = {
|
|||
/**
|
||||
* hb_font_funcs_create: (Xconstructor)
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -538,9 +540,9 @@ hb_font_funcs_create ()
|
|||
/**
|
||||
* hb_font_funcs_get_empty:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -554,9 +556,9 @@ hb_font_funcs_get_empty ()
|
|||
* hb_font_funcs_reference: (skip)
|
||||
* @ffuncs: font functions.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -570,7 +572,7 @@ hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
|
|||
* hb_font_funcs_destroy: (skip)
|
||||
* @ffuncs: font functions.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -590,14 +592,14 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
|
|||
/**
|
||||
* hb_font_funcs_set_user_data: (skip)
|
||||
* @ffuncs: font functions.
|
||||
* @key:
|
||||
* @data:
|
||||
* @destroy:
|
||||
* @replace:
|
||||
* @key:
|
||||
* @data:
|
||||
* @destroy:
|
||||
* @replace:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -614,11 +616,11 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
|
|||
/**
|
||||
* hb_font_funcs_get_user_data: (skip)
|
||||
* @ffuncs: font functions.
|
||||
* @key:
|
||||
* @key:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value: (transfer none):
|
||||
*
|
||||
* Return value: (transfer none):
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -634,7 +636,7 @@ hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
|
|||
* hb_font_funcs_make_immutable:
|
||||
* @ffuncs: font functions.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -651,9 +653,9 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
|
|||
* hb_font_funcs_is_immutable:
|
||||
* @ffuncs: font functions.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -749,13 +751,13 @@ hb_font_get_v_extents (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph:
|
||||
* @font: a font.
|
||||
* @unicode:
|
||||
* @variation_selector:
|
||||
* @glyph: (out):
|
||||
* @unicode:
|
||||
* @variation_selector:
|
||||
* @glyph: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -772,12 +774,12 @@ hb_font_get_glyph (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_nominal_glyph:
|
||||
* @font: a font.
|
||||
* @unicode:
|
||||
* @glyph: (out):
|
||||
* @unicode:
|
||||
* @glyph: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 1.2.3
|
||||
**/
|
||||
|
@ -792,13 +794,13 @@ hb_font_get_nominal_glyph (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_variation_glyph:
|
||||
* @font: a font.
|
||||
* @unicode:
|
||||
* @variation_selector:
|
||||
* @glyph: (out):
|
||||
* @unicode:
|
||||
* @variation_selector:
|
||||
* @glyph: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 1.2.3
|
||||
**/
|
||||
|
@ -813,11 +815,11 @@ hb_font_get_variation_glyph (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_h_advance:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @glyph:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -831,11 +833,11 @@ hb_font_get_glyph_h_advance (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_v_advance:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @glyph:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -850,7 +852,7 @@ hb_font_get_glyph_v_advance (hb_font_t *font,
|
|||
* hb_font_get_glyph_h_advances:
|
||||
* @font: a font.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 1.8.6
|
||||
**/
|
||||
|
@ -868,7 +870,7 @@ hb_font_get_glyph_h_advances (hb_font_t* font,
|
|||
* hb_font_get_glyph_v_advances:
|
||||
* @font: a font.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 1.8.6
|
||||
**/
|
||||
|
@ -886,13 +888,13 @@ hb_font_get_glyph_v_advances (hb_font_t* font,
|
|||
/**
|
||||
* hb_font_get_glyph_h_origin:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
* @glyph:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -907,13 +909,13 @@ hb_font_get_glyph_h_origin (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_v_origin:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
* @glyph:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -928,15 +930,14 @@ hb_font_get_glyph_v_origin (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_h_kerning:
|
||||
* @font: a font.
|
||||
* @left_glyph:
|
||||
* @right_glyph:
|
||||
* @left_glyph:
|
||||
* @right_glyph:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
* Deprecated: 2.0.0
|
||||
**/
|
||||
hb_position_t
|
||||
hb_font_get_glyph_h_kerning (hb_font_t *font,
|
||||
|
@ -945,15 +946,16 @@ hb_font_get_glyph_h_kerning (hb_font_t *font,
|
|||
return font->get_glyph_h_kerning (left_glyph, right_glyph);
|
||||
}
|
||||
|
||||
#ifndef HB_DISABLE_DEPRECATED
|
||||
/**
|
||||
* hb_font_get_glyph_v_kerning:
|
||||
* @font: a font.
|
||||
* @top_glyph:
|
||||
* @bottom_glyph:
|
||||
* @top_glyph:
|
||||
* @bottom_glyph:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
* Deprecated: 2.0.0
|
||||
|
@ -964,16 +966,17 @@ hb_font_get_glyph_v_kerning (hb_font_t *font,
|
|||
{
|
||||
return font->get_glyph_v_kerning (top_glyph, bottom_glyph);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_font_get_glyph_extents:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @extents: (out):
|
||||
* @glyph:
|
||||
* @extents: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -988,14 +991,14 @@ hb_font_get_glyph_extents (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_contour_point:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @point_index:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
* @glyph:
|
||||
* @point_index:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1010,13 +1013,13 @@ hb_font_get_glyph_contour_point (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_name:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @name: (array length=size):
|
||||
* @size:
|
||||
* @glyph:
|
||||
* @name: (array length=size):
|
||||
* @size:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1031,13 +1034,13 @@ hb_font_get_glyph_name (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_from_name:
|
||||
* @font: a font.
|
||||
* @name: (array length=len):
|
||||
* @len:
|
||||
* @glyph: (out):
|
||||
* @name: (array length=len):
|
||||
* @len:
|
||||
* @glyph: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1072,12 +1075,12 @@ hb_font_get_extents_for_direction (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_advance_for_direction:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
* @glyph:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1092,9 +1095,9 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_advances_for_direction:
|
||||
* @font: a font.
|
||||
* @direction:
|
||||
* @direction:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 1.8.6
|
||||
**/
|
||||
|
@ -1113,12 +1116,12 @@ hb_font_get_glyph_advances_for_direction (hb_font_t* font,
|
|||
/**
|
||||
* hb_font_get_glyph_origin_for_direction:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
* @glyph:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1134,12 +1137,12 @@ hb_font_get_glyph_origin_for_direction (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_add_glyph_origin_for_direction:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
* @glyph:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1155,12 +1158,12 @@ hb_font_add_glyph_origin_for_direction (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_subtract_glyph_origin_for_direction:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
* @glyph:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1176,16 +1179,15 @@ hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_kerning_for_direction:
|
||||
* @font: a font.
|
||||
* @first_glyph:
|
||||
* @second_glyph:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
* @first_glyph:
|
||||
* @second_glyph:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
* Deprecated: 2.0.0
|
||||
**/
|
||||
void
|
||||
hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
|
||||
|
@ -1199,13 +1201,13 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_extents_for_origin:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @direction:
|
||||
* @extents: (out):
|
||||
* @glyph:
|
||||
* @direction:
|
||||
* @extents: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1221,15 +1223,15 @@ hb_font_get_glyph_extents_for_origin (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_contour_point_for_origin:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @point_index:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
* @glyph:
|
||||
* @point_index:
|
||||
* @direction:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1246,11 +1248,11 @@ hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_glyph_to_string:
|
||||
* @font: a font.
|
||||
* @glyph:
|
||||
* @s: (array length=size):
|
||||
* @size:
|
||||
* @glyph:
|
||||
* @s: (array length=size):
|
||||
* @size:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1266,13 +1268,13 @@ hb_font_glyph_to_string (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_glyph_from_string:
|
||||
* @font: a font.
|
||||
* @s: (array length=len) (element-type uint8_t):
|
||||
* @len:
|
||||
* @glyph: (out):
|
||||
* @s: (array length=len) (element-type uint8_t):
|
||||
* @len:
|
||||
* @glyph: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1298,6 +1300,8 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
|
|||
|
||||
1000, /* x_scale */
|
||||
1000, /* y_scale */
|
||||
1<<16, /* x_mult */
|
||||
1<<16, /* y_mult */
|
||||
|
||||
0, /* x_ppem */
|
||||
0, /* y_ppem */
|
||||
|
@ -1328,6 +1332,7 @@ _hb_font_create (hb_face_t *face)
|
|||
font->klass = hb_font_funcs_get_empty ();
|
||||
font->data.init0 (font);
|
||||
font->x_scale = font->y_scale = hb_face_get_upem (face);
|
||||
font->x_mult = font->y_mult = 1 << 16;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
@ -1336,9 +1341,9 @@ _hb_font_create (hb_face_t *face)
|
|||
* hb_font_create: (Xconstructor)
|
||||
* @face: a face.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1347,8 +1352,10 @@ hb_font_create (hb_face_t *face)
|
|||
{
|
||||
hb_font_t *font = _hb_font_create (face);
|
||||
|
||||
#ifndef HB_NO_OT_FONT
|
||||
/* Install our in-house, very lightweight, funcs. */
|
||||
hb_ot_font_set_funcs (font);
|
||||
#endif
|
||||
|
||||
return font;
|
||||
}
|
||||
|
@ -1357,9 +1364,9 @@ hb_font_create (hb_face_t *face)
|
|||
* hb_font_create_sub_font:
|
||||
* @parent: parent font.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1383,9 +1390,7 @@ hb_font_create_sub_font (hb_font_t *parent)
|
|||
font->ptem = parent->ptem;
|
||||
|
||||
font->num_coords = parent->num_coords;
|
||||
if (!font->num_coords)
|
||||
font->coords = nullptr;
|
||||
else
|
||||
if (font->num_coords)
|
||||
{
|
||||
unsigned int size = parent->num_coords * sizeof (parent->coords[0]);
|
||||
font->coords = (int *) malloc (size);
|
||||
|
@ -1401,7 +1406,7 @@ hb_font_create_sub_font (hb_font_t *parent)
|
|||
/**
|
||||
* hb_font_get_empty:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value: (transfer full)
|
||||
*
|
||||
|
@ -1417,9 +1422,9 @@ hb_font_get_empty ()
|
|||
* hb_font_reference: (skip)
|
||||
* @font: a font.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1433,7 +1438,7 @@ hb_font_reference (hb_font_t *font)
|
|||
* hb_font_destroy: (skip)
|
||||
* @font: a font.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1459,14 +1464,14 @@ hb_font_destroy (hb_font_t *font)
|
|||
/**
|
||||
* hb_font_set_user_data: (skip)
|
||||
* @font: a font.
|
||||
* @key:
|
||||
* @data:
|
||||
* @destroy:
|
||||
* @replace:
|
||||
* @key:
|
||||
* @data:
|
||||
* @destroy:
|
||||
* @replace:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1483,11 +1488,11 @@ hb_font_set_user_data (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_user_data: (skip)
|
||||
* @font: a font.
|
||||
* @key:
|
||||
* @key:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value: (transfer none):
|
||||
*
|
||||
* Return value: (transfer none):
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1502,7 +1507,7 @@ hb_font_get_user_data (hb_font_t *font,
|
|||
* hb_font_make_immutable:
|
||||
* @font: a font.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1522,9 +1527,9 @@ hb_font_make_immutable (hb_font_t *font)
|
|||
* hb_font_is_immutable:
|
||||
* @font: a font.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1564,9 +1569,9 @@ hb_font_set_parent (hb_font_t *font,
|
|||
* hb_font_get_parent:
|
||||
* @font: a font.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value: (transfer none):
|
||||
*
|
||||
* Return value: (transfer none):
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1597,7 +1602,9 @@ hb_font_set_face (hb_font_t *font,
|
|||
|
||||
hb_face_t *old = font->face;
|
||||
|
||||
hb_face_make_immutable (face);
|
||||
font->face = hb_face_reference (face);
|
||||
font->mults_changed ();
|
||||
|
||||
hb_face_destroy (old);
|
||||
}
|
||||
|
@ -1606,9 +1613,9 @@ hb_font_set_face (hb_font_t *font,
|
|||
* hb_font_get_face:
|
||||
* @font: a font.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value: (transfer none):
|
||||
*
|
||||
* Return value: (transfer none):
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1623,10 +1630,10 @@ hb_font_get_face (hb_font_t *font)
|
|||
* hb_font_set_funcs:
|
||||
* @font: a font.
|
||||
* @klass: (closure font_data) (destroy destroy) (scope notified):
|
||||
* @font_data:
|
||||
* @destroy:
|
||||
* @font_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1660,9 +1667,9 @@ hb_font_set_funcs (hb_font_t *font,
|
|||
* hb_font_set_funcs_data:
|
||||
* @font: a font.
|
||||
* @font_data: (destroy destroy) (scope notified):
|
||||
* @destroy:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1690,10 +1697,10 @@ hb_font_set_funcs_data (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_set_scale:
|
||||
* @font: a font.
|
||||
* @x_scale:
|
||||
* @y_scale:
|
||||
* @x_scale:
|
||||
* @y_scale:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1707,15 +1714,16 @@ hb_font_set_scale (hb_font_t *font,
|
|||
|
||||
font->x_scale = x_scale;
|
||||
font->y_scale = y_scale;
|
||||
font->mults_changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_get_scale:
|
||||
* @font: a font.
|
||||
* @x_scale: (out):
|
||||
* @y_scale: (out):
|
||||
* @x_scale: (out):
|
||||
* @y_scale: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1731,10 +1739,10 @@ hb_font_get_scale (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_set_ppem:
|
||||
* @font: a font.
|
||||
* @x_ppem:
|
||||
* @y_ppem:
|
||||
* @x_ppem:
|
||||
* @y_ppem:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1753,10 +1761,10 @@ hb_font_set_ppem (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_ppem:
|
||||
* @font: a font.
|
||||
* @x_ppem: (out):
|
||||
* @y_ppem: (out):
|
||||
* @x_ppem: (out):
|
||||
* @y_ppem: (out):
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -1805,6 +1813,7 @@ hb_font_get_ptem (hb_font_t *font)
|
|||
return font->ptem;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
/*
|
||||
* Variations
|
||||
*/
|
||||
|
@ -1872,6 +1881,33 @@ hb_font_set_var_coords_design (hb_font_t *font,
|
|||
_hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_var_named_instance:
|
||||
* @font: a font.
|
||||
* @instance_index: named instance index.
|
||||
*
|
||||
* Sets design coords of a font from a named instance index.
|
||||
*
|
||||
* Since: 2.6.0
|
||||
*/
|
||||
void
|
||||
hb_font_set_var_named_instance (hb_font_t *font,
|
||||
unsigned instance_index)
|
||||
{
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr);
|
||||
|
||||
float *coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
|
||||
if (unlikely (coords_length && !coords))
|
||||
return;
|
||||
|
||||
hb_ot_var_named_instance_get_design_coords (font->face, instance_index, &coords_length, coords);
|
||||
hb_font_set_var_coords_design (font, coords, coords_length);
|
||||
free (coords);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_var_coords_normalized:
|
||||
*
|
||||
|
@ -1912,8 +1948,9 @@ hb_font_get_var_coords_normalized (hb_font_t *font,
|
|||
|
||||
return font->coords;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HB_DISABLE_DEPRECATED
|
||||
/*
|
||||
* Deprecated get_glyph_func():
|
||||
*/
|
||||
|
@ -2036,3 +2073,4 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
|
|||
trampoline,
|
||||
trampoline_destroy);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -157,6 +157,11 @@ typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *fon
|
|||
typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t;
|
||||
typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t;
|
||||
|
||||
typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
|
||||
void *user_data);
|
||||
typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
|
||||
|
||||
|
||||
typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
|
@ -219,7 +224,7 @@ hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 1.2.3
|
||||
**/
|
||||
|
@ -251,7 +256,7 @@ hb_font_funcs_set_nominal_glyphs_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 1.2.3
|
||||
**/
|
||||
|
@ -267,7 +272,7 @@ hb_font_funcs_set_variation_glyph_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -283,7 +288,7 @@ hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -299,7 +304,7 @@ hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 1.8.6
|
||||
**/
|
||||
|
@ -315,7 +320,7 @@ hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 1.8.6
|
||||
**/
|
||||
|
@ -331,7 +336,7 @@ hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -347,7 +352,7 @@ hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -356,6 +361,22 @@ hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
|
|||
hb_font_get_glyph_v_origin_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_glyph_h_kerning_func:
|
||||
* @ffuncs: font functions.
|
||||
* @func: (closure user_data) (destroy destroy) (scope notified):
|
||||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_get_glyph_h_kerning_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_glyph_extents_func:
|
||||
* @ffuncs: font functions.
|
||||
|
@ -363,7 +384,7 @@ hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -379,7 +400,7 @@ hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -395,7 +416,7 @@ hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -411,7 +432,7 @@ hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs,
|
|||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -469,6 +490,10 @@ hb_font_get_glyph_v_origin (hb_font_t *font,
|
|||
hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y);
|
||||
|
||||
HB_EXTERN hb_position_t
|
||||
hb_font_get_glyph_h_kerning (hb_font_t *font,
|
||||
hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_font_get_glyph_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
|
@ -531,6 +556,12 @@ hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
|
|||
hb_direction_t direction,
|
||||
hb_position_t *x, hb_position_t *y);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
|
||||
hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
|
||||
hb_direction_t direction,
|
||||
hb_position_t *x, hb_position_t *y);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_font_get_glyph_extents_for_origin (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
|
@ -674,6 +705,10 @@ HB_EXTERN const int *
|
|||
hb_font_get_var_coords_normalized (hb_font_t *font,
|
||||
unsigned int *length);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_var_named_instance (hb_font_t *font,
|
||||
unsigned instance_index);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_FONT_H */
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
|
||||
HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning)) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_name) \
|
||||
|
@ -107,8 +107,10 @@ struct hb_font_t
|
|||
hb_font_t *parent;
|
||||
hb_face_t *face;
|
||||
|
||||
int x_scale;
|
||||
int y_scale;
|
||||
int32_t x_scale;
|
||||
int32_t y_scale;
|
||||
int64_t x_mult;
|
||||
int64_t y_mult;
|
||||
|
||||
unsigned int x_ppem;
|
||||
unsigned int y_ppem;
|
||||
|
@ -127,16 +129,16 @@ struct hb_font_t
|
|||
|
||||
|
||||
/* Convert from font-space to user-space */
|
||||
int dir_scale (hb_direction_t direction)
|
||||
{ return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
|
||||
hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
|
||||
hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
|
||||
hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
|
||||
hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
|
||||
int64_t dir_mult (hb_direction_t direction)
|
||||
{ return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
|
||||
hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
|
||||
hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); }
|
||||
hb_position_t em_scalef_x (float v) { return em_scalef (v, x_scale); }
|
||||
hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); }
|
||||
float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
|
||||
float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
|
||||
hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
|
||||
{ return em_scale (v, dir_scale (direction)); }
|
||||
{ return em_mult (v, dir_mult (direction)); }
|
||||
|
||||
/* Convert from parent-font user-space to our user-space */
|
||||
hb_position_t parent_scale_x_distance (hb_position_t v)
|
||||
|
@ -304,17 +306,25 @@ struct hb_font_t
|
|||
hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
|
||||
hb_codepoint_t right_glyph)
|
||||
{
|
||||
#ifdef HB_DISABLE_DEPRECATED
|
||||
return 0;
|
||||
#else
|
||||
return klass->get.f.glyph_h_kerning (this, user_data,
|
||||
left_glyph, right_glyph,
|
||||
klass->user_data.glyph_h_kerning);
|
||||
#endif
|
||||
}
|
||||
|
||||
hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
|
||||
hb_codepoint_t bottom_glyph)
|
||||
{
|
||||
#ifdef HB_DISABLE_DEPRECATED
|
||||
return 0;
|
||||
#else
|
||||
return klass->get.f.glyph_v_kerning (this, user_data,
|
||||
top_glyph, bottom_glyph,
|
||||
klass->user_data.glyph_v_kerning);
|
||||
#endif
|
||||
}
|
||||
|
||||
hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
|
||||
|
@ -599,15 +609,19 @@ struct hb_font_t
|
|||
return false;
|
||||
}
|
||||
|
||||
hb_position_t em_scale (int16_t v, int scale)
|
||||
void mults_changed ()
|
||||
{
|
||||
int upem = face->get_upem ();
|
||||
int64_t scaled = v * (int64_t) scale;
|
||||
scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
|
||||
return (hb_position_t) (scaled / upem);
|
||||
signed upem = face->get_upem ();
|
||||
x_mult = ((int64_t) x_scale << 16) / upem;
|
||||
y_mult = ((int64_t) y_scale << 16) / upem;
|
||||
}
|
||||
|
||||
hb_position_t em_mult (int16_t v, int64_t mult)
|
||||
{
|
||||
return (hb_position_t) ((v * mult) >> 16);
|
||||
}
|
||||
hb_position_t em_scalef (float v, int scale)
|
||||
{ return (hb_position_t) round (v * scale / face->get_upem ()); }
|
||||
{ return (hb_position_t) roundf (v * scale / face->get_upem ()); }
|
||||
float em_fscale (int16_t v, int scale)
|
||||
{ return (float) v * scale / face->get_upem (); }
|
||||
};
|
||||
|
|
46
src/hb-ft.cc
46
src/hb-ft.cc
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
|
||||
#include "hb-ft.h"
|
||||
|
||||
#include "hb-font.hh"
|
||||
|
@ -96,7 +98,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
|
|||
|
||||
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
|
||||
|
||||
ft_font->cached_x_scale.set (0);
|
||||
ft_font->cached_x_scale.set_relaxed (0);
|
||||
ft_font->advance_cache.init ();
|
||||
|
||||
return ft_font;
|
||||
|
@ -228,8 +230,8 @@ hb_ft_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
|
|||
done < count && (*first_glyph = FT_Get_Char_Index (ft_font->ft_face, *first_unicode));
|
||||
done++)
|
||||
{
|
||||
first_unicode = &StructAtOffset<hb_codepoint_t> (first_unicode, unicode_stride);
|
||||
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
}
|
||||
/* We don't need to do ft_font->symbol dance here, since HB calls the singular
|
||||
* nominal_glyph() for what we don't handle here. */
|
||||
|
@ -292,8 +294,8 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
|||
}
|
||||
|
||||
*first_advance = (v * mult + (1<<9)) >> 10;
|
||||
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,6 +348,25 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE_FALLBACK
|
||||
static hb_position_t
|
||||
hb_ft_get_glyph_h_kerning (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t left_glyph,
|
||||
hb_codepoint_t right_glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
FT_Vector kerningv;
|
||||
|
||||
FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
|
||||
if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv))
|
||||
return 0;
|
||||
|
||||
return kerningv.x;
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_bool_t
|
||||
hb_ft_get_glyph_extents (hb_font_t *font,
|
||||
void *font_data,
|
||||
|
@ -439,7 +460,7 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED,
|
|||
else {
|
||||
/* Make a nul-terminated version. */
|
||||
char buf[128];
|
||||
len = MIN (len, (int) sizeof (buf) - 1);
|
||||
len = hb_min (len, (int) sizeof (buf) - 1);
|
||||
strncpy (buf, name, len);
|
||||
buf[len] = '\0';
|
||||
*glyph = FT_Get_Name_Index (ft_face, buf);
|
||||
|
@ -497,6 +518,10 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
|
|||
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);
|
||||
#ifndef HB_NO_OT_SHAPE_FALLBACK
|
||||
hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
|
||||
#endif
|
||||
//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);
|
||||
|
@ -539,7 +564,7 @@ _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
|
|||
|
||||
|
||||
static hb_blob_t *
|
||||
reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
_hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
{
|
||||
FT_Face ft_face = (FT_Face) user_data;
|
||||
FT_Byte *buffer;
|
||||
|
@ -594,7 +619,7 @@ hb_ft_face_create (FT_Face ft_face,
|
|||
face = hb_face_create (blob, ft_face->face_index);
|
||||
hb_blob_destroy (blob);
|
||||
} else {
|
||||
face = hb_face_create_for_tables (reference_table, ft_face, destroy);
|
||||
face = hb_face_create_for_tables (_hb_ft_reference_table, ft_face, destroy);
|
||||
}
|
||||
|
||||
hb_face_set_index (face, ft_face->face_index);
|
||||
|
@ -748,7 +773,7 @@ hb_ft_font_create_referenced (FT_Face ft_face)
|
|||
static void free_static_ft_library ();
|
||||
#endif
|
||||
|
||||
static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (FT_Library),
|
||||
static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<FT_Library>,
|
||||
hb_ft_library_lazy_loader_t>
|
||||
{
|
||||
static FT_Library create ()
|
||||
|
@ -854,3 +879,6 @@ hb_ft_font_set_funcs (hb_font_t *font)
|
|||
_hb_ft_font_set_funcs (font, ft_face, true);
|
||||
hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
73
src/hb-gdi.cc
Normal file
73
src/hb-gdi.cc
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright © 2019 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.
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifdef HAVE_GDI
|
||||
|
||||
#include "hb-gdi.h"
|
||||
|
||||
static hb_blob_t *
|
||||
_hb_gdi_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
{
|
||||
char *buffer = nullptr;
|
||||
DWORD length = 0;
|
||||
|
||||
HDC hdc = GetDC (nullptr);
|
||||
if (unlikely (!SelectObject (hdc, (HFONT) user_data))) goto fail;
|
||||
|
||||
length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
|
||||
if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc;
|
||||
|
||||
buffer = (char *) malloc (length);
|
||||
if (unlikely (!buffer)) goto fail_with_releasedc;
|
||||
length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
|
||||
if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc_and_free;
|
||||
ReleaseDC (nullptr, hdc);
|
||||
|
||||
return hb_blob_create ((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, buffer, free);
|
||||
|
||||
fail_with_releasedc_and_free:
|
||||
free (buffer);
|
||||
fail_with_releasedc:
|
||||
ReleaseDC (nullptr, hdc);
|
||||
fail:
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_gdi_face_create:
|
||||
* @hdc: a HFONT object.
|
||||
*
|
||||
* Return value: #hb_face_t object corresponding to the given input
|
||||
*
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
hb_face_t *
|
||||
hb_gdi_face_create (HFONT hfont)
|
||||
{
|
||||
return hb_face_create_for_tables (_hb_gdi_reference_table, (void *) hfont, nullptr);
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue