Compare commits

..

1 Commits

Author SHA1 Message Date
Behdad Esfahbod 8eb8494e8d WIP 2021-02-12 14:13:11 -07:00
3744 changed files with 80857 additions and 122236 deletions

View File

@ -1,21 +1,8 @@
#!/bin/bash
set -e
meson --cross-file=.ci/win32-cross-file.txt \
--wrap-mode=default \
-Dtests=disabled \
-Dcairo=enabled \
-Dcairo:fontconfig=disabled \
-Dcairo:freetype=disabled \
-Dcairo:dwrite=disabled \
-Dcairo:tests=disabled \
-Dglib=enabled \
-Dfreetype=disabled \
-Dgdi=enabled \
-Ddirectwrite=enabled \
win32build \
$@
meson --cross-file=.ci/win32-cross-file.txt win32build --wrap-mode=forcefallback -Dtests=disabled \
-Dglib=enabled -Dfreetype=enabled -Dgdi=enabled -Dcairo=enabled --buildtype=release $@
ninja -Cwin32build -j3 # building with all the cores won't work fine with CricleCI for some reason
rm -rf win32build/harfbuzz-win32

View File

@ -1,28 +0,0 @@
#!/bin/bash
set -e
meson --cross-file=.ci/win64-cross-file.txt \
--wrap-mode=default \
-Dtests=disabled \
-Dcairo=enabled \
-Dcairo:fontconfig=disabled \
-Dcairo:freetype=disabled \
-Dcairo:dwrite=disabled \
-Dcairo:tests=disabled \
-Dglib=enabled \
-Dfreetype=disabled \
-Dgdi=enabled \
-Ddirectwrite=enabled \
win64build \
$@
ninja -Cwin64build -j3 # building with all the cores won't work fine with CricleCI for some reason
rm -rf win64build/harfbuzz-win64
mkdir win64build/harfbuzz-win64
cp win64build/util/hb-*.exe win64build/harfbuzz-win64
find win64build -name '*.dll' -exec cp {} win64build/harfbuzz-win64 \;
x86_64-w64-mingw32-strip win64build/harfbuzz-win64/*.{dll,exe}
rm -f harfbuzz-win64.zip
(cd win64build && zip -r ../harfbuzz-win64.zip harfbuzz-win64)
echo "harfbuzz-win64.zip is ready."

View File

@ -3,6 +3,8 @@
set -x
set -o errexit -o nounset
TAG="$(git describe --exact-match --match "[0-9]*" HEAD 2>/dev/null || true)"
DOCSDIR=build-docs
REVISION=$(git rev-parse --short HEAD)
@ -14,20 +16,19 @@ cp ../build/docs/html/* .
#cp ../build/docs/CNAME .
git init
git branch -m main
git config user.name "CI"
git config user.email "harfbuzz-admin@googlegroups.com"
git config user.name "Travis CI"
git config user.email "travis@harfbuzz.org"
set +x
echo "git remote add upstream \"https://\$GH_TOKEN@github.com/harfbuzz/harfbuzz.github.io.git\""
git remote add upstream "https://$GH_TOKEN@github.com/harfbuzz/harfbuzz.github.io.git"
set -x
git fetch upstream
git reset upstream/main
git reset upstream/master
touch .
git add -A .
if [[ $(git status -s) ]]; then
git commit -m "Rebuild docs for https://github.com/harfbuzz/harfbuzz/commit/$REVISION"
git push -q upstream HEAD:main
git push -q upstream HEAD:master
fi

View File

@ -1,5 +1,4 @@
#!/usr/bin/env bash
set -e
set -o pipefail
@ -8,13 +7,11 @@ if [[ -z $GITHUB_TOKEN ]]; then
exit
fi
if ! hash ghr 2> /dev/null; then
_GHR_VER=v0.14.0
_GHR=ghr_${_GHR_VER}_linux_amd64
mkdir -p $HOME/.local/bin
curl -sfL https://github.com/tcnksm/ghr/releases/download/$_GHR_VER/$_GHR.tar.gz |
tar xz -C $HOME/.local/bin --strip-components=1 $_GHR/ghr
fi
mkdir -p $HOME/.local/bin
export _GHR_VER=v0.13.0
export _GHR=ghr_${_GHR_VER}_linux_amd64
curl -sfL https://github.com/tcnksm/ghr/releases/download/$_GHR_VER/$_GHR.tar.gz |
tar xz -C $HOME/.local/bin --strip-components=1 $_GHR/ghr
ghr -replace \
-u $CIRCLE_PROJECT_USERNAME \

View File

@ -4,23 +4,46 @@ executors:
win32-executor:
docker:
- image: cimg/base:edge-20.04
win64-executor:
docker:
- image: cimg/base:edge-20.04
autotools-executor:
docker:
- image: cimg/base:edge-20.04
jobs:
macos-aat-fonts:
macos-10_13_6-aat-fonts:
macos:
xcode: "12.5.1"
xcode: "10.1.0"
steps:
- checkout
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config ragel freetype glib cairo python3 icu4c graphite2 gobject-introspection ninja
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config ragel freetype glib cairo python3 ninja
- run: pip3 install meson --upgrade
- run: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson setup build -Dcoretext=enabled -Dgraphite=enabled -Dauto_features=enabled -Dchafa=disabled -Ddocs=disabled
- run: meson build
- run: meson compile -Cbuild
- run: meson test -Cbuild --print-errorlogs
- store_artifacts:
path: build/meson-logs/
macos-10_14_4-aat-fonts:
macos:
xcode: "11.1.0"
steps:
- checkout
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config ragel freetype glib cairo python3 icu4c graphite2 ninja
- run: pip3 install meson --upgrade
- run: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson build -Dcoretext=enabled
- run: meson compile -Cbuild
- run: meson test -Cbuild --print-errorlogs
- store_artifacts:
path: build/meson-logs/
macos-10_15_3-aat-fonts:
macos:
xcode: "11.4.0"
steps:
- checkout
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config ragel freetype glib cairo python3 icu4c graphite2 gobject-introspection gtk-doc ninja
- run: pip3 install meson --upgrade
- run: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson build -Dcoretext=enabled -Dgraphite=enabled -Dauto_features=enabled
- run: meson compile -Cbuild
- run: meson test -Cbuild --print-errorlogs
- store_artifacts:
@ -31,12 +54,14 @@ jobs:
executor: autotools-executor
steps:
- checkout
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y git ninja-build binutils libtool autoconf automake make gcc g++ pkg-config ragel gtk-doc-tools gobject-introspection libfreetype6-dev libglib2.0-dev libgirepository1.0-dev libcairo2-dev libicu-dev libgraphite2-dev python3 python3-pip
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y git ninja-build binutils libtool autoconf automake make gcc g++ pkg-config ragel gtk-doc-tools gobject-introspection libfontconfig1-dev libfreetype6-dev libglib2.0-dev libgirepository1.0-dev libcairo2-dev libicu-dev libgraphite2-dev python3 python3-pip cmake
- run: pip3 install fonttools meson --upgrade
- run: ./autogen.sh
- run: make -j2 distcheck
- run: make -j32
- run: make distcheck
- run: rm harfbuzz-* && make distdir
- run: cd harfbuzz-* && meson build && ninja -j2 -Cbuild test
- run: cd harfbuzz-* && meson build && ninja -Cbuild test
- run: cd harfbuzz-* && cmake -Bcmakebuild -H. && cmake --build cmakebuild
- run: make dist
- persist_to_workspace:
root: .
@ -53,14 +78,14 @@ jobs:
fedora-valgrind:
docker:
- image: fedora:36
- image: fedora
steps:
- checkout
- run: dnf install -y pkg-config ragel valgrind gcc gcc-c++ meson git glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python python-pip || true
- run: meson setup build --buildtype=debugoptimized
- run: meson compile -Cbuild -j9
- run: meson build --buildtype=debugoptimized
- run: ninja -Cbuild -j9
# TOOD: increase timeouts and remove --no-suite=slow
- run: RUN_VALGRIND=1 meson test -Cbuild --no-suite=slow --wrap='valgrind --leak-check=full --error-exitcode=1' --print-errorlogs --num-processes=$(($(nproc)/2 + 1))
- run: RUN_VALGRIND=1 meson test -Cbuild --no-suite=slow --wrap='valgrind --leak-check=full --error-exitcode=1' --print-errorlogs
alpine:
docker:
@ -68,63 +93,56 @@ jobs:
steps:
- checkout
- run: apk update && apk add ragel gcc g++ glib-dev freetype-dev cairo-dev git py3-pip ninja
- run: pip3 install meson==0.56.0
- run: meson setup build --buildtype=minsize
- run: meson compile -Cbuild -j9
- run: pip3 install meson==0.47.0
- run: meson build --buildtype=minsize
- run: ninja -Cbuild -j9
- run: meson test -Cbuild --print-errorlogs
asan-ubsan:
archlinux:
docker:
- image: ubuntu:20.04
- image: archlinux/base
steps:
- checkout
- run: apt update || true
- run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
- run: pip3 install meson==0.56.0
- run: CC=clang CXX=clang++ meson setup build --default-library=static -Db_sanitize=address,undefined --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
- run: pacman --noconfirm -Syu freetype2 meson git clang cairo icu gettext gobject-introspection gcc gcc-libs glib2 graphite pkg-config ragel python python-pip base-devel gtk-doc
- run: pip install flake8 fonttools
- run: flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
- run: meson build -Dgraphite=enabled -Dauto_features=enabled -Dexperimental_api=true
- run: meson compile -Cbuild -j9
- run: meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
- run: meson test -Cbuild --print-errorlogs
- run: meson dist -Cbuild
- run: clang -c src/harfbuzz.cc -DHB_NO_MT
- run: clang -c src/hb-*.cc -DHB_NO_MT -DHB_TINY -DHB_NO_OT_FONT
tsan:
sanitizers:
docker:
- image: ubuntu:20.04
steps:
- checkout
- run: apt update || true
- run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
- run: pip3 install meson==0.56.0
- run: CC=clang CXX=clang++ meson setup build --default-library=static -Db_sanitize=thread --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
- run: meson compile -Cbuild -j9
- run: meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
msan:
docker:
- image: ubuntu:20.04
steps:
- checkout
- run: apt update || true
- run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
- run: pip3 install meson==0.56.0
- run: apt update || true; DEBIAN_FRONTEND=noninteractive apt install -y wget gnupg
#- run: wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
#- run: echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal main" > /etc/apt/sources.list.d/llvmdev.list
#- run: echo "deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal main" > /etc/apt/sources.list.d/llvmdevsrc.list
#- run: apt update || true
- run: DEBIAN_FRONTEND=noninteractive apt install -y clang lld git binutils meson pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
# asan+ubsan
- run: rm -rf build && meson build --default-library=static -Db_sanitize=address,undefined --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
- run: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
# tsan
- run: rm -rf build && meson build --default-library=static -Db_sanitize=thread --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
- run: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
# msan, needs --force-fallback-for=glib,freetype2 also which doesn't work yet but runs fuzzer cases at least
- run: CC=clang CXX=clang++ meson setup build --default-library=static -Db_sanitize=memory --buildtype=debugoptimized --wrap-mode=nodownload -Dauto_features=disabled -Dtests=enabled -Dexperimental_api=true
- run: meson compile -Cbuild -j9
- run: meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
clang-cxx2a:
docker:
- image: ubuntu:20.04
steps:
- checkout
- run: apt update || true
- run: DEBIAN_FRONTEND=noninteractive apt install -y clang lld git binutils
- run: clang -c src/harfbuzz-subset.cc -DHB_NO_MT -Werror -std=c++2a
- run: rm -rf build && meson build --default-library=static -Db_sanitize=memory --buildtype=debugoptimized --wrap-mode=nodownload -Dauto_features=disabled -Dtests=enabled -Dexperimental_api=true
- run: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
# test -std=c++2a and -Weverything of nightly clang builds
- run: clang -c src/harfbuzz.cc src/hb-subset*.cc -DHB_NO_MT -Werror -std=c++2a
- run: clang -c src/hb-*.cc -DHB_NO_MT -Werror -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 -DHB_WITH_WIN1256
crossbuild-win32:
executor: win32-executor
steps:
- checkout
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build python3 python3-pip git g++-mingw-w64-i686 zip
- run: pip3 install meson==0.60.0
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build binutils gcc g++ pkg-config ragel gtk-doc-tools libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python3 python3-pip git g++-mingw-w64-i686 zip
- run: pip3 install meson==0.56.0 --upgrade
- run: .ci/build-win32.sh
- store_artifacts:
path: harfbuzz-win32.zip
@ -142,40 +160,18 @@ jobs:
mv harfbuzz-win32{,-$CIRCLE_TAG}.zip
.ci/publish_release_artifact.sh harfbuzz-win32-$CIRCLE_TAG.zip
crossbuild-win64:
executor: win64-executor
steps:
- checkout
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build python3 python3-pip git g++-mingw-w64-x86-64 zip
- run: pip3 install meson==0.60.0
- run: bash .ci/build-win64.sh
- store_artifacts:
path: harfbuzz-win64.zip
- persist_to_workspace:
root: .
paths: harfbuzz-win64.zip
publish-win64:
executor: win64-executor
steps:
- checkout
- attach_workspace:
at: .
- run: |
mv harfbuzz-win64{,-$CIRCLE_TAG}.zip
.ci/publish_release_artifact.sh harfbuzz-win64-$CIRCLE_TAG.zip
workflows:
version: 2
build:
jobs:
- macos-aat-fonts
- distcheck:
filters: # must have filter or won't work as a dependency
- macos-10_13_6-aat-fonts
- macos-10_14_4-aat-fonts
- macos-10_15_3-aat-fonts
- distcheck: # will be dropped with autotools removal
filters:
tags:
only: /.*/
only: /^\d+.\d+.\d+$/
- publish-dist:
requires:
- distcheck
@ -186,18 +182,12 @@ workflows:
ignore: /.*/
- fedora-valgrind
- alpine
- asan-ubsan
- tsan
- msan
- clang-cxx2a
#- archlinux
- sanitizers
- crossbuild-win32:
filters: # must have filter or won't work as a dependency
filters:
tags:
only: /.*/
- crossbuild-win64:
filters: # must have filter or won't work as a dependency
tags:
only: /.*/
only: /^\d+.\d+.\d+$/
- publish-win32:
requires:
- crossbuild-win32
@ -206,11 +196,3 @@ workflows:
only: /^\d+\.\d+\.\d+$/
branches:
ignore: /.*/
- publish-win64:
requires:
- crossbuild-win64
filters:
tags:
only: /^\d+\.\d+\.\d+$/
branches:
ignore: /.*/

View File

@ -1,10 +1,7 @@
comment: false
comment: off
coverage:
status:
project:
default:
informational: true
patch:
default:
informational: true
threshold: 1%

View File

@ -1,6 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@ -1,25 +0,0 @@
name: arm
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
arm-none-eabi:
runs-on: ubuntu-22.04
container:
image: devkitpro/devkitarm:latest
steps:
- uses: actions/checkout@v3
- name: Configure CMake
run: |
cmake -S . -B build \
-DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO}/cmake/3DS.cmake
- name: Build
run: make CXX_FLAGS="-w -DHB_NO_MT"
working-directory: build

View File

@ -1,28 +0,0 @@
name: CIFuzz
on: [pull_request]
permissions:
contents: read
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'harfbuzz'
dry-run: false
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'harfbuzz'
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v3
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts

View File

@ -1,27 +0,0 @@
name: configs-ci
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: install dependencies
run: sudo apt-get install gcc
- name: HB_DISABLE_DEPRECATED
run: g++ -std=c++11 -c src/harfbuzz.cc -DHB_DISABLE_DEPRECATED
- name: HB_MINI
run: g++ -std=c++11 -c src/harfbuzz.cc -DHB_MINI
- name: HB_LEAN
run: g++ -std=c++11 -c src/harfbuzz.cc -DHB_LEAN
- name: HB_TINY
run: g++ -std=c++11 -c src/harfbuzz.cc -DHB_TINY

View File

@ -4,39 +4,36 @@ on:
schedule:
- cron: '0 10 * * *' # Daily at 10:00 UTC
permissions:
contents: read
jobs:
latest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- run: sudo apt-get install gcc clang wget git curl pkg-config libfreetype6-dev libglib2.0-dev libicu-dev libgraphite2-dev
- name: Download Coverity
run: |
wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=HarfBuzz" -O cov-analysis-linux64.tar.gz
wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=behdad/harfbuzz" -O cov-analysis-linux64.tar.gz
mkdir cov-analysis-linux64
tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
# ideally we should've used meson and ninja here but it complains about coverage or something
- run: cov-analysis-linux64/bin/cov-build --dir cov-int clang src/hb-*.cc -DHAVE_FREETYPE -DHAVE_GRAPHITE2 -DHAVE_GLIB -DHAVE_ICU `pkg-config --cflags freetype2 graphite2 glib-2.0 icu-uc` -DHAVE_ROUNDF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H -DHAVE_GETPAGESIZE -DHB_EXPERIMENTAL_API -c
- run: cov-analysis-linux64/bin/cov-build --dir cov-int clang src/hb-*.cc -DHAVE_FREETYPE -DHAVE_GRAPHITE2 -DHAVE_GLIB -DHAVE_ICU `pkg-config --cflags freetype2 graphite2 glib-2.0 icu-uc` -DHAVE_INTEL_ATOMIC_PRIMITIVES -DHAVE_ROUNDF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H -DHAVE_GETPAGESIZE -DHB_EXPERIMENTAL_API -c
- run: tar czvf harfbuzz.tgz cov-int
- name: submit to coverity
run: |
curl \
--form project=HarfBuzz \
--form project=behdad/harfbuzz \
--form token=$TOKEN \
--form email=harfbuzz-bots-chatter@googlegroups.com \
--form file=@harfbuzz.tgz \
--form version=trunk \
--form description="`git rev-parse --short HEAD`" \
https://scan.coverity.com/builds?project=HarfBuzz
https://scan.coverity.com/builds?project=behdad-harfbuzz
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}

View File

@ -2,70 +2,53 @@ name: linux-ci
on:
push:
branches: [ main ]
tags: ["*.*.*"]
branches: [ master ]
pull_request:
branches: [ main ]
permissions:
contents: read
branches: [ master ]
jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ github.job }}-${{ runner.os }}-${{ runner.arch }}
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install \
gcc \
gobject-introspection \
gtk-doc-tools \
libcairo2-dev \
libfreetype6-dev \
libgirepository1.0-dev \
libglib2.0-dev \
libgraphite2-dev \
libicu-dev \
ninja-build \
pkg-config \
python3 \
python3-setuptools
- name: Install Python Dependencies
run: sudo pip3 install fonttools meson==0.56.0 gcovr==5.0
- name: Setup Meson
run: |
ccache --version
meson setup build \
-Dauto_features=enabled \
-Dchafa=disabled \
-Dgraphite=enabled \
-Doptimization=2 \
-Db_coverage=true \
-Ddoc_tests=true \
-Dragel_subproject=true
- name: Build
run: meson compile -Cbuild
- name: Test
- uses: actions/checkout@v2
- name: install dependencies
run: sudo apt-get install pkg-config gcc ragel gcovr gtk-doc-tools libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python3 python3-setuptools ninja-build gobject-introspection libgirepository1.0-dev
- run: sudo pip3 install fonttools
- run: sudo pip3 install git+https://github.com/mesonbuild/meson
- name: run
run: meson build -Db_coverage=true --auto-features=enabled -Dgraphite=enabled -Doptimization=2
- name: ci
run: meson test --print-errorlogs -Cbuild
- name: Generate Documentations
- name: generate documentations
run: ninja -Cbuild harfbuzz-doc
- name: Deploy Documentations
if: github.ref_type == 'tag'
- name: deploy documentations
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
run: .ci/deploy-docs.sh
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
REVISION: ${{ github.sha }}
- name: Generate Coverage
run: ninja -Cbuild coverage-xml
- name: Upload Coverage
uses: codecov/codecov-action@v3
# waiting for https://github.com/rhysd/github-action-benchmark/issues/36 to happen
# - name: benchmark
# run: build/perf/perf --benchmark_format=json > perf/result.json
# - name: store benchmark result
# uses: rhysd/github-action-benchmark@b2ee598
# if: github.event_name != 'pull_request'
# with:
# name: C++ Benchmark
# tool: 'googlecpp'
# output-file-path: perf/result.json
# gh-pages-branch: gh-pages
# github-token: ${{ secrets.PERSONAL_GITHUB_TOKEN }}
# auto-push: true
# alert-threshold: '150%'
# comment-on-alert: true
# fail-on-alert: true
- name: cov
run: ninja -Cbuild coverage
- uses: codecov/codecov-action@v1
with:
file: build/meson-logs/coverage.xml

View File

@ -1,60 +0,0 @@
name: macos-ci
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
build:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ github.job }}-${{ runner.os }}-${{ runner.arch }}
- name: Install Dependencies
run: |
export HOMEBREW_NO_AUTO_UPDATE=1
export HOMEBREW_NO_INSTALL_CLEANUP=1
brew install \
cairo \
freetype \
glib \
gobject-introspection \
graphite2 \
icu4c \
meson \
ninja \
pkg-config
- name: Install Python Dependencies
run: pip3 install fonttools gcovr==5.0
- name: Setup Meson
run: |
export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig"
ccache --version
meson setup build \
-Dauto_features=enabled \
-Ddocs=disabled \
-Dchafa=disabled \
-Dcoretext=enabled \
-Dgraphite=enabled \
-Doptimization=2 \
-Db_coverage=true \
- name: Build
run: meson compile -Cbuild
- name: Test
run: meson test --print-errorlogs -Cbuild
- name: Generate Coverage
run: ninja -Cbuild coverage-xml
- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
file: build/meson-logs/coverage.xml

View File

@ -2,24 +2,18 @@ name: msvc
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
msvc:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-2019, windows-latest]
os: [windows-2016, windows-latest]
include:
- name: msvc-2019-x86
os: windows-2019
- name: msvc-2017-x86
os: windows-2016
ARCH: x86
- name: msvc-2019-amd64
os: windows-latest
@ -27,35 +21,30 @@ jobs:
name: ${{ matrix.name }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
variant: sccache
key: ${{ github.job }}-${{ matrix.os }}-${{ matrix.ARCH }}
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
with:
arch : ${{ matrix.ARCH }}
- name: Install Python Dependencies
run: |
pip install --upgrade meson ninja fonttools
- name: Setup Meson
run: |
sccache --version
meson setup build `
--wrap-mode=forcefallback `
--buildtype=release `
-Dglib=enabled `
-Dfreetype=enabled `
-Dgdi=enabled `
-Ddirectwrite=enabled
- name: Build
run: meson compile -Cbuild
- name: Test
run: meson test --print-errorlogs --suite=harfbuzz -Cbuild
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- uses: ilammy/msvc-dev-cmd@v1
with:
arch : ${{ matrix.ARCH }}
- name: Install Dependencies
run: |
pip install --upgrade meson ninja fonttools
- name: Build
run: |
# This dir contains a pkg-config which meson will happily use and later fail, so remove it
$env:path = ($env:path.Split(';') | Where-Object { $_ -ne 'C:\Strawberry\perl\bin' }) -join ';'
meson setup build `
--wrap-mode=default `
--buildtype=release `
-Dglib=enabled `
-Dfreetype=enabled `
-Dgdi=enabled `
-Ddirectwrite=enabled
meson compile -C build
- name: Test
run: |
meson test --print-errorlogs --suite=harfbuzz -C build

View File

@ -2,19 +2,13 @@ name: msys2
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
msys2:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- MSYSTEM: MINGW32
@ -23,51 +17,46 @@ jobs:
MSYS2_ARCH: x86_64
name: ${{ matrix.MSYSTEM }}
env:
# XXX: For some reason enabling jit debugging "fixes" random python crashes
# see https://github.com/msys2/MINGW-packages/issues/11864
MSYS: "winjitdebug"
defaults:
run:
shell: msys2 {0}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.MSYSTEM }}
update: true
install: >-
mingw-w64-${{ matrix.MSYS2_ARCH }}-cairo
mingw-w64-${{ matrix.MSYS2_ARCH }}-freetype
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc-libs
mingw-w64-${{ matrix.MSYS2_ARCH }}-gettext
mingw-w64-${{ matrix.MSYS2_ARCH }}-glib2
mingw-w64-${{ matrix.MSYS2_ARCH }}-gobject-introspection
mingw-w64-${{ matrix.MSYS2_ARCH }}-graphite2
mingw-w64-${{ matrix.MSYS2_ARCH }}-icu
mingw-w64-${{ matrix.MSYS2_ARCH }}-meson
mingw-w64-${{ matrix.MSYS2_ARCH }}-ninja
mingw-w64-${{ matrix.MSYS2_ARCH }}-pkg-config
mingw-w64-${{ matrix.MSYS2_ARCH }}-python
mingw-w64-${{ matrix.MSYS2_ARCH }}-python-pip
- name: Install Python Dependencies
run: |
pip install --upgrade fonttools
- name: Setup Meson
run: |
meson setup build \
--wrap-mode=nodownload \
--auto-features=enabled \
-Ddocs=disabled \
-Ddirectwrite=enabled \
-Dgdi=enabled \
-Dgraphite=enabled \
-Dchafa=disabled
- name: Build
run: meson compile -Cbuild
- name: Test
run: meson test --print-errorlogs --suite=harfbuzz -Cbuild
- uses: actions/checkout@v2
- uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.MSYSTEM }}
update: true
install: >-
mingw-w64-${{ matrix.MSYS2_ARCH }}-cairo
mingw-w64-${{ matrix.MSYS2_ARCH }}-freetype
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc-libs
mingw-w64-${{ matrix.MSYS2_ARCH }}-gettext
mingw-w64-${{ matrix.MSYS2_ARCH }}-glib2
mingw-w64-${{ matrix.MSYS2_ARCH }}-gobject-introspection
mingw-w64-${{ matrix.MSYS2_ARCH }}-graphite2
mingw-w64-${{ matrix.MSYS2_ARCH }}-icu
mingw-w64-${{ matrix.MSYS2_ARCH }}-meson
mingw-w64-${{ matrix.MSYS2_ARCH }}-ninja
mingw-w64-${{ matrix.MSYS2_ARCH }}-pkg-config
mingw-w64-${{ matrix.MSYS2_ARCH }}-python
mingw-w64-${{ matrix.MSYS2_ARCH }}-python-pip
mingw-w64-${{ matrix.MSYS2_ARCH }}-ragel
- name: Install Python Dependencies
run: |
pip install --upgrade fonttools
- name: Build
run: |
meson build \
--wrap-mode=nodownload \
--auto-features=enabled \
-Ddirectwrite=enabled \
-Dgdi=enabled \
-Dgraphite=enabled
ninja -C build
- name: Test
run: |
meson test \
--print-errorlogs \
--suite=harfbuzz \
-C build

View File

@ -1,29 +1,27 @@
On Linux, install the development packages for FreeType, Cairo, and GLib. For
example, on Ubuntu / Debian, you would do:
On Linux, install the development packages for FreeType,
Cairo, and GLib. For example, on Ubuntu / Debian, you would do:
$ sudo apt-get install meson pkg-config ragel gtk-doc-tools gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev
sudo apt-get install meson pkg-config ragel gtk-doc-tools gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev
whereas on Fedora, RHEL, CentOS, and other Red Hat based systems you would do:
$ sudo dnf install meson pkgconfig gtk-doc gcc gcc-c++ freetype-devel glib2-devel cairo-devel
sudo dnf install meson pkgconfig gtk-doc gcc gcc-c++ freetype-devel glib2-devel cairo-dev
and on ArchLinux and Manjaro:
$ sudo pacman -Suy meson pkg-config ragel gcc freetype2 glib2 cairo
sudo pacman -Suy meson pkg-config ragel gcc freetype2 glib2 cairo
then use meson to build the project like `meson build && meson test -Cbuild`.
On macOS, `brew install pkg-config ragel gtk-doc freetype glib cairo meson`
then use meson like above.
On macOS, `brew install pkg-config ragel gtk-doc freetype glib cairo meson` then use
meson like above.
On Windows, meson can build the project like above if a working MSVC's cl.exe
(`vcvarsall.bat`) or gcc/clang is already on your path, and if you use
something like `meson build --wrap-mode=default` it fetches and compiles most
of the dependencies also. It is recommended to install CMake either manually
or via the Visual Studio installer when building with MSVC, using meson.
On Windows, meson can build the project like above if a working MSVC's cl.exe (`vcvarsall.bat`)
or gcc/clang is already on your path, and if you use something like `meson build --wrap-mode=default`
it fetches and compiles most of the dependencies also.
Our CI configurations is also a good source of learning how to build HarfBuzz.
There is also amalgam source provided with HarfBuzz which reduces whole process
of building HarfBuzz like `g++ src/harfbuzz.cc -fno-exceptions` but there is
not guarantee provided with buildability and reliability of features you get.
There is also amalgam source provided with HarfBuzz which reduces whole process of building
HarfBuzz like `g++ src/harfbuzz.cc -fno-exceptions` but there is not guarantee provided
with buildability and reliability of features you get.

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.12)
cmake_minimum_required(VERSION 2.8.0)
project(harfbuzz)
message(WARN "HarfBuzz has a Meson port and tries to migrate all the other build systems to it, please consider using it as we might remove our cmake port soon.")
@ -37,10 +37,6 @@ option(HB_HAVE_FREETYPE "Enable freetype interop helpers" OFF)
option(HB_HAVE_GRAPHITE2 "Enable Graphite2 complementary shaper" OFF)
option(HB_HAVE_GLIB "Enable glib unicode functions" OFF)
option(HB_HAVE_ICU "Enable icu unicode functions" OFF)
if (TARGET freetype)
set (HB_HAVE_FREETYPE ON)
add_definitions(-DHAVE_FREETYPE=1)
endif ()
if (APPLE)
option(HB_HAVE_CORETEXT "Enable CoreText shaper backend on macOS" ON)
set (CMAKE_MACOSX_RPATH ON)
@ -80,7 +76,6 @@ include (FindPythonInterp)
## Functions and headers
include (CheckFunctionExists)
include (CheckIncludeFile)
include (CheckIncludeFiles)
macro (check_funcs) # Similar to AC_CHECK_FUNCS of autotools
foreach (func_name ${ARGN})
string(TOUPPER ${func_name} definition_to_add)
@ -107,19 +102,6 @@ if (${HAVE_STDBOOL_H})
add_definitions(-DHAVE_STDBOOL_H)
endif ()
# These will be used while making pkg-config .pc files
set(PC_REQUIRES_PRIV "")
set(PC_LIBS_PRIV "")
if (NOT MSVC)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
if (CMAKE_USE_PTHREADS_INIT)
add_definitions("-DHAVE_PTHREAD")
list(APPEND THIRD_PARTY_LIBS Threads::Threads)
list(APPEND PC_LIBS_PRIV -pthread)
endif ()
endif ()
if (MSVC)
add_definitions(-wd4244 -wd4267 -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
@ -194,7 +176,7 @@ 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 AND NOT TARGET freetype)
if (HB_HAVE_FREETYPE)
include (FindFreetype)
if (NOT FREETYPE_FOUND)
message(FATAL_ERROR "HB_HAVE_FREETYPE was set, but we failed to find it. Maybe add a CMAKE_PREFIX_PATH= to your Freetype2 install prefix")
@ -213,10 +195,6 @@ if (HB_HAVE_FREETYPE AND NOT TARGET freetype)
check_funcs(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var)
endif ()
if (HB_HAVE_FREETYPE)
list(APPEND PC_REQUIRES_PRIV "freetype2 >= 12.0.6")
endif ()
if (HB_HAVE_GRAPHITE2)
add_definitions(-DHAVE_GRAPHITE2)
@ -229,8 +207,6 @@ if (HB_HAVE_GRAPHITE2)
list(APPEND THIRD_PARTY_LIBS ${GRAPHITE2_LIBRARY})
list(APPEND PC_REQUIRES_PRIV "graphite2 >= 1.2.0")
mark_as_advanced(GRAPHITE2_INCLUDE_DIR GRAPHITE2_LIBRARY)
endif ()
@ -251,8 +227,6 @@ if (HB_HAVE_GLIB)
list(APPEND THIRD_PARTY_LIBS ${GLIB_LIBRARIES})
list(APPEND PC_REQUIRES_PRIV "glib-2.0 >= 2.19.1")
mark_as_advanced(GLIB_LIBRARIES GLIBCONFIG_INCLUDE_DIR GLIB_INCLUDE_DIR)
endif ()
@ -285,28 +259,24 @@ if (APPLE AND HB_HAVE_CORETEXT)
find_library(COREFOUNDATION CoreFoundation)
if (COREFOUNDATION)
list(APPEND THIRD_PARTY_LIBS ${COREFOUNDATION})
list(APPEND PC_LIBS_PRIV "-framework CoreFoundation")
endif ()
mark_as_advanced(COREFOUNDATION)
find_library(CORETEXT CoreText)
if (CORETEXT)
list(APPEND THIRD_PARTY_LIBS ${CORETEXT})
list(APPEND PC_LIBS_PRIV "-framework CoreText")
endif ()
mark_as_advanced(CORETEXT)
find_library(COREGRAPHICS CoreGraphics)
if (COREGRAPHICS)
list(APPEND THIRD_PARTY_LIBS ${COREGRAPHICS})
list(APPEND PC_LIBS_PRIV "-framework CoreGraphics")
endif ()
mark_as_advanced(COREGRAPHICS)
else ()
find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices)
if (APPLICATION_SERVICES_FRAMEWORK)
list(APPEND THIRD_PARTY_LIBS ${APPLICATION_SERVICES_FRAMEWORK})
list(APPEND PC_LIBS_PRIV "-framework ApplicationServices")
endif ()
mark_as_advanced(APPLICATION_SERVICES_FRAMEWORK)
@ -317,27 +287,18 @@ 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)
list(APPEND PC_LIBS_PRIV -lgdi32)
endif ()
if (WIN32 AND HB_HAVE_UNISCRIBE)
add_definitions(-DHAVE_UNISCRIBE)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h)
list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4)
list(APPEND PC_LIBS_PRIV -lusp10 -lgdi32 -lrpcrt4)
endif ()
if (WIN32 AND HB_HAVE_DIRECTWRITE)
if (CMAKE_VERSION VERSION_GREATER 3.12)
check_include_files("windows.h;dwrite_1.h" HAVE_DWRITE_1_H LANGUAGE CXX)
else ()
check_include_files("windows.h;dwrite_1.h" HAVE_DWRITE_1_H)
endif ()
if (NOT HAVE_DWRITE_1_H)
message(FATAL_ERROR "DirectWrite was enabled explicitly, but required header is missing")
endif ()
add_definitions(-DHAVE_DIRECTWRITE)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-directwrite.h)
list(APPEND THIRD_PARTY_LIBS dwrite rpcrt4)
endif ()
if (HB_HAVE_GOBJECT)
@ -445,16 +406,41 @@ 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 (); }
int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); }
int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); }
void mutex_unlock (int *m) { __sync_lock_release (m); }
int main () { return 0; }
")
try_compile(HB_HAVE_INTEL_ATOMIC_PRIMITIVES
${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives
${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c)
if (HB_HAVE_INTEL_ATOMIC_PRIMITIVES)
add_definitions(-DHAVE_INTEL_ATOMIC_PRIMITIVES)
endif ()
file(WRITE "${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops.c"
" #include <atomic.h>
/* This requires Solaris Studio 12.2 or newer: */
#include <mbarrier.h>
void memory_barrier (void) { __machine_rw_barrier (); }
int atomic_add (volatile unsigned *i) { return atomic_add_int_nv (i, 1); }
void *atomic_ptr_cmpxchg (volatile void **target, void *cmp, void *newval) { return atomic_cas_ptr (target, cmp, newval); }
int main () { return 0; }
")
try_compile(HB_HAVE_SOLARIS_ATOMIC_OPS
${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops
${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops.c)
if (HB_HAVE_SOLARIS_ATOMIC_OPS)
add_definitions(-DHAVE_SOLARIS_ATOMIC_OPS)
endif ()
## Define harfbuzz library
add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers})
target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
target_include_directories(harfbuzz PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz>")
if (HB_HAVE_FREETYPE AND TARGET freetype)
target_link_libraries(harfbuzz freetype)
endif ()
## Define harfbuzz-icu library
@ -472,7 +458,6 @@ endif ()
## Define harfbuzz-subset library
if (HB_BUILD_SUBSET)
add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-subset.h)
add_dependencies(harfbuzz-subset harfbuzz)
target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
@ -489,9 +474,7 @@ if (UNIX OR MINGW)
link_libraries(-Bsymbolic-functions)
endif ()
# As of CMake 3.0.0, the compiler id for Apple-provided Clang is now "AppleClang";
# thus we use MATCHES instead of STREQUAL to include either regular Clang or AppleClang
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# Make sure we don't link to libstdc++
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "m") # libm
@ -566,7 +549,7 @@ if (HB_HAVE_INTROSPECTION)
# We need to account for the varying output directories
# when we build using Visual Studio projects
if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
else ()
set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
endif ()
@ -720,44 +703,6 @@ if (NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL)
endif ()
endif ()
# get these variables in the required format
list(REMOVE_DUPLICATES PC_REQUIRES_PRIV)
string(REPLACE ";" ", " PC_REQUIRES_PRIV "${PC_REQUIRES_PRIV}")
list(REMOVE_DUPLICATES PC_LIBS_PRIV)
string(REPLACE ";" " " PC_LIBS_PRIV "${PC_LIBS_PRIV}")
# Macro to write pkg-config .pc configuration files
macro ( make_pkgconfig_pc_file name )
file(READ "${PROJECT_SOURCE_DIR}/src/${name}.pc.in" FSTR)
string(REPLACE "%prefix%" "${CMAKE_INSTALL_PREFIX}" FSTR ${FSTR})
string(REPLACE "%exec_prefix%" "\${prefix}" FSTR ${FSTR})
if (IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
string(REPLACE "%includedir%" "${CMAKE_INSTALL_INCLUDEDIR}" FSTR ${FSTR})
else ()
string(REPLACE "%includedir%" "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}" FSTR ${FSTR})
endif ()
if (IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
string(REPLACE "%libdir%" "${CMAKE_INSTALL_LIBDIR}" FSTR ${FSTR})
else ()
string(REPLACE "%libdir%" "\${prefix}/${CMAKE_INSTALL_LIBDIR}" FSTR ${FSTR})
endif ()
string(REPLACE "%VERSION%" "${HB_VERSION}" FSTR ${FSTR})
string(REPLACE "%requires_private%" "${PC_REQUIRES_PRIV}" FSTR ${FSTR})
string(REPLACE "%libs_private%" "${PC_LIBS_PRIV}" FSTR ${FSTR})
file(WRITE "${PROJECT_BINARY_DIR}/${name}.pc" ${FSTR})
install(
FILES "${PROJECT_BINARY_DIR}/${name}.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
COMPONENT pkgconfig
)
endmacro ( make_pkgconfig_pc_file )
if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
install(TARGETS harfbuzz
EXPORT harfbuzzConfig
@ -766,7 +711,6 @@ if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
FRAMEWORK DESTINATION Library/Frameworks
)
make_pkgconfig_pc_file("harfbuzz")
install(EXPORT harfbuzzConfig
NAMESPACE harfbuzz::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/harfbuzz
@ -778,13 +722,6 @@ if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
FRAMEWORK DESTINATION Library/Frameworks
)
make_pkgconfig_pc_file("harfbuzz-icu")
endif ()
if (HB_BUILD_SUBSET)
install(TARGETS harfbuzz-subset
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
make_pkgconfig_pc_file("harfbuzz-subset")
endif ()
if (HB_BUILD_UTILS)
if (WIN32 AND BUILD_SHARED_LIBS)
@ -813,10 +750,9 @@ if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
make_pkgconfig_pc_file("harfbuzz-gobject")
if (HB_HAVE_INTROSPECTION)
if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
else ()
set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
endif ()

View File

@ -100,16 +100,15 @@ 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. This is defined by the `HB_TINY` profile already
(more below).
(unused) "fallback" shaper.
## Thread-safety
By default HarfBuzz builds as a thread-safe library. The exception is that
the `HB_TINY` predefined configuration (more below) disables thread-safety.
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
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`.
@ -136,23 +135,16 @@ The pre-defined configurations are:
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.
However, configuration can still be overridden from a file. To do that, add your
override instructions (mostly `undef` instructions) to a header file and define
the macro `HB_CONFIG_OVERRIDE_H` to the string containing to that header file's
name. HarfBuzz will then include that file at the appropriate place during
configuration.
Up until HarfBuzz 3.1.2 the the configuration override header file's name was
fixed and called `config-override.h`, and was activated by defining the macro
`HAVE_CONFIG_OVERRIDE_H`. That still works.
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.
`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 extents
for CFF fonts, which many clients might not need.
This option disables (among other things) the code to calculate glyph exntents
for CFF fonts.

22
COPYING
View File

@ -2,23 +2,19 @@ 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-2022 Google, Inc.
Copyright © 2015-2020 Ebrahim Byagowi
Copyright © 2019,2020 Facebook, Inc.
Copyright © 2012,2015 Mozilla Foundation
Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 Google, Inc.
Copyright © 2018,2019,2020 Ebrahim Byagowi
Copyright © 2019,2020 Facebook, Inc.
Copyright © 2012 Mozilla Foundation
Copyright © 2011 Codethink Limited
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
Copyright © 2009 Keith Stribley
Copyright © 2011 Martin Hosken and SIL International
Copyright © 2009 Martin Hosken and SIL International
Copyright © 2007 Chris Wilson
Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod
Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc.
Copyright © 1998-2005 David Turner and Werner Lemberg
Copyright © 2016 Igalia S.L.
Copyright © 2022 Matthias Clasen
Copyright © 2018,2021 Khaled Hosny
Copyright © 2018,2019,2020 Adobe, Inc
Copyright © 2013-2015 Alexei Podtelezhnikov
Copyright © 2006 Behdad Esfahbod
Copyright © 2005 David Turner
Copyright © 2004,2007,2008,2009,2010 Red Hat, Inc.
Copyright © 1998-2004 David Turner and Werner Lemberg
For full copyright notices consult the individual files in the package.

View File

@ -4,7 +4,7 @@ NULL =
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src util test perf docs
SUBDIRS = src util test docs
EXTRA_DIST = \
autogen.sh \
@ -19,12 +19,29 @@ EXTRA_DIST = \
replace-enum-strings.cmake \
meson.build \
meson_options.txt \
subprojects/cairo.wrap \
subprojects/expat.wrap \
subprojects/fontconfig.wrap \
subprojects/freetype2.wrap \
subprojects/glib.wrap \
subprojects/libffi.wrap \
subprojects/proxy-libintl.wrap \
subprojects/zlib.wrap \
subprojects/google-benchmark.wrap \
subprojects/ragel.wrap \
subprojects/packagefiles/ragel/meson.build \
perf/meson.build \
perf/perf-draw.hh \
perf/perf-extents.hh \
perf/perf-shaping.hh \
perf/perf.cc \
perf/fonts/Amiri-Regular.ttf \
perf/fonts/NotoNastaliqUrdu-Regular.ttf \
perf/fonts/NotoSansDevanagari-Regular.ttf \
perf/fonts/Roboto-Regular.ttf \
perf/texts/en-thelittleprince.txt \
perf/texts/en-words.txt \
perf/texts/fa-monologue.txt \
perf/texts/fa-thelittleprince.txt \
meson-cc-tests/intel-atomic-primitives-test.c \
meson-cc-tests/solaris-atomic-operations.c \
mingw-configure.sh \
$(NULL)

791
NEWS
View File

@ -1,787 +1,3 @@
Overview of changes leading to 7.1.0
Friday, March 3, 2023
====================================
- New experimental hb_shape_justify() API that uses font variations to expand
or shrink the text to a given advance. (Behdad Esfahbod)
- Various build and bug fixes. (Behdad Esfahbod, Garret Rieger, Qunxin Liu)
- New API:
+hb_font_set_variation()
Overview of changes leading to 7.0.1
Monday, February 20, 2023
====================================
- Various build and bug fixes.
Overview of changes leading to 7.0.0
Saturday, February 11, 2023
====================================
- New hb-paint API that is designed mainly to paint “COLRv1” glyphs, but can be
also used as a unified API to paint any of the glyph representations
supported by HarfBuzz (B/W outlines, color layers, or color bitmaps).
(Behdad Esfahbod, Matthias Clasen)
- New hb-cairo API for integrating with cairo graphics library. This is provided
as a separate harfbuzz-cairo library. (Behdad Esfahbod, Matthias Clasen)
- Support for instancing “CFF2” table. (Behdad Esfahbod)
- Support font emboldening. (Behdad Esfahbod)
- Support feature ranges with AAT shaping. (Behdad Esfahbod)
- Experimental support to cubic curves in “glyf” table, see
https://github.com/harfbuzz/boring-expansion-spec/blob/main/glyf1-cubicOutlines.md
for spec. (Behdad Esfahbod)
- Various subsetter improvements. (Garret Rieger, Qunxin Liu, Behdad Esfahbod)
- Various documentation improvements.
(Behdad Esfahbod, Matthias Clasen, Khaled Hosny)
- Significantly reduced memory use during shaping. (Behdad Esfahbod)
- Greatly reduced memory use during subsetting “CFF” table. (Behdad Esfahbod)
- New command line utility, hb-info, for querying various font information.
(Behdad Esfahbod, Matthias Clasen)
- New hb-shape/hb-view options: --glyphs, --color-palette, --font-bold,
--font-grade, and --named-instance. (Behdad Esfahbod)
- Miscellaneous fixes and improvements.
(Amir Masoud Abdol, Andres Salomon, Behdad Esfahbod, Chun-wei Fan,
Garret Rieger, Jens Kutilek, Khaled Hosny, Konstantin Käfer, Matthias Clasen,
Nirbheek Chauhan, Pedro J. Estébanez, Qunxin Liu, Sergei Trofimovich)
- New API:
+HB_FONT_NO_VAR_NAMED_INSTANCE
+HB_PAINT_IMAGE_FORMAT_BGRA
+HB_PAINT_IMAGE_FORMAT_PNG
+HB_PAINT_IMAGE_FORMAT_SVG
+hb_cairo_font_face_create_for_face
+hb_cairo_font_face_create_for_font
+hb_cairo_font_face_get_face
+hb_cairo_font_face_get_font
+hb_cairo_font_face_get_scale_factor
+hb_cairo_font_face_set_font_init_func
+hb_cairo_font_face_set_scale_factor
+hb_cairo_font_init_func_t
+hb_cairo_glyphs_from_buffer
+hb_cairo_scaled_font_get_font
+hb_color_line_get_color_stops
+hb_color_line_get_color_stops_func_t
+hb_color_line_get_extend
+hb_color_line_get_extend_func_t
+hb_color_line_t
+hb_color_stop_t
+hb_draw_funcs_get_empty
+hb_draw_funcs_get_user_data
+hb_draw_funcs_set_user_data
+hb_face_collect_nominal_glyph_mapping
+hb_font_draw_glyph
+hb_font_draw_glyph_func_t
+hb_font_funcs_set_draw_glyph_func
+hb_font_funcs_set_paint_glyph_func
+hb_font_get_synthetic_bold
+hb_font_get_var_named_instance
+hb_font_paint_glyph
+hb_font_paint_glyph_func_t
+hb_font_set_synthetic_bold
+hb_map_keys
+hb_map_next
+hb_map_update
+hb_map_values
+hb_ot_color_glyph_has_paint
+hb_ot_color_has_paint
+hb_ot_layout_script_select_language2
+hb_ot_name_id_predefined_t
+hb_paint_color
+hb_paint_color_func_t
+hb_paint_composite_mode_t
+hb_paint_custom_palette_color
+hb_paint_custom_palette_color_func_t
+hb_paint_extend_t
+hb_paint_funcs_create
+hb_paint_funcs_destroy
+hb_paint_funcs_get_empty
+hb_paint_funcs_get_user_data
+hb_paint_funcs_is_immutable
+hb_paint_funcs_make_immutable
+hb_paint_funcs_reference
+hb_paint_funcs_set_color_func
+hb_paint_funcs_set_custom_palette_color_func
+hb_paint_funcs_set_image_func
+hb_paint_funcs_set_linear_gradient_func
+hb_paint_funcs_set_pop_clip_func
+hb_paint_funcs_set_pop_group_func
+hb_paint_funcs_set_pop_transform_func
+hb_paint_funcs_set_push_clip_glyph_func
+hb_paint_funcs_set_push_clip_rectangle_func
+hb_paint_funcs_set_push_group_func
+hb_paint_funcs_set_push_transform_func
+hb_paint_funcs_set_radial_gradient_func
+hb_paint_funcs_set_sweep_gradient_func
+hb_paint_funcs_set_user_data
+hb_paint_funcs_t
+hb_paint_image
+hb_paint_image_func_t
+hb_paint_linear_gradient
+hb_paint_linear_gradient_func_t
+hb_paint_pop_clip
+hb_paint_pop_clip_func_t
+hb_paint_pop_group
+hb_paint_pop_group_func_t
+hb_paint_pop_transform
+hb_paint_pop_transform_func_t
+hb_paint_push_clip_glyph
+hb_paint_push_clip_glyph_func_t
+hb_paint_push_clip_rectangle
+hb_paint_push_clip_rectangle_func_t
+hb_paint_push_group
+hb_paint_push_group_func_t
+hb_paint_push_transform
+hb_paint_push_transform_func_t
+hb_paint_radial_gradient
+hb_paint_radial_gradient_func_t
+hb_paint_sweep_gradient
+hb_paint_sweep_gradient_func_t
+hb_set_is_inverted
+hb_subset_input_keep_everything
- Deprecated API:
+hb_font_funcs_set_glyph_shape_func
+hb_font_get_glyph_shape_func_t
+hb_font_get_glyph_shape
Overview of changes leading to 6.0.0
Friday, December 16, 2022
====================================
- A new API have been added to pre-process the face and speed up future
subsetting operations on that face. Provides up to a 95% reduction in
subsetting times when the same face is subset more than once.
For more details and benchmarks, see:
https://github.com/harfbuzz/harfbuzz/blob/main/docs/subset-preprocessing.md
(Garret Rieger, Behdad Esfahbod)
- Shaping have been speedup by skipping entire lookups when the buffer contents
don't intersect with the lookup. Shows up to a 10% speedup in shaping some
fonts. (Behdad Esfahbod)
- A new experimental feature, “Variable Composites” (enabled by passing
-Dexperimental_api=true to meson), is also featured in this release.
This technology enables drastic compression of fonts in the Chinese,
Japanese, Korean, and other writing systems, by reusing the OpenType Font
Variations technology for encoding “smart components” into the font.
The specification for these extensions to the font format can be found in:
https://github.com/harfbuzz/boring-expansion-spec/blob/glyf1/glyf1.md
A test variable-font with ~7160 Hangul syllables derived from the
NotoSerifKR-VF font has been built, with existing OpenType technology, as
well as with the new Variable Composites (VarComposites) technology. The
VarComposites font is over 90% smaller than the OpenType version of the font!
Both fonts can be obtained from the “smarties” repository:
https://github.com/behdad/smarties/tree/3.0/fonts/hangul/serif
When building HarfBuzz with experimental features enabled, you can test
the “smarties” font with a sample character like this:
$ hb-view butchered-hangul-serif-smarties-variable.ttf -u AE01 --variations=wght=700
(Behdad Esfahbod)
- The HarfBuzz subsetter can now drop axes by pinning them to specific values
(also referred to as instancing). There are a couple of restrictions
currently:
- Only works with TrueType (“glyf”) based fonts. “CFF2” fonts are not yet
supported.
- Only supports the case where all axes in a font are pinned.
(Garret Rieger, Qunxin Liu)
- Miscellaneous fixes and improvements.
(Behdad Esfahbod, Christoph Reiter, David Corbett, Eli Schwartz, Garret
Rieger, Joel Auterson, Jordan Petridis, Khaled Hosny, Lorenz Wildberg,
Marco Rebhan, Martin Storsjö, Matthias Clasen, Qunxin Liu, Satadru Pramanik)
- New API
+hb_subset_input_pin_axis_location()
+hb_subset_input_pin_axis_to_default()
+hb_subset_preprocess()
Overview of changes leading to 5.3.1
Wednesday, October 19, 2022
====================================
- Subsetter repacker fixes. (Garret Rieger)
- Adjust Grapheme clusters for Katakana voiced sound marks. (Behdad Esfahbod)
- New “hb-subset” option “--preprocess-face”. (Garret Rieger)
Overview of changes leading to 5.3.0
Saturday, October 8, 2022
"Women, Life, Freedom" #MahsaAmini
====================================
- Dont add glyphs from dropped MATH or COLR tables to the subset glyphs.
(Khaled Hosny)
- Map “rlig” to appropriate AAT feature selectors. (Jonathan Kew)
- Update USE data files to latest version. (David Corbett)
- Check “CBDT” extents first before outline tables, to help with fonts that
also include an empty “glyf” table. (Khaled Hosny)
- More work towards variable font instancing in the subsetter. (Qunxin Liu)
- Subsetter repacker improvements. (Garret Rieger)
- New API:
+hb_ot_layout_lookup_get_optical_bound()
+hb_face_builder_sort_tables()
Overview of changes leading to 5.2.0
Saturday, September 17, 2022
====================================
- Fix regressions in hb-ft font functions for FT_Faces with transformation
matrix. (Behdad Esfahbod)
- The experimental hb-repacker API now supports splitting several GPOS subtable
types when needed. (Garret Rieger)
- The HarfBuzz extensions to OpenType font format are now opt-in behind
build-time flags. (Behdad Esfahbod)
- The experimental hb-subset variable fonts instantiation API can now
instantiate more font tables and arbitrary axis locations. (Qunxin Liu)
- Unicode 15 support. (David Corbett)
- Various documentation improvements. (Behdad Esfahbod, Matthias Clasen)
- The hb-view command line tool now detects WezTerm inline images support.
(Wez Furlong)
- Fix FreeType and ICU dependency lookup with meson. (Xavier Claessens)
- New API:
+HB_SCRIPT_KAWI
+HB_SCRIPT_NAG_MUNDARI
Overview of changes leading to 5.1.0
Sunday, July 31, 2022
====================================
- More extensive buffer tracing messages. (Behdad Esfahbod)
- Fix hb-ft regression in bitmap fonts rendering. (Behdad Esfahbod)
- Support extension promotion of lookups in hb-subset-repacker. (Garret Rieger)
- A new HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL for scripts that use elongation
(e.g. Arabic) to signify where it is safe to insert tatweel glyph without
interrupting shaping. (Behdad Esfahbod)
- Add “--safe-to-insert-tatweel” to “hb-shape” tool. (Behdad Esfahbod)
- New API
+HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL
+HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL
Overview of changes leading to 5.0.1
Saturday, July 23, 2022
====================================
- Fix version 2 “avar” table with hb-ft. (Behdad Esfahbod)
Overview of changes leading to 5.0.0
Saturday, July 23, 2022
====================================
- Support fonts with more than 65535 glyphs in “GDEF”, “GSUB”, and “GPOS”
tables. This is part of https://github.com/be-fonts/boring-expansion-spec to
extend OpenType in a backward-compatible way.
(Behdad Esfahbod, Garret Rieger)
- Complete support for more than 65535 glyphs in “glyf” table that started in
4.0.0 release. Part of boring-expansion-spec. (Behdad Esfahbod)
- Support version 2 of “avar” table. Part of boring-expansion-spec.
(Behdad Esfahbod)
- Fix mark attachment on multiple substitutions in some cases.
(Behdad Esfahbod)
- Fix application of “calt”, “rclt”, and “ccmp” features to better match
Uniscribe behaviour with some Arabic fonts. (Behdad Esfahbod)
- Improvement to interaction between multiple cursive attachments.
(Behdad Esfahbod)
- Improve multiple mark interactions in Hebrew. (Behdad Esfahbod)
- Implement language-specific forms in AAT shaping. (Behdad Esfahbod)
- Fix variation of “VORG” table. (Behdad Esfahbod)
- Support for specific script tags to be retained in the subsetter, and add
“--layout-scripts” option to “hb-subset” tool. (Garret Rieger)
- Accept space as delimiter for --features/--variations in command line tools.
- Improve subsetting of “COLR” table. (Qunxin Liu)
- Improved fuzzing coverage for ot-math API. (Frédéric Wang)
- Fix “kern” table version 2 (AAT) sanitization on 32-bit systems.
(Behdad Esfahbod)
- Allow negative glyph advances from “graphite2” shaper. (Stephan Bergmann)
- Implement loading (color) bitmap fonts with hb-ft. (Behdad Esfahbod)
- Fix regression in hb-ft when changing font size. (Behdad Esfahbod)
- Fix build on GCC < 7. (Kleis Auke Wolthuizen)
- Dynamically load dwrite.dll on windows if “directwrite” shaper is enabled.
(Luca Bacci)
- Provide a single-file harfbuzz-subset.cc file for easier alternate building
of hb-subset library, similar to harfbuzz.cc. (Khaled Hosny)
- New API
+HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG
+hb_language_matches()
Overview of changes leading to 4.4.1
Wednesday, June 29, 2022
====================================
- Fix test failure with some compilers.
- Fix Telugu and Kannada kerning regression.
Overview of changes leading to 4.4.0
Monday, June 27, 2022
====================================
- Caching of variable fonts shaping, in particular when using HarfBuzzs own
font loading functions (ot). Bringing performance of variable shaping in par
with non-variable fonts shaping. (Behdad Esfahbod)
- Caching of format 2 “Contextual Substitution” and “Chained Contexts
Substitution” lookups. Resulting in up to 20% speedup of lookup-heavy fonts
like Gulzar or Noto Nastaliq Urdu. (Behdad Esfahbod)
- Improved ANSI output from hb-view. (Behdad Esfahbod)
- Support for shaping legacy, pre-OpenType Windows 3.1-era, Arabic fonts that
relied on a fixed PUA encoding. (Khaled Hosny, Behdad Esfahbod)
- Sinhala script is now shaped by the USE shaper instead of “indic” one.
(Behdad Esfahbod, David Corbett)
- Thai shaper improvements. (David Corbett)
- hb-ot-name API supports approximate BCP-47 language matching, for example
asking for “en_US” in a font that has only “en” names will return them.
(Behdad Esfahbod)
- Optimized TrueType glyph shape loading. (Behdad Esfahbod)
- Fix subsetting of HarfBuzz faces created via hb_face_create_for_tables().
(Garret Rieger)
- Add 32 bit var store support to the subsetter. (Garret Rieger)
- New API
+HB_BUFFER_FLAG_DEFINED
+HB_BUFFER_SERIALIZE_FLAG_DEFINED
+hb_font_changed()
+hb_font_get_serial()
+hb_ft_hb_font_changed()
+hb_set_hash()
+hb_map_copy()
+hb_map_hash()
Overview of changes leading to 4.3.0
Friday, May 20, 2022
====================================
- Major speed up in loading and subsetting fonts, especially in
handling CFF table. Subsetting some fonts is now 3 times faster.
(Behdad Esfahbod, Garret Rieger)
- Speed up blending CFF2 table. (Behdad Esfahbod)
- Speed up hb_ot_tags_from_language(). (Behdad Esfahbod, David Corbett)
- Fix USE classification of U+10A38 to fix multiple marks on single Kharoshthi
base. (David Corbett)
- Fix parsing of empty CFF Index. (Behdad Esfahbod)
- Fix subsetting CPAL table with partial palette overlaps. (Garret Rieger)
- New API
+hb_map_is_equal() (Behdad Esfahbod)
Overview of changes leading to 4.2.1
Sunday, April 24, 2022
====================================
- Make sure hb_blob_create_from_file_or_fail() always returns nullptr in case
of failure and not empty blob sometimes. (Khaled Hosny)
- Add --passthrough-tables option to hb-subset. (Cosimo Lupo)
- Reinstate a pause after basic features in Khmer shaper, fixing a regression
introduced in previous release. (Behdad Esfahbod)
- Better handling of Regional_Indicator when shaped with RTL-native scripts,
reverting earlier fix that caused regressions in AAT shaping. (Behdad Esfahbod)
Overview of changes leading to 4.2.0
Wednesday, March 30, 2022
====================================
- Source code reorganization, splitting large hb-ot-layout files into smaller,
per-subtable ones under OT/Layout/*. Code for more tables will follow suit in
later releases. (Garret Rieger, Behdad Esfahbod)
- Revert Indic shaper change in previous release that broke some fonts and
instead make per-syllable restriction of “GSUB” application limited to
script-specific Indic features, while applying them and discretionary
features in one go. (Behdad Esfahbod)
- Fix decoding of private in gvar table. (Behdad Esfahbod)
- Fix handling of contextual lookups that delete too many glyphs. (Behdad Esfahbod)
- Make “morx” deleted glyphs dont block “GPOS” application. (Behdad Esfahbod)
- Various build fixes. (Chun-wei Fan, Khaled Hosny)
- New API
+hb_set_next_many() (Andrew John)
Overview of changes leading to 4.1.0
Wednesday, March 23, 2022
====================================
- Various OSS-Fuzz fixes. (Behdad Esfahbod)
- Make fallback vertical-origin match FreeTypes. (Behdad Esfahbod)
- Treat visible viramas like dependent vowels in USE shaper. (David Corbett)
- Apply presentation forms features and discretionary features in one go in
Indic shaper, which seems to match Uniscribe and CoreText behaviour.
(Behdad Esfahbod, David Corbett)
- Various bug fixes.
- New API
+hb_set_add_sorted_array() (Andrew John)
Overview of changes leading to 4.0.1
Friday, March 11, 2022
====================================
- Update OpenType to AAT mappings for “hist” and “vrtr” features.
(Florian Pircher)
- Update IANA Language Subtag Registry to 2022-03-02. (David Corbett)
- Update USE shaper to allow any non-numeric tail in a symbol cluster, and
remove obsolete data overrides. (David Corbett)
- Fix handling of baseline variations to return correctly scaled values.
(Matthias Clasen)
- A new experimental hb_subset_repack_or_fail() to repack an array of objects,
eliminating offset overflows. The API is not available unless HarfBuzz is
built with experimental APIs enabled. (Qunxin Liu)
- New experimental API
+hb_link_t
+hb_object_t
+hb_subset_repack_or_fail()
Overview of changes leading to 4.0.0
Tuesday, March 1, 2022
====================================
- New public API to create subset plan and gather information on things like
glyph mappings in the final subset. The plan can then be passed on to perform
the subsetting operation. (Garret Rieger)
- Draw API for extracting glyph shapes have been extended and finalized and is
no longer an experimental API. The draw API supports glyf, CFF and CFF2
glyph outlines tables, and applies variation settings set on the font as well
as synthetic slant. The new public API is not backward compatible with the
previous, non-public, experimental API. (Behdad Esfahbod)
- The hb-view tool will use HarfBuzz draw API to render the glyphs instead of
cairo-ft when compiled with Cairo 1.17.5 or newer, setting HB_DRAW
environment variable to 1 or 0 will force using or not use the draw API,
respectively. (Behdad Esfahbod)
- The hb-shape and hb-view tools now default to using HarfBuzzs own font
loading functions (ot) instead of FreeType ones (ft). They also have a new
option, --font-slant, to apply synthetic slant to the font. (Behdad Esfahbod)
- HarfBuzz now supports more than 65535 (the OpenType limit) glyph shapes and
metrics. See https://github.com/be-fonts/boring-expansion-spec/issues/6 and
https://github.com/be-fonts/boring-expansion-spec/issues/7 for details.
(Behdad Esfahbod)
- New API to get the dominant horizontal baseline tag for a given script.
(Behdad Esfahbod)
- New API to get the baseline positions from the font, and synthesize missing
ones. As well as new API to get font metrics and synthesize missing ones.
(Matthias Clasen)
- Improvements to finding dependencies on Windows when building with Visual
Studio. (Chun-wei Fan)
- New buffer flag, HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT, that must be set
during shaping for HB_GLYPH_FLAG_UNSAFE_TO_CONCAT flag to be reliably
produced. This is to limit the performance hit of producing this flag to when
it is actually needed. (Behdad Esfahbod)
- Documentation improvements. (Matthias Clasen)
- New API
- General:
+HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT
+hb_var_num_t
- Draw:
+hb_draw_funcs_t
+hb_draw_funcs_create()
+hb_draw_funcs_reference()
+hb_draw_funcs_destroy()
+hb_draw_funcs_is_immutable()
+hb_draw_funcs_make_immutable()
+hb_draw_move_to_func_t
+hb_draw_funcs_set_move_to_func()
+hb_draw_line_to_func_t
+hb_draw_funcs_set_line_to_func()
+hb_draw_quadratic_to_func_t
+hb_draw_funcs_set_quadratic_to_func()
+hb_draw_cubic_to_func_t
+hb_draw_funcs_set_cubic_to_func()
+hb_draw_close_path_func_t
+hb_draw_funcs_set_close_path_func()
+hb_draw_state_t
+HB_DRAW_STATE_DEFAULT
+hb_draw_move_to()
+hb_draw_line_to()
+hb_draw_quadratic_to()
+hb_draw_cubic_to()
+hb_draw_close_path()
+hb_font_get_glyph_shape_func_t
+hb_font_funcs_set_glyph_shape_func()
+hb_font_get_glyph_shape()
- OpenType layout
+HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL
+HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL
+hb_ot_layout_get_horizontal_baseline_tag_for_script()
+hb_ot_layout_get_baseline_with_fallback()
- Metrics:
+hb_ot_metrics_get_position_with_fallback()
- Subset:
+hb_subset_plan_t
+hb_subset_plan_create_or_fail()
+hb_subset_plan_reference()
+hb_subset_plan_destroy()
+hb_subset_plan_set_user_data()
+hb_subset_plan_get_user_data()
+hb_subset_plan_execute_or_fail()
+hb_subset_plan_unicode_to_old_glyph_mapping()
+hb_subset_plan_new_to_old_glyph_mapping()
+hb_subset_plan_old_to_new_glyph_mapping()
Overview of changes leading to 3.4.0
Sunday, February 13, 2022
====================================
- Perform sanity checks on shaping results is now part of “harfbuzz” library
and can be enabled by setting the buffer flag HB_BUFFER_FLAG_VERIFY.
(Behdad Esfahbod)
- Arabic Mark Transient Reordering Algorithm have been updated to revision 6.
(Khaled Hosny)
- ISO 15924 code for mathematical notation, Zmth, now maps to the OpenType
math tag. (Alexis King)
- It is now possible to get at once all math kerning values for a given glyph
at a given corner. (Alexis King)
- Fix locale_t portability issues on systems the typedefs it to a void
pointer. (Behdad Esfahbod)
- New API:
+HB_BUFFER_FLAG_VERIFY
+HB_OT_TAG_MATH_SCRIPT
+HB_SCRIPT_MATH
+hb_ot_math_kern_entry_t
+hb_ot_math_get_glyph_kernings()
- Deprecated API
+HB_OT_MATH_SCRIPT
Overview of changes leading to 3.3.2
Sunday, February 6, 2022
====================================
- Revert splitting of pair positioning values introduced in 3.3.0 as it proved
problematic. (Behdad Esfahbod)
Overview of changes leading to 3.3.1
Monday, January 31, 2022
====================================
- Fix heap-use-after-free in harfbuzz-subset introduced in previous release.
(Garret Rieger)
Overview of changes leading to 3.3.0
Monday, January 31, 2022
====================================
- Improved documentation. (Matthias Clasen)
- Internal code cleanup, using C++ standard library more. (Behdad Esfahbod)
- The low 16-bits of face index will be used by hb_face_create() to select a
face inside a font collection file format, while the high 16-bits will be
used by hb_font_create() to load the named instance. (Behdad Esfahbod)
- Glyph positions and other font metrics now apply synthetic slant set by
hb_font_set_synthetic_slant(), for improved positioning for synthetically
slanted fonts. (Behdad Esfahbod)
- Fixed unintentional locale dependency in hb_variation_to_string() for decimal
point representation. (Matthias Clasen)
- When applying pair positioning (kerning) the positioning value is split
between the two sides of the pair for improved cursor positioning between
such pairs. (Behdad Esfahbod)
- Introduced new HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, to be used in conjunction
with HB_GLYPH_FLAG_UNSAFE_TO_BREAK for optimizing re-shaping during line
breaking. Check the documentation for further details. (Behdad Esfahbod)
- Improved handling of macrolanguages when mapping BCP 47 codes to OpenType
tags. (David Corbett)
- New API:
+HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
+hb_segment_properties_overlay()
+hb_buffer_create_similar()
+hb_font_set_synthetic_slant()
+hb_font_get_synthetic_slant()
+hb_font_get_var_coords_design()
Overview of changes leading to 3.2.0
Friday, November 26, 2021
====================================
“harfbuzz” library improvements:
- Fixed shaping of Apple Color Emoji flags in right-to-left context. (Behdad Esfahbod)
- Fixed positioning of CFF fonts in HB_TINY profile. (Behdad Esfahbod)
- OpenType 1.9 language tags update. (David Corbett)
- Add HB_NO_VERTICAL config option.
- Add HB_CONFIG_OVERRIDE_H for easier configuration. (Behdad Esfahbod)
“harfbuzz-subset” library improvements:
- Improved packing of cmap, loca, and Ligature tables. (Garret Rieger)
- Significantly improved overflow-resolution strategy in the repacker. (Garret Rieger)
Overview of changes leading to 3.1.2
Friday, November 26, 2021
====================================
- hb-shape / hb-view: revert treating text on the commandline as single
paragraph (was introduced in 3.0.0); add new --single-par to do that.
(Behdad Esfahbod)
- Subsetter bug fixes. (Garret Rieger, Qunxin Liu, Behdad Esfahbod)
Overview of changes leading to 3.1.1
Wednesday, November 8, 2021
====================================
- Work around GCC cast-align error/warning on some platforms. (Behdad Esfahbod)
- Documentation improvements. (Matthias Clasen)
Overview of changes leading to 3.1.0
Wednesday, November 3, 2021
====================================
- Better offset-overflow handling in the subsetter library. (Garret Rieger)
- Improved Unicode 14 properties in the USE shaper, and various other USE
shaper fixes. (David Corbett)
- MATH and COLR v1 tables subsetting support, and various other subsetter fixes.
(Qunxin Liu)
- Support for Pwo Karen / Ason Chin medial la. (Simon Cozens)
- Apply GPOS positioning when substituting with morx table, if kerx is missing.
(Behdad Esfahbod)
- Apply calt and clig features across syllable boundaries in Indic shaper.
(Behdad Esfahbod)
- meson option for enabling Graphite 2 has been renamed to graphite2.
- Build and documentation fixes.
- New API:
+hb_buffer_set_not_found_glyph()
+hb_buffer_get_not_found_glyph()
Overview of changes leading to 3.0.0
Friday, September 17, 2021
====================================
- Unicode 14.0 support (David Corbett).
- The hb-subset API and the harfbuzz-subset library's ABI are now declared
stable. The harfbuzz-subset library would not have been possible without the
work of Garret Rieger and Qunxin Liu from Google Fonts, and the earlier work
of Michiharu Ariza from Adobe.
- The hb-style API is now stable and no longer experimental.
- New API:
+hb_style_tag_t
+hb_style_get_value()
+hb_subset_input_t
+hb_subset_flags_t
+hb_subset_sets_t
+hb_subset_input_create_or_fail()
+hb_subset_input_reference()
+hb_subset_input_destroy()
+hb_subset_input_set_user_data()
+hb_subset_input_get_user_data()
+hb_subset_input_unicode_set()
+hb_subset_input_glyph_set()
+hb_subset_input_set()
+hb_subset_input_get_flags()
+hb_subset_input_set_flags()
+hb_subset_or_fail()
- Removed old unstable harfbuzz-subset API:
-hb_subset_input_nameid_set()
-hb_subset_input_namelangid_set()
-hb_subset_input_layout_features_set()
-hb_subset_input_no_subset_tables_set()
-hb_subset_input_drop_tables_set()
-hb_subset_input_set_drop_hints()
-hb_subset_input_get_drop_hints()
-hb_subset_input_set_desubroutinize()
-hb_subset_input_get_desubroutinize()
-hb_subset_input_set_retain_gids()
-hb_subset_input_get_retain_gids()
-hb_subset_input_set_name_legacy()
-hb_subset_input_get_name_legacy()
-hb_subset_input_set_overlaps_flag()
-hb_subset_input_get_overlaps_flag()
-hb_subset_input_set_notdef_outline()
-hb_subset_input_get_notdef_outline()
-hb_subset_input_set_no_prune_unicode_ranges()
-hb_subset_input_get_no_prune_unicode_ranges()
-hb_subset()
Overview of changes leading to 2.9.1
Tuesday, September 7, 2021
====================================
- Final subset API is in place and if no issues are discovered, it will be the
stable subset API of HarfBuzz 3.0.0. Old API is kept to ease transition, but
will be removed in 3.0.0.
- Various fuzzer-found bug fixes.
- hb_buffer_append() now handles the pre- and post-context which previously
were left unchanged in the destination buffer.
- hb-view / hb-shape now accept following new arguments:
o --unicodes-before/after: takes a list of hex numbers that represent Unicode
codepoints.
- Undeprecated API:
hb_set_invert()
Overview of changes leading to 2.9.0
Wednesday, August 18, 2021
History Repeats Itself (Afghanistan)
====================================
- Subsetter API is being stabilized, with the first stable API to happen in
3.0.0 release (https://github.com/harfbuzz/harfbuzz/issues/3078).
- Support multiple variation axes with same tag, aka HOI.
- The “coretext” testing shaper now passes font variations to CoreText.
- hb-shape/hb-view does not break line at new lines unless text is read from
file.
- hb-view and hb-subset has a --batch now, similar to hb-shape.
- The --batch mode now uses ; as argument separator instead of : used previously.
- The --batch in hb-shape does not expect 0th argument anymore. That is, the
lines read are interpreted as argv[1:], instead of argv[0:].
- The --batch option has been undocumented. We are ready to document it; send
feedback if you find it useful.
- hb-subset got arguments revamps. Added much-requested --gids-file, --glyphs,
--glyphs-file, --unicodes-file, supporting ranges in --unicodes.
- Various bug fixes.
Overview of changes leading to 2.8.2
Tuesday, July 8, 2021
====================================
- Shaping LTR digits for RTL scripts now makes the native direction of the
digits LTR, applying shaping and positioning rules on the same glyph order as
Uniscribe. (Jonathan Kew, Khaled Hosny).
- Subsetting COLR v1 and CPAL tables is now supported. (Garret Rieger, Qunxin Liu)
- Various fixes and improvements to the subsetter. (Garret Rieger, Qunxin Liu, Behdad)
- When applying morx table, mark glyph widths should not be zeroed. (Jonathan Kew)
- GPOS is preferred over kerx, if GSUB was applied. (Behdad)
- Regional_Indicator pairs are grouped together when clustering. (Behdad)
- New API:
+hb_blob_create_or_fail()
+hb_blob_create_from_file_or_fail()
+hb_set_copy()
Overview of changes leading to 2.8.1
Tuesday, May 4, 2021
====================================
- Subsetter now fully supports GSUB/GPOS/GDEF tables (including variations); as
such, layout tables are retained by subsetter by default. (Garret Rieger, Qunxin Liu)
- Build scripts no longer check for FontConfig as HarfBuzz does not use it.
- hb-view supports iTerm2 and kitty inline image protocols (Khaled Hosny),
it can also use Chafa for terminal graphics if available (Hans Petter Jansson).
Overview of changes leading to 2.8.0
Tuesday, March 16, 2021
====================================
- Shape joining scripts other than Arabic/Syriac using the Universal Shaping Engine.
Previously these were shaped using the generalized Arabic shaper. (David Corbett)
- Fix regression in shaping of U+0B55 ORIYA SIGN OVERLINE. (David Corbett)
- Update language tags. (David Corbett)
- Variations: reduce error: do not round each interpolated delta. (Just van Rossum)
- Documentation improvements. (Khaled Hosny, Nathan Willis)
- Subsetter improvements: subsets most, if not all, lookup types now. (Garret Rieger, Qunxin Liu)
- Fuzzer-found fixes and other improvements when memory failures happen. (Behdad)
- Removed most atomic implementations now that we have C++11 atomic impl. (Behdad)
- General codebase upkeep; using more C++11 features: constexpr constructors, etc. (Behdad)
Overview of changes leading to 2.7.4
Sunday, December 27, 2020
====================================
@ -789,7 +5,6 @@ Sunday, December 27, 2020
tarball.
- Documentation updates.
Overview of changes leading to 2.7.3
Wednesday, December 23, 2020
====================================
@ -986,7 +201,7 @@ Friday, May 24, 2019
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 Database implementation that is half the size of previously-used
- New Unicode Character Databse implementation that is half the size of previously-used
UCDN.
- Subsetter improvements.
- Improved documentation, thanks to Nathan Willis.
@ -1834,7 +1049,7 @@ Thursday, February 25, 2016
due to bug in glyph class of ASCII double-quote character. This should
address "regression" introduced in 1.2.0 when we switched mark zeroing
in most shapers from BY_UNICODE_LATE to BY_GDEF_LATE.
This fourth release in a week should finally stabilize things...
This fourth release in a week should finally stablize things...
- hb-ot-font's get_glyph() implementation saw some optimizations. Though,
might be really hard to measure in real-world situations.
@ -2882,7 +2097,7 @@ o Changed API:
- hb_buffer_create() takes zero arguments now.
Use hb_buffer_pre_allocate() to pre-allocate.
- hb_buffer_add_utf*() now accept -1 for length parameters,
- hb_buffer_add_utf*() now accept -1 for length parameteres,
meaning "nul-terminated".
- hb_direction_t enum values changed.

1
README
View File

@ -1 +0,0 @@
README.md

15
README Normal file
View File

@ -0,0 +1,15 @@
This is HarfBuzz, a text shaping library.
For bug reports, mailing list, and other information please visit:
http://harfbuzz.org/
For license information, see https://github.com/harfbuzz/harfbuzz/blob/master/COPYING
For build information, see https://github.com/harfbuzz/harfbuzz/blob/master/BUILD.md
For custom configurations, see https://github.com/harfbuzz/harfbuzz/blob/master/CONFIG.md
For test execution, see https://github.com/harfbuzz/harfbuzz/blob/master/TESTING.md
Documentation: https://harfbuzz.github.io

View File

@ -1,17 +1,14 @@
[![Linux CI Status](https://github.com/harfbuzz/harfbuzz/workflows/linux-ci/badge.svg)](https://github.com/harfbuzz/harfbuzz/workflows/linux-ci/badge.svg)
[![CircleCI Build Status](https://circleci.com/gh/harfbuzz/harfbuzz/tree/main.svg?style=svg)](https://circleci.com/gh/harfbuzz/harfbuzz/tree/main)
[![CircleCI Build Status](https://circleci.com/gh/harfbuzz/harfbuzz/tree/master.svg?style=svg)](https://circleci.com/gh/harfbuzz/harfbuzz/tree/master)
[![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/harfbuzz.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/15166/badge.svg)](https://scan.coverity.com/projects/harfbuzz)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/89c872f5ce1c42af802602bfcd15d90a)](https://www.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=harfbuzz/harfbuzz&amp;utm_campaign=Badge_Grade)
[![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
[![Coverity Code Health](https://img.shields.io/coverity/scan/5450.svg)](https://scan.coverity.com/projects/behdad-harfbuzz)
[![Codacy Code Health](https://api.codacy.com/project/badge/Grade/f17f1708783c447488bc8dd317150eaa)](https://app.codacy.com/app/behdad/harfbuzz)
[![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/master/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
[![Coverals Code Coverage](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz)
[![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions)
[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
# HarfBuzz
HarfBuzz is a text shaping engine. It primarily supports [OpenType][1], but also
[Apple Advanced Typography][2]. HarfBuzz is used in Android, Chrome,
ChromeOS, Firefox, GNOME, GTK+, KDE, LibreOffice, OpenJDK, PlayStation, Qt,
XeTeX, and other places.
This is HarfBuzz, a text shaping library.
For bug reports, mailing list, and other information please visit:
@ -19,66 +16,14 @@ For bug reports, mailing list, and other information please visit:
For license information, see [COPYING](COPYING).
## Documentation
For user manual as well as API documentation, check: https://harfbuzz.github.io
## Download
For tarball releases of HarfBuzz, look [here][3]. At the same place you
will also find Win32/Win64 binary bundles that include libharfbuzz DLL,
hb-view.exe, hb-shape.exe, and all dependencies.
The canonical source tree is available on [github][4].
The API that comes with `hb.h` will not change incompatibly. Other, peripheral,
headers are more likely to go through minor modifications, but again, we do our
best to never change API in an incompatible way. We will never break the ABI.
If you are not sure whether Pango or HarfBuzz is right for you, read [Pango vs
HarfBuzz][5].
## Development
For build information, see [BUILD.md](BUILD.md).
For custom configurations, see [CONFIG.md](CONFIG.md).
For testing and profiling, see [TESTING.md](TESTING.md).
For test execution, see [TESTING.md](TESTING.md).
To get a better idea of where HarfBuzz stands in the text rendering stack you
may want to read [State of Text Rendering][6], though, that document is many
years old. Here are a few presentation slides about HarfBuzz at the
Internationalization and Unicode Conference over the years:
Documentation: https://harfbuzz.github.io
* November 2014, [Unicode, OpenType, and HarfBuzz: Closing the Circle][7],
* October 2012, [HarfBuzz, The Free and Open Text Shaping Engine][8],
* October 2009, [HarfBuzz: the Free and Open Shaping Engine][9].
Both development and user support discussion around HarfBuzz happens on the
[github][4].
To report bugs or submit patches please use [github][4] issues and
pull-requests.
For a comparison of old vs new HarfBuzz memory consumption see [this][10].
<!--See past and upcoming [HarfBuzz Hackfests](https://freedesktop.org/wiki/Software/HarfBuzz/Hackfests/)!-->
## Name
HarfBuzz (حرف‌باز) is my Persian translation of “[OpenType][1]”,
transliterated using the Latin script. It sports a second meaning, but that
aint translatable.
> Background: Originally there was this font format called TrueType. People and
> companies started calling their type engines all things ending in Type:
> FreeType, CoolType, ClearType, etc. And then came OpenType, which is the
> successor of TrueType. So, for my OpenType implementation, I decided to stick
> with the concept but use the Persian translation. Which is fitting given that
> Persian is written in the Arabic script, and OpenType is an extension of
> TrueType that adds support for complex script rendering, and HarfBuzz is an
> implementation of OpenType complex text shaping.
<details>
<summary>Packaging status of HarfBuzz</summary>
@ -86,14 +31,3 @@ aint translatable.
[![Packaging status](https://repology.org/badge/vertical-allrepos/harfbuzz.svg?header=harfbuzz)](https://repology.org/project/harfbuzz/versions)
</details>
[1]: https://docs.microsoft.com/en-us/typography/opentype/spec/
[2]: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html
[3]: https://github.com/harfbuzz/harfbuzz/releases
[4]: https://github.com/harfbuzz/harfbuzz
[5]: http://mces.blogspot.com/2009/11/pango-vs-harfbuzz.html
[6]: http://behdad.org/text/
[7]: https://goo.gl/FSIQuC
[8]: https://goo.gl/2wSRu
[9]: http://behdad.org/download/Presentations/slippy/harfbuzz_slides.pdf
[10]: https://goo.gl/woyty

View File

@ -29,12 +29,6 @@ for reference.
- 32bit: `../mingw-configure.sh i686`
- 64bit: `../mingw-configure.sh x86_64`
c) Build as usual:
- make
d) Configure your wine to find system mingw libraries. See:
https://fedoraproject.org/wiki/MinGW/Configure_wine
Now you can use `hb-shape` by `(cd win32build/util && wine hb-shape.exe)`
but if you like to shape with the Microsoft Uniscribe:
@ -51,8 +45,3 @@ but if you like to shape with the Microsoft Uniscribe:
5. `WINEDLLOVERRIDES="usp10=n" wine 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)
When you have built that, you can test HarfBuzz's native shaper against Uniscribe
following these instructions:
https://github.com/harfbuzz/harfbuzz/issues/3671

View File

@ -1,37 +1,44 @@
# HarfBuzz release walk-through checklist:
HarfBuzz release walk-through checklist:
- [ ] Open gitk and review changes since last release.
1. Open gitk and review changes since last release.
- [ ] Print all public API changes:
`git diff $(git describe | sed 's/-.*//').. src/*.h`
* `git diff $(git describe | sed 's/-.*//').. src/*.h` prints all public API
changes.
- [ ] Document them in NEWS.
All API and API semantic changes should be clearly marked as API additions, API changes, or API deletions.
Document them in NEWS. All API and API semantic changes should be clearly
marked as API additions, API changes, or API deletions. Document
deprecations. Ensure all new API / deprecations are in listed correctly in
docs/harfbuzz-sections.txt. If release added new API, add entry for new
API index at the end of docs/harfbuzz-docs.xml.
- [ ] Document deprecations.
Ensure all new API / deprecations are in listed correctly in docs/harfbuzz-sections.txt.
If release added new API, add entry for new API index at the end of docs/harfbuzz-docs.xml.
If there's a backward-incompatible API change (including deletions for API
used anywhere), that's a release blocker. Do NOT release.
If there's a backward-incompatible API change (including deletions for API used anywhere), that's a release blocker.
Do NOT release.
2. Based on severity of changes, decide whether it's a minor or micro release
number bump,
- [ ] Based on severity of changes, decide whether it's a minor or micro release number bump.
3. Search for REPLACEME on the repository and replace it with the chosen version
for the release.
- [ ] Search for 'XSince: REPLACEME' on the repository and replace it with the chosen version for the release, e.g. 'Since: 1.4.7'.
4. Make sure you have correct date and new version at the top of NEWS file.
- [ ] Make sure you have correct date and new version at the top of NEWS file.
5. Bump version in line 3 of meson.build and configure.ac.
Do a `meson test -Cbuild` so it both checks the tests and updates
hb-version.h (use `git diff` to see if is really updated).
- [ ] Bump version in line 3 of meson.build and configure.ac.
6. Commit NEWS, meson.build, 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"
- [ ] Do a `meson test -Cbuild` so it both checks the tests and updates hb-version.h (use `git diff` to see if is really updated).
- [ ] Commit NEWS, meson.build, configure.ac, and src/hb-version.h, as well as any REPLACEME changes you made.
The commit message is simply the release number, e. g. "1.4.7"
- [ ] Do a `meson dist -Cbuild` that runs the tests against the latest committed changes.
7. Do a `meson dist -Cbuild` that runs the tests against the latest commited changes.
If doesn't pass, something fishy is going on, reset the repo and start over.
- [ ] Tag the release and sign it: e.g. `git tag -s 1.4.7 -m 1.4.7`.
Enter your GPG password.
8. Tag the release and sign it: Eg. "git tag -s 1.4.7 -m 1.4.7". Enter your
GPG password.
- [ ] Push the commit and tag out: `git push --follow-tags`.
9. Build win32 bundle. See [README.mingw.md](README.mingw.md).
10. Push the commit and tag out: "git push --follow-tags".
11. Go to GitHub release page [here](https://github.com/harfbuzz/harfbuzz/releases),
edit the tag, upload win32 bundle and NEWS entry and save.
No need to upload source tarball as we rely to GitHub's automatic tar.gz generation.

View File

@ -1,20 +0,0 @@
# Security Policy
If you have discovered a security vulnerability in this project, please report it
privately. **Do not disclose it as a public issue.** This gives me time to work with you
to fix the issue before public exposure, reducing the chance that the exploit will be
used before a patch is released.
You may submit the report in the following ways:
- send an email to behdad@behdad.org and harfbuzz-admin@googlegroups.com; and/or
- send me a [private vulnerability report](https://github.com/harfbuzz/harfbuzz/security/advisories/new)
Please provide the following information in your report:
- A description of the vulnerability and its impact
- How to reproduce the issue
This project is mostly maintained by two developers, working on a reasonable effort
basis. As such, we ask that you give us 90 days to work on a fix before public
disclosure.

View File

@ -39,9 +39,17 @@ ninja -C build
## Test with the Fuzzer
FOr fuzzing, see `test/fuzzing/README.md`.
```shell
CXXFLAGS="-fsanitize=address,fuzzer-no-link" meson fuzzbuild --default-library=static -Dfuzzer_ldflags="-fsanitize=address,fuzzer" -Dexperimental_api=true
ninja -Cfuzzbuild test/fuzzing/hb-{shape,draw,subset,set}-fuzzer
fuzzbuild/test/fuzzing/hb-subset-fuzzer test/fuzzing/fonts
```
## Profiling
For profiling, see `perf/README.md`.
```
meson build --reconfigure
meson compile -C build
build/perf/perf
```

28
TODO Normal file
View File

@ -0,0 +1,28 @@
API issues:
===========
- API to accept a list of languages?
- Remove hb_ot_shape_glyphs_closure()?
API additions
=============
- Language to/from script.
- Add hb-cairo glue
- Add sanitize API.
- Add query / enumeration API for aalt-like features?
- Add segmentation API
- Add hb-fribidi glue?
hb-view / hb-shape enhancements:
===============================
- Add --width, --height, --auto-size, --ink-box, --align, etc?

View File

@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
[7.1.0],
[2.7.4],
[https://github.com/harfbuzz/harfbuzz/issues/new],
[harfbuzz],
[http://harfbuzz.org/])
@ -45,7 +45,7 @@ AC_SUBST(HB_VERSION)
# Libtool version
m4_define([hb_version_int],
m4_eval(60000 + hb_version_major*100 + hb_version_minor*10 + hb_version_micro))
m4_eval(hb_version_major*10000 + hb_version_minor*100 + hb_version_micro))
HB_LIBTOOL_VERSION_INFO=hb_version_int:0:hb_version_int
AC_SUBST(HB_LIBTOOL_VERSION_INFO)
@ -68,8 +68,8 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
])
# Functions and headers
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale uselocale)
AC_CHECK_HEADERS(unistd.h sys/mman.h stdbool.h xlocale.h)
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty)
AC_CHECK_HEADERS(unistd.h sys/mman.h stdbool.h)
# Compiler flags
AC_CANONICAL_HOST
@ -194,10 +194,6 @@ AC_ARG_WITH(cairo,
have_cairo=false
if test "x$with_cairo" = "xyes" -o "x$with_cairo" = "xauto"; then
PKG_CHECK_MODULES(CAIRO, cairo >= 1.8.0, have_cairo=true, :)
save_libs=$LIBS
LIBS="$LIBS $CAIRO_LIBS"
AC_CHECK_FUNCS(cairo_user_font_face_set_render_color_glyph_func)
LIBS=$save_libs
fi
if test "x$with_cairo" = "xyes" -a "x$have_cairo" != "xtrue"; then
AC_MSG_ERROR([cairo support requested but not found])
@ -218,21 +214,21 @@ AM_CONDITIONAL(HAVE_CAIRO_FT, $have_cairo_ft)
dnl ==========================================================================
AC_ARG_WITH(chafa,
[AS_HELP_STRING([--with-chafa=@<:@yes/no/auto@:>@],
[Use chafa @<:@default=auto@:>@])],,
[with_chafa=auto])
have_chafa=false
if test "x$with_chafa" = "xyes" -o "x$with_chafa" = "xauto"; then
PKG_CHECK_MODULES(CHAFA, chafa >= 1.6.0, have_chafa=true, :)
AC_ARG_WITH(fontconfig,
[AS_HELP_STRING([--with-fontconfig=@<:@yes/no/auto@:>@],
[Use fontconfig @<:@default=auto@:>@])],,
[with_fontconfig=auto])
have_fontconfig=false
if test "x$with_fontconfig" = "xyes" -o "x$with_fontconfig" = "xauto"; then
PKG_CHECK_MODULES(FONTCONFIG, fontconfig, have_fontconfig=true, :)
fi
if test "x$with_chafa" = "xyes" -a "x$have_chafa" != "xtrue"; then
AC_MSG_ERROR([chafa support requested but not found])
if test "x$with_fontconfig" = "xyes" -a "x$have_fontconfig" != "xtrue"; then
AC_MSG_ERROR([fontconfig support requested but not found])
fi
if $have_chafa; then
AC_DEFINE(HAVE_CHAFA, 1, [Have chafa terminal graphics library])
if $have_fontconfig; then
AC_DEFINE(HAVE_FONTCONFIG, 1, [Have fontconfig library])
fi
AM_CONDITIONAL(HAVE_CHAFA, $have_chafa)
AM_CONDITIONAL(HAVE_FONTCONFIG, $have_fontconfig)
dnl ==========================================================================
@ -308,7 +304,7 @@ if $have_freetype; then
AC_DEFINE(HAVE_FREETYPE, 1, [Have FreeType 2 library])
save_libs=$LIBS
LIBS="$LIBS $FREETYPE_LIBS"
AC_CHECK_FUNCS(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var FT_Get_Transform)
AC_CHECK_FUNCS(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var)
LIBS=$save_libs
fi
AM_CONDITIONAL(HAVE_FREETYPE, $have_freetype)
@ -366,13 +362,17 @@ AC_ARG_WITH(directwrite,
have_directwrite=false
AC_LANG_PUSH([C++])
if test "x$with_directwrite" = "xyes" -o "x$with_directwrite" = "xauto"; then
AC_CHECK_HEADERS(dwrite_1.h, have_directwrite=true)
AC_CHECK_HEADERS(dwrite.h, have_directwrite=true)
fi
AC_LANG_POP([C++])
if test "x$with_directwrite" = "xyes" -a "x$have_directwrite" != "xtrue"; then
AC_MSG_ERROR([directwrite support requested but not found])
fi
if $have_directwrite; then
DIRECTWRITE_CXXFLAGS=
DIRECTWRITE_LIBS=
AC_SUBST(DIRECTWRITE_CXXFLAGS)
AC_SUBST(DIRECTWRITE_LIBS)
AC_DEFINE(HAVE_DIRECTWRITE, 1, [Have DirectWrite library])
fi
AM_CONDITIONAL(HAVE_DIRECTWRITE, $have_directwrite)
@ -417,6 +417,45 @@ AM_CONDITIONAL(HAVE_CORETEXT, $have_coretext)
dnl ===========================================================================
AC_CACHE_CHECK([for Intel atomic primitives], hb_cv_have_intel_atomic_primitives, [
hb_cv_have_intel_atomic_primitives=false
AC_TRY_LINK([
void memory_barrier (void) { __sync_synchronize (); }
int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); }
int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); }
void mutex_unlock (int *m) { __sync_lock_release (m); }
], [], hb_cv_have_intel_atomic_primitives=true
)
])
if $hb_cv_have_intel_atomic_primitives; then
AC_DEFINE(HAVE_INTEL_ATOMIC_PRIMITIVES, 1, [Have Intel __sync_* atomic primitives])
fi
dnl ===========================================================================
AC_CACHE_CHECK([for Solaris atomic operations], hb_cv_have_solaris_atomic_ops, [
hb_cv_have_solaris_atomic_ops=false
AC_TRY_LINK([
#include <atomic.h>
/* This requires Solaris Studio 12.2 or newer: */
#include <mbarrier.h>
void memory_barrier (void) { __machine_rw_barrier (); }
int atomic_add (volatile unsigned *i) { return atomic_add_int_nv (i, 1); }
void *atomic_ptr_cmpxchg (volatile void **target, void *cmp, void *newval) { return atomic_cas_ptr (target, cmp, newval); }
], [], hb_cv_have_solaris_atomic_ops=true
)
])
if $hb_cv_have_solaris_atomic_ops; then
AC_DEFINE(HAVE_SOLARIS_ATOMIC_OPS, 1, [Have Solaris __machine_*_barrier and atomic_* operations])
fi
if test "$os_win32" = no && ! $have_pthread; then
AC_CHECK_HEADERS(sched.h)
AC_SEARCH_LIBS(sched_yield,rt,AC_DEFINE(HAVE_SCHED_YIELD, 1, [Have sched_yield]))
fi
dnl ===========================================================================
AC_CONFIG_FILES([
Makefile
src/Makefile
@ -425,16 +464,13 @@ util/Makefile
test/Makefile
test/api/Makefile
test/fuzzing/Makefile
test/shape/Makefile
test/shape/data/Makefile
test/shape/data/aots/Makefile
test/shape/data/in-house/Makefile
test/shape/data/text-rendering-tests/Makefile
test/shaping/Makefile
test/shaping/data/Makefile
test/shaping/data/aots/Makefile
test/shaping/data/in-house/Makefile
test/shaping/data/text-rendering-tests/Makefile
test/subset/Makefile
test/subset/data/Makefile
test/subset/data/repack_tests/Makefile
test/threads/Makefile
perf/Makefile
docs/Makefile
docs/version.xml
])
@ -468,7 +504,7 @@ Font callbacks (the more the merrier):
Tools used for command-line utilities:
Cairo: ${have_cairo}
Chafa: ${have_chafa}
Fontconfig: ${have_fontconfig}
Additional shapers:
Graphite2: ${have_graphite2}

View File

@ -29,7 +29,7 @@ SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=--rebuild-types --deprecated-guards="HB_DISABLE_DEPRECATED" \
--ignore-decorators='HB_EXTERN|HB_DEPRECATED|HB_DEPRECATED_FOR()'
--ignore-decorators='HB_EXTERN|HB_DEPRECATED'
# Header files or dirs to ignore when scanning. Use base file/dir names
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
@ -83,7 +83,7 @@ content_files= \
usermanual-integration.xml \
version.xml
# SGML files where gtk-doc abbreviations (#GtkWidget) are expanded
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
expand_content_files=

View File

@ -1,259 +0,0 @@
digraph {
graph [outputorder=edgefirst];
node [shape="record", fontname="Noto Sans Mono SemiBold", fontsize=15];
edge [fontname="Verdana", fontsize=12,labeldistance=7.5 ];
fontname="Verdana";
ranksep=0.02; nodesep=0.5;
subgraph {
ranksep="0.02 equally";
preprocessing[style=filled,fillcolor="lightgreen",fontname="Verdana",label="Glyph pre-processing"];
orthographic[style=filled,fillcolor="lightblue",fontname="Verdana",label="Orthographic Unit Shaping"];
reordering[style=filled, fillcolor="lightcoral",fontname="Verdana",label="Reordering group (USE)"];
topographic[style=filled,fillcolor="lightgoldenrod",fontname="Verdana",label="Topographical Features‡"];
typographic[style=filled,fillcolor="lightpink",fontname="Verdana",label="Typographic Presentation"];
positioning[style=filled,fillcolor="lightsalmon",fontname="Verdana",label="Positioning"];
preprocessing->reordering->orthographic->topographic->typographic->positioning;
}
decision1 [shape="diamond", label="Script\ndirection?",fontname="Verdana"];
rvrn->decision1;
ltrfeatures [label="{ltra|ltrm}", fillcolor="lightgreen",style="filled"];
{
rtlfeatures [label="{rtla|rtlm¹}", fillcolor="lightgreen",style="filled"];
}
{
rank=same;
fracfeatures [label="frac²|numr³|dnom⁴", fillcolor="lightpink",style="filled"];
fracnotes [fontname="Verdana",shape=plaintext,label=<<table border="0" cellborder="0" cellspacing="0">
<tr><td align="left">¹ rtlm is scoped to characters with a Unicode mirroring property</td></tr>
<tr><td align="left">² frac is scoped to numr + the slash + dnom</td></tr>
<tr><td align="left">³ numr is scoped to all decimal numbers before a U+2044 FRACTION SLASH.</td></tr>
<tr><td align="left">⁴ dnom is scoped to all decimal numbers after a U+2044 FRACTION SLASH.</td></tr>
</table>
>];
}
rand [fillcolor="lightpink",style="filled"];
decision1 -> ltrfeatures [label="Left-to-right"];
decision1 -> rtlfeatures [label="Right-to-left"];
decision1 -> fracfeatures [label="Other"];
ltrfeatures -> fracfeatures;
rtlfeatures -> fracfeatures;
fracfeatures->rand;
decision2 [shape="diamond", label="Script?",fontname="Verdana"];
{rank=same; HARF [label="{Harf|HARF}"]; notes;}
rand -> trak -> HARF -> decision2;
commonfeatures [shape=none,label=<<table border="0" cellspacing="0">
<tr>
<td border="1" bgcolor="lightsalmon">abvm</td>
<td border="1" bgcolor="lightsalmon">blwm</td>
<td border="1" bgcolor="lightgreen">ccmp</td>
<td border="1" bgcolor="lightgreen">locl</td>
<td border="1" bgcolor="lightsalmon">mark</td>
<td border="1" bgcolor="lightsalmon">mkmk</td>
<td border="1" bgcolor="lightpink">rlig</td>
</tr>
</table>>
];
decision3 [shape="diamond", label="Script\ndirection?",fontname="Verdana"];
BUZZ [label="{Buzz|BUZZ}"];
BUZZ -> commonfeatures -> decision3;
horizontalfeatures [
shape=none,label=<<table border="0" cellspacing="0">
<tr><td border="1" bgcolor="lightpink">calt <font face="Verdana">(not Hangul)</font></td></tr>
<tr><td border="1" bgcolor="lightpink">clig <font face="Verdana">(not Khmer)</font></td></tr>
<tr><td border="1" bgcolor="lightsalmon">curs</td></tr>
<tr><td border="1" bgcolor="lightsalmon">dist</td></tr>
<tr><td border="1" bgcolor="lightsalmon">kern</td></tr>
<tr><td border="1" bgcolor="lightpink">liga <font face="Verdana">(not Khmer)</font></td></tr>
<tr><td border="1" bgcolor="lightpink">rclt</td></tr>
</table>>
];
vert [label="vert",style=filled,fillcolor="lightpink"];
decision3 -> horizontalfeatures [label="Horizontal"];
decision3 -> vert [label="Vertical"];
discretionary [label="User-selected\ndiscretionary\nfeatures",fontname="Verdana"];
horizontalfeatures -> discretionary;
vert -> discretionary;
decision2->stch;
BUZZ;
subgraph shapers {
subgraph cluster_arabic {
bgcolor="lightyellow"
label="Arabic, Syriac";
stch [ style="filled", fillcolor="lightgreen",label="stch"];
ccmplocl [ style="filled", label="ccmp|locl", fillcolor="lightgreen"];
arabicfeatures [label="isol|fina|fin2|fin3|medi|med2|init", style="filled", fillcolor="lightgoldenrod"];
arabicfeatures2 [label="rclt|calt", style="filled",fillcolor="lightpink"];
rlig[style="filled",fillcolor="lightpink"];
mset [fillcolor="lightpink",style="filled"]
stch->ccmplocl->arabicfeatures->rlig->arabicfeatures2->mset;
}
mset->BUZZ:n;
subgraph cluster_hangul {
bgcolor="lightyellow"
label="Hangul";
hangulfeatures [label="ljmo|vjmo|tjmo", style="filled",fillcolor="lightgoldenrod"]
}
hangulfeatures->BUZZ:n;
subgraph cluster_indic {
label="Indic";
bgcolor="lightyellow"
// Preprocessing
loclccmpindic [label="locl†|ccmp†",style=filled,fillcolor="lightgreen"];
node[style=filled,fillcolor="lightgreen"];
nukt [label="nukt†"];
akhn [label="akhn†"];
loclccmpindic->indic_reorder_1->nukt->akhn;
indic_reorder_1[label="Initial reordering", fontname="Verdana",fillcolor="lightgrey",shape=ellipse,style=filled]
// Orthographic
node[style=filled,fillcolor="lightblue"]
rphf [label="rphf⁵"];
rkpf [label="rkpf†"];
pref [label="pref⁶"];
blwf [label="blwf⁷"];
abvf [label="abvf⁸"];
half [label="half⁹"];
pstf [label="pstf⁸"];
vatu [label="vatu†"];
cjct [label="cjct†"];
akhn ->rphf -> rkpf -> pref -> blwf -> abvf -> half -> pstf -> vatu -> cjct;
// Typographic presentation
indic_typographic[style=filled,fillcolor="lightpink",label="init|pres|abvs|blws|psts|haln"]
indic_reorder_2[label="Final reordering",fillcolor="lightgrey",fontname="Verdana", shape=ellipse,style=filled]
cjct->indic_reorder_2->indic_typographic;
notes2 [fontname="Verdana",shape=plaintext,style="",label=<<table border="0" cellborder="0" cellspacing="0">
<tr><td align="right">⁵ rphf is scoped to pre-base ra+halant sequences</td></tr>
<tr><td align="right">⁶ pref is scoped to the two glyphs after the base; outputs are reordered</td></tr>
<tr><td align="right">⁷ blwf is usually scoped to the whole syllable, except in Telugu and Kannada where it is post-base</td></tr>
<tr><td align="right">⁸ abvf and pstf are scoped to post-base</td></tr>
<tr><td align="right">⁹ half is scoped to pre-base</td></tr>
</table>
>];
indic_typographic -> notes2 [style=invis];
}
subgraph cluster_khmer {
label="Khmer";
bgcolor="lightyellow"
khmerbasic [style=filled,fillcolor="lightgreen",label="locl†|ccmp†|pref†|bwlf†|abvf†|pstf†|cfar†"]
khmerother [style=filled,fillcolor="lightpink",label="pres|abvs|blws|psts"]
khmerbasic -> khmerother -> khmerclig;
khmerclig [label="clig",style=filled,fillcolor="lightpink"];
}
subgraph cluster_myanmar {
label="Myanmar";
bgcolor="lightyellow"
loclccmpmyanmar [label="locl†|ccmp†",style=filled,fillcolor="lightgreen"];
rphfmymr [label="rphf†",style=filled,fillcolor="lightblue"]
prefmymr [label="pref†",style=filled,fillcolor="lightblue"]
blwfmymr [label="blwf†",style=filled,fillcolor="lightblue"]
pstfmymr [label="pstf†",style=filled,fillcolor="lightblue"]
myanmarother [label="pres|abvs|blws|psts",style=filled,fillcolor="lightpink"];
reorder_myanmar[label="Reordering", shape=ellipse,style=filled,fontname="Verdana"]
loclccmpmyanmar -> reorder_myanmar-> rphfmymr -> prefmymr -> blwfmymr -> pstfmymr -> myanmarother;
}
subgraph cluster_use {
label="Universal Shaping Engine"
bgcolor="lightyellow"
use_preprocessing [style=filled, label="locl†|ccmp†|nukt†|akhn†", fillcolor="lightgreen"];
// Reoredering
rphfuse [label="rphf¹⁰", style=filled, fillcolor="lightcoral"];
prefuse [label="pref¹¹", style=filled, fillcolor="lightcoral"];
// Orthographic
orthographicuse [label="rkrf†|abvf†|blwf†|half†|pstf†|vatu†|cjct†", style="filled", fillcolor="lightblue"];
topographicaluse [label="isol|init|medi|fina", style="filled", fillcolor="lightgoldenrod"];
typographicaluse [label="abvs|blws|haln|pres|psts", style="filled", fillcolor="lightpink"];
reorder_use[label="Reordering", shape=ellipse,style=filled,fontname="Verdana"]
use_preprocessing -> rphfuse -> prefuse->orthographicuse ->reorder_use -> topographicaluse -> typographicaluse;
notes3 [fontname="Verdana",shape=plaintext,label=<<table border="0" cellborder="0" cellspacing="0">
<tr><td align="left">¹⁰ Outputs are reordered as category R</td></tr>
<tr><td align="left">¹¹ Outputs are reordered to before base</td></tr>
</table>
>];
typographicaluse -> notes3 [style=invis];
}
}
indic_typographic->BUZZ:n;
typographicaluse->BUZZ:n;
khmerclig -> BUZZ:n;
myanmarother -> BUZZ:n;
decision2->hangulfeatures;
decision2->loclccmpindic;
decision2->khmerbasic;
decision2->loclccmpmyanmar;
decision2->use_preprocessing;
decision2->BUZZ [label=" Hebrew, Thai,\n Lao, other"];
notes [fontname="Verdana",shape=box,label=<<table border="0" cellborder="0" cellspacing="0">
<tr><td align="left">
<b>Indic</b> scripts are: Bengali, Devanagari,
Gujarati, Gurmukhi, Kannada,
Malayalam, Oriya, Tamil,
Telugu
</td></tr>
<tr><td align="left">
<b>USE</b> scripts are:
Adlam, Ahom, Balinese, Batak, Bhaiksuki, Brahmi, Buginese,
Buhid, Chakma, Cham, Chorasmian, Dives Akuru, Dogra, Duployan,
</td></tr>
<tr><td align="left">
Egyptian hieroglyphs, Elymaic, Grantha, Gunjala Ggondi, Hanifi Rohingya,
Hanunoo, Javanese, Kaithi, Kayah li, Kharoshthi, Khojki,
</td></tr>
<tr><td align="left">
Khudawadi, Lepcha, Limbu, Mahajani, Makasar, Mandaic, Manichaean,
Marchen, Masaram Gondi, Medefaidrin, Meetei Mayek, Miao, Modi,
</td></tr>
<tr><td align="left">
Mongolian, Multani, Nandinagari, Newa, Nko, Nyiakeng Puachue Hmong,
Old Sogdian, Pahawh Hmong, Phags Pa, Psalter Pahlavi, Rejang,
</td></tr>
<tr><td align="left">
Saurashtra, Sharada, Siddham, Sinhala, Sogdian, Soyombo, Sundanese,
Syloti Nagri, Tagalog, Tagbanwa, Tai Le, Tai Tham, Tai Viet,
</td></tr>
<tr><td align="left">
Takri, Tibetan, Tifinagh, Tirhuta, Wancho, Zanabazar square,
</td></tr>
</table>>]
footnote[fontname="Verdana",label=<<table border="0" cellborder="0" cellspacing="0">
<tr><td align="left">† Feature is scoped to each syllable</td></tr>
<tr><td align="left">‡ All topographic features are scoped based on topographic position</td></tr>
</table>>];
notes3->footnote[style=invis];
}

View File

@ -49,16 +49,13 @@
<ulink role="online-location" url="http://[SERVER]/libharfbuzz/index.html">http://[SERVER]/libharfbuzz/</ulink>.-->
</releaseinfo>
</partinfo>
<title>Reference manual</title>
<chapter id="core-api">
<title>Core API</title>
<xi:include href="xml/hb-blob.xml"/>
<xi:include href="xml/hb-buffer.xml"/>
<xi:include href="xml/hb-common.xml"/>
<xi:include href="xml/hb-features.xml"/>
<xi:include href="xml/hb-draw.xml"/>
<xi:include href="xml/hb-paint.xml"/>
<xi:include href="xml/hb-deprecated.xml"/>
<xi:include href="xml/hb-face.xml"/>
<xi:include href="xml/hb-font.xml"/>
@ -98,99 +95,71 @@
<xi:include href="xml/hb-uniscribe.xml"/>
<xi:include href="xml/hb-gdi.xml"/>
<xi:include href="xml/hb-directwrite.xml"/>
<xi:include href="xml/hb-cairo.xml"/>
</chapter>
<chapter id="style-api">
<title>Style API</title>
<xi:include href="xml/hb-style.xml"/>
</chapter>
<chapter id="subset-api">
<title>Subset API</title>
<xi:include href="xml/hb-subset.xml"/>
</chapter>
<!--chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter-->
<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"><title>Index of deprecated API</title><xi:include href="xml/api-index-deprecated.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-7-1-0"><title>Index of new symbols in 7.1.0</title><xi:include href="xml/api-index-7.1.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-7-0-0"><title>Index of new symbols in 7.0.0</title><xi:include href="xml/api-index-7.0.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-6-0-0"><title>Index of new symbols in 6.0.0</title><xi:include href="xml/api-index-6.0.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-5-3-0"><title>Index of new symbols in 5.3.0</title><xi:include href="xml/api-index-5.3.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-5-0-0"><title>Index of new symbols in 5.0.0</title><xi:include href="xml/api-index-5.0.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-4-4-0"><title>Index of new symbols in 4.4.0</title><xi:include href="xml/api-index-4.4.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-4-3-0"><title>Index of new symbols in 4.3.0</title><xi:include href="xml/api-index-4.3.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-4-2-0"><title>Index of new symbols in 4.2.0</title><xi:include href="xml/api-index-4.2.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-4-1-0"><title>Index of new symbols in 4.1.0</title><xi:include href="xml/api-index-4.1.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-4-0-0"><title>Index of new symbols in 4.0.0</title><xi:include href="xml/api-index-4.0.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-3-4-0"><title>Index of new symbols in 3.4.0</title><xi:include href="xml/api-index-3.4.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-3-3-0"><title>Index of new symbols in 3.3.0</title><xi:include href="xml/api-index-3.3.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-3-1-0"><title>Index of new symbols in 3.1.0</title><xi:include href="xml/api-index-3.1.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-3-0-0"><title>Index of new symbols in 3.0.0</title><xi:include href="xml/api-index-3.0.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-2-9-1"><title>Index of new symbols in 2.9.1</title><xi:include href="xml/api-index-2.9.1.xml"><xi:fallback /></xi:include></index>
<index id="api-index-2-9-0"><title>Index of new symbols in 2.9.0</title><xi:include href="xml/api-index-2.9.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-2-8-2"><title>Index of new symbols in 2.8.2</title><xi:include href="xml/api-index-2.8.2.xml"><xi:fallback /></xi:include></index>
<index id="api-index-2-7-3"><title>Index of new symbols in 2.7.3</title><xi:include href="xml/api-index-2.7.3.xml"><xi:fallback /></xi:include></index>
<index id="api-index-2-6-8"><title>Index of new symbols in 2.6.8</title><xi:include href="xml/api-index-2.6.8.xml"><xi:fallback /></xi:include></index>
<index id="api-index-2-6-5"><title>Index of new symbols in 2.6.5</title><xi:include href="xml/api-index-2.6.5.xml"><xi:fallback /></xi:include></index>
<index id="api-index-2-6-3"><title>Index of new symbols in 2.6.3</title><xi:include href="xml/api-index-2.6.3.xml"><xi:fallback /></xi:include></index>
<index id="api-index-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"><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"><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"><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"><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"><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"><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"><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>
<index id="api-index-1-8-6"><title>Index of new symbols in 1.8.6</title><xi:include href="xml/api-index-1.8.6.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-8-5"><title>Index of new symbols in 1.8.5</title><xi:include href="xml/api-index-1.8.5.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-8-1"><title>Index of new symbols in 1.8.1</title><xi:include href="xml/api-index-1.8.1.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-8-0"><title>Index of new symbols in 1.8.0</title><xi:include href="xml/api-index-1.8.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-7-7"><title>Index of new symbols in 1.7.7</title><xi:include href="xml/api-index-1.7.7.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-7-2"><title>Index of new symbols in 1.7.2</title><xi:include href="xml/api-index-1.7.2.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-6-0"><title>Index of new symbols in 1.6.0</title><xi:include href="xml/api-index-1.6.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-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"><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"><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"><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"><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"><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"><title>Index of new symbols in 1.1.3</title><xi:include href="xml/api-index-1.1.3.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-1-2"><title>Index of new symbols in 1.1.2</title><xi:include href="xml/api-index-1.1.2.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-0-5"><title>Index of new symbols in 1.0.5</title><xi:include href="xml/api-index-1.0.5.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-42"><title>Index of new symbols in 0.9.42</title><xi:include href="xml/api-index-0.9.42.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-41"><title>Index of new symbols in 0.9.41</title><xi:include href="xml/api-index-0.9.41.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-39"><title>Index of new symbols in 0.9.39</title><xi:include href="xml/api-index-0.9.39.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-38"><title>Index of new symbols in 0.9.38</title><xi:include href="xml/api-index-0.9.38.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-33"><title>Index of new symbols in 0.9.33</title><xi:include href="xml/api-index-0.9.33.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-31"><title>Index of new symbols in 0.9.31</title><xi:include href="xml/api-index-0.9.31.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-30"><title>Index of new symbols in 0.9.30</title><xi:include href="xml/api-index-0.9.30.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-28"><title>Index of new symbols in 0.9.28</title><xi:include href="xml/api-index-0.9.28.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-26"><title>Index of new symbols in 0.9.26</title><xi:include href="xml/api-index-0.9.26.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-22"><title>Index of new symbols in 0.9.22</title><xi:include href="xml/api-index-0.9.22.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-21"><title>Index of new symbols in 0.9.21</title><xi:include href="xml/api-index-0.9.21.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-20"><title>Index of new symbols in 0.9.20</title><xi:include href="xml/api-index-0.9.20.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-11"><title>Index of new symbols in 0.9.11</title><xi:include href="xml/api-index-0.9.11.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-10"><title>Index of new symbols in 0.9.10</title><xi:include href="xml/api-index-0.9.10.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-8"><title>Index of new symbols in 0.9.8</title><xi:include href="xml/api-index-0.9.8.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-7"><title>Index of new symbols in 0.9.7</title><xi:include href="xml/api-index-0.9.7.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-5"><title>Index of new symbols in 0.9.5</title><xi:include href="xml/api-index-0.9.5.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-2"><title>Index of new symbols in 0.9.2</title><xi:include href="xml/api-index-0.9.2.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-6-0"><title>Index of new symbols in 0.6.0</title><xi:include href="xml/api-index-0.6.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-2-7-3" role="2.7.3"><title>Index of new symbols in 2.7.3</title><xi:include href="xml/api-index-2.7.3.xml"><xi:fallback /></xi:include></index>
<index id="api-index-2-6-8" role="2.6.8"><title>Index of new symbols in 2.6.8</title><xi:include href="xml/api-index-2.6.8.xml"><xi:fallback /></xi:include></index>
<index id="api-index-2-6-5" role="2.6.5"><title>Index of new symbols in 2.6.5</title><xi:include href="xml/api-index-2.6.5.xml"><xi:fallback /></xi:include></index>
<index id="api-index-2-6-3" role="2.6.3"><title>Index of new symbols in 2.6.3</title><xi:include href="xml/api-index-2.6.3.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>
<index id="api-index-1-8-6" role="1.8.6"><title>Index of new symbols in 1.8.6</title><xi:include href="xml/api-index-1.8.6.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-8-5" role="1.8.5"><title>Index of new symbols in 1.8.5</title><xi:include href="xml/api-index-1.8.5.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-8-1" role="1.8.1"><title>Index of new symbols in 1.8.1</title><xi:include href="xml/api-index-1.8.1.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-8-0" role="1.8.0"><title>Index of new symbols in 1.8.0</title><xi:include href="xml/api-index-1.8.0.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-7-7" role="1.7.7"><title>Index of new symbols in 1.7.7</title><xi:include href="xml/api-index-1.7.7.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-7-5" role="1.7.5"><title>Index of new symbols in 1.7.5</title><xi:include href="xml/api-index-1.7.5.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-7-2" role="1.7.2"><title>Index of new symbols in 1.7.2</title><xi:include href="xml/api-index-1.7.2.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-6-0" role="1.6.0"><title>Index of new symbols in 1.6.0</title><xi:include href="xml/api-index-1.6.0.xml"><xi:fallback /></xi:include></index>
<index id="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>
<index id="api-index-1-1-2" role="1.1.2"><title>Index of new symbols in 1.1.2</title><xi:include href="xml/api-index-1.1.2.xml"><xi:fallback /></xi:include></index>
<index id="api-index-1-0-5" role="1.0.5"><title>Index of new symbols in 1.0.5</title><xi:include href="xml/api-index-1.0.5.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-42" role="0.9.42"><title>Index of new symbols in 0.9.42</title><xi:include href="xml/api-index-0.9.42.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-41" role="0.9.41"><title>Index of new symbols in 0.9.41</title><xi:include href="xml/api-index-0.9.41.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-39" role="0.9.39"><title>Index of new symbols in 0.9.39</title><xi:include href="xml/api-index-0.9.39.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-38" role="0.9.38"><title>Index of new symbols in 0.9.38</title><xi:include href="xml/api-index-0.9.38.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-33" role="0.9.33"><title>Index of new symbols in 0.9.33</title><xi:include href="xml/api-index-0.9.33.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-31" role="0.9.31"><title>Index of new symbols in 0.9.31</title><xi:include href="xml/api-index-0.9.31.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-30" role="0.9.30"><title>Index of new symbols in 0.9.30</title><xi:include href="xml/api-index-0.9.30.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-28" role="0.9.28"><title>Index of new symbols in 0.9.28</title><xi:include href="xml/api-index-0.9.28.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-26" role="0.9.26"><title>Index of new symbols in 0.9.26</title><xi:include href="xml/api-index-0.9.26.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-22" role="0.9.22"><title>Index of new symbols in 0.9.22</title><xi:include href="xml/api-index-0.9.22.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-21" role="0.9.21"><title>Index of new symbols in 0.9.21</title><xi:include href="xml/api-index-0.9.21.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-20" role="0.9.20"><title>Index of new symbols in 0.9.20</title><xi:include href="xml/api-index-0.9.20.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-11" role="0.9.11"><title>Index of new symbols in 0.9.11</title><xi:include href="xml/api-index-0.9.11.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-10" role="0.9.10"><title>Index of new symbols in 0.9.10</title><xi:include href="xml/api-index-0.9.10.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-8" role="0.9.8"><title>Index of new symbols in 0.9.8</title><xi:include href="xml/api-index-0.9.8.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-7" role="0.9.7"><title>Index of new symbols in 0.9.7</title><xi:include href="xml/api-index-0.9.7.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-5" role="0.9.5"><title>Index of new symbols in 0.9.5</title><xi:include href="xml/api-index-0.9.5.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-9-2" role="0.9.2"><title>Index of new symbols in 0.9.2</title><xi:include href="xml/api-index-0.9.2.xml"><xi:fallback /></xi:include></index>
<index id="api-index-0-6-0" role="0.6.0"><title>Index of new symbols in 0.6.0</title><xi:include href="xml/api-index-0.6.0.xml"><xi:fallback /></xi:include></index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</part>
<note>
<para>
The current HarfBuzz codebase is stable
The current HarfBuzz codebase is versioned 2.x.x and is stable
and under active maintenance. This is what is used in latest
versions of Firefox, GNOME, ChromeOS, Chrome, LibreOffice,
XeTeX, Android, and KDE, among other places.

View File

@ -1,4 +1,3 @@
<SECTION>
<SUBSECTION Private>
HB_H_IN
HB_OT_H_IN
@ -22,38 +21,35 @@ hb_aat_layout_has_tracking
<SECTION>
<FILE>hb-blob</FILE>
hb_blob_create
hb_blob_create_or_fail
hb_blob_create_from_file
hb_blob_create_from_file_or_fail
hb_blob_create_sub_blob
hb_blob_copy_writable_or_fail
hb_blob_get_empty
hb_blob_reference
hb_blob_destroy
hb_blob_set_user_data
hb_blob_get_user_data
hb_blob_make_immutable
hb_blob_is_immutable
hb_blob_get_data
hb_blob_get_data_writable
hb_blob_get_empty
hb_blob_get_length
hb_blob_get_user_data
hb_blob_is_immutable
hb_blob_make_immutable
hb_blob_reference
hb_blob_set_user_data
hb_blob_t
hb_memory_mode_t
</SECTION>
<SECTION>
<FILE>hb-buffer</FILE>
HB_SEGMENT_PROPERTIES_DEFAULT
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT
hb_buffer_create
hb_buffer_allocation_successful
hb_buffer_create_similar
hb_buffer_get_empty
hb_buffer_reference
hb_buffer_get_empty
hb_buffer_destroy
hb_buffer_set_user_data
hb_buffer_get_user_data
hb_buffer_reset
hb_buffer_clear_contents
hb_buffer_pre_allocate
hb_buffer_allocation_successful
hb_buffer_add
hb_buffer_add_codepoints
hb_buffer_add_utf32
@ -80,14 +76,13 @@ hb_buffer_get_segment_properties
hb_buffer_guess_segment_properties
hb_buffer_set_unicode_funcs
hb_buffer_get_unicode_funcs
hb_buffer_set_user_data
hb_buffer_get_user_data
hb_buffer_get_glyph_infos
hb_glyph_info_get_glyph_flags
hb_buffer_get_glyph_positions
hb_buffer_has_positions
hb_buffer_set_invisible_glyph
hb_buffer_get_invisible_glyph
hb_buffer_set_not_found_glyph
hb_buffer_get_not_found_glyph
hb_buffer_set_invisible_glyph
hb_buffer_set_replacement_codepoint
hb_buffer_get_replacement_codepoint
hb_buffer_normalize_glyphs
@ -104,13 +99,10 @@ hb_buffer_serialize_format_to_string
hb_buffer_serialize_list_formats
hb_segment_properties_equal
hb_segment_properties_hash
hb_segment_properties_overlay
hb_buffer_diff
hb_buffer_message_func_t
hb_buffer_set_message_func
HB_SEGMENT_PROPERTIES_DEFAULT
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT
hb_buffer_t
hb_glyph_info_get_glyph_flags
hb_glyph_info_t
hb_glyph_flags_t
hb_glyph_position_t
@ -121,30 +113,22 @@ hb_segment_properties_t
hb_buffer_serialize_format_t
hb_buffer_serialize_flags_t
hb_buffer_diff_flags_t
hb_buffer_message_func_t
</SECTION>
<SECTION>
<FILE>hb-common</FILE>
HB_TAG
HB_UNTAG
hb_tag_from_string
hb_tag_to_string
hb_direction_from_string
hb_direction_to_string
HB_DIRECTION_REVERSE
HB_DIRECTION_IS_BACKWARD
HB_DIRECTION_IS_FORWARD
HB_DIRECTION_IS_HORIZONTAL
HB_DIRECTION_IS_VALID
HB_DIRECTION_IS_VERTICAL
hb_script_from_iso15924_tag
hb_script_to_iso15924_tag
hb_script_from_string
hb_script_to_iso15924_tag
hb_script_get_horizontal_direction
hb_language_from_string
hb_language_to_string
hb_language_get_default
hb_language_matches
hb_feature_from_string
hb_feature_to_string
hb_variation_from_string
@ -161,9 +145,17 @@ hb_position_t
hb_tag_t
hb_script_t
hb_user_data_key_t
HB_TAG
HB_TAG_NONE
HB_TAG_MAX
HB_TAG_MAX_SIGNED
HB_UNTAG
HB_DIRECTION_REVERSE
HB_DIRECTION_IS_BACKWARD
HB_DIRECTION_IS_FORWARD
HB_DIRECTION_IS_HORIZONTAL
HB_DIRECTION_IS_VALID
HB_DIRECTION_IS_VERTICAL
HB_LANGUAGE_INVALID
HB_FEATURE_GLOBAL_END
HB_FEATURE_GLOBAL_START
@ -171,7 +163,6 @@ HB_FEATURE_GLOBAL_START
HB_BEGIN_DECLS
HB_END_DECLS
hb_var_int_t
hb_var_num_t
int16_t
int32_t
int64_t
@ -180,120 +171,12 @@ uint16_t
uint32_t
uint64_t
uint8_t
<SUBSECTION Private>
HB_EXTERN
HB_DEPRECATED
HB_DEPRECATED_FOR
</SECTION>
<SECTION>
<FILE>hb-features</FILE>
HB_HAS_CAIRO
HB_HAS_CORETEXT
HB_HAS_DIRECTWRITE
HB_HAS_FREETYPE
HB_HAS_GDI
HB_HAS_GLIB
HB_HAS_GOBJECT
HB_HAS_GRAPHITE
HB_HAS_ICU
HB_HAS_UNISCRIBE
</SECTION>
<SECTION>
<FILE>hb-draw</FILE>
hb_draw_funcs_create
hb_draw_funcs_get_empty
hb_draw_funcs_reference
hb_draw_funcs_destroy
hb_draw_funcs_set_user_data
hb_draw_funcs_get_user_data
hb_draw_funcs_make_immutable
hb_draw_funcs_is_immutable
hb_draw_move_to_func_t
hb_draw_funcs_set_move_to_func
hb_draw_line_to_func_t
hb_draw_funcs_set_line_to_func
hb_draw_quadratic_to_func_t
hb_draw_funcs_set_quadratic_to_func
hb_draw_cubic_to_func_t
hb_draw_funcs_set_cubic_to_func
hb_draw_close_path_func_t
hb_draw_funcs_set_close_path_func
hb_draw_move_to
hb_draw_line_to
hb_draw_quadratic_to
hb_draw_cubic_to
hb_draw_close_path
HB_DRAW_STATE_DEFAULT
hb_draw_funcs_t
hb_draw_state_t
</SECTION>
<SECTION>
<FILE>hb-paint</FILE>
hb_paint_funcs_t
hb_paint_funcs_create
hb_paint_funcs_get_empty
hb_paint_funcs_reference
hb_paint_funcs_destroy
hb_paint_funcs_set_user_data
hb_paint_funcs_get_user_data
hb_paint_funcs_make_immutable
hb_paint_funcs_is_immutable
hb_paint_push_transform_func_t
hb_paint_funcs_set_push_transform_func
hb_paint_pop_transform_func_t
hb_paint_funcs_set_pop_transform_func
hb_paint_push_clip_glyph_func_t
hb_paint_funcs_set_push_clip_glyph_func
hb_paint_push_clip_rectangle_func_t
hb_paint_funcs_set_push_clip_rectangle_func
hb_paint_pop_clip_func_t
hb_paint_funcs_set_pop_clip_func
hb_paint_color_func_t
hb_paint_funcs_set_color_func
HB_PAINT_IMAGE_FORMAT_PNG
HB_PAINT_IMAGE_FORMAT_SVG
HB_PAINT_IMAGE_FORMAT_BGRA
hb_paint_image_func_t
hb_paint_funcs_set_image_func
hb_color_line_t
hb_color_stop_t
hb_color_line_get_color_stops_func_t
hb_color_line_get_color_stops
hb_paint_extend_t
hb_color_line_get_extend_func_t
hb_color_line_get_extend
hb_paint_linear_gradient_func_t
hb_paint_funcs_set_linear_gradient_func
hb_paint_radial_gradient_func_t
hb_paint_funcs_set_radial_gradient_func
hb_paint_sweep_gradient_func_t
hb_paint_funcs_set_sweep_gradient_func
hb_paint_composite_mode_t
hb_paint_push_group_func_t
hb_paint_funcs_set_push_group_func
hb_paint_pop_group_func_t
hb_paint_funcs_set_pop_group_func
hb_paint_custom_palette_color_func_t
hb_paint_funcs_set_custom_palette_color_func
hb_paint_push_transform
hb_paint_pop_transform
hb_paint_push_clip_glyph
hb_paint_push_clip_rectangle
hb_paint_pop_clip
hb_paint_color
hb_paint_image
hb_paint_linear_gradient
hb_paint_radial_gradient
hb_paint_sweep_gradient
hb_paint_push_group
hb_paint_pop_group
hb_paint_custom_palette_color
</SECTION>
<SECTION>
<FILE>hb-deprecated</FILE>
HB_BUFFER_FLAGS_DEFAULT
@ -302,7 +185,6 @@ HB_SCRIPT_CANADIAN_ABORIGINAL
hb_font_funcs_set_glyph_func
hb_font_get_glyph_func_t
HB_MATH_GLYPH_PART_FLAG_EXTENDER
HB_OT_MATH_SCRIPT
hb_ot_layout_table_choose_script
hb_ot_layout_table_find_script
hb_ot_tag_from_language
@ -311,6 +193,7 @@ HB_OT_VAR_NO_AXIS_INDEX
hb_ot_var_axis_t
hb_ot_var_find_axis
hb_ot_var_get_axes
hb_set_invert
hb_unicode_eastasian_width_func_t
hb_unicode_eastasian_width
hb_unicode_funcs_set_eastasian_width_func
@ -338,6 +221,8 @@ hb_coretext_font_get_ct_font
<FILE>hb-directwrite</FILE>
hb_directwrite_face_create
hb_directwrite_face_get_font_face
<SUBSECTION Private>
hb_directwrite_shape_experimental_width
</SECTION>
<SECTION>
@ -346,29 +231,27 @@ hb_face_count
hb_face_t
hb_face_create
hb_face_create_for_tables
hb_face_get_empty
hb_face_reference
hb_face_destroy
hb_face_set_user_data
hb_face_get_user_data
hb_face_make_immutable
hb_face_is_immutable
hb_face_get_empty
hb_face_get_table_tags
hb_face_set_glyph_count
hb_face_get_glyph_count
hb_face_set_index
hb_face_get_index
hb_face_set_upem
hb_face_get_upem
hb_face_get_user_data
hb_face_is_immutable
hb_face_make_immutable
hb_face_reference
hb_face_reference_blob
hb_face_reference_table
hb_face_set_glyph_count
hb_face_set_index
hb_face_set_upem
hb_face_set_user_data
hb_face_collect_unicodes
hb_face_collect_nominal_glyph_mapping
hb_face_collect_variation_selectors
hb_face_collect_variation_unicodes
hb_face_builder_create
hb_face_builder_add_table
hb_face_builder_sort_tables
</SECTION>
<SECTION>
@ -376,126 +259,110 @@ hb_face_builder_sort_tables
hb_font_add_glyph_origin_for_direction
hb_font_create
hb_font_create_sub_font
hb_font_get_empty
hb_font_reference
hb_font_destroy
hb_font_set_user_data
hb_font_get_user_data
hb_font_make_immutable
hb_font_is_immutable
hb_font_set_face
hb_font_funcs_create
hb_font_funcs_destroy
hb_font_funcs_get_empty
hb_font_funcs_get_user_data
hb_font_funcs_is_immutable
hb_font_funcs_make_immutable
hb_font_funcs_reference
hb_font_funcs_set_glyph_contour_point_func
hb_font_funcs_set_glyph_extents_func
hb_font_funcs_set_glyph_from_name_func
hb_font_funcs_set_glyph_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
hb_font_funcs_set_glyph_v_advances_func
hb_font_funcs_set_glyph_v_origin_func
hb_font_funcs_set_nominal_glyph_func
hb_font_funcs_set_nominal_glyphs_func
hb_font_funcs_set_user_data
hb_font_funcs_set_variation_glyph_func
hb_font_funcs_t
hb_font_get_empty
hb_font_get_face
hb_font_get_glyph
hb_font_get_glyph_advance_for_direction
hb_font_get_glyph_advance_func_t
hb_font_get_glyph_advances_for_direction
hb_font_get_glyph_advances_func_t
hb_font_get_glyph_contour_point
hb_font_get_glyph_contour_point_for_origin
hb_font_get_glyph_contour_point_func_t
hb_font_get_glyph_extents
hb_font_get_glyph_extents_for_origin
hb_font_get_glyph_extents_func_t
hb_font_get_glyph_from_name
hb_font_get_glyph_from_name_func_t
hb_font_get_glyph_h_advance
hb_font_get_glyph_v_advance
hb_font_get_glyph_h_advance_func_t
hb_font_get_glyph_h_advances
hb_font_get_glyph_v_advances
hb_font_get_glyph_h_advances_func_t
hb_font_get_glyph_h_kerning
hb_font_get_glyph_kerning_for_direction
hb_font_get_glyph_h_kerning_func_t
hb_font_get_glyph_h_origin
hb_font_get_glyph_v_origin
hb_font_get_glyph_origin_for_direction
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_shape
hb_font_draw_glyph
hb_font_paint_glyph
hb_font_get_glyph_name_func_t
hb_font_get_glyph_origin_for_direction
hb_font_get_glyph_origin_func_t
hb_font_get_glyph_v_advance
hb_font_get_glyph_v_advance_func_t
hb_font_get_glyph_v_advances
hb_font_get_glyph_v_advances_func_t
hb_font_get_glyph_v_origin
hb_font_get_glyph_v_origin_func_t
hb_font_get_nominal_glyph
hb_font_get_nominal_glyph_func_t
hb_font_get_nominal_glyphs
hb_font_get_variation_glyph
hb_font_set_parent
hb_font_get_nominal_glyphs_func_t
hb_font_get_parent
hb_font_set_ppem
hb_font_get_ppem
hb_font_set_ptem
hb_font_get_ptem
hb_font_set_scale
hb_font_get_scale
hb_font_get_synthetic_bold
hb_font_set_synthetic_bold
hb_font_set_synthetic_slant
hb_font_get_synthetic_slant
hb_font_set_variations
hb_font_set_variation
HB_FONT_NO_VAR_NAMED_INSTANCE
hb_font_set_var_named_instance
hb_font_get_var_named_instance
hb_font_set_var_coords_design
hb_font_get_var_coords_design
hb_font_set_var_coords_normalized
hb_font_get_user_data
hb_font_get_variation_glyph
hb_font_get_variation_glyph_func_t
hb_font_get_var_coords_normalized
hb_font_glyph_from_string
hb_font_glyph_to_string
hb_font_get_serial
hb_font_changed
hb_font_is_immutable
hb_font_make_immutable
hb_font_reference
hb_font_set_face
hb_font_set_funcs
hb_font_set_funcs_data
hb_font_set_parent
hb_font_set_ppem
hb_font_set_ptem
hb_font_set_scale
hb_font_set_user_data
hb_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_funcs_create
hb_font_funcs_get_empty
hb_font_funcs_reference
hb_font_funcs_destroy
hb_font_funcs_set_user_data
hb_font_funcs_get_user_data
hb_font_funcs_make_immutable
hb_font_funcs_is_immutable
hb_font_get_glyph_contour_point_func_t
hb_font_funcs_set_glyph_contour_point_func
hb_font_get_glyph_extents_func_t
hb_font_funcs_set_glyph_extents_func
hb_font_get_glyph_from_name_func_t
hb_font_funcs_set_glyph_from_name_func
hb_font_get_glyph_advance_func_t
hb_font_get_glyph_h_advance_func_t
hb_font_funcs_set_glyph_h_advance_func
hb_font_get_glyph_v_advance_func_t
hb_font_funcs_set_glyph_v_advance_func
hb_font_get_glyph_advances_func_t
hb_font_get_glyph_h_advances_func_t
hb_font_funcs_set_glyph_h_advances_func
hb_font_get_glyph_v_advances_func_t
hb_font_funcs_set_glyph_v_advances_func
hb_font_get_glyph_kerning_func_t
hb_font_get_glyph_h_kerning_func_t
hb_font_funcs_set_glyph_h_kerning_func
hb_font_get_glyph_origin_func_t
hb_font_get_glyph_h_origin_func_t
hb_font_funcs_set_glyph_h_origin_func
hb_font_get_glyph_v_origin_func_t
hb_font_funcs_set_glyph_v_origin_func
hb_font_get_glyph_name_func_t
hb_font_funcs_set_glyph_name_func
hb_font_get_glyph_shape_func_t
hb_font_funcs_set_glyph_shape_func
hb_font_draw_glyph_func_t
hb_font_funcs_set_draw_glyph_func
hb_font_paint_glyph_func_t
hb_font_funcs_set_paint_glyph_func
hb_font_get_nominal_glyph_func_t
hb_font_funcs_set_nominal_glyph_func
hb_font_get_nominal_glyphs_func_t
hb_font_funcs_set_nominal_glyphs_func
hb_font_get_variation_glyph_func_t
hb_font_funcs_set_variation_glyph_func
hb_font_funcs_t
hb_font_t
hb_reference_table_func_t
hb_font_funcs_set_font_h_extents_func
hb_font_funcs_set_font_v_extents_func
hb_font_get_extents_for_direction
hb_font_get_font_extents_func_t
hb_font_get_font_h_extents_func_t
hb_font_funcs_set_font_h_extents_func
hb_font_get_font_v_extents_func_t
hb_font_funcs_set_font_v_extents_func
hb_font_get_h_extents
hb_font_get_v_extents
hb_font_get_extents_for_direction
hb_font_extents_t
hb_glyph_extents_t
<SUBSECTION Private>
hb_font_get_var_coords_design
hb_font_draw_glyph
</SECTION>
<SECTION>
@ -512,7 +379,6 @@ hb_ft_font_unlock_face
hb_ft_font_set_load_flags
hb_ft_font_get_load_flags
hb_ft_font_set_funcs
hb_ft_hb_font_changed
</SECTION>
<SECTION>
@ -544,33 +410,27 @@ hb_icu_script_to_script
<SECTION>
<FILE>hb-map</FILE>
hb_map_create
hb_map_allocation_successful
hb_map_copy
hb_map_clear
hb_map_get_empty
hb_map_reference
hb_map_destroy
hb_map_set_user_data
hb_map_get_user_data
hb_map_set
hb_map_get
hb_map_del
hb_map_has
hb_map_get_population
hb_map_is_empty
hb_map_is_equal
hb_map_hash
hb_map_update
hb_map_next
hb_map_keys
hb_map_values
HB_MAP_VALUE_INVALID
hb_map_allocation_successful
hb_map_clear
hb_map_create
hb_map_del
hb_map_destroy
hb_map_get
hb_map_get_empty
hb_map_get_population
hb_map_get_user_data
hb_map_has
hb_map_is_empty
hb_map_reference
hb_map_set
hb_map_set_user_data
hb_map_t
</SECTION>
<SECTION>
<FILE>hb-ot-color</FILE>
hb_color_t
HB_COLOR
hb_color_get_alpha
hb_color_get_blue
@ -580,19 +440,16 @@ hb_ot_color_glyph_get_layers
hb_ot_color_glyph_reference_png
hb_ot_color_glyph_reference_svg
hb_ot_color_has_layers
hb_ot_color_has_paint
hb_ot_color_glyph_has_paint
hb_ot_color_has_palettes
hb_ot_color_has_png
hb_ot_color_has_svg
hb_ot_color_layer_t
hb_ot_color_palette_color_get_name_id
hb_ot_color_palette_flags_t
hb_ot_color_palette_get_colors
hb_ot_color_palette_get_count
hb_ot_color_palette_get_flags
hb_ot_color_palette_get_name_id
hb_color_t
hb_ot_color_layer_t
hb_ot_color_palette_flags_t
</SECTION>
<SECTION>
@ -602,63 +459,25 @@ hb_ot_font_set_funcs
<SECTION>
<FILE>hb-ot-name</FILE>
hb_ot_name_id_t
HB_OT_NAME_ID_INVALID
hb_ot_name_entry_t
hb_ot_name_list_names
hb_ot_name_get_utf16
hb_ot_name_get_utf32
hb_ot_name_get_utf8
hb_ot_name_id_t
hb_ot_name_id_predefined_t
hb_ot_name_entry_t
</SECTION>
<SECTION>
<FILE>hb-ot-layout</FILE>
hb_ot_tag_to_language
hb_ot_tag_to_script
hb_ot_tags_from_script_and_language
hb_ot_tags_to_script_and_language
hb_ot_layout_collect_lookups
hb_ot_layout_collect_features
hb_ot_layout_feature_get_characters
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_horizontal_baseline_tag_for_script
hb_ot_layout_get_baseline
hb_ot_layout_get_baseline_with_fallback
hb_ot_layout_get_glyph_class
hb_ot_layout_get_glyphs_in_class
hb_ot_layout_get_ligature_carets
hb_ot_layout_get_size_params
hb_ot_layout_has_glyph_classes
hb_ot_layout_has_positioning
hb_ot_layout_has_substitution
hb_ot_layout_language_find_feature
hb_ot_layout_language_get_feature_indexes
hb_ot_layout_language_get_feature_tags
hb_ot_layout_language_get_required_feature
hb_ot_layout_lookup_collect_glyphs
hb_ot_layout_lookup_get_glyph_alternates
hb_ot_layout_lookup_get_optical_bound
hb_ot_layout_lookup_substitute_closure
hb_ot_layout_lookups_substitute_closure
hb_ot_layout_lookup_would_substitute
hb_ot_layout_script_find_language
hb_ot_layout_script_get_language_tags
hb_ot_layout_script_select_language
hb_ot_layout_script_select_language2
hb_ot_layout_table_find_feature_variations
hb_ot_layout_table_get_feature_tags
hb_ot_layout_table_get_script_tags
hb_ot_layout_table_get_lookup_count
hb_ot_layout_table_select_script
hb_ot_shape_plan_collect_lookups
hb_ot_layout_language_get_required_feature_index
HB_OT_MAX_TAGS_PER_LANGUAGE
HB_OT_MAX_TAGS_PER_SCRIPT
HB_OT_TAG_DEFAULT_LANGUAGE
HB_OT_TAG_DEFAULT_SCRIPT
hb_ot_tag_to_language
hb_ot_tag_to_script
hb_ot_tags_from_script_and_language
hb_ot_tags_to_script_and_language
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX
HB_OT_LAYOUT_NO_FEATURE_INDEX
HB_OT_LAYOUT_NO_SCRIPT_INDEX
@ -669,46 +488,83 @@ 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
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
hb_ot_layout_get_size_params
hb_ot_layout_glyph_class_t
hb_ot_layout_has_glyph_classes
hb_ot_layout_has_positioning
hb_ot_layout_has_substitution
hb_ot_layout_language_find_feature
hb_ot_layout_language_get_feature_indexes
hb_ot_layout_language_get_feature_tags
hb_ot_layout_language_get_required_feature
hb_ot_layout_lookup_collect_glyphs
hb_ot_layout_lookup_get_glyph_alternates
hb_ot_layout_lookup_substitute_closure
hb_ot_layout_lookups_substitute_closure
hb_ot_layout_lookup_would_substitute
hb_ot_layout_script_find_language
hb_ot_layout_script_get_language_tags
hb_ot_layout_script_select_language
hb_ot_layout_table_find_feature_variations
hb_ot_layout_table_get_feature_tags
hb_ot_layout_table_get_script_tags
hb_ot_layout_table_get_lookup_count
hb_ot_layout_table_select_script
hb_ot_shape_plan_collect_lookups
hb_ot_layout_language_get_required_feature_index
<SUBSECTION Private>
Xhb_ot_layout_lookup_enumerate_sequences
Xhb_ot_layout_lookup_position
Xhb_ot_layout_lookup_substitute
hb_ot_layout_glyph_sequence_t
hb_ot_layout_glyph_sequence_func_t
</SECTION>
<SECTION>
<FILE>hb-ot-math</FILE>
HB_OT_TAG_MATH
HB_OT_MATH_SCRIPT
hb_ot_math_constant_t
hb_ot_math_kern_t
hb_ot_math_glyph_variant_t
hb_ot_math_glyph_part_flags_t
hb_ot_math_glyph_part_t
hb_ot_math_has_data
hb_ot_math_get_constant
hb_ot_math_get_glyph_italics_correction
hb_ot_math_get_glyph_top_accent_attachment
hb_ot_math_get_glyph_kerning
hb_ot_math_get_glyph_kernings
hb_ot_math_is_glyph_extended_shape
hb_ot_math_get_glyph_variants
hb_ot_math_get_min_connector_overlap
hb_ot_math_get_glyph_assembly
HB_OT_TAG_MATH
HB_OT_TAG_MATH_SCRIPT
hb_ot_math_constant_t
hb_ot_math_kern_t
hb_ot_math_kern_entry_t
hb_ot_math_glyph_variant_t
hb_ot_math_glyph_part_flags_t
hb_ot_math_glyph_part_t
</SECTION>
<SECTION>
<FILE>hb-ot-meta</FILE>
hb_ot_meta_tag_t
hb_ot_meta_get_entry_tags
hb_ot_meta_reference_entry
hb_ot_meta_tag_t
</SECTION>
<SECTION>
<FILE>hb-ot-metrics</FILE>
hb_ot_metrics_tag_t
hb_ot_metrics_get_position
hb_ot_metrics_get_position_with_fallback
hb_ot_metrics_get_variation
hb_ot_metrics_get_x_variation
hb_ot_metrics_get_y_variation
hb_ot_metrics_tag_t
</SECTION>
<SECTION>
@ -718,7 +574,14 @@ hb_ot_shape_glyphs_closure
<SECTION>
<FILE>hb-ot-var</FILE>
HB_OT_TAG_VAR_AXIS_ITALIC
HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
HB_OT_TAG_VAR_AXIS_SLANT
HB_OT_TAG_VAR_AXIS_WEIGHT
HB_OT_TAG_VAR_AXIS_WIDTH
hb_ot_var_has_data
hb_ot_var_axis_flags_t
hb_ot_var_axis_info_t
hb_ot_var_find_axis_info
hb_ot_var_get_axis_count
hb_ot_var_get_axis_infos
@ -728,60 +591,46 @@ hb_ot_var_named_instance_get_postscript_name_id
hb_ot_var_named_instance_get_design_coords
hb_ot_var_normalize_variations
hb_ot_var_normalize_coords
HB_OT_TAG_VAR_AXIS_ITALIC
HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
HB_OT_TAG_VAR_AXIS_SLANT
HB_OT_TAG_VAR_AXIS_WEIGHT
HB_OT_TAG_VAR_AXIS_WIDTH
hb_ot_var_axis_flags_t
hb_ot_var_axis_info_t
</SECTION>
<SECTION>
<FILE>hb-set</FILE>
hb_set_create
hb_set_allocation_successful
hb_set_copy
hb_set_get_empty
hb_set_reference
hb_set_destroy
hb_set_set_user_data
hb_set_get_user_data
hb_set_clear
hb_set_set
hb_set_has
HB_SET_VALUE_INVALID
hb_set_add
hb_set_add_range
hb_set_add_sorted_array
hb_set_allocation_successful
hb_set_clear
hb_set_create
hb_set_del
hb_set_del_range
hb_set_destroy
hb_set_get_empty
hb_set_get_max
hb_set_get_min
hb_set_get_population
hb_set_is_empty
hb_set_hash
hb_set_subtract
hb_set_get_user_data
hb_set_has
hb_set_intersect
hb_set_union
hb_set_symmetric_difference
hb_set_invert
hb_set_is_inverted
hb_set_is_empty
hb_set_is_equal
hb_set_is_subset
hb_set_next
hb_set_next_range
hb_set_next_many
hb_set_previous
hb_set_previous_range
HB_SET_VALUE_INVALID
hb_set_reference
hb_set_set
hb_set_set_user_data
hb_set_subtract
hb_set_symmetric_difference
hb_set_t
hb_set_union
</SECTION>
<SECTION>
<FILE>hb-shape</FILE>
hb_shape
hb_shape_full
hb_shape_justify
hb_shape_list_shapers
</SECTION>
@ -791,50 +640,50 @@ hb_shape_plan_create
hb_shape_plan_create_cached
hb_shape_plan_create2
hb_shape_plan_create_cached2
hb_shape_plan_get_empty
hb_shape_plan_reference
hb_shape_plan_destroy
hb_shape_plan_set_user_data
hb_shape_plan_get_user_data
hb_shape_plan_execute
hb_shape_plan_get_empty
hb_shape_plan_get_shaper
hb_shape_plan_get_user_data
hb_shape_plan_reference
hb_shape_plan_set_user_data
hb_shape_plan_t
</SECTION>
<SECTION>
<FILE>hb-unicode</FILE>
hb_unicode_general_category
hb_unicode_combining_class
hb_unicode_mirroring
hb_unicode_script
hb_unicode_compose
hb_unicode_decompose
hb_unicode_funcs_create
hb_unicode_funcs_get_empty
hb_unicode_funcs_reference
hb_unicode_funcs_destroy
hb_unicode_funcs_set_user_data
hb_unicode_funcs_get_user_data
hb_unicode_funcs_make_immutable
hb_unicode_funcs_is_immutable
hb_unicode_funcs_get_default
hb_unicode_funcs_get_parent
hb_unicode_general_category_func_t
hb_unicode_funcs_set_general_category_func
hb_unicode_combining_class_func_t
hb_unicode_funcs_set_combining_class_func
hb_unicode_mirroring_func_t
hb_unicode_funcs_set_mirroring_func
hb_unicode_script_func_t
hb_unicode_funcs_set_script_func
hb_unicode_compose_func_t
hb_unicode_funcs_set_compose_func
hb_unicode_decompose_func_t
hb_unicode_funcs_set_decompose_func
HB_UNICODE_MAX
hb_unicode_combining_class
hb_unicode_combining_class_func_t
hb_unicode_combining_class_t
hb_unicode_general_category_t
hb_unicode_compose
hb_unicode_compose_func_t
hb_unicode_decompose
hb_unicode_decompose_func_t
hb_unicode_funcs_create
hb_unicode_funcs_destroy
hb_unicode_funcs_get_default
hb_unicode_funcs_get_empty
hb_unicode_funcs_get_parent
hb_unicode_funcs_get_user_data
hb_unicode_funcs_is_immutable
hb_unicode_funcs_make_immutable
hb_unicode_funcs_reference
hb_unicode_funcs_set_combining_class_func
hb_unicode_funcs_set_compose_func
hb_unicode_funcs_set_decompose_func
hb_unicode_funcs_set_general_category_func
hb_unicode_funcs_set_mirroring_func
hb_unicode_funcs_set_script_func
hb_unicode_funcs_set_user_data
hb_unicode_funcs_t
hb_unicode_general_category
hb_unicode_general_category_func_t
hb_unicode_general_category_t
hb_unicode_mirroring
hb_unicode_mirroring_func_t
hb_unicode_script
hb_unicode_script_func_t
</SECTION>
<SECTION>
@ -846,68 +695,11 @@ hb_uniscribe_font_get_logfontw
<SECTION>
<FILE>hb-version</FILE>
HB_VERSION_ATLEAST
hb_version
hb_version_atleast
hb_version_string
HB_VERSION_MAJOR
HB_VERSION_MICRO
HB_VERSION_MINOR
HB_VERSION_STRING
</SECTION>
<SECTION>
<FILE>hb-style</FILE>
hb_style_tag_t
hb_style_get_value
</SECTION>
<SECTION>
<FILE>hb-subset</FILE>
hb_subset_input_create_or_fail
hb_subset_input_reference
hb_subset_input_destroy
hb_subset_input_set_user_data
hb_subset_input_get_user_data
hb_subset_input_keep_everything
hb_subset_input_set_flags
hb_subset_input_get_flags
hb_subset_input_unicode_set
hb_subset_input_glyph_set
hb_subset_input_set
hb_subset_input_pin_axis_location
hb_subset_input_pin_axis_to_default
hb_subset_or_fail
hb_subset_plan_create_or_fail
hb_subset_plan_reference
hb_subset_plan_destroy
hb_subset_plan_set_user_data
hb_subset_plan_get_user_data
hb_subset_plan_execute_or_fail
hb_subset_plan_unicode_to_old_glyph_mapping
hb_subset_plan_new_to_old_glyph_mapping
hb_subset_plan_old_to_new_glyph_mapping
hb_subset_preprocess
hb_subset_flags_t
hb_subset_input_t
hb_subset_sets_t
hb_subset_plan_t
<SUBSECTION Private>
hb_link_t
hb_object_t
hb_subset_repack_or_fail
hb_subset_input_override_name_table
</SECTION>
<SECTION>
<FILE>hb-cairo</FILE>
hb_cairo_font_face_create_for_font
hb_cairo_font_face_get_font
hb_cairo_font_face_create_for_face
hb_cairo_font_face_get_face
hb_cairo_font_init_func_t
hb_cairo_font_face_set_font_init_func
hb_cairo_scaled_font_get_font
hb_cairo_font_face_set_scale_factor
hb_cairo_font_face_get_scale_factor
hb_cairo_glyphs_from_buffer
hb_version
hb_version_atleast
hb_version_string
</SECTION>

View File

@ -1,3 +1,8 @@
if build_machine.system() == 'windows'
message('Skipping gtk-doc while building on Windows')
subdir_done()
endif
if not find_program('gtkdoc-scan', required: get_option('docs')).found()
message('Not building documentation as gtk-doc was not found')
subdir_done()
@ -36,7 +41,6 @@ html_images = [
]
ignore_headers = [
'hb-features.h',
'hb-gobject.h',
'hb-gobject-enums.h',
'hb-gobject-enums-tmp.h',
@ -45,11 +49,11 @@ ignore_headers = [
gnome.gtkdoc('harfbuzz',
main_sgml: 'harfbuzz-docs.xml',
src_dir: [meson.current_source_dir() / '..' / 'src',
meson.current_build_dir() / '..' / 'src',
src_dir: [join_paths(meson.current_source_dir(), '../src'),
join_paths(meson.current_build_dir(), '../src'),
],
scan_args: ['--deprecated-guards=HB_DISABLE_DEPRECATED',
'--ignore-decorators=HB_EXTERN|HB_DEPRECATED|HB_DEPRECATED_FOR()',
'--ignore-decorators=HB_EXTERN|HB_DEPRECATED',
],
mkdb_args: ['--source-suffixes=h,cc',
'--xml-mode',
@ -59,6 +63,4 @@ gnome.gtkdoc('harfbuzz',
html_assets: html_images,
ignore_headers: ignore_headers,
dependencies: [libharfbuzz_dep],
install: true,
check: get_option('doc_tests'),
)
install: true)

View File

@ -1,294 +0,0 @@
# Introduction
Several tables in the opentype format are formed internally by a graph of subtables. Parent node's
reference their children through the use of positive offsets, which are typically 16 bits wide.
Since offsets are always positive this forms a directed acyclic graph. For storage in the font file
the graph must be given a topological ordering and then the subtables packed in serial according to
that ordering. Since 16 bit offsets have a maximum value of 65,535 if the distance between a parent
subtable and a child is more then 65,535 bytes then it's not possible for the offset to encode that
edge.
For many fonts with complex layout rules (such as Arabic) it's not unusual for the tables containing
layout rules ([GSUB/GPOS](https://docs.microsoft.com/en-us/typography/opentype/spec/gsub)) to be
larger than 65kb. As a result these types of fonts are susceptible to offset overflows when
serializing to the binary font format.
Offset overflows can happen for a variety of reasons and require different strategies to resolve:
* Simple overflows can often be resolved with a different topological ordering.
* If a subtable has many parents this can result in the link from furthest parent(s)
being at risk for overflows. In these cases it's possible to duplicate the shared subtable which
allows it to be placed closer to it's parent.
* If subtables exist which are themselves larger than 65kb it's not possible for any offsets to point
past them. In these cases the subtable can usually be split into two smaller subtables to allow
for more flexibility in the ordering.
* In GSUB/GPOS overflows from Lookup subtables can be resolved by changing the Lookup to an extension
lookup which uses a 32 bit offset instead of 16 bit offset.
In general there isn't a simple solution to produce an optimal topological ordering for a given graph.
Finding an ordering which doesn't overflow is a NP hard problem. Existing solutions use heuristics
which attempt a combination of the above strategies to attempt to find a non-overflowing configuration.
The harfbuzz subsetting library
[includes a repacking algorithm](https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-repacker.hh)
which is used to resolve offset overflows that are present in the subsetted tables it produces. This
document provides a deep dive into how the harfbuzz repacking algorithm works.
Other implementations exist, such as in
[fontTools](https://github.com/fonttools/fonttools/blob/7af43123d49c188fcef4e540fa94796b3b44e858/Lib/fontTools/ttLib/tables/otBase.py#L72), however these are not covered in this document.
# Foundations
There's four key pieces to the harfbuzz approach:
* Subtable Graph: a table's internal structure is abstracted out into a lightweight graph
representation where each subtable is a node and each offset forms an edge. The nodes only need
to know how many bytes the corresponding subtable occupies. This lightweight representation can
be easily modified to test new ordering's and strategies as the repacking algorithm iterates.
* [Topological sorting algorithm](https://en.wikipedia.org/wiki/Topological_sorting): an algorithm
which given a graph gives a linear sorting of the nodes such that all offsets will be positive.
* Overflow check: given a graph and a topological sorting it checks if there will be any overflows
in any of the offsets. If there are overflows it returns a list of (parent, child) tuples that
will overflow. Since the graph has information on the size of each subtable it's straightforward
to calculate the final position of each subtable and then check if any offsets to it will
overflow.
* Content Aware Preprocessing: if the overflow resolver is aware of the format of the underlying
tables (eg. GSUB, GPOS) then in some cases preprocessing can be done to increase the chance of
successfully packing the graph. For example for GSUB and GPOS we can preprocess the graph and
promote lookups to extension lookups (upgrades a 16 bit offset to 32 bits) or split large lookup
subtables into two or more pieces.
* Offset resolution strategies: given a particular occurrence of an overflow these strategies
modify the graph to attempt to resolve the overflow.
# High Level Algorithm
```
def repack(graph):
graph.topological_sort()
if (graph.will_overflow())
preprocess(graph)
assign_spaces(graph)
graph.topological_sort()
while (overflows = graph.will_overflow()):
for overflow in overflows:
apply_offset_resolution_strategy (overflow, graph)
graph.topological_sort()
```
The actual code for this processing loop can be found in the function hb_resolve_overflows () of
[hb-repacker.hh](https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-repacker.hh).
# Topological Sorting Algorithms
The harfbuzz repacker uses two different algorithms for topological sorting:
* [Kahn's Algorithm](https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm)
* Sorting by shortest distance
Kahn's algorithm is approximately twice as fast as the shortest distance sort so that is attempted
first (only on the first topological sort). If it fails to eliminate overflows then shortest distance
sort will be used for all subsequent topological sorting operations.
## Shortest Distance Sort
This algorithm orders the nodes based on total distance to each node. Nodes with a shorter distance
are ordered first.
The "weight" of an edge is the sum of the size of the sub-table being pointed to plus 2^16 for a 16 bit
offset and 2^32 for a 32 bit offset.
The distance of a node is the sum of all weights along the shortest path from the root to that node
plus a priority modifier (used to change where nodes are placed by moving increasing or
decreasing the effective distance). Ties between nodes with the same distance are broken based
on the order of the offset in the sub table bytes.
The shortest distance to each node is determined using
[Djikstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm). Then the topological
ordering is produce by applying a modified version of Kahn's algorithm that uses a priority queue
based on the shortest distance to each node.
## Optimizing the Sorting
The topological sorting operation is the core of the repacker and is run on each iteration so it needs
to be as fast as possible. There's a few things that are done to speed up subsequent sorting
operations:
* The number of incoming edges to each node is cached. This is required by the Kahn's algorithm
portion of both sorts. Where possible when the graph is modified we manually update the cached
edge counts of affected nodes.
* The distance to each node is cached. Where possible when the graph is modified we manually update
the cached distances of any affected nodes.
Caching these values allows the repacker to avoid recalculating them for the full graph on each
iteration.
The other important factor to speed is a fast priority queue which is a core datastructure to
the topological sorting algorithm. Currently a basic heap based queue is used. Heap based queue's
don't support fast priority decreases, but that can be worked around by just adding redundant entries
to the priority queue and filtering the older ones out when poppping off entries. This is based
on the recommendations in
[a study of the practical performance of priority queues in Dijkstra's algorithm](https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf)
## Special Handling of 32 bit Offsets
If a graph contains multiple 32 bit offsets then the shortest distance sorting will be likely be
suboptimal. For example consider the case where a graph contains two 32 bit offsets that each point
to a subgraph which are not connected to each other. The shortest distance sort will interleave the
subtables of the two subgraphs, potentially resulting in overflows. Since each of these subgraphs are
independent of each other, and 32 bit offsets can point extremely long distances a better strategy is
to pack the first subgraph in it's entirety and then have the second subgraph packed after with the 32
bit offset pointing over the first subgraph. For example given the graph:
```
a--- b -- d -- f
\
\_ c -- e -- g
```
Where the links from a to b and a to c are 32 bit offsets, the shortest distance sort would be:
```
a, b, c, d, e, f, g
```
If nodes d and e have a combined size greater than 65kb then the offset from d to f will overflow.
A better ordering is:
```
a, b, d, f, c, e, g
```
The ability for 32 bit offsets to point long distances is utilized to jump over the subgraph of
b which gives the remaining 16 bit offsets a better chance of not overflowing.
The above is an ideal situation where the subgraphs are disconnected from each other, in practice
this is often not this case. So this idea can be generalized as follows:
If there is a subgraph that is only reachable from one or more 32 bit offsets, then:
* That subgraph can be treated as an independent unit and all nodes of the subgraph packed in isolation
from the rest of the graph.
* In a table that occupies less than 4gb of space (in practice all fonts), that packed independent
subgraph can be placed anywhere after the parent nodes without overflowing the 32 bit offsets from
the parent nodes.
The sorting algorithm incorporates this via a "space" modifier that can be applied to nodes in the
graph. By default all nodes are treated as being in space zero. If a node is given a non-zero space, n,
then the computed distance to the node will be modified by adding `n * 2^32`. This will cause that
node and it's descendants to be packed between all nodes in space n-1 and space n+1. Resulting in a
topological sort like:
```
| space 0 subtables | space 1 subtables | .... | space n subtables |
```
The assign_spaces() step in the high level algorithm is responsible for identifying independent
subgraphs and assigning unique spaces to each one. More information on the space assignment can be
found in the next section.
# Graph Preprocessing
For certain table types we can preprocess and modify the graph structure to reduce the occurences
of overflows. Currently the repacker implements preprocessing only for GPOS and GSUB tables.
## GSUB/GPOS Table Splitting
The GSUB/GPOS preprocessor scans each lookup subtable and determines if the subtable's children are
so large that no overflow resolution is possible (for example a single subtable that exceeds 65kb
cannot be pointed over). When such cases are detected table splitting is invoked:
* The subtable is first analyzed to determine the smallest number of split points that will allow
for successful offset overflow resolution.
* Then the subtable in the graph representation is modified to actually perform the split at the
previously computed split points. At a high level splits are done by inserting new subtables
which contain a subset of the data of the original subtable and then shrinking the original subtable.
Table splitting must be aware of the underlying format of each subtable type and thus needs custom
code for each subtable type. Currently subtable splitting is only supported for GPOS subtable types.
## GSUB/GPOS Extension Lookup Promotion
In GSUB/GPOS tables lookups can be regular lookups which use 16 bit offsets to the children subtables
or extension lookups which use 32 bit offsets to the children subtables. If the sub graph of all
regular lookups is too large then it can be difficult to find an overflow free configuration. This
can be remedied by promoting one or more regular lookups to extension lookups.
During preprocessing the graph is scanned to determine the size of the subgraph of regular lookups.
If the graph is found to be too big then the analysis finds a set of lookups to promote to reduce
the subgraph size. Lastly the graph is modified to convert those lookups to extension lookups.
# Offset Resolution Strategies
## Space Assignment
The goal of space assignment is to find connected subgraphs that are only reachable via 32 bit offsets
and then assign each such subgraph to a unique non-zero space. The algorithm is roughly:
1. Collect the set, `S`, of nodes that are children of 32 bit offsets.
2. Do a directed traversal from each node in `S` and collect all encountered nodes into set `T`.
Mark all nodes in the graph that are not in `T` as being in space 0.
3. Set `next_space = 1`.
4. While set `S` is not empty:
a. Pick a node `n` in set `S` then perform an undirected graph traversal and find the set `Q` of
nodes that are reachable from `n`.
b. During traversal if a node, `m`, has a edge to a node in space 0 then `m` must be duplicated
to disconnect it from space 0.
d. Remove all nodes in `Q` from `S` and assign all nodes in `Q` to `next_space`.
c. Increment `next_space` by one.
## Manual Iterative Resolutions
For each overflow in each iteration the algorithm will attempt to apply offset overflow resolution
strategies to eliminate the overflow. The type of strategy applied is dependent on the characteristics
of the overflowing link:
* If the overflowing offset is inside a space other than space 0 and the subgraph space has more
than one 32 bit offset pointing into the subgraph then subdivide the space by moving subgraph
from one of the 32 bit offsets into a new space via the duplication of shared nodes.
* If the overflowing offset is pointing to a subtable with more than one incoming edge: duplicate
the node so that the overflowing offset is pointing at it's own copy of that node.
* Otherwise, attempt to move the child subtable closer to it's parent. This is accomplished by
raising the priority of all children of the parent. Next time the topological sort is run the
children will be ordered closer to the parent.
# Test Cases
The harfbuzz repacker has tests defined using generic graphs: https://github.com/harfbuzz/harfbuzz/blob/main/src/test-repacker.cc
# Future Improvements
Currently for GPOS tables the repacker implementation is sufficient to handle both subsetting and the
general case of font compilation repacking. However for GSUB the repacker is only sufficient for
subsetting related overflows. To enable general case repacking of GSUB, support for splitting of
GSUB subtables will need to be added. Other table types such as COLRv1 shouldn't require table
splitting due to the wide use of 24 bit offsets throughout the table.
Beyond subtable splitting there are a couple of "nice to have" improvements, but these are not required
to support the general case:
* Extension demotion: currently extension promotion is supported but in some cases if the non-extension
subgraph is underfilled then packed size can be reduced by demoting extension lookups back to regular
lookups.
* Currently only children nodes are moved to resolve offsets. However, in many cases moving a parent
node closer to it's children will have less impact on the size of other offsets. Thus the algorithm
should use a heuristic (based on parent and child subtable sizes) to decide if the children's
priority should be increased or the parent's priority decreased.

View File

@ -1,178 +0,0 @@
# Introduction
In hb-subset serialization is the process of writing the subsetted font
tables out to actual bytes in the final format. All serialization works
through an object called the serialize context
([hb_serialize_context_t](https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-serialize.hh)).
Internally the serialize context holds a fixed size memory buffer. For simple
tables the final bytes are written into the buffer sequentially to produce
the final serialized bytes.
## Simple Tables
Simple tables are tables that do not use offset graphs.
To write a struct into the serialization context, first you call an
allocation method on the context which requests a writable array of bytes of
a fixed size. If the requested array will not exceed the bounds of the fixed
buffer the serializer will return a pointer to the next unwritten portion
of the buffer. Then the struct is cast onto the returned pointer and values
are written to the structs fields.
Internally the serialization context ends up looking like:
```
+-------+-------+-----+-------+--------------+
| Obj 1 | Obj 2 | ... | Obj N | Unused Space |
+-------+-------+-----+-------+--------------+
```
Here Obj N, is the object currently being written.
## Complex Tables
Complex tables are made up of graphs of objects, where offset's are used
to form the edges of the graphs. Each object is a continuous slice of bytes
that contains zero or more offsets pointing to more objects.
In this case the serialization buffer has a different layout:
```
|- in progress objects -| |--- packed objects --|
+-----------+-----------+--------------+-------+-----+-------+
| Obj n+2 | Obj n+1 | Unused Space | Obj n | ... | Obj 0 |
+-----------+-----------+--------------+-------+-----+-------+
|-----------------------> <---------------------|
```
The buffer holds two stacks:
1. In progress objects are held in a stack starting from the start of buffer
that grows towards the end of the buffer.
2. Packed objects are held in a stack that starts at the end of the buffer
and grows towards the start of the buffer.
Once the object on the top of the in progress stack is finished being written
its bytes are popped from the in progress stack and copied to the top of
the packed objects stack. In the example above, finalizing Obj n+1
would result in the following state:
```
+---------+--------------+---------+-------+-----+-------+
| Obj n+2 | Unused Space | Obj n+1 | Obj n | ... | Obj 0 |
+---------+--------------+---------+-------+-----+-------+
```
Each packed object is associated with an ID, it's zero based position in the packed
objects stack. In this example Obj 0, would have an ID of 0.
During serialization offsets that link from one object to another are stored
using object ids. The serialize context maintains a list of links between
objects. Each link records the parent object id, the child object id, the position
of the offset field within the parent object, and the width of the offset.
Links are always added to the current in progress object and you can only link too
objects that have been packed and thus have an ID.
### Object De-duplication
An important optimization in packing offset graphs is de-duplicating equivalent objects. If you
have two or more parent objects that point to child objects that are equivalent then you only need
to encode the child once and can have the parents point to the same child. This can significantly
reduce the final size of a serialized graph.
During packing of an inprogress object the serialization context checks if any existing packed
objects are equivalent to the object being packed. Here equivalence means the object has the
exact same bytes and all of it's links are equivalent. If an equivalent object is found the
in progress object is discarded and not copied to the packed object stack. The object id of
the equivalent object is instead returned. Thus parent objects will then link to the existing
equivalent object.
To find equivalent objects the serialization context maintains a hashmap from object to the canonical
object id.
### Link Resolution
Once all objects have been packed the next step is to assign actual values to all of the offset
fields. Prior to this point all links in the graph have been recorded using object id's. For each
link the resolver computes the offset between the parent and child and writes the offset into
the serialization buffer at the appropriate location.
### Offset Overflow Resolution
If during link resolution the resolver finds that an offsets value would exceed what can be encoded
in that offset field link resolution is aborted and the offset overflow resolver is invoked.
That process is documented [here](reapcker.md).
### Example of Complex Serialization
If we wanted to serialize the following graph:
```
a--b--d
\ /
c
```
Serializer would be called like this:
```c++
hb_serialize_context_t ctx;
struct root {
char name;
Offset16To<child> child_1;
Offset16To<child> child_2;
}
struct child {
char name;
Offset16To<char> leaf;
}
// Object A.
ctx->push();
root* a = ctx->start_embed<root> ();
ctx->extend_min (a);
a->name = 'a';
// Object B.
ctx->push();
child* b = ctx->start_embed<child> ();
ctx->extend_min (b);
b->name = 'b';
// Object D.
ctx->push();
*ctx->allocate_size<char> (1) = 'd';
unsigned d_id = ctx->pop_pack ();
ctx->add_link (b->leaf, d_id);
unsigned b_id = ctx->pop_pack ();
// Object C
ctx->push();
child* c = ctx->start_embed<child> ();
ctx->extend_min (c);
c->name = 'c';
// Object D.
ctx->push();
*ctx->allocate_size<char> (1) = 'd';
d_id = ctx->pop_pack (); // Serializer will automatically de-dup this with the previous 'd'
ctx->add_link (c->leaf, d_id);
unsigned c_id = ctx->pop_pack ();
// Object A's links:
ctx->add_link (a->child_1, b_id);
ctx->add_link (a->child_2, c_id);
ctx->pop_pack ();
ctx->end_serialize ();
```

View File

@ -1,228 +0,0 @@
# Introduction
Subset preprocessing is a mechanism which can significantly speed up font subsetting operations.
It works by prepopulating datastructures from the source font which can be used in later subsetting
operations to more quickly produce the subset. Preprocessing is useful in cases where multiple subsets
will be cut from the same source font.
# Usage
```c++
hb_face_t* preprocessed = hb_subset_preprocess (source_face);
...
hb_face_t* subset = hb_subset_or_fail (preprocessed, subset_input);
```
# Additional Details
* A subset produced from a preprocessed face should be identical to a subset produced from only the
original face. The preprocessor does not change the functionality of the subsetter, just speeds
things up.
* The preprocessing operation may take longer than the time it takes to produce a subset from the
source font. Thus the main performance gains are made when a preprocessed face is reused for
multiple subsetting operations.
* Currently the largest performance gains are seen when using a preprocessed face for CFF subsetting.
* The preprocessed face may contain references to the memory backing the source face. If this memory
is fully owned by a harfbuzz hb_blob_t* then it will automatically be kept alive for the lifetime
of the preprocessed face. However, if this memory is not fully owned by a harfbuzz hb_blob_t* then
it is necessary to ensure that the memory is kept alive for the lifetime of the preprocessed face.
# Performance Improvements
Here is the performance difference of producing a subset with a preprocessed face vs producing
a subset with the source face:
Benchmark | Delta Time (%)
----------|-----------------
BM_subset/subset_glyphs/Roboto-Regular.ttf/10_median|-56%
BM_subset/subset_glyphs/Roboto-Regular.ttf/64_median|-33%
BM_subset/subset_glyphs/Roboto-Regular.ttf/512_median|-28%
BM_subset/subset_glyphs/Roboto-Regular.ttf/1000_median|-11%
BM_subset/subset_glyphs/Roboto-Regular.ttf/nohinting/10_median|-56%
BM_subset/subset_glyphs/Roboto-Regular.ttf/nohinting/64_median|-33%
BM_subset/subset_glyphs/Roboto-Regular.ttf/nohinting/512_median|-21%
BM_subset/subset_glyphs/Roboto-Regular.ttf/nohinting/1000_median|-9%
BM_subset/subset_glyphs/Amiri-Regular.ttf/10_median|-67%
BM_subset/subset_glyphs/Amiri-Regular.ttf/64_median|-48%
BM_subset/subset_glyphs/Amiri-Regular.ttf/512_median|-21%
BM_subset/subset_glyphs/Amiri-Regular.ttf/4096_median|-9%
BM_subset/subset_glyphs/Amiri-Regular.ttf/nohinting/10_median|-66%
BM_subset/subset_glyphs/Amiri-Regular.ttf/nohinting/64_median|-50%
BM_subset/subset_glyphs/Amiri-Regular.ttf/nohinting/512_median|-8%
BM_subset/subset_glyphs/Amiri-Regular.ttf/nohinting/4096_median|-9%
BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/10_median|-85%
BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/64_median|-71%
BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/512_median|-3%
BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/1400_median|4%
BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/nohinting/10_median|-84%
BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/nohinting/64_median|-72%
BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/nohinting/512_median|0%
BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/nohinting/1400_median|0%
BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/10_median|-30%
BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/64_median|-24%
BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/512_median|-3%
BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/1000_median|-3%
BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/nohinting/10_median|-30%
BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/nohinting/64_median|-24%
BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/nohinting/512_median|-3%
BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/nohinting/1000_median|-5%
BM_subset/subset_glyphs/Mplus1p-Regular.ttf/10_median|-96%
BM_subset/subset_glyphs/Mplus1p-Regular.ttf/64_median|-90%
BM_subset/subset_glyphs/Mplus1p-Regular.ttf/512_median|-74%
BM_subset/subset_glyphs/Mplus1p-Regular.ttf/4096_median|-25%
BM_subset/subset_glyphs/Mplus1p-Regular.ttf/10000_median|-23%
BM_subset/subset_glyphs/Mplus1p-Regular.ttf/nohinting/10_median|-95%
BM_subset/subset_glyphs/Mplus1p-Regular.ttf/nohinting/64_median|-90%
BM_subset/subset_glyphs/Mplus1p-Regular.ttf/nohinting/512_median|-73%
BM_subset/subset_glyphs/Mplus1p-Regular.ttf/nohinting/4096_median|-24%
BM_subset/subset_glyphs/Mplus1p-Regular.ttf/nohinting/10000_median|-11%
BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/10_median|-84%
BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/64_median|-77%
BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/512_median|-70%
BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/4096_median|-80%
BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/10000_median|-86%
BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/nohinting/10_median|-84%
BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/nohinting/64_median|-78%
BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/nohinting/512_median|-71%
BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/nohinting/4096_median|-86%
BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/nohinting/10000_median|-88%
BM_subset/subset_glyphs/SourceSansPro-Regular.otf/10_median|-59%
BM_subset/subset_glyphs/SourceSansPro-Regular.otf/64_median|-55%
BM_subset/subset_glyphs/SourceSansPro-Regular.otf/512_median|-67%
BM_subset/subset_glyphs/SourceSansPro-Regular.otf/2000_median|-68%
BM_subset/subset_glyphs/SourceSansPro-Regular.otf/nohinting/10_median|-60%
BM_subset/subset_glyphs/SourceSansPro-Regular.otf/nohinting/64_median|-58%
BM_subset/subset_glyphs/SourceSansPro-Regular.otf/nohinting/512_median|-72%
BM_subset/subset_glyphs/SourceSansPro-Regular.otf/nohinting/2000_median|-71%
BM_subset/subset_glyphs/AdobeVFPrototype.otf/10_median|-70%
BM_subset/subset_glyphs/AdobeVFPrototype.otf/64_median|-64%
BM_subset/subset_glyphs/AdobeVFPrototype.otf/300_median|-73%
BM_subset/subset_glyphs/AdobeVFPrototype.otf/nohinting/10_median|-71%
BM_subset/subset_glyphs/AdobeVFPrototype.otf/nohinting/64_median|-68%
BM_subset/subset_glyphs/AdobeVFPrototype.otf/nohinting/300_median|-72%
BM_subset/subset_glyphs/MPLUS1-Variable.ttf/10_median|-90%
BM_subset/subset_glyphs/MPLUS1-Variable.ttf/64_median|-82%
BM_subset/subset_glyphs/MPLUS1-Variable.ttf/512_median|-31%
BM_subset/subset_glyphs/MPLUS1-Variable.ttf/4096_median|-9%
BM_subset/subset_glyphs/MPLUS1-Variable.ttf/6000_median|-22%
BM_subset/subset_glyphs/MPLUS1-Variable.ttf/nohinting/10_median|-88%
BM_subset/subset_glyphs/MPLUS1-Variable.ttf/nohinting/64_median|-83%
BM_subset/subset_glyphs/MPLUS1-Variable.ttf/nohinting/512_median|-31%
BM_subset/subset_glyphs/MPLUS1-Variable.ttf/nohinting/4096_median|-16%
BM_subset/subset_glyphs/MPLUS1-Variable.ttf/nohinting/6000_median|-18%
BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/10_median|-44%
BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/64_median|-18%
BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/512_median|-2%
BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/900_median|-6%
BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/nohinting/10_median|-45%
BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/nohinting/64_median|-17%
BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/nohinting/512_median|-15%
BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/nohinting/900_median|-3%
BM_subset/subset_codepoints/Roboto-Regular.ttf/10_median|-20%
BM_subset/subset_codepoints/Roboto-Regular.ttf/64_median|-16%
BM_subset/subset_codepoints/Roboto-Regular.ttf/512_median|-12%
BM_subset/subset_codepoints/Roboto-Regular.ttf/1000_median|-10%
BM_subset/subset_codepoints/Roboto-Regular.ttf/nohinting/10_median|-24%
BM_subset/subset_codepoints/Roboto-Regular.ttf/nohinting/64_median|-14%
BM_subset/subset_codepoints/Roboto-Regular.ttf/nohinting/512_median|-15%
BM_subset/subset_codepoints/Roboto-Regular.ttf/nohinting/1000_median|-9%
BM_subset/subset_codepoints/Amiri-Regular.ttf/10_median|-51%
BM_subset/subset_codepoints/Amiri-Regular.ttf/64_median|-37%
BM_subset/subset_codepoints/Amiri-Regular.ttf/512_median|-12%
BM_subset/subset_codepoints/Amiri-Regular.ttf/4096_median|-1%
BM_subset/subset_codepoints/Amiri-Regular.ttf/nohinting/10_median|-49%
BM_subset/subset_codepoints/Amiri-Regular.ttf/nohinting/64_median|-35%
BM_subset/subset_codepoints/Amiri-Regular.ttf/nohinting/512_median|-6%
BM_subset/subset_codepoints/Amiri-Regular.ttf/nohinting/4096_median|-1%
BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/10_median|-82%
BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/64_median|-9%
BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/512_median|0%
BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/1400_median|0%
BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/nohinting/10_median|-82%
BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/nohinting/64_median|-13%
BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/nohinting/512_median|-3%
BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/nohinting/1400_median|2%
BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/10_median|-40%
BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/64_median|-26%
BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/512_median|-5%
BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/1000_median|3%
BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/nohinting/10_median|-43%
BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/nohinting/64_median|-24%
BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/nohinting/512_median|-2%
BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/nohinting/1000_median|2%
BM_subset/subset_codepoints/Mplus1p-Regular.ttf/10_median|-83%
BM_subset/subset_codepoints/Mplus1p-Regular.ttf/64_median|-67%
BM_subset/subset_codepoints/Mplus1p-Regular.ttf/512_median|-39%
BM_subset/subset_codepoints/Mplus1p-Regular.ttf/4096_median|-20%
BM_subset/subset_codepoints/Mplus1p-Regular.ttf/10000_median|-25%
BM_subset/subset_codepoints/Mplus1p-Regular.ttf/nohinting/10_median|-83%
BM_subset/subset_codepoints/Mplus1p-Regular.ttf/nohinting/64_median|-65%
BM_subset/subset_codepoints/Mplus1p-Regular.ttf/nohinting/512_median|-42%
BM_subset/subset_codepoints/Mplus1p-Regular.ttf/nohinting/4096_median|-34%
BM_subset/subset_codepoints/Mplus1p-Regular.ttf/nohinting/10000_median|-21%
BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/10_median|-69%
BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/64_median|-69%
BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/512_median|-70%
BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/4096_median|-84%
BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/10000_median|-83%
BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/nohinting/10_median|-71%
BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/nohinting/64_median|-68%
BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/nohinting/512_median|-70%
BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/nohinting/4096_median|-86%
BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/nohinting/10000_median|-88%
BM_subset/subset_codepoints/SourceSansPro-Regular.otf/10_median|-45%
BM_subset/subset_codepoints/SourceSansPro-Regular.otf/64_median|-48%
BM_subset/subset_codepoints/SourceSansPro-Regular.otf/512_median|-57%
BM_subset/subset_codepoints/SourceSansPro-Regular.otf/2000_median|-66%
BM_subset/subset_codepoints/SourceSansPro-Regular.otf/nohinting/10_median|-43%
BM_subset/subset_codepoints/SourceSansPro-Regular.otf/nohinting/64_median|-50%
BM_subset/subset_codepoints/SourceSansPro-Regular.otf/nohinting/512_median|-63%
BM_subset/subset_codepoints/SourceSansPro-Regular.otf/nohinting/2000_median|-72%
BM_subset/subset_codepoints/AdobeVFPrototype.otf/10_median|-69%
BM_subset/subset_codepoints/AdobeVFPrototype.otf/64_median|-66%
BM_subset/subset_codepoints/AdobeVFPrototype.otf/300_median|-74%
BM_subset/subset_codepoints/AdobeVFPrototype.otf/nohinting/10_median|-70%
BM_subset/subset_codepoints/AdobeVFPrototype.otf/nohinting/64_median|-71%
BM_subset/subset_codepoints/AdobeVFPrototype.otf/nohinting/300_median|-75%
BM_subset/subset_codepoints/MPLUS1-Variable.ttf/10_median|-66%
BM_subset/subset_codepoints/MPLUS1-Variable.ttf/64_median|-46%
BM_subset/subset_codepoints/MPLUS1-Variable.ttf/512_median|-15%
BM_subset/subset_codepoints/MPLUS1-Variable.ttf/4096_median|-5%
BM_subset/subset_codepoints/MPLUS1-Variable.ttf/6000_median|-16%
BM_subset/subset_codepoints/MPLUS1-Variable.ttf/nohinting/10_median|-66%
BM_subset/subset_codepoints/MPLUS1-Variable.ttf/nohinting/64_median|-45%
BM_subset/subset_codepoints/MPLUS1-Variable.ttf/nohinting/512_median|-14%
BM_subset/subset_codepoints/MPLUS1-Variable.ttf/nohinting/4096_median|-11%
BM_subset/subset_codepoints/MPLUS1-Variable.ttf/nohinting/6000_median|-27%
BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/10_median|-38%
BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/64_median|-9%
BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/512_median|-3%
BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/900_median|-16%
BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/nohinting/10_median|-39%
BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/nohinting/64_median|-12%
BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/nohinting/512_median|-4%
BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/nohinting/900_median|-2%
BM_subset/instance/MPLUS1-Variable.ttf/10_median|-68%
BM_subset/instance/MPLUS1-Variable.ttf/64_median|-45%
BM_subset/instance/MPLUS1-Variable.ttf/512_median|-18%
BM_subset/instance/MPLUS1-Variable.ttf/4096_median|-2%
BM_subset/instance/MPLUS1-Variable.ttf/6000_median|4%
BM_subset/instance/MPLUS1-Variable.ttf/nohinting/10_median|-69%
BM_subset/instance/MPLUS1-Variable.ttf/nohinting/64_median|-46%
BM_subset/instance/MPLUS1-Variable.ttf/nohinting/512_median|-11%
BM_subset/instance/MPLUS1-Variable.ttf/nohinting/4096_median|4%
BM_subset/instance/MPLUS1-Variable.ttf/nohinting/6000_median|-5%
BM_subset/instance/RobotoFlex-Variable.ttf/10_median|-34%
BM_subset/instance/RobotoFlex-Variable.ttf/64_median|-12%
BM_subset/instance/RobotoFlex-Variable.ttf/512_median|6%
BM_subset/instance/RobotoFlex-Variable.ttf/900_median|-6%
BM_subset/instance/RobotoFlex-Variable.ttf/nohinting/10_median|-33%
BM_subset/instance/RobotoFlex-Variable.ttf/nohinting/64_median|-11%
BM_subset/instance/RobotoFlex-Variable.ttf/nohinting/512_median|3%
BM_subset/instance/RobotoFlex-Variable.ttf/nohinting/900_median|0%

View File

@ -182,7 +182,8 @@
</para>
<itemizedlist>
<listitem>
<para><emphasis>Level 0</emphasis> is the default.
<para><emphasis>Level 0</emphasis> is the default and
reproduces the behavior of the old HarfBuzz library.
</para>
<para>
The distinguishing feature of level 0 behavior is that, at
@ -193,7 +194,7 @@
as well as the <emphasis>Zero Width Joiner</emphasis> and
<emphasis>Zero Width Non-Joiner</emphasis> code points, are
assigned the cluster value of the closest preceding code
point from <emphasis>different</emphasis> category.
point from <emphasis>different</emphasis> category.
</para>
<para>
In essence, whenever a base character is followed by a mark
@ -205,11 +206,6 @@
url="https://www.unicode.org/reports/tr29/#Regex_Definitions">Unicode
Technical Report 29</ulink>.
</para>
<para>
This cluster level is suitable for code that likes to use
HarfBuzz cluster values as an approximation of the Unicode
Grapheme Cluster Boundaries as well.
</para>
<para>
Client programs can specify level 0 behavior for a buffer by
setting its <literal>cluster_level</literal> to
@ -224,13 +220,13 @@
implement backward compatibility with the old HarfBuzz.
</para>
<para>
<emphasis>Level 1</emphasis> differs from level 0 by not merging the
Level 1 differs from level 0 by not merging the
clusters of marks and other modifier code points with the
preceding "base" code point's cluster. By preserving the
separate cluster values of these marks and modifier code
points, script shapers can perform additional operations
that might lead to improved results (for example, coloring
mark glyphs differently than their base).
that might lead to improved results (for example, reordering
a sequence of marks).
</para>
<para>
Client programs can specify level 1 behavior for a buffer by
@ -246,7 +242,7 @@
</para>
<para>
This difference can be seen most clearly when HarfBuzz processes
ligature substitutions and glyph decompositions. In level 0
ligature substitutions and glyph decompositions. In level 0
and level 1, ligatures and glyph decomposition both involve
merging clusters; in level 2, neither of these operations
triggers a merge.
@ -263,7 +259,7 @@
assign initial cluster values in a buffer by reusing the indices
of the code points in the input text. This gives a sequence of
cluster values that is monotonically increasing (for example,
0,1,2,3,4).
0,1,2,3,4).
</para>
<para>
It is not <emphasis>required</emphasis> that the cluster values
@ -318,7 +314,7 @@
</listitem>
</itemizedlist>
</section>
<section id="a-clustering-example-for-levels-0-and-1">
<title>A clustering example for levels 0 and 1</title>
<para>
@ -423,7 +419,7 @@
<section id="reordering-in-levels-0-and-1">
<title>Reordering in levels 0 and 1</title>
<para>
Another common operation in some shapers is glyph
Another common operation in the more complex shapers is glyph
reordering. In order to maintain a monotonic cluster sequence
when glyph reordering takes place, HarfBuzz merges the clusters
of everything in the reordering sequence.

View File

@ -55,7 +55,7 @@
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 more variation-axis settings (or a
you may need to specify one or variation-axis settings (or a
named instance) in order to get the output you need.
</para>
<para>
@ -256,18 +256,6 @@
<para>
<function>hb_font_get_glyph_from_name_func_t</function>: returns
the glyph index that corresponds to a given glyph name.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_draw_glyph_func_t</function>: gets the outlines
of a glyph (by calling #hb_draw_funcs_t callbacks).
</para>
</listitem>
<listitem>
<para>
<function>hb_font_paint_glyph_func_t</function>: paints a glyph
(by calling #hb_paint_funcs_t callbacks).
</para>
</listitem>
</itemizedlist>
@ -387,6 +375,20 @@
</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>
<para>
</para>
</section> -->
<section id="fonts-and-faces-variable">
<title>Working with OpenType Variable Fonts</title>
<para>
@ -453,66 +455,13 @@
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.
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>
<para>
In addition to providing the variation axes themselves, fonts may also
pre-define certain variation coordinates as named instances. HarfBuzz
makes these coordinates (and their associated names) available via
<function>hb_ot_var_named_instance_get_design_coords()</function> and
<function>hb_ot_var_named_instance_get_subfamily_name_id()</function>.
</para>
<para>
Applications should treat named instances like multiple independent,
static fonts.
</para>
</section>
<section id="glyphs-and-rendering">
<title>Glyphs and rendering</title>
<para>
The main purpose of HarfBuzz is shaping, which creates a list of positioned
glyphs as output. The remaining task for text layout is to convert this list
into rendered output. While HarfBuzz does not handle rasterization of glyphs
per se, it does have APIs that provide access to the font data that is needed
to perform this task.
</para>
<para>
Traditionally, the shapes of glyphs in scalable fonts are provided as quadratic
or cubic Beziér curves defining outlines to be filled. To obtain the outlines
for a glyph, call <function>hb_font_draw_glyph()</function> and pass a
<type>hb_draw_funcs_t</type> struct. The callbacks in that struct will be called
for each segment of the outline. Note that this API provides access to outlines
as they are defined in the font, without applying hinting to fit the curves
to the pixel grid.
</para>
<para>
Fonts may provide pre-rendered images for glyphs instead of or in addition to
outlines. This is most common for fonts that contain colored glyphs, such as
Emoji. To access these images, use <function>hb_ot_color_reference_png()</function>
or <function>hb_ot_color_reference_svg()</function>.
</para>
<para>
Another way in which fonts provide colored glyphs is via paint graphs that
combine glyph outlines with gradients and allow for transformations and
compositing. In its simplest form, this can be presented as a series of
layers that are rendered on top of each other, each with its own color.
HarfBuzz has the <function>hb_ot_color_glyph_get_layers()</function> to
access glyph data in this form.
</para>
<para>
In the general case, you have to use <function>hb_font_paint_glyph()</function>
and pass a <type>hb_paint_funcs_t</type> struct with callbacks to obtain paint
graphs for glyphs that have them. The <function>hb_font_paint_glyph()</function>
API can handle outline and image glyphs as well, so it provides a unified API for
access to glyph rendering information.
</para>
</section>
</chapter>

View File

@ -51,7 +51,7 @@
<para>
Although the default <function>hb_shape()</function> function is
sufficient for most use cases, a variant is also provided that
sufficient for most use cases, a variant is also provide that
lets you specify which of HarfBuzz's shapers to use on a buffer.
</para>
@ -117,7 +117,7 @@
implements separate shapers for Indic, Arabic, Thai and
Lao, Khmer, Myanmar, Tibetan, Hangul, Hebrew, the
Universal Shaping Engine (USE), and a default shaper for
scripts with no script-specific shaping model.
non-complex scripts.
</para>
</listitem>
</varlistentry>
@ -241,7 +241,7 @@
</listitem>
</orderedlist>
<programlisting language="C">
hb_blob_t *blob = hb_blob_create_from_file(filename); /* or hb_blob_create_from_file_or_fail() */
hb_blob_t *blob = hb_blob_create_from_file(filename);
hb_face_t *face = hb_face_create(blob, 0);
hb_font_t *font = hb_font_create(face);
</programlisting>

View File

@ -23,8 +23,9 @@
Release notes are posted with each new release to provide an
overview of the changes. The project <ulink url="https://github.com/harfbuzz/harfbuzz/issues">tracks bug
reports and other issues</ulink> on GitHub. Discussion and
questions are welcome on <ulink
url="https://github.com/harfbuzz/harfbuzz/discussions">GitHub</ulink> as well.
questions are welcome on the <ulink
url="http://freedesktop.org/mailman/listinfo/harfbuzz/">HarfBuzz
mailing list</ulink>.
</para>
<para>
The API included in the <filename
@ -237,6 +238,26 @@
</listitem>
</varlistentry>
<varlistentry>
<term><command>-Dfontconfig=enabled</command></term>
<listitem>
<para>
Use <ulink url="https://www.freedesktop.org/wiki/Software/fontconfig/">Fontconfig</ulink>. <emphasis>(Default = auto)</emphasis>
</para>
<para>
This option enables or disables usage of the Fontconfig
library, which provides font-matching functions and
provides access to font properties. The default setting
is to check for the presence of Fontconfig and, if it is
found, build with Fontconfig support.
</para>
<para>
Note: Fontconfig is used only by the HarfBuzz
command-line utilities, and not by the HarfBuzz library.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>-Dicu=enabled</command></term>
<listitem>
@ -335,7 +356,7 @@
<term><command>-Ddocs=enabled</command></term>
<listitem>
<para>
Use <ulink url="https://github.com/GNOME/gtk-doc">GTK-Doc</ulink>. <emphasis>(Default = no)</emphasis>
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.

View File

@ -174,9 +174,7 @@
<para>
HarfBuzz provides integration points with FreeType at the
face-object and font-object level and for the font-functions
virtual-method structure of a font object. These functions
make it easy for clients that use FreeType for rasterization
or font-loading, to use HarfBuzz for shaping. To use the
virtual-method structure of a font object. To use the
FreeType-integration API, include the
<filename>hb-ft.h</filename> header.
</para>
@ -310,49 +308,7 @@
it when it is unneeded.
</para>
</section>
<section id="integration-cairo">
<title>Cairo integration</title>
<para>
Cairo is a 2D graphics library that is frequently used together
with GTK and Pango. Cairo supports rendering text using FreeType, or
by using callback-based 'user fonts'.
</para>
<para>
HarfBuzz provides integration points with cairo for fonts as well as
for buffers. To use the Cairo-integration API, link against libharfbuzz-cairo,
and include the <filename>hb-cairo.h</filename> header. For easy buildsystem
integration, HarfBuzz comes with a <filename>harfbuzz-cairo.pc</filename>
pkg-config file.
</para>
<para>
To create a <type>cairo_scaled_font_t</type> font from a HarfBuzz
<type>hb_font_t</type>, you can use <function>hb_cairo_font_face_create_for_font()</function>
or <function>hb_cairo_font_face_create_for_face()</function>. The former API
applies variations and synthetic slant from the <type>hb_font_t</type> when
rendering, the latter takes them from the <type>cairo_font_options_t</type>
that were passed when creating the <type>cairo_scaled_font_t</type>.
</para>
<para>
The Cairo fonts created in this way make use of Cairo's user-font facilities.
They can be used to render on any Cairo context, and provide full support for
font rendering features, including color. One current limitation of the
implementation is that it does not support hinting for glyph outlines.
</para>
<para>
When using color fonts with this API, the color palette index is taken from
the <type>cairo_font_options_t</type> (with new enough Cairo), and the foreground
color is extracted from the source of the Cairo context.
</para>
<para>
To render the results of shaping a piece of text, use
<function>hb_cairo_glyphs_from_buffer()</function> to obtain the glyphs in
a form that can be passed to <function>cairo_show_text_glyphs()</function> or
<function>cairo_show_glyphs()</function>.
</para>
</section>
<section id="integration-uniscribe">
<title>Uniscribe integration</title>
<para>
@ -391,7 +347,7 @@
<structname>hb_glyph_position_t</structname> structures.
</para>
<para>
Your client program only needs to ensure that it converts
Your client program only needs to ensure that it coverts
correctly between HarfBuzz's low-level data types (such as
<type>hb_position_t</type>) and Windows's corresponding types
(such as <type>GOFFSET</type> and <type>ABC</type>). Be sure you
@ -489,7 +445,7 @@
is slightly lower-level than Core Text, provides
<ulink url="https://developer.apple.com/documentation/coregraphics/cgfontref"><type>CGFontRef</type></ulink>, which enables access to typeface
properties, but does not include size information. Core Text's
<ulink url="https://developer.apple.com/documentation/coretext/ctfont-q6r"><type>CTFontRef</type></ulink> is analogous to a HarfBuzz font object,
<ulink url="https://developer.apple.com/documentation/coretext/ctfont-q6r"><type>CTFontRef</type></ulink> is analagous to a HarfBuzz font object,
with all of the properties required to render text at a specific
size and configuration.
Consequently, a HarfBuzz <type>hb_font_t</type> font object can

View File

@ -12,7 +12,7 @@
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.
API/ABI compatibility (almost) indefinitely.
</para>
<para>
<emphasis>Value types:</emphasis> The non-opaque, pass-by-value
@ -32,8 +32,8 @@
possible future members. As such, its 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.
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
@ -42,7 +42,7 @@
OpenType properties.
</para>
</section>
<section id="object-model-object-types">
<title>Objects in HarfBuzz</title>
<para>
@ -63,17 +63,13 @@
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.
<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>
Note that many object types can be marked as read-only or immutable,
facilitating their use in multi-threaded environments.
</para>
<para>
Key object types provided by HarfBuzz include:
</para>
@ -114,11 +110,11 @@
</para>
</listitem>
</itemizedlist>
</section>
<section id="object-model-lifecycle">
<title>Object lifecycle management</title>
<para>
@ -135,7 +131,7 @@
<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
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
@ -145,8 +141,8 @@
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
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>
@ -164,7 +160,7 @@
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.
Reference manual for specifics.
</para>
<para>
Note also that there are no "make mutable" methods. If client
@ -191,7 +187,7 @@
</para>
</section>
<section id="object-model-user-data">
<title>User data</title>
<para>
@ -199,7 +195,7 @@
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.
together, or for creating language bindings.
</para>
<para>
Each object type has a <function>set_user_data()</function>
@ -224,10 +220,10 @@
existing <literal>user_data</literal>
associated with the specified key.
</para>
</section>
</section>
<section id="object-model-blobs">
<title>Blobs</title>
<para>
@ -236,15 +232,15 @@
different.
</para>
<para>
Blobs are an abstraction designed to negotiate lifecycle and
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 HarfBuzz's
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
callbacks. If you allocated the memory for the data using
<function>malloc()</function>, you would create the blob using
</para>
<programlisting language="C">
@ -255,12 +251,8 @@
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>
<para>
Most of the time, blobs are read-only, facilitating their use in
immutable objects.
take care of that.
</para>
</section>
</chapter>

View File

@ -65,10 +65,10 @@
</para>
<para>
The algorithms
used for shaping can be quite involved; HarfBuzz tries
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, to the extent that is feasible and desirable. See the <ulink
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>
@ -131,7 +131,7 @@
</para>
<para>
Some OpenType features are defined for the purpose of supporting
script-specific shaping, and are automatically activated, but
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>

View File

@ -22,7 +22,7 @@
correct amount for each successive glyph.
</para>
<para>
But, for other scripts (often unceremoniously called <emphasis>complex scripts</emphasis>), any combination of
But, for <emphasis>complex scripts</emphasis>, any combination of
several shaping operations may be required, and the rules for how
and when they are applied vary from script to script. HarfBuzz and
other shaping engines implement these rules.
@ -36,35 +36,42 @@
</para>
</section>
<section id="script-specific-shaping">
<title>Script-specific shaping</title>
<section id="complex-scripts">
<title>Complex scripts</title>
<para>
In many scripts, transforming the input
sequence into the final layout often requires some combination of
In text-shaping terminology, scripts are generally classified as
either <emphasis>complex</emphasis> or <emphasis>non-complex</emphasis>.
</para>
<para>
Complex scripts are those for which transforming the input
sequence into the final layout requires some combination of
operations&mdash;such as context-dependent substitutions,
context-dependent mark positioning, glyph-to-glyph joining,
glyph reordering, or glyph stacking.
</para>
<para>
In some scripts, the shaping rules require that a text
In some complex scripts, the shaping rules require that a text
run be divided into syllables before the operations can be
applied. Other scripts may apply shaping operations over
applied. Other complex scripts may apply shaping operations over
entire words or over the entire text run, with no subdivision
required.
</para>
<para>
Other scripts, do not require these
operations. However, correctly shaping a text run in
any script may still involve Unicode normalization,
Non-complex scripts, by definition, do not require these
operations. However, correctly shaping a text run in a
non-complex script may still involve Unicode normalization,
ligature substitutions, mark positioning, kerning, and applying
other font features.
other font features. The key difference is that a text run in a
non-complex script can be processed sequentially and in the same
order as the input sequence of Unicode codepoints, without
requiring an analysis stage.
</para>
</section>
<section id="shaping-operations">
<title>Shaping operations</title>
<para>
Shaping a text run involves transforming the
Shaping a complex-script text run involves transforming the
input sequence of Unicode codepoints with some combination of
operations that is specified in the shaping model for the
script.
@ -74,7 +81,7 @@
text run varies from script to script, as do the order that the
operations are performed in and which codepoints are
affected. However, the same general set of shaping operations is
common to all of the script shaping models.
common to all of the complex-script shaping models.
</para>
<itemizedlist>
@ -85,7 +92,7 @@
some other ("visual") position.
</para>
<para>
The shaping model for a given script might involve
The shaping model for a given complex script might involve
more than one reordering step.
</para>
</listitem>
@ -112,7 +119,7 @@
particular string pattern.
</para>
<para>
The shaping model for a given script might involve
The shaping model for a given complex script might involve
multiple contextual-substitution operations, each applying
to different target glyphs and patterns, and which are
performed in separate steps.
@ -131,7 +138,7 @@
Many contextual positioning operations are used to place
<emphasis>mark</emphasis> glyphs (such as diacritics, vowel
signs, and tone markers) with respect to
<emphasis>base</emphasis> glyphs. However, some
<emphasis>base</emphasis> glyphs. However, some complex
scripts may use contextual positioning operations to
correctly place base glyphs as well, such as
when the script uses <emphasis>stacking</emphasis> characters.
@ -187,7 +194,7 @@
multiple positions).
</para>
<para>
Some scripts require that the text run be split into
Some complex scripts require that the text run be split into
syllables. What constitutes a valid syllable in these
scripts is specified in regular expressions, formed from the
Letter and Mark codepoints, that take the UISC and UIPC
@ -228,7 +235,7 @@
<listitem>
<para>
The <emphasis>default</emphasis> shaping model handles all
scripts with no script-specific shaping model, and may also be used as a fallback for
non-complex scripts, and may also be used as a fallback for
handling unrecognized scripts.
</para>
</listitem>
@ -237,7 +244,7 @@
<para>
The <emphasis>Indic</emphasis> shaping model handles the Indic
scripts Bengali, Devanagari, Gujarati, Gurmukhi, Kannada,
Malayalam, Oriya, Tamil, and Telugu.
Malayalam, Oriya, Tamil, Telugu, and Sinhala.
</para>
<para>
The Indic shaping model was revised significantly in
@ -303,7 +310,7 @@
<listitem>
<para>
The <emphasis>Universal Shaping Engine</emphasis> (USE)
shaping model supports scripts not covered by one of
shaping model supports complex scripts not covered by one of
the above, script-specific shaping models, including
Javanese, Balinese, Buginese, Batak, Chakma, Lepcha, Modi,
Phags-pa, Tagalog, Siddham, Sundanese, Tai Le, Tai Tham, Tai

View File

@ -237,7 +237,8 @@
<listitem>
<para>
Indic (covering Devanagari, Bengali, Gujarati,
Gurmukhi, Kannada, Malayalam, Oriya, Tamil, and Telugu)
Gurmukhi, Kannada, Malayalam, Oriya, Tamil, Telugu, and
Sinhala)
</para>
</listitem>
<listitem>

7
git.mk
View File

@ -204,7 +204,7 @@ git-mk-update:
# Actual .gitignore generation:
###############################################################################
$(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk $(top_srcdir)/configure.ac
$(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
@echo "git.mk: Generating $@"
@{ \
if test "x$(DOC_MODULE)" = x -o "x$(DOC_MAIN_SGML_FILE)" = x; then :; else \
@ -375,9 +375,8 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk $(top_srcdir)/configure.a
} | \
sed "s@^/`echo "$(srcdir)" | sed 's/\(.\)/[\1]/g'`/@/@" | \
sed 's@/[.]/@/@g' | \
LC_ALL=C sort | uniq > .gitignore.tmp && \
(mv .gitignore.tmp $@ || (echo "WARNING: Cannot create $@ file; skipping"; \
$(RM) .gitignore.tmp));
LC_ALL=C sort | uniq > $@.tmp && \
mv $@.tmp $@;
all: $(srcdir)/.gitignore gitignore-recurse-maybe
gitignore: $(srcdir)/.gitignore gitignore-recurse

View File

@ -7,11 +7,11 @@
<shortdesc xml:lang="en">Text shaping library</shortdesc>
<homepage
rdf:resource="https://github.com/harfbuzz/harfbuzz" />
rdf:resource="http://harfbuzz.org/" />
<mailing-list
rdf:resource="https://github.com/harfbuzz/harfbuzz/discussions" />
<download-page
rdf:resource="https://github.com/harfbuzz/harfbuzz/releases" />
rdf:resource="http://lists.freedesktop.org/mailman/listinfo/harfbuzz" />
<!--download-page
rdf:resource=""/-->
<bug-database
rdf:resource="https://github.com/harfbuzz/harfbuzz/issues" />

View File

@ -0,0 +1,6 @@
void memory_barrier (void) { __sync_synchronize (); }
int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); }
int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); }
void mutex_unlock (int *m) { __sync_lock_release (m); }
int main(void) { return 0;}

View File

@ -0,0 +1,8 @@
#include <atomic.h>
/* This requires Solaris Studio 12.2 or newer: */
#include <mbarrier.h>
void memory_barrier (void) { __machine_rw_barrier (); }
int atomic_add (volatile unsigned *i) { return atomic_add_int_nv (i, 1); }
void *atomic_ptr_cmpxchg (volatile void **target, void *cmp, void *newval) { return atomic_cas_ptr (target, cmp, newval); }
int main(void) { return 0; }

View File

@ -1,9 +1,9 @@
project('harfbuzz', 'c', 'cpp',
meson_version: '>= 0.55.0',
version: '7.1.0',
meson_version: '>= 0.47.0',
version: '2.7.4',
default_options: [
'cpp_eh=none', # Just to support msvc, we are passing -fno-exceptions also anyway
'cpp_rtti=false', # Just to support msvc, we are passing -fno-rtti also anyway
'cpp_eh=none', # Just to support msvc, we are passing -fno-rtti also anyway
'cpp_rtti=false', # Just to support msvc, we are passing -fno-exceptions also anyway
'cpp_std=c++11',
'wrap_mode=nofallback', # Use --wrap-mode=default to revert, https://github.com/harfbuzz/harfbuzz/pull/2548
],
@ -15,20 +15,23 @@ hb_version_minor = hb_version_arr[1].to_int()
hb_version_micro = hb_version_arr[2].to_int()
# libtool versioning
hb_version_int = 60000 + hb_version_major*100 + hb_version_minor*10 + hb_version_micro
hb_version_int = hb_version_major*10000 + hb_version_minor*100 + hb_version_micro
hb_libtool_version_info = '@0@:0:@0@'.format(hb_version_int)
pkgmod = import('pkgconfig')
cpp = meson.get_compiler('cpp')
null_dep = dependency('', required: false)
if cpp.get_argument_syntax() == 'msvc'
if cpp.get_id() == 'msvc'
# Ignore several spurious warnings for things HarfBuzz does very commonly.
# If a warning is completely useless and spammy, use '/wdXXXX' to suppress it
# If a warning is harmless but hard to fix, use '/woXXXX' so it's shown once
# NOTE: Only add warnings here if you are sure they're spurious
msvc_args = [
'/wd4018', # implicit signed/unsigned conversion
'/wd4146', # unary minus on unsigned (beware INT_MIN)
'/wd4244', # lossy type conversion (e.g. double -> int)
'/wd4305', # truncating type conversion (e.g. double -> float)
cpp.get_supported_arguments(['/utf-8']), # set the input encoding to utf-8
]
add_project_arguments(msvc_args, language: ['c', 'cpp'])
@ -53,17 +56,10 @@ if host_machine.cpu_family() == 'arm' and cpp.alignment('struct { char c; }') !=
endif
endif
if host_machine.system() == 'windows'
add_project_arguments(cpp.get_supported_arguments([
'-Wa,-mbig-obj'
]), language : 'cpp')
endif
check_headers = [
['unistd.h'],
['sys/mman.h'],
['stdbool.h'],
['xlocale.h'],
]
check_funcs = [
@ -73,84 +69,57 @@ check_funcs = [
['getpagesize'],
['mmap'],
['isatty'],
['uselocale'],
['newlocale'],
]
m_dep = cpp.find_library('m', required: false)
if meson.version().version_compare('>=0.60.0')
# pkg-config: freetype2, cmake: Freetype
freetype_dep = dependency('freetype2', 'Freetype',
required: get_option('freetype'),
default_options: ['harfbuzz=disabled'],
allow_fallback: true)
else
# painful hack to handle multiple dependencies but also respect options
freetype_opt = get_option('freetype')
# we want to handle enabled manually after fallbacks, but also handle disabled normally
if freetype_opt.enabled()
freetype_opt = false
freetype_dep = null_dep
if not get_option('freetype').disabled()
freetype_dep = dependency('freetype2', required: false)
if (not freetype_dep.found() and
cpp.get_id() == 'msvc' and
cpp.has_header('ft2build.h'))
freetype_dep = cpp.find_library('freetype', required: false)
endif
# try pkg-config name
freetype_dep = dependency('freetype2', method: 'pkg-config', required: freetype_opt)
# when disabled, leave it not-found
if not freetype_dep.found() and not get_option('freetype').disabled()
# Try cmake name
freetype_dep = dependency('Freetype', method: 'cmake', required: false)
# Subproject fallback, `allow_fallback: true` means the fallback will be
# tried even if the freetype option is set to `auto`.
if not freetype_dep.found()
freetype_dep = dependency('freetype2',
method: 'pkg-config',
required: get_option('freetype'),
default_options: ['harfbuzz=disabled'],
allow_fallback: true)
endif
if not freetype_dep.found()
# https://github.com/harfbuzz/harfbuzz/pull/2498
freetype_dep = dependency('freetype2', required: get_option('freetype'),
fallback: ['freetype2', 'freetype_dep'],
default_options: ['harfbuzz=disabled'])
endif
endif
glib_dep = dependency('glib-2.0', required: get_option('glib'))
gobject_dep = dependency('gobject-2.0', required: get_option('gobject'))
graphite2_dep = dependency('graphite2', required: get_option('graphite2'))
graphite_dep = dependency('graphite2', required: get_option('graphite'))
glib_dep = dependency('glib-2.0', required: get_option('glib'),
fallback: ['glib', 'libglib_dep'])
gobject_dep = dependency('gobject-2.0', required: get_option('gobject'),
fallback: ['glib', 'libgobject_dep'])
fontconfig_dep = dependency('fontconfig', required: get_option('fontconfig'),
fallback: ['fontconfig', 'fontconfig_dep'])
graphite2_dep = dependency('graphite2', required: get_option('graphite'))
if meson.version().version_compare('>=0.60.0')
# pkg-config: icu-uc, cmake: ICU but with components
icu_dep = dependency('icu-uc', 'ICU',
components: 'uc',
required: get_option('icu'),
default_options: ['harfbuzz=disabled'],
allow_fallback: true)
else
# painful hack to handle multiple dependencies but also respect options
icu_opt = get_option('icu')
# we want to handle enabled manually after fallbacks, but also handle disabled normally
if icu_opt.enabled()
icu_opt = false
endif
# try pkg-config name
icu_dep = dependency('icu-uc', method: 'pkg-config', required: icu_opt)
# when disabled, leave it not-found
if not icu_dep.found() and not get_option('icu').disabled()
# Try cmake name
icu_dep = dependency('ICU', method: 'cmake', components: 'uc', required: false)
# Try again with subproject fallback. `allow_fallback: true` means the
# fallback will be tried even if the icu option is set to `auto`, but
# we cannot pass this option until Meson 0.59.0, because no wrap file
# is checked into git.
if not icu_dep.found()
icu_dep = dependency('icu-uc',
method: 'pkg-config',
required: get_option('icu'))
icu_dep = null_dep
if not get_option('icu').disabled()
icu_dep = dependency('icu-uc', required: false)
if (not icu_dep.found() and
cpp.get_id() == 'msvc' and
cpp.has_header('unicode/uchar.h') and
cpp.has_header('unicode/unorm2.h') and
cpp.has_header('unicode/ustring.h') and
cpp.has_header('unicode/utf16.h') and
cpp.has_header('unicode/uversion.h') and
cpp.has_header('unicode/uscript.h'))
if get_option('buildtype') == 'debug'
icu_dep = cpp.find_library('icuucd', required: false)
else
icu_dep = cpp.find_library('icuuc', required: false)
endif
endif
endif
if icu_dep.found() and icu_dep.type_name() == 'pkgconfig'
icu_defs = icu_dep.get_variable(pkgconfig: 'DEFS', default_value: '').split()
if icu_defs.length() > 0
add_project_arguments(icu_defs, language: ['c', 'cpp'])
if not icu_dep.found()
icu_dep = dependency('icu-uc', required: get_option('icu'))
endif
endif
@ -161,7 +130,7 @@ if not get_option('cairo').disabled()
cairo_ft_dep = dependency('cairo-ft', required: false)
if (not cairo_dep.found() and
cpp.get_argument_syntax() == 'msvc' and
cpp.get_id() == 'msvc' and
cpp.has_header('cairo.h'))
cairo_dep = cpp.find_library('cairo', required: false)
if cairo_dep.found() and cpp.has_function('cairo_ft_font_face_create_for_ft_face',
@ -172,18 +141,21 @@ if not get_option('cairo').disabled()
endif
if not cairo_dep.found()
# Note that we don't have harfbuzz -> cairo -> freetype2 -> harfbuzz fallback
# dependency cycle here because we have configured freetype2 above with
# harfbuzz support disabled, so when cairo will lookup freetype2 dependency
# it will be forced to use that one.
cairo_dep = dependency('cairo', required: get_option('cairo'))
cairo_ft_required = get_option('cairo').enabled() and get_option('freetype').enabled()
cairo_ft_dep = dependency('cairo-ft', required: cairo_ft_required)
# Requires Meson 0.54.0 to use cairo subproject
if meson.version().version_compare('>=0.54.0')
# Note that we don't have harfbuzz -> cairo -> freetype2 -> harfbuzz fallback
# dependency cycle here because we have configured freetype2 above with
# harfbuzz support disabled, so when cairo will lookup freetype2 dependency
# it will be forced to use that one.
cairo_dep = dependency('cairo', fallback: 'cairo', required: get_option('cairo'))
cairo_ft_dep = dependency('cairo-ft', fallback: 'cairo', required: get_option('cairo'))
elif get_option('cairo').enabled()
error('cairo feature is enabled but it cannot be found on the system and ' +
'meson>=0.54.0 is required to build it as subproject')
endif
endif
endif
chafa_dep = dependency('chafa', version: '>= 1.6.0', required: get_option('chafa'))
conf = configuration_data()
incconfig = include_directories('.')
@ -205,31 +177,13 @@ endif
if cairo_dep.found()
conf.set('HAVE_CAIRO', 1)
check_cairo_funcs = [
['cairo_user_font_face_set_render_color_glyph_func', {'deps': cairo_dep}],
['cairo_font_options_get_custom_palette_color', {'deps': cairo_dep}],
['cairo_user_scaled_font_get_foreground_source', {'deps': cairo_dep}],
]
if cairo_dep.type_name() == 'internal'
foreach func: check_cairo_funcs
name = func[0]
conf.set('HAVE_@0@'.format(name.to_upper()), 1)
endforeach
else
check_funcs += check_cairo_funcs
endif
endif
if cairo_ft_dep.found()
conf.set('HAVE_CAIRO_FT', 1)
endif
if chafa_dep.found()
conf.set('HAVE_CHAFA', 1)
endif
if graphite2_dep.found() or graphite_dep.found()
if graphite2_dep.found()
conf.set('HAVE_GRAPHITE2', 1)
endif
@ -251,7 +205,6 @@ if freetype_dep.found()
['FT_Get_Var_Blend_Coordinates', {'deps': freetype_dep}],
['FT_Set_Var_Blend_Coordinates', {'deps': freetype_dep}],
['FT_Done_MM_Var', {'deps': freetype_dep}],
['FT_Get_Transform', {'deps': freetype_dep}],
]
if freetype_dep.type_name() == 'internal'
@ -264,6 +217,10 @@ if freetype_dep.found()
endif
endif
if fontconfig_dep.found()
conf.set('HAVE_FONTCONFIG', 1)
endif
gdi_uniscribe_deps = []
# GDI (Uniscribe) (Windows)
if host_machine.system() == 'windows' and not get_option('gdi').disabled()
@ -286,12 +243,17 @@ if host_machine.system() == 'windows' and not get_option('gdi').disabled()
endif
# DirectWrite (Windows)
directwrite_dep = null_dep
if host_machine.system() == 'windows' and not get_option('directwrite').disabled()
if get_option('directwrite').enabled() and not cpp.has_header('dwrite_1.h')
error('DirectWrite was enabled explicitly, but required header is missing.')
endif
conf.set('HAVE_DIRECTWRITE', 1)
directwrite_dep = cpp.find_library('dwrite', required: get_option('directwrite'))
if directwrite_dep.found()
conf.set('HAVE_DIRECTWRITE', 1)
endif
endif
# CoreText (macOS)
@ -323,6 +285,9 @@ if host_machine.system() != 'windows'
if thread_dep.found()
conf.set('HAVE_PTHREAD', 1)
else
check_headers += ['sched.h']
check_funcs += ['sched_yield', {'link_with': 'rt'}]
endif
endif
@ -372,12 +337,17 @@ foreach check : check_funcs
endif
endforeach
subdir('src')
if not get_option('utilities').disabled()
subdir('util')
if cpp.links(files('meson-cc-tests/intel-atomic-primitives-test.c'), name: 'Intel atomics')
conf.set('HAVE_INTEL_ATOMIC_PRIMITIVES', 1)
endif
if cpp.links(files('meson-cc-tests/solaris-atomic-operations.c'), name: 'Solaris atomic ops')
conf.set('HAVE_SOLARIS_ATOMIC_OPS', 1)
endif
subdir('src')
subdir('util')
if not get_option('tests').disabled()
subdir('test')
endif
@ -392,9 +362,6 @@ endif
configure_file(output: 'config.h', configuration: conf)
alias_target('lib', libharfbuzz)
alias_target('libs', libharfbuzz, libharfbuzz_subset)
build_summary = {
'Directories':
{'prefix': get_option('prefix'),
@ -409,12 +376,11 @@ build_summary = {
'ICU': conf.get('HAVE_ICU', 0) == 1,
},
'Font callbacks (the more the merrier)':
{'Builtin' : true,
'FreeType': conf.get('HAVE_FREETYPE', 0) == 1,
{'FreeType': conf.get('HAVE_FREETYPE', 0) == 1,
},
'Dependencies used for command-line utilities':
{'Cairo': conf.get('HAVE_CAIRO', 0) == 1,
'Chafa': conf.get('HAVE_CHAFA', 0) == 1,
'Fontconfig': conf.get('HAVE_FONTCONFIG', 0) == 1,
},
'Additional shapers':
{'Graphite2': conf.get('HAVE_GRAPHITE2', 0) == 1,
@ -427,7 +393,6 @@ build_summary = {
'Other features':
{'Documentation': conf.get('HAVE_GTK_DOC', 0) == 1,
'GObject bindings': conf.get('HAVE_GOBJECT', 0) == 1,
'Cairo integration': conf.get('HAVE_CAIRO', 0) == 1,
'Introspection': conf.get('HAVE_INTROSPECTION', 0) == 1,
'Experimental APIs': conf.get('HB_EXPERIMENTAL_API', 0) == 1,
},
@ -436,6 +401,19 @@ build_summary = {
'Benchmark': get_option('benchmark').enabled(),
},
}
foreach section_title, section : build_summary
summary(section, bool_yn: true, section: section_title)
endforeach
if meson.version().version_compare('>=0.53')
foreach section_title, section : build_summary
summary(section, bool_yn: true, section: section_title)
endforeach
else
summary = ['']
foreach section_title, section : build_summary
summary += ' @0@:'.format(section_title)
foreach feature, value : section
summary += ' @0@:'.format(feature)
summary += ' @0@'.format(value)
endforeach
summary += ''
endforeach
message('\n'.join(summary))
endif

View File

@ -5,13 +5,11 @@ option('gobject', type: 'feature', value: 'auto',
description: 'Enable GObject bindings')
option('cairo', type: 'feature', value: 'auto',
description: 'Use Cairo graphics library')
option('chafa', type: 'feature', value: 'auto',
description: 'Use Chafa terminal graphics library')
option('fontconfig', type: 'feature', value: 'auto',
description: 'Use fontconfig')
option('icu', type: 'feature', value: 'auto',
description: 'Enable ICU library unicode functions')
option('graphite', type: 'feature', value: 'disabled',
description: 'Deprecated use graphite2 option instead')
option('graphite2', type: 'feature', value: 'disabled',
description: 'Enable Graphite2 complementary shaper')
option('freetype', type: 'feature', value: 'auto',
description: 'Enable freetype interop helpers')
@ -29,10 +27,6 @@ option('introspection', type: 'feature', value: 'auto', yield: true,
description: 'Generate gobject-introspection bindings (.gir/.typelib files)')
option('docs', type: 'feature', value: 'auto', yield: true,
description: 'Generate documentation with gtk-doc')
option('doc_tests', type: 'boolean', value: false,
description: 'Run gtkdoc-check tests')
option('utilities', type: 'feature', value: 'enabled', yield: true,
description: 'Build harfbuzz utils')
option('benchmark', type: 'feature', value: 'disabled',
description: 'Enable benchmark tests')
@ -40,7 +34,5 @@ option('icu_builtin', type: 'boolean', value: false,
description: 'Don\'t separate ICU support as harfbuzz-icu module')
option('experimental_api', type: 'boolean', value: false,
description: 'Enable experimental APIs')
option('ragel_subproject', type: 'boolean', value: false,
description: 'Build Ragel subproject if no suitable version is found')
option('fuzzer_ldflags', type: 'string',
description: 'Extra LDFLAGS used during linking of fuzzing binaries')

View File

@ -17,14 +17,12 @@ exec "$(dirname "$0")"/configure \
CPP= \
LD= \
CFLAGS="-static-libgcc" \
CXXFLAGS="-O2 -static-libgcc -static-libstdc++" \
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-gdi \
--with-uniscribe \
--with-directwrite=auto \
"$@"

View File

@ -1,23 +0,0 @@
# Process this file with automake to produce Makefile.in
NULL =
EXTRA_DIST =
SUBDIRS =
EXTRA_DIST += \
meson.build \
benchmark-font.cc \
benchmark-map.cc \
benchmark-ot.cc \
benchmark-set.cc \
benchmark-shape.cc \
benchmark-subset.cc \
fonts \
texts \
$(NULL)
# Convenience targets:
lib:
@$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
-include $(top_srcdir)/git.mk

View File

@ -1,54 +0,0 @@
# Building and Running
Benchmarks are implemented using [Google Benchmark](https://github.com/google/benchmark).
To build the benchmarks in this directory you need to set the benchmark
option while configuring the build with meson:
```
meson build -Dbenchmark=enabled --buildtype=release
```
or:
```
meson build -Dbenchmark=enabled --buildtype=debugoptimized
```
Then build a specific benchmark binaries with ninja:
```
ninja -Cbuild perf/benchmark-set
```
or just build the whole project:
```
ninja -Cbuild
```
Finally, to run one of the benchmarks:
```
./build/perf/benchmark-set
```
It's possible to filter the benchmarks being run and customize the output
via flags to the benchmark binary. See the
[Google Benchmark User Guide](https://github.com/google/benchmark/blob/main/docs/user_guide.md#user-guide) for more details.
# Profiling
Configure the build to include debug information for profiling:
```
CXXFLAGS="-fno-omit-frame-pointer" meson --reconfigure build -Dbenchmark=enabled --buildtype=debug
ninja -Cbuild
```
Then run the benchmark with perf:
```
perf record -g build/perf/benchmark-subset --benchmark_filter="BM_subset_codepoints/subset_notocjk/100000" --benchmark_repetitions=5
```
You probably want to filter to a specific benchmark of interest and set the number of repititions high enough to get a good sampling of profile data.
Finally view the profile with:
perf report

View File

@ -1,245 +0,0 @@
#include "benchmark/benchmark.h"
#include <cassert>
#include <cstring>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "hb.h"
#include "hb-ot.h"
#ifdef HAVE_FREETYPE
#include "hb-ft.h"
#endif
#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
struct test_input_t
{
bool is_variable;
const char *font_path;
} default_tests[] =
{
{true , SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf"},
{false, SUBSET_FONT_BASE_PATH "SourceSansPro-Regular.otf"},
{true , SUBSET_FONT_BASE_PATH "AdobeVFPrototype.otf"},
{true , SUBSET_FONT_BASE_PATH "SourceSerifVariable-Roman.ttf"},
{false, SUBSET_FONT_BASE_PATH "Comfortaa-Regular-new.ttf"},
{false, SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf"},
{false, SUBSET_FONT_BASE_PATH "NotoSerifMyanmar-Regular.otf"},
};
static test_input_t *tests = default_tests;
static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
enum backend_t { HARFBUZZ, FREETYPE };
enum operation_t
{
nominal_glyphs,
glyph_h_advances,
glyph_extents,
glyph_shape,
};
static void
_hb_move_to (hb_draw_funcs_t *, void *, hb_draw_state_t *, float, float, void *) {}
static void
_hb_line_to (hb_draw_funcs_t *, void *, hb_draw_state_t *, float, float, void *) {}
//static void
//_hb_quadratic_to (hb_draw_funcs_t *, void *, hb_draw_state_t *, float, float, float, float, void *) {}
static void
_hb_cubic_to (hb_draw_funcs_t *, void *, hb_draw_state_t *, float, float, float, float, float, float, void *) {}
static void
_hb_close_path (hb_draw_funcs_t *, void *, hb_draw_state_t *, void *) {}
static hb_draw_funcs_t *
_draw_funcs_create (void)
{
hb_draw_funcs_t *draw_funcs = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (draw_funcs, _hb_move_to, nullptr, nullptr);
hb_draw_funcs_set_line_to_func (draw_funcs, _hb_line_to, nullptr, nullptr);
//hb_draw_funcs_set_quadratic_to_func (draw_funcs, _hb_quadratic_to, nullptr, nullptr);
hb_draw_funcs_set_cubic_to_func (draw_funcs, _hb_cubic_to, nullptr, nullptr);
hb_draw_funcs_set_close_path_func (draw_funcs, _hb_close_path, nullptr, nullptr);
return draw_funcs;
}
static void BM_Font (benchmark::State &state,
bool is_var, backend_t backend, operation_t operation,
const test_input_t &test_input)
{
hb_font_t *font;
unsigned num_glyphs;
{
hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
assert (blob);
hb_face_t *face = hb_face_create (blob, 0);
hb_blob_destroy (blob);
num_glyphs = hb_face_get_glyph_count (face);
font = hb_font_create (face);
hb_face_destroy (face);
}
if (is_var)
{
hb_variation_t wght = {HB_TAG ('w','g','h','t'), 500};
hb_font_set_variations (font, &wght, 1);
}
switch (backend)
{
case HARFBUZZ:
hb_ot_font_set_funcs (font);
break;
case FREETYPE:
#ifdef HAVE_FREETYPE
hb_ft_font_set_funcs (font);
#endif
break;
}
switch (operation)
{
case nominal_glyphs:
{
hb_set_t *set = hb_set_create ();
hb_face_collect_unicodes (hb_font_get_face (font), set);
unsigned pop = hb_set_get_population (set);
hb_codepoint_t *unicodes = (hb_codepoint_t *) calloc (pop, sizeof (hb_codepoint_t));
hb_codepoint_t *glyphs = (hb_codepoint_t *) calloc (pop, sizeof (hb_codepoint_t));
hb_codepoint_t *p = unicodes;
for (hb_codepoint_t u = HB_SET_VALUE_INVALID;
hb_set_next (set, &u);)
*p++ = u;
assert (p == unicodes + pop);
for (auto _ : state)
hb_font_get_nominal_glyphs (font,
pop,
unicodes, sizeof (*unicodes),
glyphs, sizeof (*glyphs));
free (glyphs);
free (unicodes);
hb_set_destroy (set);
break;
}
case glyph_h_advances:
{
hb_codepoint_t *glyphs = (hb_codepoint_t *) calloc (num_glyphs, sizeof (hb_codepoint_t));
hb_position_t *advances = (hb_position_t *) calloc (num_glyphs, sizeof (hb_codepoint_t));
for (unsigned g = 0; g < num_glyphs; g++)
glyphs[g] = g;
for (auto _ : state)
hb_font_get_glyph_h_advances (font,
num_glyphs,
glyphs, sizeof (*glyphs),
advances, sizeof (*advances));
free (advances);
free (glyphs);
break;
}
case glyph_extents:
{
hb_glyph_extents_t extents;
for (auto _ : state)
for (unsigned gid = 0; gid < num_glyphs; ++gid)
hb_font_get_glyph_extents (font, gid, &extents);
break;
}
case glyph_shape:
{
hb_draw_funcs_t *draw_funcs = _draw_funcs_create ();
for (auto _ : state)
for (unsigned gid = 0; gid < num_glyphs; ++gid)
hb_font_draw_glyph (font, gid, draw_funcs, nullptr);
break;
hb_draw_funcs_destroy (draw_funcs);
}
}
hb_font_destroy (font);
}
static void test_backend (backend_t backend,
const char *backend_name,
bool variable,
operation_t op,
const char *op_name,
benchmark::TimeUnit time_unit,
const test_input_t &test_input)
{
char name[1024] = "BM_Font/";
strcat (name, op_name);
strcat (name, "/");
const char *p = strrchr (test_input.font_path, '/');
strcat (name, p ? p + 1 : test_input.font_path);
strcat (name, variable ? "/var" : "");
strcat (name, "/");
strcat (name, backend_name);
benchmark::RegisterBenchmark (name, BM_Font, variable, backend, op, test_input)
->Unit(time_unit);
}
static void test_operation (operation_t op,
const char *op_name,
benchmark::TimeUnit time_unit)
{
for (unsigned i = 0; i < num_tests; i++)
{
auto& test_input = tests[i];
for (int variable = 0; variable < int (test_input.is_variable) + 1; variable++)
{
bool is_var = (bool) variable;
test_backend (HARFBUZZ, "hb", is_var, op, op_name, time_unit, test_input);
#ifdef HAVE_FREETYPE
test_backend (FREETYPE, "ft", is_var, op, op_name, time_unit, test_input);
#endif
}
}
}
int main(int argc, char** argv)
{
benchmark::Initialize(&argc, argv);
if (argc > 1)
{
num_tests = argc - 1;
tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
for (unsigned i = 0; i < num_tests; i++)
{
tests[i].is_variable = true;
tests[i].font_path = argv[i + 1];
}
}
#define TEST_OPERATION(op, time_unit) test_operation (op, #op, time_unit)
TEST_OPERATION (nominal_glyphs, benchmark::kMicrosecond);
TEST_OPERATION (glyph_h_advances, benchmark::kMicrosecond);
TEST_OPERATION (glyph_extents, benchmark::kMicrosecond);
TEST_OPERATION (glyph_shape, benchmark::kMicrosecond);
#undef TEST_OPERATION
benchmark::RunSpecifiedBenchmarks();
benchmark::Shutdown();
if (tests != default_tests)
free (tests);
}

View File

@ -1,68 +0,0 @@
/*
* Benchmarks for hb_map_t operations.
*/
#include "benchmark/benchmark.h"
#include <cassert>
#include <cstdlib>
#include "hb.h"
void RandomMap(unsigned size, hb_map_t* out) {
hb_map_clear(out);
srand(size);
for (unsigned i = 0; i < size; i++) {
while (true) {
hb_codepoint_t next = rand();
if (hb_map_has (out, next)) continue;
hb_map_set (out, next, rand ());
break;
}
}
}
/* Insert a single value into map of varying sizes. */
static void BM_MapInsert(benchmark::State& state) {
unsigned map_size = state.range(0);
hb_map_t* original = hb_map_create ();
RandomMap(map_size, original);
assert(hb_map_get_population(original) == map_size);
auto needle = map_size / 2;
auto v = 0;
for (auto _ : state) {
// TODO(garretrieger): create a copy of the original map.
// Needs a hb_map_copy(..) in public api.
hb_map_set (original, needle++, v++);
}
hb_map_destroy(original);
}
BENCHMARK(BM_MapInsert)
->Range(1 << 4, 1 << 20);
/* Single value lookup on map of various sizes. */
static void BM_MapLookup(benchmark::State& state) {
unsigned map_size = state.range(0);
hb_map_t* original = hb_map_create ();
RandomMap(map_size, original);
assert(hb_map_get_population(original) == map_size);
auto needle = map_size / 2;
for (auto _ : state) {
benchmark::DoNotOptimize(
hb_map_get (original, needle++));
}
hb_map_destroy(original);
}
BENCHMARK(BM_MapLookup)
->Range(1 << 4, 1 << 20); // Map size
BENCHMARK_MAIN();

View File

@ -1,44 +0,0 @@
/*
* Benchmarks for hb_set_t operations.
*/
#include "benchmark/benchmark.h"
#include "hb-ot.h"
static void BM_hb_ot_tags_from_script_and_language (benchmark::State& state,
hb_script_t script,
const char *language_str) {
hb_language_t language = hb_language_from_string (language_str, -1);
for (auto _ : state)
{
hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
unsigned script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
unsigned language_count = HB_OT_MAX_TAGS_PER_LANGUAGE;
hb_ot_tags_from_script_and_language (script,
language,
&script_count /* IN/OUT */,
script_tags /* OUT */,
&language_count /* IN/OUT */,
language_tags /* OUT */);
}
}
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON zh_abcd, HB_SCRIPT_COMMON, "zh_abcd");
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON zh_hans, HB_SCRIPT_COMMON, "zh_hans");
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON ab_abcd, HB_SCRIPT_COMMON, "ab_abcd");
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON ab_abc, HB_SCRIPT_COMMON, "ab_abc");
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON abcdef_XY, HB_SCRIPT_COMMON, "abcdef_XY");
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON abcd_XY, HB_SCRIPT_COMMON, "abcd_XY");
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON cxy_CN, HB_SCRIPT_COMMON, "cxy_CN");
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON exy_CN, HB_SCRIPT_COMMON, "exy_CN");
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON zh_CN, HB_SCRIPT_COMMON, "zh_CN");
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON en_US, HB_SCRIPT_COMMON, "en_US");
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, LATIN en_US, HB_SCRIPT_LATIN, "en_US");
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON none, HB_SCRIPT_LATIN, nullptr);
BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, LATIN none, HB_SCRIPT_LATIN, nullptr);
BENCHMARK_MAIN();

View File

@ -1,151 +0,0 @@
/*
* Benchmarks for hb_set_t operations.
*/
#include "benchmark/benchmark.h"
#include <cassert>
#include <cstdlib>
#include "hb.h"
void RandomSet(unsigned size, unsigned max_value, hb_set_t* out) {
hb_set_clear(out);
srand(size * max_value);
for (unsigned i = 0; i < size; i++) {
while (true) {
unsigned next = rand() % max_value;
if (hb_set_has (out, next)) continue;
hb_set_add(out, next);
break;
}
}
}
// TODO(garretrieger): benchmark union/subtract/intersection etc.
/* Insert a 1000 values into set of varying sizes. */
static void BM_SetInsert_1000(benchmark::State& state) {
unsigned set_size = state.range(0);
unsigned max_value = state.range(0) * state.range(1);
hb_set_t* original = hb_set_create ();
RandomSet(set_size, max_value, original);
assert(hb_set_get_population(original) == set_size);
for (auto _ : state) {
state.PauseTiming ();
hb_set_t* data = hb_set_copy(original);
state.ResumeTiming ();
for (int i = 0; i < 1000; i++) {
hb_set_add(data, i * 2654435761u % max_value);
}
hb_set_destroy(data);
}
hb_set_destroy(original);
}
BENCHMARK(BM_SetInsert_1000)
->Unit(benchmark::kMicrosecond)
->Ranges(
{{1 << 10, 1 << 16}, // Set Size
{2, 512}}); // Density
/* Insert a 1000 values into set of varying sizes. */
static void BM_SetOrderedInsert_1000(benchmark::State& state) {
unsigned set_size = state.range(0);
unsigned max_value = state.range(0) * state.range(1);
hb_set_t* original = hb_set_create ();
RandomSet(set_size, max_value, original);
assert(hb_set_get_population(original) == set_size);
for (auto _ : state) {
state.PauseTiming ();
hb_set_t* data = hb_set_copy(original);
state.ResumeTiming ();
for (int i = 0; i < 1000; i++) {
hb_set_add(data, i);
}
hb_set_destroy(data);
}
hb_set_destroy(original);
}
BENCHMARK(BM_SetOrderedInsert_1000)
->Unit(benchmark::kMicrosecond)
->Ranges(
{{1 << 10, 1 << 16}, // Set Size
{2, 512}}); // Density
/* Single value lookup on sets of various sizes. */
static void BM_SetLookup(benchmark::State& state, unsigned interval) {
unsigned set_size = state.range(0);
unsigned max_value = state.range(0) * state.range(1);
hb_set_t* original = hb_set_create ();
RandomSet(set_size, max_value, original);
assert(hb_set_get_population(original) == set_size);
auto needle = max_value / 2;
for (auto _ : state) {
benchmark::DoNotOptimize(
hb_set_has (original, (needle += interval) % max_value));
}
hb_set_destroy(original);
}
BENCHMARK_CAPTURE(BM_SetLookup, ordered, 3)
->Ranges(
{{1 << 10, 1 << 16}, // Set Size
{2, 512}}); // Density
BENCHMARK_CAPTURE(BM_SetLookup, random, 12345)
->Ranges(
{{1 << 10, 1 << 16}, // Set Size
{2, 512}}); // Density
/* Full iteration of sets of varying sizes. */
static void BM_SetIteration(benchmark::State& state) {
unsigned set_size = state.range(0);
unsigned max_value = state.range(0) * state.range(1);
hb_set_t* original = hb_set_create ();
RandomSet(set_size, max_value, original);
assert(hb_set_get_population(original) == set_size);
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
for (auto _ : state) {
hb_set_next (original, &cp);
}
hb_set_destroy(original);
}
BENCHMARK(BM_SetIteration)
->Ranges(
{{1 << 10, 1 << 16}, // Set Size
{2, 512}}); // Density
/* Set copy. */
static void BM_SetCopy(benchmark::State& state) {
unsigned set_size = state.range(0);
unsigned max_value = state.range(0) * state.range(1);
hb_set_t* original = hb_set_create ();
RandomSet(set_size, max_value, original);
assert(hb_set_get_population(original) == set_size);
for (auto _ : state) {
hb_set_t *s = hb_set_create ();
hb_set_set (s, original);
hb_set_destroy (s);
}
hb_set_destroy(original);
}
BENCHMARK(BM_SetCopy)
->Unit(benchmark::kMicrosecond)
->Ranges(
{{1 << 10, 1 << 16}, // Set Size
{2, 512}}); // Density
BENCHMARK_MAIN();

View File

@ -1,180 +0,0 @@
#include "benchmark/benchmark.h"
#include <cstring>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <cassert>
#include "hb.h"
#include "hb-ot.h"
#ifdef HAVE_FREETYPE
#include "hb-ft.h"
#endif
#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
struct test_input_t
{
const char *font_path;
const char *text_path;
bool is_variable;
} default_tests[] =
{
{"perf/fonts/NotoNastaliqUrdu-Regular.ttf",
"perf/texts/fa-thelittleprince.txt",
false},
{"perf/fonts/NotoNastaliqUrdu-Regular.ttf",
"perf/texts/fa-words.txt",
false},
{"perf/fonts/Amiri-Regular.ttf",
"perf/texts/fa-thelittleprince.txt",
false},
{SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf",
"perf/texts/hi-words.txt",
false},
{"perf/fonts/Roboto-Regular.ttf",
"perf/texts/en-thelittleprince.txt",
false},
{"perf/fonts/Roboto-Regular.ttf",
"perf/texts/en-words.txt",
false},
{SUBSET_FONT_BASE_PATH "SourceSerifVariable-Roman.ttf",
"perf/texts/en-thelittleprince.txt",
true},
};
static test_input_t *tests = default_tests;
static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
enum backend_t { HARFBUZZ, FREETYPE };
static void BM_Shape (benchmark::State &state,
bool is_var,
backend_t backend,
const test_input_t &input)
{
hb_font_t *font;
{
hb_blob_t *blob = hb_blob_create_from_file_or_fail (input.font_path);
assert (blob);
hb_face_t *face = hb_face_create (blob, 0);
hb_blob_destroy (blob);
font = hb_font_create (face);
hb_face_destroy (face);
}
if (is_var)
{
hb_variation_t wght = {HB_TAG ('w','g','h','t'), 500};
hb_font_set_variations (font, &wght, 1);
}
switch (backend)
{
case HARFBUZZ:
hb_ot_font_set_funcs (font);
break;
case FREETYPE:
#ifdef HAVE_FREETYPE
hb_ft_font_set_funcs (font);
#endif
break;
}
hb_blob_t *text_blob = hb_blob_create_from_file_or_fail (input.text_path);
assert (text_blob);
unsigned orig_text_length;
const char *orig_text = hb_blob_get_data (text_blob, &orig_text_length);
hb_buffer_t *buf = hb_buffer_create ();
for (auto _ : state)
{
unsigned text_length = orig_text_length;
const char *text = orig_text;
const char *end;
while ((end = (const char *) memchr (text, '\n', text_length)))
{
hb_buffer_clear_contents (buf);
hb_buffer_add_utf8 (buf, text, text_length, 0, end - text);
hb_buffer_guess_segment_properties (buf);
hb_shape (font, buf, nullptr, 0);
unsigned skip = end - text + 1;
text_length -= skip;
text += skip;
}
}
hb_buffer_destroy (buf);
hb_blob_destroy (text_blob);
hb_font_destroy (font);
}
static void test_backend (backend_t backend,
const char *backend_name,
bool variable,
const test_input_t &test_input)
{
char name[1024] = "BM_Shape";
const char *p;
strcat (name, "/");
p = strrchr (test_input.font_path, '/');
strcat (name, p ? p + 1 : test_input.font_path);
strcat (name, "/");
p = strrchr (test_input.text_path, '/');
strcat (name, p ? p + 1 : test_input.text_path);
strcat (name, variable ? "/var" : "");
strcat (name, "/");
strcat (name, backend_name);
benchmark::RegisterBenchmark (name, BM_Shape, variable, backend, test_input)
->Unit(benchmark::kMillisecond);
}
int main(int argc, char** argv)
{
benchmark::Initialize(&argc, argv);
if (argc > 2)
{
num_tests = (argc - 1) / 2;
tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
for (unsigned i = 0; i < num_tests; i++)
{
tests[i].is_variable = true;
tests[i].font_path = argv[1 + i * 2];
tests[i].text_path = argv[2 + i * 2];
}
}
for (unsigned i = 0; i < num_tests; i++)
{
auto& test_input = tests[i];
for (int variable = 0; variable < int (test_input.is_variable) + 1; variable++)
{
bool is_var = (bool) variable;
test_backend (HARFBUZZ, "hb", is_var, test_input);
#ifdef HAVE_FREETYPE
test_backend (FREETYPE, "ft", is_var, test_input);
#endif
}
}
benchmark::RunSpecifiedBenchmarks();
benchmark::Shutdown();
if (tests != default_tests)
free (tests);
}

View File

@ -1,259 +0,0 @@
#include "benchmark/benchmark.h"
#include <cassert>
#include <cstring>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "hb-subset.h"
enum operation_t
{
subset_codepoints,
subset_glyphs,
instance,
};
struct axis_location_t
{
hb_tag_t axis_tag;
float axis_value;
};
static const axis_location_t
_roboto_flex_instance_opts[] =
{
{HB_TAG ('w', 'g', 'h', 't'), 600.f},
{HB_TAG ('w', 'd', 't', 'h'), 75.f},
{HB_TAG ('o', 'p', 's', 'z'), 90.f},
{HB_TAG ('G', 'R', 'A', 'D'), -100.f},
{HB_TAG ('s', 'l', 'n', 't'), -3.f},
{HB_TAG ('X', 'T', 'R', 'A'), 500.f},
{HB_TAG ('X', 'O', 'P', 'Q'), 150.f},
{HB_TAG ('Y', 'O', 'P', 'Q'), 100.f},
{HB_TAG ('Y', 'T', 'L', 'C'), 480.f},
{HB_TAG ('Y', 'T', 'U', 'C'), 600.f},
{HB_TAG ('Y', 'T', 'A', 'S'), 800.f},
{HB_TAG ('Y', 'T', 'D', 'E'), -50.f},
{HB_TAG ('Y', 'T', 'F', 'I'), 600.f},
};
static const axis_location_t
_mplus_instance_opts[] =
{
{HB_TAG ('w', 'g', 'h', 't'), 800.f},
};
template <typename Type, unsigned int n>
static inline unsigned int ARRAY_LEN (const Type (&)[n]) { return n; }
#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
struct test_input_t
{
const char *font_path;
unsigned max_subset_size;
const axis_location_t *instance_opts;
unsigned num_instance_opts;
} default_tests[] =
{
{SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf", 1000, nullptr, 0},
{SUBSET_FONT_BASE_PATH "Amiri-Regular.ttf", 4096, nullptr, 0},
{SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf", 1400, nullptr, 0},
{SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf", 1000, nullptr, 0},
{SUBSET_FONT_BASE_PATH "Mplus1p-Regular.ttf", 10000, nullptr, 0},
{SUBSET_FONT_BASE_PATH "SourceHanSans-Regular_subset.otf", 10000, nullptr, 0},
{SUBSET_FONT_BASE_PATH "SourceSansPro-Regular.otf", 2000, nullptr, 0},
{SUBSET_FONT_BASE_PATH "AdobeVFPrototype.otf", 300, nullptr, 0},
{SUBSET_FONT_BASE_PATH "MPLUS1-Variable.ttf", 6000, _mplus_instance_opts, ARRAY_LEN (_mplus_instance_opts)},
{SUBSET_FONT_BASE_PATH "RobotoFlex-Variable.ttf", 900, _roboto_flex_instance_opts, ARRAY_LEN (_roboto_flex_instance_opts)},
#if 0
{"perf/fonts/NotoSansCJKsc-VF.ttf", 100000},
#endif
};
static test_input_t *tests = default_tests;
static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
void AddCodepoints(const hb_set_t* codepoints_in_font,
unsigned subset_size,
hb_subset_input_t* input)
{
auto *unicodes = hb_subset_input_unicode_set (input);
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
for (unsigned i = 0; i < subset_size; i++) {
// TODO(garretrieger): pick randomly.
if (!hb_set_next (codepoints_in_font, &cp)) return;
hb_set_add (unicodes, cp);
}
}
void AddGlyphs(unsigned num_glyphs_in_font,
unsigned subset_size,
hb_subset_input_t* input)
{
auto *glyphs = hb_subset_input_glyph_set (input);
for (unsigned i = 0; i < subset_size && i < num_glyphs_in_font; i++) {
// TODO(garretrieger): pick randomly.
hb_set_add (glyphs, i);
}
}
// Preprocess face and populate the subset accelerator on it to speed up
// the subsetting operations.
static hb_face_t* preprocess_face(hb_face_t* face)
{
hb_face_t* new_face = hb_subset_preprocess(face);
hb_face_destroy(face);
return new_face;
}
/* benchmark for subsetting a font */
static void BM_subset (benchmark::State &state,
operation_t operation,
const test_input_t &test_input,
bool hinting)
{
unsigned subset_size = state.range(0);
hb_face_t *face = nullptr;
static hb_face_t *cached_face;
static const char *cached_font_path;
if (!cached_font_path || strcmp (cached_font_path, test_input.font_path))
{
hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
assert (blob);
face = hb_face_create (blob, 0);
hb_blob_destroy (blob);
face = preprocess_face (face);
if (cached_face)
hb_face_destroy (cached_face);
cached_face = hb_face_reference (face);
cached_font_path = test_input.font_path;
}
else
face = hb_face_reference (cached_face);
hb_subset_input_t* input = hb_subset_input_create_or_fail ();
assert (input);
if (!hinting)
hb_subset_input_set_flags (input, HB_SUBSET_FLAGS_NO_HINTING);
switch (operation)
{
case subset_codepoints:
{
hb_set_t* all_codepoints = hb_set_create ();
hb_face_collect_unicodes (face, all_codepoints);
AddCodepoints(all_codepoints, subset_size, input);
hb_set_destroy (all_codepoints);
}
break;
case subset_glyphs:
{
unsigned num_glyphs = hb_face_get_glyph_count (face);
AddGlyphs(num_glyphs, subset_size, input);
}
break;
case instance:
{
hb_set_t* all_codepoints = hb_set_create ();
hb_face_collect_unicodes (face, all_codepoints);
AddCodepoints(all_codepoints, subset_size, input);
hb_set_destroy (all_codepoints);
for (unsigned i = 0; i < test_input.num_instance_opts; i++)
hb_subset_input_pin_axis_location (input, face,
test_input.instance_opts[i].axis_tag,
test_input.instance_opts[i].axis_value);
}
break;
}
for (auto _ : state)
{
hb_face_t* subset = hb_subset_or_fail (face, input);
assert (subset);
hb_face_destroy (subset);
}
hb_subset_input_destroy (input);
hb_face_destroy (face);
}
static void test_subset (operation_t op,
const char *op_name,
bool hinting,
benchmark::TimeUnit time_unit,
const test_input_t &test_input)
{
if (op == instance && test_input.instance_opts == nullptr)
return;
char name[1024] = "BM_subset/";
strcat (name, op_name);
strcat (name, "/");
const char *p = strrchr (test_input.font_path, '/');
strcat (name, p ? p + 1 : test_input.font_path);
if (!hinting)
strcat (name, "/nohinting");
benchmark::RegisterBenchmark (name, BM_subset, op, test_input, hinting)
->Range(10, test_input.max_subset_size)
->Unit(time_unit);
}
static void test_operation (operation_t op,
const char *op_name,
const test_input_t *tests,
unsigned num_tests,
benchmark::TimeUnit time_unit)
{
for (unsigned i = 0; i < num_tests; i++)
{
auto& test_input = tests[i];
test_subset (op, op_name, true, time_unit, test_input);
test_subset (op, op_name, false, time_unit, test_input);
}
}
int main(int argc, char** argv)
{
benchmark::Initialize(&argc, argv);
if (argc > 1)
{
num_tests = (argc - 1) / 2;
tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
for (unsigned i = 0; i < num_tests; i++)
{
tests[i].font_path = argv[1 + i * 2];
tests[i].max_subset_size = atoi (argv[2 + i * 2]);
}
}
#define TEST_OPERATION(op, time_unit) test_operation (op, #op, tests, num_tests, time_unit)
TEST_OPERATION (subset_glyphs, benchmark::kMillisecond);
TEST_OPERATION (subset_codepoints, benchmark::kMillisecond);
TEST_OPERATION (instance, benchmark::kMillisecond);
#undef TEST_OPERATION
benchmark::RunSpecifiedBenchmarks();
benchmark::Shutdown();
if (tests != default_tests)
free (tests);
}

View File

@ -1,62 +1,27 @@
google_benchmark = subproject('google-benchmark')
google_benchmark_dep = google_benchmark.get_variable('google_benchmark_dep')
benchmark('benchmark-font', executable('benchmark-font', 'benchmark-font.cc',
ttf_parser_dep = null_dep
if get_option('experimental_api') and add_languages('rust', required: false, native: true)
ttf_parser_dep = subproject('ttf-parser').get_variable('ttf_parser_dep')
endif
if ttf_parser_dep.found()
benchmark_cpp_args = ['-DHAVE_TTFPARSER']
else
benchmark_cpp_args = []
endif
benchmark('perf', executable('perf', 'perf.cc',
dependencies: [
google_benchmark_dep, freetype_dep,
# the last two, thread and dl, aren't nice as ttf-parser isn't no_std yet
# https://github.com/RazrFalcon/ttf-parser/issues/29
ttf_parser_dep, thread_dep, cpp.find_library('dl'),
],
cpp_args: [],
cpp_args: benchmark_cpp_args,
include_directories: [incconfig, incsrc],
link_with: [libharfbuzz],
install: false,
), workdir: meson.current_source_dir() / '..', timeout: 100)
benchmark('benchmark-map', executable('benchmark-map', 'benchmark-map.cc',
dependencies: [
google_benchmark_dep,
],
cpp_args: [],
include_directories: [incconfig, incsrc],
link_with: [libharfbuzz],
install: false,
), workdir: meson.current_source_dir() / '..', timeout: 100)
benchmark('benchmark-ot', executable('benchmark-ot', 'benchmark-ot.cc',
dependencies: [
google_benchmark_dep,
],
cpp_args: [],
include_directories: [incconfig, incsrc],
link_with: [libharfbuzz],
install: false,
), workdir: meson.current_source_dir() / '..', timeout: 100)
benchmark('benchmark-set', executable('benchmark-set', 'benchmark-set.cc',
dependencies: [
google_benchmark_dep,
],
cpp_args: [],
include_directories: [incconfig, incsrc],
link_with: [libharfbuzz],
install: false,
), workdir: meson.current_source_dir() / '..', timeout: 100)
benchmark('benchmark-shape', executable('benchmark-shape', 'benchmark-shape.cc',
dependencies: [
google_benchmark_dep, freetype_dep,
],
cpp_args: [],
include_directories: [incconfig, incsrc],
link_with: [libharfbuzz],
install: false,
), workdir: meson.current_source_dir() / '..', timeout: 100)
benchmark('benchmark-subset', executable('benchmark-subset', 'benchmark-subset.cc',
dependencies: [
google_benchmark_dep,
],
cpp_args: [],
include_directories: [incconfig, incsrc],
link_with: [libharfbuzz, libharfbuzz_subset],
install: false,
), workdir: meson.current_source_dir() / '..', timeout: 100)
), workdir: join_paths(meson.current_source_dir(), '..'), timeout: 100)

177
perf/perf-draw.hh Normal file
View File

@ -0,0 +1,177 @@
#include "benchmark/benchmark.h"
#include "hb.h"
#include "hb-ot.h"
#include "hb-ft.h"
#include FT_OUTLINE_H
#ifdef HAVE_TTFPARSER
#include "ttfparser.h"
#endif
#define HB_UNUSED __attribute__((unused))
static void
_hb_move_to (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
static void
_hb_line_to (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
static void
_hb_quadratic_to (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED,
hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
static void
_hb_cubic_to (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED,
hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED,
hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
static void
_hb_close_path (void *user_data HB_UNUSED) {}
static void
_ft_move_to (const FT_Vector* to HB_UNUSED, void* user HB_UNUSED) {}
static void
_ft_line_to (const FT_Vector* to HB_UNUSED, void* user HB_UNUSED) {}
static void
_ft_conic_to (const FT_Vector* control HB_UNUSED, const FT_Vector* to HB_UNUSED,
void* user HB_UNUSED) {}
static void
_ft_cubic_to (const FT_Vector* control1 HB_UNUSED, const FT_Vector* control2 HB_UNUSED,
const FT_Vector* to HB_UNUSED, void* user HB_UNUSED) {}
#ifdef HAVE_TTFPARSER
static void _tp_move_to (float x HB_UNUSED, float y HB_UNUSED, void *data HB_UNUSED) {}
static void _tp_line_to (float x, float y, void *data) {}
static void _tp_quad_to (float x1, float y1, float x, float y, void *data) {}
static void _tp_curve_to (float x1, float y1, float x2, float y2, float x, float y, void *data) {}
static void _tp_close_path (void *data) {}
#endif
static void draw (benchmark::State &state, const char *font_path, bool is_var, backend_t backend)
{
hb_font_t *font;
unsigned num_glyphs;
{
hb_blob_t *blob = hb_blob_create_from_file (font_path);
assert (hb_blob_get_length (blob));
hb_face_t *face = hb_face_create (blob, 0);
hb_blob_destroy (blob);
num_glyphs = hb_face_get_glyph_count (face);
font = hb_font_create (face);
hb_face_destroy (face);
}
if (backend == HARFBUZZ)
{
if (is_var)
{
hb_variation_t wght = {HB_TAG ('w','g','h','t'), 500};
hb_font_set_variations (font, &wght, 1);
}
hb_draw_funcs_t *draw_funcs = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (draw_funcs, _hb_move_to);
hb_draw_funcs_set_line_to_func (draw_funcs, _hb_line_to);
hb_draw_funcs_set_quadratic_to_func (draw_funcs, _hb_quadratic_to);
hb_draw_funcs_set_cubic_to_func (draw_funcs, _hb_cubic_to);
hb_draw_funcs_set_close_path_func (draw_funcs, _hb_close_path);
for (auto _ : state)
for (unsigned gid = 0; gid < num_glyphs; ++gid)
hb_font_draw_glyph (font, gid, draw_funcs, nullptr);
hb_draw_funcs_destroy (draw_funcs);
}
else if (backend == FREETYPE)
{
if (is_var)
{
hb_variation_t wght = {HB_TAG ('w','g','h','t'), 500};
hb_font_set_variations (font, &wght, 1);
}
hb_ft_font_set_funcs (font);
FT_Face ft_face = hb_ft_font_get_face (font);
hb_ft_font_set_load_flags (font, FT_LOAD_NO_HINTING | FT_LOAD_NO_SCALE);
FT_Outline_Funcs draw_funcs;
draw_funcs.move_to = (FT_Outline_MoveToFunc) _ft_move_to;
draw_funcs.line_to = (FT_Outline_LineToFunc) _ft_line_to;
draw_funcs.conic_to = (FT_Outline_ConicToFunc) _ft_conic_to;
draw_funcs.cubic_to = (FT_Outline_CubicToFunc) _ft_cubic_to;
draw_funcs.shift = 0;
draw_funcs.delta = 0;
for (auto _ : state)
for (unsigned gid = 0; gid < num_glyphs; ++gid)
{
FT_Load_Glyph (ft_face, gid, FT_LOAD_NO_HINTING | FT_LOAD_NO_SCALE);
FT_Outline_Decompose (&ft_face->glyph->outline, &draw_funcs, nullptr);
}
}
else if (backend == TTF_PARSER)
{
#ifdef HAVE_TTFPARSER
ttfp_face *tp_font = (ttfp_face *) malloc (ttfp_face_size_of ());
hb_blob_t *blob = hb_face_reference_blob (hb_font_get_face (font));
assert (ttfp_face_init (hb_blob_get_data (blob, nullptr), hb_blob_get_length (blob), 0, tp_font));
if (is_var) ttfp_set_variation (tp_font, TTFP_TAG('w','g','h','t'), 500);
ttfp_outline_builder builder;
builder.move_to = _tp_move_to;
builder.line_to = _tp_line_to;
builder.quad_to = _tp_quad_to;
builder.curve_to = _tp_curve_to;
builder.close_path = _tp_close_path;
ttfp_rect bbox;
for (auto _ : state)
for (unsigned gid = 0; gid < num_glyphs; ++gid)
ttfp_outline_glyph (tp_font, builder, &builder, gid, &bbox);
hb_blob_destroy (blob);
free (tp_font);
#endif
}
else abort ();
hb_font_destroy (font);
}
#define FONT_BASE_PATH "test/subset/data/fonts/"
BENCHMARK_CAPTURE (draw, cff - ot - SourceSansPro, FONT_BASE_PATH "SourceSansPro-Regular.otf", false, HARFBUZZ);
BENCHMARK_CAPTURE (draw, cff - ft - SourceSansPro, FONT_BASE_PATH "SourceSansPro-Regular.otf", false, FREETYPE);
BENCHMARK_CAPTURE (draw, cff - tp - SourceSansPro, FONT_BASE_PATH "SourceSansPro-Regular.otf", false, TTF_PARSER);
BENCHMARK_CAPTURE (draw, cff2 - ot - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", false, HARFBUZZ);
BENCHMARK_CAPTURE (draw, cff2 - ft - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", false, FREETYPE);
BENCHMARK_CAPTURE (draw, cff2 - tp - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", false, TTF_PARSER);
BENCHMARK_CAPTURE (draw, cff2/vf - ot - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", true, HARFBUZZ);
BENCHMARK_CAPTURE (draw, cff2/vf - ft - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", true, FREETYPE);
BENCHMARK_CAPTURE (draw, cff2/vf - tp - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", true, TTF_PARSER);
BENCHMARK_CAPTURE (draw, glyf - ot - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", false, HARFBUZZ);
BENCHMARK_CAPTURE (draw, glyf - ft - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", false, FREETYPE);
BENCHMARK_CAPTURE (draw, glyf - tp - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", false, TTF_PARSER);
BENCHMARK_CAPTURE (draw, glyf/vf - ot - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", true, HARFBUZZ);
BENCHMARK_CAPTURE (draw, glyf/vf - ft - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", true, FREETYPE);
BENCHMARK_CAPTURE (draw, glyf/vf - tp - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", true, TTF_PARSER);
BENCHMARK_CAPTURE (draw, glyf - ot - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", false, HARFBUZZ);
BENCHMARK_CAPTURE (draw, glyf - ft - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", false, FREETYPE);
BENCHMARK_CAPTURE (draw, glyf - tp - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", false, TTF_PARSER);
BENCHMARK_CAPTURE (draw, glyf/vf - ot - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", true, HARFBUZZ);
BENCHMARK_CAPTURE (draw, glyf/vf - ft - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", true, FREETYPE);
BENCHMARK_CAPTURE (draw, glyf/vf - tp - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", true, TTF_PARSER);
BENCHMARK_CAPTURE (draw, glyf - ot - Roboto, FONT_BASE_PATH "Roboto-Regular.ttf", false, HARFBUZZ);
BENCHMARK_CAPTURE (draw, glyf - ft - Roboto, FONT_BASE_PATH "Roboto-Regular.ttf", false, FREETYPE);
BENCHMARK_CAPTURE (draw, glyf - tp - Roboto, FONT_BASE_PATH "Roboto-Regular.ttf", false, TTF_PARSER);

98
perf/perf-extents.hh Normal file
View File

@ -0,0 +1,98 @@
#include "benchmark/benchmark.h"
#include "hb.h"
#include "hb-ft.h"
#include "hb-ot.h"
#ifdef HAVE_TTFPARSER
#include "ttfparser.h"
#endif
static void extents (benchmark::State &state, const char *font_path, bool is_var, backend_t backend)
{
hb_font_t *font;
unsigned num_glyphs;
{
hb_blob_t *blob = hb_blob_create_from_file (font_path);
assert (hb_blob_get_length (blob));
hb_face_t *face = hb_face_create (blob, 0);
hb_blob_destroy (blob);
num_glyphs = hb_face_get_glyph_count (face);
font = hb_font_create (face);
hb_face_destroy (face);
}
if (is_var)
{
hb_variation_t wght = {HB_TAG ('w','g','h','t'), 500};
hb_font_set_variations (font, &wght, 1);
}
if (backend == HARFBUZZ || backend == FREETYPE)
{
if (backend == FREETYPE)
{
hb_ft_font_set_funcs (font);
hb_ft_font_set_load_flags (font, FT_LOAD_NO_HINTING | FT_LOAD_NO_SCALE);
}
hb_glyph_extents_t extents;
for (auto _ : state)
for (unsigned gid = 0; gid < num_glyphs; ++gid)
hb_font_get_glyph_extents (font, gid, &extents);
}
else if (backend == TTF_PARSER)
{
#ifdef HAVE_TTFPARSER
ttfp_face *tp_font = (ttfp_face *) malloc (ttfp_face_size_of ());
hb_blob_t *blob = hb_face_reference_blob (hb_font_get_face (font));
assert (ttfp_face_init (hb_blob_get_data (blob, nullptr), hb_blob_get_length (blob), 0, tp_font));
if (is_var) ttfp_set_variation (tp_font, TTFP_TAG('w','g','h','t'), 500);
ttfp_rect bbox;
for (auto _ : state)
for (unsigned gid = 0; gid < num_glyphs; ++gid)
ttfp_get_glyph_bbox(tp_font, gid, &bbox);
hb_blob_destroy (blob);
free (tp_font);
#endif
}
hb_font_destroy (font);
}
#define FONT_BASE_PATH "test/subset/data/fonts/"
BENCHMARK_CAPTURE (extents, cff - ot - SourceSansPro, FONT_BASE_PATH "SourceSansPro-Regular.otf", false, HARFBUZZ);
BENCHMARK_CAPTURE (extents, cff - ft - SourceSansPro, FONT_BASE_PATH "SourceSansPro-Regular.otf", false, FREETYPE);
BENCHMARK_CAPTURE (extents, cff - tp - SourceSansPro, FONT_BASE_PATH "SourceSansPro-Regular.otf", false, TTF_PARSER);
BENCHMARK_CAPTURE (extents, cff2 - ot - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", false, HARFBUZZ);
BENCHMARK_CAPTURE (extents, cff2 - ft - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", false, FREETYPE);
BENCHMARK_CAPTURE (extents, cff2 - tp - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", false, TTF_PARSER);
BENCHMARK_CAPTURE (extents, cff2/vf - ot - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", true, HARFBUZZ);
BENCHMARK_CAPTURE (extents, cff2/vf - ft - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", true, FREETYPE);
BENCHMARK_CAPTURE (extents, cff2/vf - tp - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", true, TTF_PARSER);
BENCHMARK_CAPTURE (extents, glyf - ot - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", false, HARFBUZZ);
BENCHMARK_CAPTURE (extents, glyf - ft - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", false, FREETYPE);
BENCHMARK_CAPTURE (extents, glyf - tp - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", false, TTF_PARSER);
BENCHMARK_CAPTURE (extents, glyf/vf - ot - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", true, HARFBUZZ);
BENCHMARK_CAPTURE (extents, glyf/vf - ft - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", true, FREETYPE);
BENCHMARK_CAPTURE (extents, glyf/vf - tp - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", true, TTF_PARSER);
BENCHMARK_CAPTURE (extents, glyf - ot - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", false, HARFBUZZ);
BENCHMARK_CAPTURE (extents, glyf - ft - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", false, FREETYPE);
BENCHMARK_CAPTURE (extents, glyf - tp - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", false, TTF_PARSER);
BENCHMARK_CAPTURE (extents, glyf/vf - ot - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", true, HARFBUZZ);
BENCHMARK_CAPTURE (extents, glyf/vf - ft - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", true, FREETYPE);
BENCHMARK_CAPTURE (extents, glyf/vf - tp - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", true, TTF_PARSER);
BENCHMARK_CAPTURE (extents, glyf - ot - Roboto, FONT_BASE_PATH "Roboto-Regular.ttf", false, HARFBUZZ);
BENCHMARK_CAPTURE (extents, glyf - ft - Roboto, FONT_BASE_PATH "Roboto-Regular.ttf", false, FREETYPE);
BENCHMARK_CAPTURE (extents, glyf - tp - Roboto, FONT_BASE_PATH "Roboto-Regular.ttf", false, TTF_PARSER);

65
perf/perf-shaping.hh Normal file
View File

@ -0,0 +1,65 @@
#include "benchmark/benchmark.h"
#include "hb.h"
static void shape (benchmark::State &state, const char *text_path,
hb_direction_t direction, hb_script_t script,
const char *font_path)
{
hb_font_t *font;
{
hb_blob_t *blob = hb_blob_create_from_file (font_path);
assert (hb_blob_get_length (blob));
hb_face_t *face = hb_face_create (blob, 0);
hb_blob_destroy (blob);
font = hb_font_create (face);
hb_face_destroy (face);
}
hb_blob_t *text_blob = hb_blob_create_from_file (text_path);
unsigned text_length;
const char *text = hb_blob_get_data (text_blob, &text_length);
assert (text_length);
hb_buffer_t *buf = hb_buffer_create ();
for (auto _ : state)
{
hb_buffer_add_utf8 (buf, text, text_length, 0, -1);
hb_buffer_set_direction (buf, direction);
hb_buffer_set_script (buf, script);
hb_shape (font, buf, nullptr, 0);
hb_buffer_clear_contents (buf);
}
hb_buffer_destroy (buf);
hb_blob_destroy (text_blob);
hb_font_destroy (font);
}
BENCHMARK_CAPTURE (shape, fa-thelittleprince.txt - Amiri,
"perf/texts/fa-thelittleprince.txt",
HB_DIRECTION_RTL, HB_SCRIPT_ARABIC,
"perf/fonts/Amiri-Regular.ttf");
BENCHMARK_CAPTURE (shape, fa-thelittleprince.txt - NotoNastaliqUrdu,
"perf/texts/fa-thelittleprince.txt",
HB_DIRECTION_RTL, HB_SCRIPT_ARABIC,
"perf/fonts/NotoNastaliqUrdu-Regular.ttf");
BENCHMARK_CAPTURE (shape, fa-monologue.txt - Amiri,
"perf/texts/fa-monologue.txt",
HB_DIRECTION_RTL, HB_SCRIPT_ARABIC,
"perf/fonts/Amiri-Regular.ttf");
BENCHMARK_CAPTURE (shape, fa-monologue.txt - NotoNastaliqUrdu,
"perf/texts/fa-monologue.txt",
HB_DIRECTION_RTL, HB_SCRIPT_ARABIC,
"perf/fonts/NotoNastaliqUrdu-Regular.ttf");
BENCHMARK_CAPTURE (shape, en-thelittleprince.txt - Roboto,
"perf/texts/en-thelittleprince.txt",
HB_DIRECTION_LTR, HB_SCRIPT_LATIN,
"perf/fonts/Roboto-Regular.ttf");
BENCHMARK_CAPTURE (shape, en-words.txt - Roboto,
"perf/texts/en-words.txt",
HB_DIRECTION_LTR, HB_SCRIPT_LATIN,
"perf/fonts/Roboto-Regular.ttf");

16
perf/perf.cc Normal file
View File

@ -0,0 +1,16 @@
#include "benchmark/benchmark.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "perf-shaping.hh"
#ifdef HAVE_FREETYPE
enum backend_t { HARFBUZZ, FREETYPE, TTF_PARSER };
#include "perf-extents.hh"
#ifdef HB_EXPERIMENTAL_API
#include "perf-draw.hh"
#endif
#endif
BENCHMARK_MAIN ();

25
perf/run.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
CXX=clang++
FONT=fonts/NotoNastaliqUrdu-Regular.ttf
TEXT=texts/fa-monologue.txt
$CXX ../util/hb-shape.cc ../util/options.cc ../src/harfbuzz.cc \
-lm -fno-rtti -fno-exceptions -fno-omit-frame-pointer -DHB_NO_MT \
-I../src $FLAGS $SOURCES \
-DPACKAGE_NAME='""' -DPACKAGE_VERSION='""' \
-DHAVE_GLIB $(pkg-config --cflags --libs glib-2.0) \
-o hb-shape -g -O2 # -O3 \
#-march=native -mtune=native \
#-Rpass=loop-vectorize -Rpass-missed=loop-vectorize \
#-Rpass-analysis=loop-vectorize -fsave-optimization-record
# -march=native: enable all vector instructions current CPU can offer
# -Rpass*: https://llvm.org/docs/Vectorizers.html#diagnostics
#sudo rm capture.syscap > /dev/null
#sysprof-cli -c "./a.out $@"
#sysprof capture.syscap
perf stat ./hb-shape -o /dev/null $FONT --text-file $TEXT --num-iterations=100 --font-funcs=ot
#perf record -g ./hb-shape -O '' -o /dev/null $FONT --text-file $TEXT --num-iterations=100 --font-funcs=ot
#perf report -g

View File

@ -2841,6 +2841,7 @@ Deseret
DESERET
deserialize
DESERIALIZE
desgined
design
Design
DESIGN
@ -4782,7 +4783,7 @@ hb
HB
HBASELINE
HBFixed
HBGlyphID16
HBGlyphID
HBINT
hbot
hbotABCD

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,250 +0,0 @@
#
# Name: Legacy Simplified Arabic encoding
#
# Format: Three tab-separated columns
# Column #1 is the PUA code (in hex as 0xXXXX)
# Column #2 is the Unicode (in hex as 0xXXXX)
# Column #3 is the Unicode name (follows a comment sign, '#')
#
# The entries are in PUA order
#
0xF100 0x063B # ARABIC LETTER KEHEH WITH TWO DOTS ABOVE
0xF100 0x063C # ARABIC LETTER KEHEH WITH THREE DOTS BELOW
0xF100 0x063D # ARABIC LETTER FARSI YEH WITH INVERTED V
0xF100 0x063E # ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE
0xF100 0x063F # ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
0xF100 0x0653 # ARABIC MADDAH ABOVE
0xF100 0x0654 # ARABIC HAMZA ABOVE
0xF100 0x0655 # ARABIC HAMZA BELOW
0xF100 0x0656 # ARABIC SUBSCRIPT ALEF
0xF100 0x0657 # ARABIC INVERTED DAMMA
0xF100 0x0658 # ARABIC MARK NOON GHUNNA
0xF100 0x0659 # ARABIC ZWARAKAY
0xF100 0x065A # ARABIC VOWEL SIGN SMALL V ABOVE
0xF100 0x065B # ARABIC VOWEL SIGN INVERTED SMALL V ABOVE
0xF100 0x065C # ARABIC VOWEL SIGN DOT BELOW
0xF100 0x065D # ARABIC REVERSED DAMMA
0xF100 0x065E # ARABIC FATHA WITH TWO DOTS
0xF10C 0x200C # ZERO WIDTH NON-JOINER
0xF10D 0x200D # ZERO WIDTH JOINER
0xF10E 0x200E # LEFT-TO-RIGHT MARK
0xF10F 0x200F # RIGHT-TO-LEFT MARK
0xF120 0x0020 # SPACE
0xF121 0x0021 # EXCLAMATION MARK
0xF122 0x0022 # QUOTATION MARK
0xF123 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
0xF124 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
0xF125 0x0025 # PERCENT SIGN
0xF126 0x00D7 # MULTIPLICATION SIGN
0xF127 0x00F7 # DIVISION SIGN
0xF128 0x0028 # LEFT PARENTHESIS
0xF129 0x0029 # RIGHT PARENTHESIS
0xF12A 0x002A # ASTERISK
0xF12B 0x002B # PLUS SIGN
0xF12C 0x060C # ARABIC COMMA
0xF12D 0x002D # HYPHEN-MINUS
0xF12E 0x002E # FULL STOP
0xF12F 0x002F # SOLIDUS
0xF130 0x0660 # ARABIC-INDIC DIGIT ZERO
0xF131 0x0661 # ARABIC-INDIC DIGIT ONE
0xF132 0x0662 # ARABIC-INDIC DIGIT TWO
0xF133 0x0663 # ARABIC-INDIC DIGIT THREE
0xF134 0x0664 # ARABIC-INDIC DIGIT FOUR
0xF135 0x0665 # ARABIC-INDIC DIGIT FIVE
0xF136 0x0666 # ARABIC-INDIC DIGIT SIX
0xF137 0x0667 # ARABIC-INDIC DIGIT SEVEN
0xF138 0x0668 # ARABIC-INDIC DIGIT EIGHT
0xF139 0x0669 # ARABIC-INDIC DIGIT NINE
0xF13A 0x003A # COLON
0xF13B 0x003B # SEMICOLON
0xF13B 0x061B # ARABIC SEMICOLON
0xF13C 0x2018 # LEFT SINGLE QUOTATION MARK
0xF13D 0x003D # EQUALS SIGN
0xF13E 0x2019 # RIGHT SINGLE QUOTATION MARK
0xF13F 0x003F # QUESTION MARK
0xF13F 0x061F # ARABIC QUESTION MARK
0xF141 0x0627 # ARABIC LETTER ALEF
0xF141 0xFE8D # ARABIC LETTER ALEF ISOLATED FORM
0xF142 0xFE8E # ARABIC LETTER ALEF FINAL FORM
0xF143 0x0623 # ARABIC LETTER ALEF WITH HAMZA ABOVE
0xF143 0xFE83 # ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM
0xF144 0xFE84 # ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
0xF145 0x0622 # ARABIC LETTER ALEF WITH MADDA ABOVE
0xF145 0xFE81 # ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
0xF146 0xFE82 # ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
0xF147 0x0625 # ARABIC LETTER ALEF WITH HAMZA BELOW
0xF147 0xFE87 # ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM
0xF148 0xFE88 # ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM
0xF149 0xFE91 # ARABIC LETTER BEH INITIAL FORM
0xF149 0xFE92 # ARABIC LETTER BEH MEDIAL FORM
0xF14A 0x0628 # ARABIC LETTER BEH
0xF14A 0xFE8F # ARABIC LETTER BEH ISOLATED FORM
0xF14A 0xFE90 # ARABIC LETTER BEH FINAL FORM
0xF14B 0xFE97 # ARABIC LETTER TEH INITIAL FORM
0xF14B 0xFE98 # ARABIC LETTER TEH MEDIAL FORM
0xF14C 0x062A # ARABIC LETTER TEH
0xF14C 0xFE95 # ARABIC LETTER TEH ISOLATED FORM
0xF14C 0xFE96 # ARABIC LETTER TEH FINAL FORM
0xF14D 0xFE9B # ARABIC LETTER THEH INITIAL FORM
0xF14D 0xFE9C # ARABIC LETTER THEH MEDIAL FORM
0xF14E 0x062B # ARABIC LETTER THEH
0xF14E 0xFE99 # ARABIC LETTER THEH ISOLATED FORM
0xF14E 0xFE9A # ARABIC LETTER THEH FINAL FORM
0xF14F 0xFE9F # ARABIC LETTER JEEM INITIAL FORM
0xF14F 0xFEA0 # ARABIC LETTER JEEM MEDIAL FORM
0xF150 0xFE9E # ARABIC LETTER JEEM FINAL FORM
0xF151 0x062C # ARABIC LETTER JEEM
0xF151 0xFE9D # ARABIC LETTER JEEM ISOLATED FORM
0xF152 0xFEA3 # ARABIC LETTER HAH INITIAL FORM
0xF152 0xFEA4 # ARABIC LETTER HAH MEDIAL FORM
0xF153 0xFEA2 # ARABIC LETTER HAH FINAL FORM
0xF154 0x062D # ARABIC LETTER HAH
0xF154 0xFEA1 # ARABIC LETTER HAH ISOLATED FORM
0xF155 0xFEA7 # ARABIC LETTER KHAH INITIAL FORM
0xF155 0xFEA8 # ARABIC LETTER KHAH MEDIAL FORM
0xF156 0xFEA6 # ARABIC LETTER KHAH FINAL FORM
0xF157 0x062E # ARABIC LETTER KHAH
0xF157 0xFEA5 # ARABIC LETTER KHAH ISOLATED FORM
0xF158 0x062F # ARABIC LETTER DAL
0xF158 0xFEA9 # ARABIC LETTER DAL ISOLATED FORM
0xF158 0xFEAA # ARABIC LETTER DAL FINAL FORM
0xF159 0x0630 # ARABIC LETTER THAL
0xF159 0xFEAB # ARABIC LETTER THAL ISOLATED FORM
0xF159 0xFEAC # ARABIC LETTER THAL FINAL FORM
0xF15A 0x0631 # ARABIC LETTER REH
0xF15A 0xFEAD # ARABIC LETTER REH ISOLATED FORM
0xF15A 0xFEAE # ARABIC LETTER REH FINAL FORM
0xF15B 0x005B # LEFT SQUARE BRACKET
0xF15C 0x005C # REVERSE SOLIDUS
0xF15D 0x005D # RIGHT SQUARE BRACKET
0xF15E 0x002C # COMMA
0xF15E 0x066B # ARABIC DECIMAL SEPARATOR
0xF15E 0x066C # ARABIC THOUSANDS SEPARATOR
0xF15F 0x0640 # ARABIC TATWEEL
0xF160 0x0632 # ARABIC LETTER ZAIN
0xF160 0xFEAF # ARABIC LETTER ZAIN ISOLATED FORM
0xF160 0xFEB0 # ARABIC LETTER ZAIN FINAL FORM
0xF161 0xFEB3 # ARABIC LETTER SEEN INITIAL FORM
0xF161 0xFEB4 # ARABIC LETTER SEEN MEDIAL FORM
0xF162 0x0633 # ARABIC LETTER SEEN
0xF162 0xFEB1 # ARABIC LETTER SEEN ISOLATED FORM
0xF162 0xFEB2 # ARABIC LETTER SEEN FINAL FORM
0xF163 0xFEB7 # ARABIC LETTER SHEEN INITIAL FORM
0xF163 0xFEB8 # ARABIC LETTER SHEEN MEDIAL FORM
0xF164 0x0634 # ARABIC LETTER SHEEN
0xF164 0xFEB5 # ARABIC LETTER SHEEN ISOLATED FORM
0xF164 0xFEB6 # ARABIC LETTER SHEEN FINAL FORM
0xF165 0xFEBB # ARABIC LETTER SAD INITIAL FORM
0xF165 0xFEBC # ARABIC LETTER SAD MEDIAL FORM
0xF166 0x0635 # ARABIC LETTER SAD
0xF166 0xFEB9 # ARABIC LETTER SAD ISOLATED FORM
0xF166 0xFEBA # ARABIC LETTER SAD FINAL FORM
0xF167 0xFEBF # ARABIC LETTER DAD INITIAL FORM
0xF167 0xFEC0 # ARABIC LETTER DAD MEDIAL FORM
0xF168 0x0636 # ARABIC LETTER DAD
0xF168 0xFEBD # ARABIC LETTER DAD ISOLATED FORM
0xF168 0xFEBE # ARABIC LETTER DAD FINAL FORM
0xF169 0x0637 # ARABIC LETTER TAH
0xF169 0xFEC1 # ARABIC LETTER TAH ISOLATED FORM
0xF169 0xFEC2 # ARABIC LETTER TAH FINAL FORM
0xF169 0xFEC3 # ARABIC LETTER TAH INITIAL FORM
0xF169 0xFEC4 # ARABIC LETTER TAH MEDIAL FORM
0xF16A 0x0638 # ARABIC LETTER ZAH
0xF16A 0xFEC5 # ARABIC LETTER ZAH ISOLATED FORM
0xF16A 0xFEC6 # ARABIC LETTER ZAH FINAL FORM
0xF16A 0xFEC7 # ARABIC LETTER ZAH INITIAL FORM
0xF16A 0xFEC8 # ARABIC LETTER ZAH MEDIAL FORM
0xF16B 0xFECB # ARABIC LETTER AIN INITIAL FORM
0xF16C 0xFECC # ARABIC LETTER AIN MEDIAL FORM
0xF16D 0xFECA # ARABIC LETTER AIN FINAL FORM
0xF16E 0x0639 # ARABIC LETTER AIN
0xF16E 0xFEC9 # ARABIC LETTER AIN ISOLATED FORM
0xF16F 0xFECF # ARABIC LETTER GHAIN INITIAL FORM
0xF170 0xFED0 # ARABIC LETTER GHAIN MEDIAL FORM
0xF171 0xFECE # ARABIC LETTER GHAIN FINAL FORM
0xF172 0x063A # ARABIC LETTER GHAIN
0xF172 0xFECD # ARABIC LETTER GHAIN ISOLATED FORM
0xF173 0xFED3 # ARABIC LETTER FEH INITIAL FORM
0xF174 0xFED4 # ARABIC LETTER FEH MEDIAL FORM
0xF175 0x0641 # ARABIC LETTER FEH
0xF175 0xFED1 # ARABIC LETTER FEH ISOLATED FORM
0xF175 0xFED2 # ARABIC LETTER FEH FINAL FORM
0xF176 0xFED7 # ARABIC LETTER QAF INITIAL FORM
0xF177 0xFED8 # ARABIC LETTER QAF MEDIAL FORM
0xF178 0x0642 # ARABIC LETTER QAF
0xF178 0xFED5 # ARABIC LETTER QAF ISOLATED FORM
0xF178 0xFED6 # ARABIC LETTER QAF FINAL FORM
0xF179 0xFEDB # ARABIC LETTER KAF INITIAL FORM
0xF179 0xFEDC # ARABIC LETTER KAF MEDIAL FORM
0xF17A 0x0643 # ARABIC LETTER KAF
0xF17A 0xFED9 # ARABIC LETTER KAF ISOLATED FORM
0xF17A 0xFEDA # ARABIC LETTER KAF FINAL FORM
0xF17B 0xFEDF # ARABIC LETTER LAM INITIAL FORM
0xF17B 0xFEE0 # ARABIC LETTER LAM MEDIAL FORM
0xF17C 0x0644 # ARABIC LETTER LAM
0xF17C 0xFEDD # ARABIC LETTER LAM ISOLATED FORM
0xF17C 0xFEDE # ARABIC LETTER LAM FINAL FORM
0xF17D 0xFEE3 # ARABIC LETTER MEEM INITIAL FORM
0xF17D 0xFEE4 # ARABIC LETTER MEEM MEDIAL FORM
0xF17E 0x0645 # ARABIC LETTER MEEM
0xF17E 0xFEE1 # ARABIC LETTER MEEM ISOLATED FORM
0xF17E 0xFEE2 # ARABIC LETTER MEEM FINAL FORM
0xF17F 0xFEE7 # ARABIC LETTER NOON INITIAL FORM
0xF17F 0xFEE8 # ARABIC LETTER NOON MEDIAL FORM
0xF1A1 0xFEEB # ARABIC LETTER HEH INITIAL FORM
0xF1A2 0xFEEC # ARABIC LETTER HEH MEDIAL FORM
0xF1A3 0xFEEA # ARABIC LETTER HEH FINAL FORM
0xF1A4 0x0647 # ARABIC LETTER HEH
0xF1A4 0xFEE9 # ARABIC LETTER HEH ISOLATED FORM
0xF1A5 0x0648 # ARABIC LETTER WAW
0xF1A5 0xFEED # ARABIC LETTER WAW ISOLATED FORM
0xF1A5 0xFEEE # ARABIC LETTER WAW FINAL FORM
0xF1A6 0xFEF3 # ARABIC LETTER YEH INITIAL FORM
0xF1A6 0xFEF4 # ARABIC LETTER YEH MEDIAL FORM
0xF1A7 0xFEF2 # ARABIC LETTER YEH FINAL FORM
0xF1A8 0x064A # ARABIC LETTER YEH
0xF1A8 0xFEF1 # ARABIC LETTER YEH ISOLATED FORM
0xF1A9 0x0629 # ARABIC LETTER TEH MARBUTA
0xF1A9 0xFE93 # ARABIC LETTER TEH MARBUTA ISOLATED FORM
0xF1AA 0xFE94 # ARABIC LETTER TEH MARBUTA FINAL FORM
0xF1AB 0xFEF0 # ARABIC LETTER ALEF MAKSURA FINAL FORM
0xF1AC 0x0649 # ARABIC LETTER ALEF MAKSURA
0xF1AC 0xFEEF # ARABIC LETTER ALEF MAKSURA ISOLATED FORM
0xF1AD 0x0621 # ARABIC LETTER HAMZA
0xF1AE 0xFE8B # ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
0xF1AE 0xFE8C # ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM
0xF1AF 0xFE8A # ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM
0xF1B0 0x0030 # DIGIT ZERO
0xF1B1 0x0031 # DIGIT ONE
0xF1B2 0x0032 # DIGIT TWO
0xF1B3 0x0033 # DIGIT THREE
0xF1B4 0x0034 # DIGIT FOUR
0xF1B5 0x0035 # DIGIT FIVE
0xF1B6 0x0036 # DIGIT SIX
0xF1B7 0x0037 # DIGIT SEVEN
0xF1B8 0x0038 # DIGIT EIGHT
0xF1B9 0x0039 # DIGIT NINE
0xF1BA 0x0626 # ARABIC LETTER YEH WITH HAMZA ABOVE
0xF1BA 0xFE89 # ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM
0xF1BB 0x0624 # ARABIC LETTER WAW WITH HAMZA ABOVE
0xF1BB 0xFE85 # ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
0xF1BB 0xFE86 # ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM
0xF1BC 0xFEFC # ARABIC LIGATURE LAM WITH ALEF FINAL FORM
0xF1BD 0xFEFB # ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
0xF1BE 0xFEF7 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
0xF1BF 0xFEF8 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
0xF1C0 0xFEF5 # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
0xF1C1 0xFEF6 # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
0xF1C2 0xFEF9 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM
0xF1C3 0xFEFA # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM
0xF1C4 0x064E # ARABIC FATHA
0xF1C5 0x064F # ARABIC DAMMA
0xF1C6 0x0652 # ARABIC SUKUN
0xF1C7 0x064B # ARABIC FATHATAN
0xF1C8 0x064C # ARABIC DAMMATAN
0xF1C9 0x0651 # ARABIC SHADDA
0xF1CA 0x0650 # ARABIC KASRA
0xF1CB 0x064D # ARABIC KASRATAN
0xF1E1 0x0646 # ARABIC LETTER NOON
0xF1E1 0xFEE5 # ARABIC LETTER NOON ISOLATED FORM
0xF1E1 0xFEE6 # ARABIC LETTER NOON FINAL FORM

View File

@ -1,295 +0,0 @@
#
# Name: Legacy Traditional Arabic encoding
#
# Format: Three tab-separated columns
# Column #1 is the PUA code (in hex as 0xXXXX)
# Column #2 is the Unicode (in hex as 0xXXXX)
# Column #3 is the Unicode name (follows a comment sign, '#')
#
# The entries are in PUA order
#
0xF200 0x063B # ARABIC LETTER KEHEH WITH TWO DOTS ABOVE
0xF200 0x063C # ARABIC LETTER KEHEH WITH THREE DOTS BELOW
0xF200 0x063D # ARABIC LETTER FARSI YEH WITH INVERTED V
0xF200 0x063E # ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE
0xF200 0x063F # ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
0xF200 0x0653 # ARABIC MADDAH ABOVE
0xF200 0x0654 # ARABIC HAMZA ABOVE
0xF200 0x0655 # ARABIC HAMZA BELOW
0xF200 0x0656 # ARABIC SUBSCRIPT ALEF
0xF200 0x0657 # ARABIC INVERTED DAMMA
0xF200 0x0658 # ARABIC MARK NOON GHUNNA
0xF200 0x0659 # ARABIC ZWARAKAY
0xF200 0x065A # ARABIC VOWEL SIGN SMALL V ABOVE
0xF200 0x065B # ARABIC VOWEL SIGN INVERTED SMALL V ABOVE
0xF200 0x065C # ARABIC VOWEL SIGN DOT BELOW
0xF200 0x065D # ARABIC REVERSED DAMMA
0xF200 0x065E # ARABIC FATHA WITH TWO DOTS
0xF202 0xFC08 # ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM
0xF203 0xFC0E # ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM
0xF204 0xFC12 # ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM
0xF205 0xFC42 # ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM
0xF206 0xFC4E # ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM
0xF20C 0x200C # ZERO WIDTH NON-JOINER
0xF20D 0x200D # ZERO WIDTH JOINER
0xF20E 0x200E # LEFT-TO-RIGHT MARK
0xF20F 0x200F # RIGHT-TO-LEFT MARK
0xF210 0xFD88 # ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM
0xF212 0xFC3F # ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM
0xF213 0xFC40 # ARABIC LIGATURE LAM WITH HAH ISOLATED FORM
0xF214 0xFC41 # ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM
0xF215 0xFC6A # ARABIC LIGATURE BEH WITH REH FINAL FORM
0xF216 0xFC70 # ARABIC LIGATURE TEH WITH REH FINAL FORM
0xF217 0xFC91 # ARABIC LIGATURE YEH WITH REH FINAL FORM
0xF218 0xFCB0 # ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM
0xF219 0xFD30 # ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM
0xF21A 0xFCCD # ARABIC LIGATURE LAM WITH HEH INITIAL FORM
0xF21C 0xFC44 # ARABIC LIGATURE LAM WITH YEH ISOLATED FORM
0xF21D 0xFC0A # ARABIC LIGATURE BEH WITH YEH ISOLATED FORM
0xF21E 0xFC10 # ARABIC LIGATURE TEH WITH YEH ISOLATED FORM
0xF21F 0xFC50 # ARABIC LIGATURE NOON WITH YEH ISOLATED FORM
0xF220 0x0020 # SPACE
0xF221 0x0021 # EXCLAMATION MARK
0xF222 0x0022 # QUOTATION MARK
0xF223 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
0xF224 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
0xF225 0x0025 # PERCENT SIGN
0xF226 0x00D7 # MULTIPLICATION SIGN
0xF227 0x00F7 # DIVISION SIGN
0xF228 0x0028 # LEFT PARENTHESIS
0xF229 0x0029 # RIGHT PARENTHESIS
0xF22A 0x002A # ASTERISK
0xF22B 0x002B # PLUS SIGN
0xF22C 0x060C # ARABIC COMMA
0xF22D 0x002D # HYPHEN-MINUS
0xF22E 0x002E # FULL STOP
0xF22F 0x002F # SOLIDUS
0xF230 0x0660 # ARABIC-INDIC DIGIT ZERO
0xF231 0x0661 # ARABIC-INDIC DIGIT ONE
0xF232 0x0662 # ARABIC-INDIC DIGIT TWO
0xF233 0x0663 # ARABIC-INDIC DIGIT THREE
0xF234 0x0664 # ARABIC-INDIC DIGIT FOUR
0xF235 0x0665 # ARABIC-INDIC DIGIT FIVE
0xF236 0x0666 # ARABIC-INDIC DIGIT SIX
0xF237 0x0667 # ARABIC-INDIC DIGIT SEVEN
0xF238 0x0668 # ARABIC-INDIC DIGIT EIGHT
0xF239 0x0669 # ARABIC-INDIC DIGIT NINE
0xF23A 0x003A # COLON
0xF23B 0x003B # SEMICOLON
0xF23B 0x061B # ARABIC SEMICOLON
0xF23C 0x201C # LEFT DOUBLE QUOTATION MARK
0xF23D 0x003D # EQUALS SIGN
0xF23E 0x201D # RIGHT DOUBLE QUOTATION MARK
0xF23F 0x003F # QUESTION MARK
0xF23F 0x061F # ARABIC QUESTION MARK
0xF241 0x0627 # ARABIC LETTER ALEF
0xF241 0xFE8D # ARABIC LETTER ALEF ISOLATED FORM
0xF242 0xFE8E # ARABIC LETTER ALEF FINAL FORM
0xF243 0x0623 # ARABIC LETTER ALEF WITH HAMZA ABOVE
0xF243 0xFE83 # ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM
0xF244 0xFE84 # ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
0xF245 0x0622 # ARABIC LETTER ALEF WITH MADDA ABOVE
0xF245 0xFE81 # ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
0xF246 0xFE82 # ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
0xF247 0x0625 # ARABIC LETTER ALEF WITH HAMZA BELOW
0xF247 0xFE87 # ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM
0xF248 0xFE88 # ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM
0xF249 0xFE91 # ARABIC LETTER BEH INITIAL FORM
0xF24A 0xFE92 # ARABIC LETTER BEH MEDIAL FORM
0xF24B 0xFE90 # ARABIC LETTER BEH FINAL FORM
0xF24C 0x0628 # ARABIC LETTER BEH
0xF24C 0xFE8F # ARABIC LETTER BEH ISOLATED FORM
0xF24D 0xFE97 # ARABIC LETTER TEH INITIAL FORM
0xF24E 0xFE98 # ARABIC LETTER TEH MEDIAL FORM
0xF24F 0xFE96 # ARABIC LETTER TEH FINAL FORM
0xF250 0x062A # ARABIC LETTER TEH
0xF250 0xFE95 # ARABIC LETTER TEH ISOLATED FORM
0xF251 0xFE9B # ARABIC LETTER THEH INITIAL FORM
0xF252 0xFE9C # ARABIC LETTER THEH MEDIAL FORM
0xF253 0xFE9A # ARABIC LETTER THEH FINAL FORM
0xF254 0x062B # ARABIC LETTER THEH
0xF254 0xFE99 # ARABIC LETTER THEH ISOLATED FORM
0xF255 0xFE9F # ARABIC LETTER JEEM INITIAL FORM
0xF256 0xFEA0 # ARABIC LETTER JEEM MEDIAL FORM
0xF257 0xFE9E # ARABIC LETTER JEEM FINAL FORM
0xF258 0x062C # ARABIC LETTER JEEM
0xF258 0xFE9D # ARABIC LETTER JEEM ISOLATED FORM
0xF259 0xFEA3 # ARABIC LETTER HAH INITIAL FORM
0xF25A 0xFEA4 # ARABIC LETTER HAH MEDIAL FORM
0xF25B 0x005B # LEFT SQUARE BRACKET
0xF25C 0xFEA2 # ARABIC LETTER HAH FINAL FORM
0xF25D 0x005D # RIGHT SQUARE BRACKET
0xF25E 0x002C # COMMA
0xF25E 0x066B # ARABIC DECIMAL SEPARATOR
0xF25E 0x066C # ARABIC THOUSANDS SEPARATOR
0xF25F 0x0640 # ARABIC TATWEEL
0xF260 0x062D # ARABIC LETTER HAH
0xF260 0xFEA1 # ARABIC LETTER HAH ISOLATED FORM
0xF261 0xFEA7 # ARABIC LETTER KHAH INITIAL FORM
0xF262 0xFEA8 # ARABIC LETTER KHAH MEDIAL FORM
0xF263 0xFEA6 # ARABIC LETTER KHAH FINAL FORM
0xF264 0x062E # ARABIC LETTER KHAH
0xF264 0xFEA5 # ARABIC LETTER KHAH ISOLATED FORM
0xF265 0x062F # ARABIC LETTER DAL
0xF265 0xFEA9 # ARABIC LETTER DAL ISOLATED FORM
0xF266 0xFEAA # ARABIC LETTER DAL FINAL FORM
0xF267 0x0630 # ARABIC LETTER THAL
0xF267 0xFEAB # ARABIC LETTER THAL ISOLATED FORM
0xF268 0xFEAC # ARABIC LETTER THAL FINAL FORM
0xF269 0x0631 # ARABIC LETTER REH
0xF269 0xFEAD # ARABIC LETTER REH ISOLATED FORM
0xF26A 0xFEAE # ARABIC LETTER REH FINAL FORM
0xF26B 0x0632 # ARABIC LETTER ZAIN
0xF26B 0xFEAF # ARABIC LETTER ZAIN ISOLATED FORM
0xF26C 0xFEB0 # ARABIC LETTER ZAIN FINAL FORM
0xF26D 0xFEB3 # ARABIC LETTER SEEN INITIAL FORM
0xF26E 0xFEB4 # ARABIC LETTER SEEN MEDIAL FORM
0xF26F 0xFEB2 # ARABIC LETTER SEEN FINAL FORM
0xF270 0x0633 # ARABIC LETTER SEEN
0xF270 0xFEB1 # ARABIC LETTER SEEN ISOLATED FORM
0xF271 0xFEB7 # ARABIC LETTER SHEEN INITIAL FORM
0xF272 0xFEB8 # ARABIC LETTER SHEEN MEDIAL FORM
0xF273 0xFEB6 # ARABIC LETTER SHEEN FINAL FORM
0xF274 0x0634 # ARABIC LETTER SHEEN
0xF274 0xFEB5 # ARABIC LETTER SHEEN ISOLATED FORM
0xF275 0xFEBB # ARABIC LETTER SAD INITIAL FORM
0xF276 0xFEBC # ARABIC LETTER SAD MEDIAL FORM
0xF277 0xFEBA # ARABIC LETTER SAD FINAL FORM
0xF278 0x0635 # ARABIC LETTER SAD
0xF278 0xFEB9 # ARABIC LETTER SAD ISOLATED FORM
0xF279 0xFEBF # ARABIC LETTER DAD INITIAL FORM
0xF27A 0xFEC0 # ARABIC LETTER DAD MEDIAL FORM
0xF27B 0xFD3E # ORNATE LEFT PARENTHESIS
0xF27C 0xFEBE # ARABIC LETTER DAD FINAL FORM
0xF27D 0xFD3F # ORNATE RIGHT PARENTHESIS
0xF27E 0x0636 # ARABIC LETTER DAD
0xF27E 0xFEBD # ARABIC LETTER DAD ISOLATED FORM
0xF27F 0xFEC3 # ARABIC LETTER TAH INITIAL FORM
0xF280 0xFC9C # ARABIC LIGATURE BEH WITH JEEM INITIAL FORM
0xF281 0xFC9D # ARABIC LIGATURE BEH WITH HAH INITIAL FORM
0xF282 0xFC9E # ARABIC LIGATURE BEH WITH KHAH INITIAL FORM
0xF283 0xFCA1 # ARABIC LIGATURE TEH WITH JEEM INITIAL FORM
0xF284 0xFCA2 # ARABIC LIGATURE TEH WITH HAH INITIAL FORM
0xF285 0xFCA3 # ARABIC LIGATURE TEH WITH KHAH INITIAL FORM
0xF286 0xFCC9 # ARABIC LIGATURE LAM WITH JEEM INITIAL FORM
0xF287 0xFCCA # ARABIC LIGATURE LAM WITH HAH INITIAL FORM
0xF288 0xFCCB # ARABIC LIGATURE LAM WITH KHAH INITIAL FORM
0xF289 0xFCCE # ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM
0xF28A 0xFCCF # ARABIC LIGATURE MEEM WITH HAH INITIAL FORM
0xF28B 0xFCD0 # ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM
0xF28D 0xFCD2 # ARABIC LIGATURE NOON WITH JEEM INITIAL FORM
0xF28E 0xFCD3 # ARABIC LIGATURE NOON WITH HAH INITIAL FORM
0xF28F 0xFCDA # ARABIC LIGATURE YEH WITH JEEM INITIAL FORM
0xF290 0xFCDB # ARABIC LIGATURE YEH WITH HAH INITIAL FORM
0xF291 0xFCDC # ARABIC LIGATURE YEH WITH KHAH INITIAL FORM
0xF292 0xFC6D # ARABIC LIGATURE BEH WITH NOON FINAL FORM
0xF293 0xFC73 # ARABIC LIGATURE TEH WITH NOON FINAL FORM
0xF294 0xFC94 # ARABIC LIGATURE YEH WITH NOON FINAL FORM
0xF295 0xFC86 # ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM
0xF296 0xFC9F # ARABIC LIGATURE BEH WITH MEEM INITIAL FORM
0xF297 0xFCA4 # ARABIC LIGATURE TEH WITH MEEM INITIAL FORM
0xF298 0xFCD5 # ARABIC LIGATURE NOON WITH MEEM INITIAL FORM
0xF299 0xFCDD # ARABIC LIGATURE YEH WITH MEEM INITIAL FORM
0xF29A 0xFCA8 # ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM
0xF29B 0xFCAA # ARABIC LIGATURE HAH WITH MEEM INITIAL FORM
0xF29C 0xFCAC # ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM
0xF29D 0xFCCC # ARABIC LIGATURE LAM WITH MEEM INITIAL FORM
0xF29E 0xFCD1 # ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM
0xF29F 0xFC32 # ARABIC LIGATURE FEH WITH YEH ISOLATED FORM
0xF2A1 0xFEC2 # ARABIC LETTER TAH FINAL FORM
0xF2A2 0x0637 # ARABIC LETTER TAH
0xF2A2 0xFEC1 # ARABIC LETTER TAH ISOLATED FORM
0xF2A3 0x0638 # ARABIC LETTER ZAH
0xF2A3 0xFEC7 # ARABIC LETTER ZAH INITIAL FORM
0xF2A4 0xFEC8 # ARABIC LETTER ZAH MEDIAL FORM
0xF2A5 0xFEC6 # ARABIC LETTER ZAH FINAL FORM
0xF2A6 0xFEC5 # ARABIC LETTER ZAH ISOLATED FORM
0xF2A7 0xFECB # ARABIC LETTER AIN INITIAL FORM
0xF2A8 0xFECC # ARABIC LETTER AIN MEDIAL FORM
0xF2A9 0xFECA # ARABIC LETTER AIN FINAL FORM
0xF2AA 0x0639 # ARABIC LETTER AIN
0xF2AA 0xFEC9 # ARABIC LETTER AIN ISOLATED FORM
0xF2AB 0xFECF # ARABIC LETTER GHAIN INITIAL FORM
0xF2AC 0xFED0 # ARABIC LETTER GHAIN MEDIAL FORM
0xF2AD 0xFECE # ARABIC LETTER GHAIN FINAL FORM
0xF2AE 0x063A # ARABIC LETTER GHAIN
0xF2AE 0xFECD # ARABIC LETTER GHAIN ISOLATED FORM
0xF2AF 0xFED3 # ARABIC LETTER FEH INITIAL FORM
0xF2B0 0xFED4 # ARABIC LETTER FEH MEDIAL FORM
0xF2B1 0xFED2 # ARABIC LETTER FEH FINAL FORM
0xF2B2 0x0641 # ARABIC LETTER FEH
0xF2B2 0xFED1 # ARABIC LETTER FEH ISOLATED FORM
0xF2B3 0xFED7 # ARABIC LETTER QAF INITIAL FORM
0xF2B4 0xFED8 # ARABIC LETTER QAF MEDIAL FORM
0xF2B5 0xFED6 # ARABIC LETTER QAF FINAL FORM
0xF2B6 0x0642 # ARABIC LETTER QAF
0xF2B6 0xFED5 # ARABIC LETTER QAF ISOLATED FORM
0xF2B7 0xFEDB # ARABIC LETTER KAF INITIAL FORM
0xF2B8 0xFEDC # ARABIC LETTER KAF MEDIAL FORM
0xF2B9 0xFEDA # ARABIC LETTER KAF FINAL FORM
0xF2BA 0x0643 # ARABIC LETTER KAF
0xF2BA 0xFED9 # ARABIC LETTER KAF ISOLATED FORM
0xF2BB 0xFEDF # ARABIC LETTER LAM INITIAL FORM
0xF2BC 0xFEE0 # ARABIC LETTER LAM MEDIAL FORM
0xF2BD 0xFEDE # ARABIC LETTER LAM FINAL FORM
0xF2BE 0x0644 # ARABIC LETTER LAM
0xF2BE 0xFEDD # ARABIC LETTER LAM ISOLATED FORM
0xF2BF 0xFEE3 # ARABIC LETTER MEEM INITIAL FORM
0xF2C0 0xFEE4 # ARABIC LETTER MEEM MEDIAL FORM
0xF2C1 0xFEE2 # ARABIC LETTER MEEM FINAL FORM
0xF2C2 0x0645 # ARABIC LETTER MEEM
0xF2C2 0xFEE1 # ARABIC LETTER MEEM ISOLATED FORM
0xF2C3 0xFEE7 # ARABIC LETTER NOON INITIAL FORM
0xF2C4 0xFEE8 # ARABIC LETTER NOON MEDIAL FORM
0xF2C5 0xFEE6 # ARABIC LETTER NOON FINAL FORM
0xF2C6 0x0646 # ARABIC LETTER NOON
0xF2C6 0xFEE5 # ARABIC LETTER NOON ISOLATED FORM
0xF2C7 0xFEEB # ARABIC LETTER HEH INITIAL FORM
0xF2C8 0xFEEC # ARABIC LETTER HEH MEDIAL FORM
0xF2C9 0xFEEA # ARABIC LETTER HEH FINAL FORM
0xF2CA 0x0647 # ARABIC LETTER HEH
0xF2CA 0xFEE9 # ARABIC LETTER HEH ISOLATED FORM
0xF2CB 0x0648 # ARABIC LETTER WAW
0xF2CB 0xFEED # ARABIC LETTER WAW ISOLATED FORM
0xF2CC 0xFEEE # ARABIC LETTER WAW FINAL FORM
0xF2CD 0xFEF3 # ARABIC LETTER YEH INITIAL FORM
0xF2CE 0xFEF4 # ARABIC LETTER YEH MEDIAL FORM
0xF2CF 0xFEF2 # ARABIC LETTER YEH FINAL FORM
0xF2D0 0x064A # ARABIC LETTER YEH
0xF2D0 0xFEF1 # ARABIC LETTER YEH ISOLATED FORM
0xF2D1 0x0629 # ARABIC LETTER TEH MARBUTA
0xF2D1 0xFE93 # ARABIC LETTER TEH MARBUTA ISOLATED FORM
0xF2D2 0xFE94 # ARABIC LETTER TEH MARBUTA FINAL FORM
0xF2D3 0xFEF0 # ARABIC LETTER ALEF MAKSURA FINAL FORM
0xF2D4 0x0649 # ARABIC LETTER ALEF MAKSURA
0xF2D4 0xFEEF # ARABIC LETTER ALEF MAKSURA ISOLATED FORM
0xF2D5 0x0621 # ARABIC LETTER HAMZA
0xF2D6 0xFE8B # ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
0xF2D7 0xFE8C # ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM
0xF2D8 0xFE8A # ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM
0xF2D9 0x0626 # ARABIC LETTER YEH WITH HAMZA ABOVE
0xF2D9 0xFE89 # ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM
0xF2DA 0x0624 # ARABIC LETTER WAW WITH HAMZA ABOVE
0xF2DA 0xFE85 # ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
0xF2DB 0xFE86 # ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM
0xF2DC 0xFEFB # ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
0xF2DD 0xFEFC # ARABIC LIGATURE LAM WITH ALEF FINAL FORM
0xF2DE 0xFEF7 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
0xF2DF 0xFEF8 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
0xF2E0 0xFEF5 # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
0xF2E1 0xFEF6 # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
0xF2E2 0xFEF9 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM
0xF2E3 0xFEFA # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM
0xF2E4 0x064E # ARABIC FATHA
0xF2E5 0x064F # ARABIC DAMMA
0xF2E6 0x0652 # ARABIC SUKUN
0xF2E7 0x064B # ARABIC FATHATAN
0xF2E8 0x064C # ARABIC DAMMATAN
0xF2E9 0x0651 # ARABIC SHADDA
0xF2EA 0x0650 # ARABIC KASRA
0xF2EB 0x064D # ARABIC KASRATAN
0xF2EC 0xFC60 # ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM
0xF2ED 0xFC61 # ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM
0xF2EF 0xFC5E # ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM
0xF2F0 0xFC62 # ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM
0xF2F1 0xFEC4 # ARABIC LETTER TAH MEDIAL FORM

View File

@ -12,7 +12,7 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
TESTS =
check_PROGRAMS =
EXTRA_DIST += harfbuzz.cc harfbuzz-subset.cc
EXTRA_DIST += harfbuzz.cc
EXTRA_DIST += meson.build
EXTRA_DIST += fix_get_types.py
@ -47,9 +47,6 @@ HBLIBS += $(GLIB_LIBS)
HBDEPS += $(GLIB_DEPS)
HBSOURCES += $(HB_GLIB_sources)
HBHEADERS += $(HB_GLIB_headers)
HB_HAS_GLIB_DEF = define HB_HAS_GLIB 1
else
HB_HAS_GLIB_DEF = undef HB_HAS_GLIB
endif
if HAVE_FREETYPE
@ -58,9 +55,6 @@ HBLIBS += $(FREETYPE_LIBS)
HBDEPS += $(FREETYPE_DEPS)
HBSOURCES += $(HB_FT_sources)
HBHEADERS += $(HB_FT_headers)
HB_HAS_FREETYPE_DEF = define HB_HAS_FREETYPE 1
else
HB_HAS_FREETYPE_DEF = undef HB_HAS_FREETYPE
endif
if HAVE_GRAPHITE2
@ -69,9 +63,6 @@ HBLIBS += $(GRAPHITE2_LIBS)
HBDEPS += $(GRAPHITE2_DEPS)
HBSOURCES += $(HB_GRAPHITE2_sources)
HBHEADERS += $(HB_GRAPHITE2_headers)
HB_HAS_GRAPHITE_DEF = define HB_HAS_GRAPHITE 1
else
HB_HAS_GRAPHITE_DEF = undef HB_HAS_GRAPHITE
endif
if HAVE_UNISCRIBE
@ -79,9 +70,6 @@ HBCFLAGS += $(UNISCRIBE_CFLAGS)
HBNONPCLIBS += $(UNISCRIBE_LIBS)
HBSOURCES += $(HB_UNISCRIBE_sources)
HBHEADERS += $(HB_UNISCRIBE_headers)
HB_HAS_UNISCRIBE_DEF = define HB_HAS_UNISCRIBE 1
else
HB_HAS_UNISCRIBE_DEF = undef HB_HAS_UNISCRIBE
endif
if HAVE_DIRECTWRITE
@ -89,9 +77,6 @@ HBCFLAGS += $(DIRECTWRITE_CXXFLAGS)
HBNONPCLIBS += $(DIRECTWRITE_LIBS)
HBSOURCES += $(HB_DIRECTWRITE_sources)
HBHEADERS += $(HB_DIRECTWRITE_headers)
HB_HAS_DIRECTWRITE_DEF = define HB_HAS_DIRECTWRITE 1
else
HB_HAS_DIRECTWRITE_DEF = undef HB_HAS_DIRECTWRITE
endif
if HAVE_GDI
@ -99,9 +84,6 @@ HBCFLAGS += $(GDI_CXXFLAGS)
HBNONPCLIBS += $(GDI_LIBS)
HBSOURCES += $(HB_GDI_sources)
HBHEADERS += $(HB_GDI_headers)
HB_HAS_GDI_DEF = define HB_HAS_GDI 1
else
HB_HAS_GDI_DEF = undef HB_HAS_GDI
endif
if HAVE_CORETEXT
@ -109,9 +91,6 @@ HBCFLAGS += $(CORETEXT_CFLAGS)
HBNONPCLIBS += $(CORETEXT_LIBS)
HBSOURCES += $(HB_CORETEXT_sources)
HBHEADERS += $(HB_CORETEXT_headers)
HB_HAS_CORETEXT_DEF = define HB_HAS_CORETEXT 1
else
HB_HAS_CORETEXT_DEF = undef HB_HAS_CORETEXT
endif
@ -135,8 +114,6 @@ export_symbols = -export-symbols harfbuzz.def
harfbuzz_def_dependency = harfbuzz.def
export_symbols_subset = -export-symbols harfbuzz-subset.def
harfbuzz_subset_def_dependency = harfbuzz-subset.def
export_symbols_cairo = -export-symbols harfbuzz-cairo.def
harfbuzz_cairo_def_dependency = harfbuzz-cairo.def
export_symbols_icu = -export-symbols harfbuzz-icu.def
harfbuzz_icu_def_dependency = harfbuzz-icu.def
export_symbols_gobject = -export-symbols harfbuzz-gobject.def
@ -170,7 +147,7 @@ pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = harfbuzz.pc
cmakedir = $(libdir)/cmake/harfbuzz
cmake_DATA = harfbuzz-config.cmake
EXTRA_DIST += hb-version.h.in hb-features.h.in harfbuzz.pc.in harfbuzz-config.cmake.in
EXTRA_DIST += hb-version.h.in harfbuzz.pc.in harfbuzz-config.cmake.in
lib_LTLIBRARIES += libharfbuzz-subset.la
libharfbuzz_subset_la_LINK = $(chosen_linker) $(libharfbuzz_subset_la_LDFLAGS)
@ -183,36 +160,12 @@ pkginclude_HEADERS += $(HB_SUBSET_headers)
pkgconfig_DATA += harfbuzz-subset.pc
EXTRA_DIST += harfbuzz-subset.pc.in
harfbuzz-subset.cc: Makefile.sources
$(AM_V_GEN) \
LANG=C; \
for f in \
$(HB_BASE_sources) \
$(HB_SUBSET_sources) \
; do echo '#include "'$$f'"'; done | \
sort -u | \
grep '[.]cc"' > $(srcdir)/harfbuzz-subset.cc \
|| ($(RM) $(srcdir)/harfbuzz-subset.cc; false)
BUILT_SOURCES += harfbuzz-subset.cc
lib_LTLIBRARIES += libharfbuzz-cairo.la
libharfbuzz_cairo_la_LINK = $(chosen_linker) $(libharfbuzz_cairo_la_LDFLAGS)
libharfbuzz_cairo_la_SOURCES = $(HB_CAIRO_sources)
libharfbuzz_cairo_la_CPPFLAGS = $(HBCFLAGS) $(CAIRO_CFLAGS) $(CODE_COVERAGE_CFLAGS)
libharfbuzz_cairo_la_LDFLAGS = $(base_link_flags) $(export_symbols_cairo) $(CODE_COVERAGE_LDFLAGS)
libharfbuzz_cairo_la_LIBADD = $(CAIRO_LIBS) libharfbuzz.la
EXTRA_libharfbuzz_cairo_la_DEPENDENCIES = $(harfbuzz_cairo_def_dependency)
pkginclude_HEADERS += $(HB_CAIRO_headers)
pkgconfig_DATA += harfbuzz-cairo.pc
EXTRA_DIST += harfbuzz-cairo.pc.in
if HAVE_ICU
if HAVE_ICU_BUILTIN
HBCFLAGS += $(ICU_CFLAGS)
HBLIBS += $(ICU_LIBS)
HBSOURCES += $(HB_ICU_sources)
HBHEADERS += $(HB_ICU_headers)
HB_HAS_ICU_DEF = define HB_HAS_ICU 1
else
lib_LTLIBRARIES += libharfbuzz-icu.la
libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
@ -222,7 +175,6 @@ libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la
EXTRA_libharfbuzz_icu_la_DEPENDENCIES = $(harfbuzz_icu_def_dependency)
pkginclude_HEADERS += $(HB_ICU_headers)
pkgconfig_DATA += harfbuzz-icu.pc
HB_HAS_ICU_DEF = undef HB_HAS_ICU
endif
endif
EXTRA_DIST += harfbuzz-icu.pc.in
@ -254,9 +206,6 @@ hb-gobject-enums.%: hb-gobject-enums.%.tmpl $(HBHEADERS)
--template $^ | \
sed 's/_t_get_type/_get_type/g; s/_T (/ (/g' > "$@" \
|| ($(RM) "$@"; false)
HB_HAS_GOBJECT_DEF = define HB_HAS_GOBJECT 1
else
HB_HAS_GOBJECT_DEF = undef HB_HAS_GOBJECT
endif
EXTRA_DIST += \
harfbuzz-gobject.pc.in \
@ -265,27 +214,6 @@ EXTRA_DIST += \
$(NULL)
BUILT_SOURCES += \
hb-features.h
DISTCLEANFILES += \
hb-features.h
hb-features.h: hb-features.h.in $(top_builddir)/config.status
$(AM_V_GEN) $(SED) \
-e 's/mesondefine HB_HAS_CAIRO/$(HB_HAS_CAIRO_DEF)/' \
-e 's/mesondefine HB_HAS_FREETYPE/$(HB_HAS_FREETYPE_DEF)/' \
-e 's/mesondefine HB_HAS_GDI/$(HB_HAS_GDI_DEF)/' \
-e 's/mesondefine HB_HAS_GDI/$(HB_HAS_GDI_DEF)/' \
-e 's/mesondefine HB_HAS_GRAPHITE/$(HB_HAS_GRAPHITE_DEF)/' \
-e 's/mesondefine HB_HAS_GLIB/$(HB_HAS_GLIB_DEF)/' \
-e 's/mesondefine HB_HAS_GOBJECT/$(HB_HAS_GOBJECT_DEF)/' \
-e 's/mesondefine HB_HAS_UNISCRIBE/$(HB_HAS_UNISCRIBE_DEF)/' \
-e 's/mesondefine HB_HAS_DIRECTWRITE/$(HB_HAS_DIRECTWRITE_DEF)/' \
-e 's/mesondefine HB_HAS_CORETEXT/$(HB_HAS_CORETEXT_DEF)/' \
-e 's/mesondefine HB_HAS_ICU/$(HB_HAS_ICU_DEF)/' \
"$<" > "$@" || ($(RM) "$@"; false)
%.pc: %.pc.in $(top_builddir)/config.status
$(AM_V_GEN) \
$(SED) -e 's@%prefix%@$(prefix)@g' \
@ -307,13 +235,10 @@ DEF_FILES += harfbuzz-gobject.def
endif
check: $(DEF_FILES) # For check-symbols.sh
CLEANFILES += $(DEF_FILES)
harfbuzz.def: $(top_builddir)/config.status
harfbuzz.def: $(HBHEADERS)
harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS)
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
harfbuzz-subset.def: $(HB_SUBSET_headers)
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
harfbuzz-cairo.def: $(HB_CAIRO_headers)
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
harfbuzz-icu.def: $(HB_ICU_headers)
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
harfbuzz-gobject.def: $(HB_GOBJECT_headers)
@ -358,7 +283,6 @@ $(srcdir)/%.hh: $(srcdir)/%.rl
harfbuzz.cc: Makefile.sources
$(AM_V_GEN) \
LANG=C; \
for f in \
$(HB_BASE_sources) \
$(HB_GLIB_sources) \
@ -369,7 +293,6 @@ harfbuzz.cc: Makefile.sources
$(HB_DIRECTWRITE_sources) \
$(HB_CORETEXT_sources) \
; do echo '#include "'$$f'"'; done | \
sort -u | \
grep '[.]cc"' > $(srcdir)/harfbuzz.cc \
|| ($(RM) $(srcdir)/harfbuzz.cc; false)
BUILT_SOURCES += harfbuzz.cc
@ -382,9 +305,7 @@ noinst_PROGRAMS = \
test-ot-name \
test-ot-glyphname \
test-gpos-size-params \
test-gsub-get-alternates \
test-gsub-would-substitute \
test-use-table \
$(NULL)
bin_PROGRAMS =
@ -412,40 +333,15 @@ test_ot_glyphname_SOURCES = test-ot-glyphname.cc
test_ot_glyphname_CPPFLAGS = $(HBCFLAGS)
test_ot_glyphname_LDADD = libharfbuzz.la $(HBLIBS)
test_use_table_SOURCES = test-use-table.cc
test_use_table_CPPFLAGS = $(HBCFLAGS)
test_use_table_LDADD = libharfbuzz.la $(HBLIBS)
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_get_alternates_SOURCES = test-gsub-get-alternates.cc
test_gsub_get_alternates_CPPFLAGS = $(HBCFLAGS)
test_gsub_get_alternates_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)
COMPILED_TESTS = \
test-algs \
test-array \
test-bimap \
test-iter \
test-machinery \
test-map \
test-multimap \
test-number \
test-ot-tag \
test-priority-queue \
test-set \
test-serialize \
test-unicode-ranges \
test-vector \
test-repacker \
test-classdef-graph \
$(NULL)
COMPILED_TESTS = test-algs test-array test-iter test-meta test-number test-ot-tag test-unicode-ranges test-bimap
COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
check_PROGRAMS += $(COMPILED_TESTS)
@ -459,25 +355,13 @@ test_array_SOURCES = test-array.cc
test_array_CPPFLAGS = $(HBCFLAGS)
test_array_LDADD = libharfbuzz.la $(HBLIBS)
test_bimap_SOURCES = test-bimap.cc hb-static.cc
test_bimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_bimap_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_machinery_SOURCES = test-machinery.cc hb-static.cc
test_machinery_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_machinery_LDADD = $(COMPILED_TESTS_LDADD)
test_map_SOURCES = test-map.cc hb-static.cc
test_map_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_map_LDADD = $(COMPILED_TESTS_LDADD)
test_multimap_SOURCES = test-multimap.cc hb-static.cc
test_multimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_multimap_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_number_SOURCES = test-number.cc hb-number.cc
test_number_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
@ -487,33 +371,13 @@ test_ot_tag_SOURCES = hb-ot-tag.cc
test_ot_tag_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_ot_tag_LDADD = $(COMPILED_TESTS_LDADD)
test_priority_queue_SOURCES = test-priority-queue.cc hb-static.cc
test_priority_queue_CPPFLAGS = $(HBCFLAGS)
test_priority_queue_LDADD = libharfbuzz.la $(HBLIBS)
test_repacker_SOURCES = test-repacker.cc hb-static.cc graph/gsubgpos-context.cc
test_repacker_CPPFLAGS = $(HBCFLAGS)
test_repacker_LDADD = libharfbuzz.la libharfbuzz-subset.la $(HBLIBS)
test_classdef_graph_SOURCES = graph/test-classdef-graph.cc hb-static.cc graph/gsubgpos-context.cc
test_classdef_graph_CPPFLAGS = $(HBCFLAGS)
test_classdef_graph_LDADD = libharfbuzz.la libharfbuzz-subset.la $(HBLIBS)
test_set_SOURCES = test-set.cc hb-static.cc
test_set_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_set_LDADD = $(COMPILED_TESTS_LDADD)
test_serialize_SOURCES = test-serialize.cc hb-static.cc
test_serialize_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_serialize_LDADD = $(COMPILED_TESTS_LDADD)
test_unicode_ranges_SOURCES = test-unicode-ranges.cc
test_unicode_ranges_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_unicode_ranges_LDADD = $(COMPILED_TESTS_LDADD)
test_vector_SOURCES = test-vector.cc hb-static.cc
test_vector_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_vector_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)
dist_check_SCRIPTS = \
check-c-linkage-decls.py \
@ -533,15 +397,10 @@ endif
TESTS_ENVIRONMENT = \
srcdir="$(srcdir)" \
base_srcdir="$(srcdir)" \
builddir="$(builddir)" \
MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
HBSOURCES="$(HBSOURCES)" \
HBHEADERS="$(HBHEADERS)" \
LDD="$(LDD)" \
NM="$(NM)" \
OBJDUMP="$(OBJDUMP)" \
OTOOL="$(OTOOL)" \
$(NULL)
if HAVE_INTROSPECTION
@ -562,7 +421,7 @@ INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
INTROSPECTION_SCANNER_ENV = CC="$(CC)"
HarfBuzz-0.0.gir: libharfbuzz.la libharfbuzz-gobject.la
HarfBuzz_0_0_gir_INCLUDES = GObject-2.0 freetype2-2.0
HarfBuzz_0_0_gir_INCLUDES = GObject-2.0
HarfBuzz_0_0_gir_CFLAGS = \
$(INCLUDES) \
$(HBCFLAGS) \

View File

@ -19,13 +19,9 @@ HB_BASE_sources = \
hb-array.hh \
hb-atomic.hh \
hb-bimap.hh \
hb-bit-page.hh \
hb-bit-set.hh \
hb-bit-set-invertible.hh \
hb-blob.cc \
hb-blob.hh \
hb-buffer-serialize.cc \
hb-buffer-verify.cc \
hb-buffer.cc \
hb-buffer.hh \
hb-cache.hh \
@ -42,19 +38,15 @@ HB_BASE_sources = \
hb-draw.hh \
hb-face.cc \
hb-face.hh \
hb-face-builder.cc \
hb-fallback-shape.cc \
hb-font.cc \
hb-font.hh \
hb-iter.hh \
hb-kern.hh \
hb-limits.hh \
hb-machinery.hh \
hb-map.cc \
hb-map.hh \
hb-meta.hh \
hb-ms-feature-ranges.hh \
hb-multimap.hh \
hb-mutex.hh \
hb-null.hh \
hb-number.cc \
@ -69,6 +61,11 @@ HB_BASE_sources = \
hb-ot-cff2-table.cc \
hb-ot-cff2-table.hh \
hb-ot-cmap-table.hh \
hb-ot-color-cbdt-table.hh \
hb-ot-color-colr-table.hh \
hb-ot-color-cpal-table.hh \
hb-ot-color-sbix-table.hh \
hb-ot-color-svg-table.hh \
hb-ot-color.cc \
hb-ot-face-table-list.hh \
hb-ot-face.cc \
@ -85,91 +82,7 @@ HB_BASE_sources = \
hb-ot-layout-common.hh \
hb-ot-layout-gdef-table.hh \
hb-ot-layout-gpos-table.hh \
hb-outline.hh \
hb-outline.cc \
hb-paint.cc \
hb-paint.hh \
hb-paint-extents.cc \
hb-paint-extents.hh \
hb-ot-layout-gsub-table.hh \
OT/Color/CBDT/CBDT.hh \
OT/Color/COLR/COLR.hh \
OT/Color/CPAL/CPAL.hh \
OT/Color/sbix/sbix.hh \
OT/Color/svg/svg.hh \
OT/glyf/glyf.hh \
OT/glyf/glyf-helpers.hh \
OT/glyf/loca.hh \
OT/glyf/path-builder.hh \
OT/glyf/Glyph.hh \
OT/glyf/GlyphHeader.hh \
OT/glyf/SimpleGlyph.hh \
OT/glyf/coord-setter.hh \
OT/glyf/composite-iter.hh \
OT/glyf/CompositeGlyph.hh \
OT/glyf/VarCompositeGlyph.hh \
OT/glyf/SubsetGlyph.hh \
OT/Layout/types.hh \
OT/Layout/Common/Coverage.hh \
OT/Layout/Common/CoverageFormat1.hh \
OT/Layout/Common/CoverageFormat2.hh \
OT/Layout/Common/RangeRecord.hh \
OT/Layout/GDEF/GDEF.hh \
OT/Layout/GPOS/AnchorFormat1.hh \
OT/Layout/GPOS/AnchorFormat2.hh \
OT/Layout/GPOS/AnchorFormat3.hh \
OT/Layout/GPOS/Anchor.hh \
OT/Layout/GPOS/AnchorMatrix.hh \
OT/Layout/GPOS/ChainContextPos.hh \
OT/Layout/GPOS/Common.hh \
OT/Layout/GPOS/ContextPos.hh \
OT/Layout/GPOS/CursivePosFormat1.hh \
OT/Layout/GPOS/CursivePos.hh \
OT/Layout/GPOS/ExtensionPos.hh \
OT/Layout/GPOS/GPOS.hh \
OT/Layout/GPOS/LigatureArray.hh \
OT/Layout/GPOS/MarkArray.hh \
OT/Layout/GPOS/MarkBasePosFormat1.hh \
OT/Layout/GPOS/MarkBasePos.hh \
OT/Layout/GPOS/MarkLigPosFormat1.hh \
OT/Layout/GPOS/MarkLigPos.hh \
OT/Layout/GPOS/MarkMarkPosFormat1.hh \
OT/Layout/GPOS/MarkMarkPos.hh \
OT/Layout/GPOS/MarkRecord.hh \
OT/Layout/GPOS/PairPosFormat1.hh \
OT/Layout/GPOS/PairPosFormat2.hh \
OT/Layout/GPOS/PairPos.hh \
OT/Layout/GPOS/PairSet.hh \
OT/Layout/GPOS/PairValueRecord.hh \
OT/Layout/GPOS/PosLookup.hh \
OT/Layout/GPOS/PosLookupSubTable.hh \
OT/Layout/GPOS/SinglePosFormat1.hh \
OT/Layout/GPOS/SinglePosFormat2.hh \
OT/Layout/GPOS/SinglePos.hh \
OT/Layout/GPOS/ValueFormat.hh \
OT/Layout/GSUB/AlternateSet.hh \
OT/Layout/GSUB/AlternateSubstFormat1.hh \
OT/Layout/GSUB/AlternateSubst.hh \
OT/Layout/GSUB/ChainContextSubst.hh \
OT/Layout/GSUB/Common.hh \
OT/Layout/GSUB/ContextSubst.hh \
OT/Layout/GSUB/ExtensionSubst.hh \
OT/Layout/GSUB/GSUB.hh \
OT/Layout/GSUB/Ligature.hh \
OT/Layout/GSUB/LigatureSet.hh \
OT/Layout/GSUB/LigatureSubstFormat1.hh \
OT/Layout/GSUB/LigatureSubst.hh \
OT/Layout/GSUB/MultipleSubstFormat1.hh \
OT/Layout/GSUB/MultipleSubst.hh \
OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh \
OT/Layout/GSUB/ReverseChainSingleSubst.hh \
OT/Layout/GSUB/Sequence.hh \
OT/Layout/GSUB/SingleSubstFormat1.hh \
OT/Layout/GSUB/SingleSubstFormat2.hh \
OT/Layout/GSUB/SingleSubst.hh \
OT/Layout/GSUB/SubstLookup.hh \
OT/Layout/GSUB/SubstLookupSubTable.hh \
OT/name/name.hh \
hb-ot-layout-gsubgpos.hh \
hb-ot-layout-jstf-table.hh \
hb-ot-layout.cc \
@ -191,29 +104,30 @@ HB_BASE_sources = \
hb-ot-os2-unicode-ranges.hh \
hb-ot-post-macroman.hh \
hb-ot-post-table.hh \
hb-ot-shaper-arabic-fallback.hh \
hb-ot-shaper-arabic-joining-list.hh \
hb-ot-shaper-arabic-pua.hh \
hb-ot-shaper-arabic-table.hh \
hb-ot-shaper-arabic-win1256.hh \
hb-ot-shaper-arabic.cc \
hb-ot-shaper-arabic.hh \
hb-ot-shaper-default.cc \
hb-ot-shaper-hangul.cc \
hb-ot-shaper-hebrew.cc \
hb-ot-shaper-indic-table.cc \
hb-ot-shaper-indic.cc \
hb-ot-shaper-indic.hh \
hb-ot-shaper-khmer.cc \
hb-ot-shaper-myanmar.cc \
hb-ot-shaper-syllabic.cc \
hb-ot-shaper-syllabic.hh \
hb-ot-shaper-thai.cc \
hb-ot-shaper-use-table.hh \
hb-ot-shaper-use.cc \
hb-ot-shaper-vowel-constraints.cc \
hb-ot-shaper-vowel-constraints.hh \
hb-ot-shaper.hh \
hb-ot-shape-complex-arabic-fallback.hh \
hb-ot-shape-complex-arabic-joining-list.hh \
hb-ot-shape-complex-arabic-table.hh \
hb-ot-shape-complex-arabic-win1256.hh \
hb-ot-shape-complex-arabic.cc \
hb-ot-shape-complex-arabic.hh \
hb-ot-shape-complex-default.cc \
hb-ot-shape-complex-hangul.cc \
hb-ot-shape-complex-hebrew.cc \
hb-ot-shape-complex-indic-table.cc \
hb-ot-shape-complex-indic.cc \
hb-ot-shape-complex-indic.hh \
hb-ot-shape-complex-khmer.cc \
hb-ot-shape-complex-khmer.hh \
hb-ot-shape-complex-myanmar.cc \
hb-ot-shape-complex-myanmar.hh \
hb-ot-shape-complex-syllabic.cc \
hb-ot-shape-complex-syllabic.hh \
hb-ot-shape-complex-thai.cc \
hb-ot-shape-complex-use-table.hh \
hb-ot-shape-complex-use.cc \
hb-ot-shape-complex-vowel-constraints.cc \
hb-ot-shape-complex-vowel-constraints.hh \
hb-ot-shape-complex.hh \
hb-ot-shape-fallback.cc \
hb-ot-shape-fallback.hh \
hb-ot-shape-normalize.cc \
@ -224,8 +138,6 @@ HB_BASE_sources = \
hb-ot-tag-table.hh \
hb-ot-tag.cc \
hb-ot-var-avar-table.hh \
hb-ot-var-common.hh \
hb-ot-var-cvar-table.hh \
hb-ot-var-fvar-table.hh \
hb-ot-var-gvar-table.hh \
hb-ot-var-hvar-table.hh \
@ -255,29 +167,26 @@ HB_BASE_sources = \
hb-unicode.hh \
hb-utf.hh \
hb-vector.hh \
hb-priority-queue.hh \
hb.hh \
$(NULL)
HB_BASE_RAGEL_GENERATED_sources = \
hb-buffer-deserialize-json.hh \
hb-buffer-deserialize-text-glyphs.hh \
hb-buffer-deserialize-text-unicode.hh \
hb-buffer-deserialize-text.hh \
hb-number-parser.hh \
hb-ot-shaper-indic-machine.hh \
hb-ot-shaper-khmer-machine.hh \
hb-ot-shaper-myanmar-machine.hh \
hb-ot-shaper-use-machine.hh \
hb-ot-shape-complex-indic-machine.hh \
hb-ot-shape-complex-khmer-machine.hh \
hb-ot-shape-complex-myanmar-machine.hh \
hb-ot-shape-complex-use-machine.hh \
$(NULL)
HB_BASE_RAGEL_sources = \
hb-buffer-deserialize-json.rl \
hb-buffer-deserialize-text-glyphs.rl \
hb-buffer-deserialize-text-unicode.rl \
hb-buffer-deserialize-text.rl \
hb-number-parser.rl \
hb-ot-shaper-indic-machine.rl \
hb-ot-shaper-khmer-machine.rl \
hb-ot-shaper-myanmar-machine.rl \
hb-ot-shaper-use-machine.rl \
hb-ot-shape-complex-indic-machine.rl \
hb-ot-shape-complex-khmer-machine.rl \
hb-ot-shape-complex-myanmar-machine.rl \
hb-ot-shape-complex-use-machine.rl \
$(NULL)
HB_BASE_headers = \
@ -286,7 +195,6 @@ HB_BASE_headers = \
hb-blob.h \
hb-buffer.h \
hb-common.h \
hb-cplusplus.hh \
hb-deprecated.h \
hb-draw.h \
hb-face.h \
@ -303,7 +211,6 @@ HB_BASE_headers = \
hb-ot-shape.h \
hb-ot-var.h \
hb-ot.h \
hb-paint.h \
hb-set.h \
hb-shape-plan.h \
hb-shape.h \
@ -315,7 +222,7 @@ HB_BASE_headers = \
# Optional Sources and Headers with external deps
HB_FT_sources = hb-ft.cc hb-ft-colr.hh
HB_FT_sources = hb-ft.cc
HB_FT_headers = hb-ft.h
HB_GLIB_sources = hb-glib.cc
@ -348,7 +255,6 @@ HB_SUBSET_sources = \
hb-number.hh \
hb-ot-cff1-table.cc \
hb-ot-cff2-table.cc \
hb-ot-post-table-v2subset.hh \
hb-static.cc \
hb-subset-cff-common.cc \
hb-subset-cff-common.hh \
@ -358,40 +264,14 @@ HB_SUBSET_sources = \
hb-subset-cff2.hh \
hb-subset-input.cc \
hb-subset-input.hh \
hb-subset-instancer-solver.cc \
hb-subset-accelerator.hh \
hb-subset-plan.cc \
hb-subset-plan.hh \
hb-subset-repacker.cc \
hb-subset.cc \
hb-subset.hh \
hb-repacker.hh \
graph/graph.hh \
graph/gsubgpos-graph.hh \
graph/gsubgpos-context.hh \
graph/gsubgpos-context.cc \
graph/coverage-graph.hh \
graph/classdef-graph.hh \
graph/pairpos-graph.hh \
graph/markbasepos-graph.hh \
graph/split-helpers.hh \
graph/serialize.hh \
OT/Color/COLR/colrv1-closure.hh \
$(NULL)
HB_SUBSET_headers = \
hb-subset.h \
hb-subset-repacker.h \
$(NULL)
HB_CAIRO_sources = \
hb-cairo.cc \
hb-cairo-utils.cc \
hb-cairo-utils.hh \
hb-static.cc \
$(NULL)
HB_CAIRO_headers = \
hb-cairo.h \
$(NULL)
HB_GOBJECT_DIST_sources = hb-gobject-structs.cc

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,107 +0,0 @@
/*
* Copyright © 2018 Ebrahim Byagowi
* Copyright © 2020 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.
*
*/
#ifndef OT_COLOR_COLR_COLRV1_CLOSURE_HH
#define OT_COLOR_COLR_COLRV1_CLOSURE_HH
#include "../../../hb-open-type.hh"
#include "COLR.hh"
/*
* COLR -- Color
* https://docs.microsoft.com/en-us/typography/opentype/spec/colr
*/
namespace OT {
HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) const
{
c->add_layer_indices (firstLayerIndex, numLayers);
const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
{
const Paint &paint = std::addressof (paint_offset_lists) + paint_offset_lists[i];
paint.dispatch (c);
}
}
HB_INTERNAL void PaintGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
{
c->add_glyph (gid);
(this+paint).dispatch (c);
}
HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
{
const COLR *colr_table = c->get_colr_table ();
const BaseGlyphPaintRecord* baseglyph_paintrecord = colr_table->get_base_glyph_paintrecord (gid);
if (!baseglyph_paintrecord) return;
c->add_glyph (gid);
const BaseGlyphList &baseglyph_list = colr_table->get_baseglyphList ();
(&baseglyph_list+baseglyph_paintrecord->paint).dispatch (c);
}
template <template<typename> class Var>
HB_INTERNAL void PaintTransform<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
{ (this+src).dispatch (c); }
HB_INTERNAL void PaintTranslate::closurev1 (hb_colrv1_closure_context_t* c) const
{ (this+src).dispatch (c); }
HB_INTERNAL void PaintScale::closurev1 (hb_colrv1_closure_context_t* c) const
{ (this+src).dispatch (c); }
HB_INTERNAL void PaintScaleAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
{ (this+src).dispatch (c); }
HB_INTERNAL void PaintScaleUniform::closurev1 (hb_colrv1_closure_context_t* c) const
{ (this+src).dispatch (c); }
HB_INTERNAL void PaintScaleUniformAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
{ (this+src).dispatch (c); }
HB_INTERNAL void PaintRotate::closurev1 (hb_colrv1_closure_context_t* c) const
{ (this+src).dispatch (c); }
HB_INTERNAL void PaintRotateAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
{ (this+src).dispatch (c); }
HB_INTERNAL void PaintSkew::closurev1 (hb_colrv1_closure_context_t* c) const
{ (this+src).dispatch (c); }
HB_INTERNAL void PaintSkewAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
{ (this+src).dispatch (c); }
HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const
{
(this+src).dispatch (c);
(this+backdrop).dispatch (c);
}
} /* namespace OT */
#endif /* OT_COLOR_COLR_COLRV1_CLOSURE_HH */

View File

@ -1,350 +0,0 @@
/*
* Copyright © 2016 Google, Inc.
* Copyright © 2018 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Sascha Brawer
*/
#ifndef OT_COLOR_CPAL_CPAL_HH
#define OT_COLOR_CPAL_CPAL_HH
#include "../../../hb-open-type.hh"
#include "../../../hb-ot-color.h"
#include "../../../hb-ot-name.h"
/*
* CPAL -- Color Palette
* https://docs.microsoft.com/en-us/typography/opentype/spec/cpal
*/
#define HB_OT_TAG_CPAL HB_TAG('C','P','A','L')
namespace OT {
struct CPALV1Tail
{
friend struct CPAL;
private:
hb_ot_color_palette_flags_t get_palette_flags (const void *base,
unsigned int palette_index,
unsigned int palette_count) const
{
if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
return (hb_ot_color_palette_flags_t) (uint32_t)
(base+paletteFlagsZ).as_array (palette_count)[palette_index];
}
hb_ot_name_id_t get_palette_name_id (const void *base,
unsigned int palette_index,
unsigned int palette_count) const
{
if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID;
return (base+paletteLabelsZ).as_array (palette_count)[palette_index];
}
hb_ot_name_id_t get_color_name_id (const void *base,
unsigned int color_index,
unsigned int color_count) const
{
if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID;
return (base+colorLabelsZ).as_array (color_count)[color_index];
}
public:
void collect_name_ids (const void *base,
unsigned palette_count,
unsigned color_count,
const hb_map_t *color_index_map,
hb_set_t *nameids_to_retain /* OUT */) const
{
if (paletteLabelsZ)
{
+ (base+paletteLabelsZ).as_array (palette_count)
| hb_sink (nameids_to_retain)
;
}
if (colorLabelsZ)
{
const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
for (unsigned i = 0; i < color_count; i++)
{
if (!color_index_map->has (i)) continue;
nameids_to_retain->add (colorLabels[i]);
}
}
}
bool serialize (hb_serialize_context_t *c,
unsigned palette_count,
unsigned color_count,
const void *base,
const hb_map_t *color_index_map) const
{
TRACE_SERIALIZE (this);
auto *out = c->allocate_size<CPALV1Tail> (static_size);
if (unlikely (!out)) return_trace (false);
out->paletteFlagsZ = 0;
if (paletteFlagsZ)
out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count);
out->paletteLabelsZ = 0;
if (paletteLabelsZ)
out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count);
const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
if (colorLabelsZ)
{
c->push ();
for (unsigned i = 0; i < color_count; i++)
{
if (!color_index_map->has (i)) continue;
if (!c->copy<NameID> (colorLabels[i]))
{
c->pop_discard ();
return_trace (false);
}
}
c->add_link (out->colorLabelsZ, c->pop_pack ());
}
return_trace (true);
}
bool sanitize (hb_sanitize_context_t *c,
const void *base,
unsigned int palette_count,
unsigned int color_count) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
(!paletteFlagsZ || (base+paletteFlagsZ).sanitize (c, palette_count)) &&
(!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) &&
(!colorLabelsZ || (base+colorLabelsZ).sanitize (c, color_count)));
}
protected:
// TODO(garretrieger): these offsets can hold nulls so we should not be using non-null offsets
// here. Currently they are needed since UnsizedArrayOf doesn't define null_size
NNOffset32To<UnsizedArrayOf<HBUINT32>>
paletteFlagsZ; /* Offset from the beginning of CPAL table to
* the Palette Type Array. Set to 0 if no array
* is provided. */
NNOffset32To<UnsizedArrayOf<NameID>>
paletteLabelsZ; /* Offset from the beginning of CPAL table to
* the palette labels array. Set to 0 if no
* array is provided. */
NNOffset32To<UnsizedArrayOf<NameID>>
colorLabelsZ; /* Offset from the beginning of CPAL table to
* the color labels array. Set to 0
* if no array is provided. */
public:
DEFINE_SIZE_STATIC (12);
};
typedef HBUINT32 BGRAColor;
struct CPAL
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_CPAL;
bool has_data () const { return numPalettes; }
unsigned int get_size () const
{ return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); }
unsigned int get_palette_count () const { return numPalettes; }
unsigned int get_color_count () const { return numColors; }
hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const
{ return v1 ().get_palette_flags (this, palette_index, numPalettes); }
hb_ot_name_id_t get_palette_name_id (unsigned int palette_index) const
{ return v1 ().get_palette_name_id (this, palette_index, numPalettes); }
hb_ot_name_id_t get_color_name_id (unsigned int color_index) const
{ return v1 ().get_color_name_id (this, color_index, numColors); }
unsigned int get_palette_colors (unsigned int palette_index,
unsigned int start_offset,
unsigned int *color_count, /* IN/OUT. May be NULL. */
hb_color_t *colors /* OUT. May be NULL. */) const
{
if (unlikely (palette_index >= numPalettes))
{
if (color_count) *color_count = 0;
return 0;
}
unsigned int start_index = colorRecordIndicesZ[palette_index];
hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
hb_array_t<const BGRAColor> palette_colors = all_colors.sub_array (start_index,
numColors);
if (color_count)
{
+ palette_colors.sub_array (start_offset, color_count)
| hb_sink (hb_array (colors, *color_count))
;
}
return numColors;
}
void collect_name_ids (const hb_map_t *color_index_map,
hb_set_t *nameids_to_retain /* OUT */) const
{
if (version == 1)
v1 ().collect_name_ids (this, numPalettes, numColors, color_index_map, nameids_to_retain);
}
private:
const CPALV1Tail& v1 () const
{
if (version == 0) return Null (CPALV1Tail);
return StructAfter<CPALV1Tail> (*this);
}
public:
bool serialize (hb_serialize_context_t *c,
const hb_array_t<const HBUINT16> &color_record_indices,
const hb_array_t<const BGRAColor> &color_records,
const hb_vector_t<unsigned>& first_color_index_for_layer,
const hb_map_t& first_color_to_layer_index,
const hb_set_t &retained_color_indices) const
{
TRACE_SERIALIZE (this);
// TODO(grieger): limit total final size.
for (const auto idx : color_record_indices)
{
hb_codepoint_t layer_index = first_color_to_layer_index[idx];
HBUINT16 new_idx;
new_idx = layer_index * retained_color_indices.get_population ();
if (!c->copy<HBUINT16> (new_idx)) return_trace (false);
}
c->push ();
for (unsigned first_color_index : first_color_index_for_layer)
{
for (hb_codepoint_t color_index : retained_color_indices)
{
if (!c->copy<BGRAColor> (color_records[first_color_index + color_index]))
{
c->pop_discard ();
return_trace (false);
}
}
}
c->add_link (colorRecordsZ, c->pop_pack ());
return_trace (true);
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
if (!numPalettes) return_trace (false);
const hb_map_t *color_index_map = &c->plan->colr_palettes;
if (color_index_map->is_empty ()) return_trace (false);
hb_set_t retained_color_indices;
for (const auto _ : color_index_map->keys ())
{
if (_ == 0xFFFF) continue;
retained_color_indices.add (_);
}
if (retained_color_indices.is_empty ()) return_trace (false);
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->version = version;
out->numColors = retained_color_indices.get_population ();
out->numPalettes = numPalettes;
hb_vector_t<unsigned> first_color_index_for_layer;
hb_map_t first_color_to_layer_index;
const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
for (const auto first_color_record_idx : colorRecordIndices)
{
if (first_color_to_layer_index.has (first_color_record_idx)) continue;
first_color_index_for_layer.push (first_color_record_idx);
first_color_to_layer_index.set (first_color_record_idx,
first_color_index_for_layer.length - 1);
}
out->numColorRecords = first_color_index_for_layer.length
* retained_color_indices.get_population ();
const hb_array_t<const BGRAColor> color_records = (this+colorRecordsZ).as_array (numColorRecords);
if (!out->serialize (c->serializer,
colorRecordIndices,
color_records,
first_color_index_for_layer,
first_color_to_layer_index,
retained_color_indices))
return_trace (false);
if (version == 1)
return_trace (v1 ().serialize (c->serializer, numPalettes, numColors, this, color_index_map));
return_trace (true);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
(this+colorRecordsZ).sanitize (c, numColorRecords) &&
colorRecordIndicesZ.sanitize (c, numPalettes) &&
(version == 0 || v1 ().sanitize (c, this, numPalettes, numColors)));
}
protected:
HBUINT16 version; /* Table version number */
/* Version 0 */
HBUINT16 numColors; /* Number of colors in each palette. */
HBUINT16 numPalettes; /* Number of palettes in the table. */
HBUINT16 numColorRecords; /* Total number of color records, combined for
* all palettes. */
NNOffset32To<UnsizedArrayOf<BGRAColor>>
colorRecordsZ; /* Offset from the beginning of CPAL table to
* the first ColorRecord. */
UnsizedArrayOf<HBUINT16>
colorRecordIndicesZ; /* Index of each palettes first color record in
* the combined color record array. */
/*CPALV1Tail v1;*/
public:
DEFINE_SIZE_ARRAY (12, colorRecordIndicesZ);
};
} /* namespace OT */
#endif /* OT_COLOR_CPAL_CPAL_HH */

View File

@ -1,452 +0,0 @@
/*
* Copyright © 2018 Ebrahim Byagowi
* Copyright © 2020 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): Calder Kitagawa
*/
#ifndef OT_COLOR_SBIX_SBIX_HH
#define OT_COLOR_SBIX_SBIX_HH
#include "../../../hb-open-type.hh"
#include "../../../hb-paint.hh"
/*
* sbix -- Standard Bitmap Graphics
* https://docs.microsoft.com/en-us/typography/opentype/spec/sbix
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6sbix.html
*/
#define HB_OT_TAG_sbix HB_TAG('s','b','i','x')
namespace OT {
struct SBIXGlyph
{
SBIXGlyph* copy (hb_serialize_context_t *c, unsigned int data_length) const
{
TRACE_SERIALIZE (this);
SBIXGlyph* new_glyph = c->start_embed<SBIXGlyph> ();
if (unlikely (!new_glyph)) return_trace (nullptr);
if (unlikely (!c->extend_min (new_glyph))) return_trace (nullptr);
new_glyph->xOffset = xOffset;
new_glyph->yOffset = yOffset;
new_glyph->graphicType = graphicType;
data.copy (c, data_length);
return_trace (new_glyph);
}
HBINT16 xOffset; /* The horizontal (x-axis) offset from the left
* edge of the graphic to the glyphs origin.
* That is, the x-coordinate of the point on the
* baseline at the left edge of the glyph. */
HBINT16 yOffset; /* The vertical (y-axis) offset from the bottom
* edge of the graphic to the glyphs origin.
* That is, the y-coordinate of the point on the
* baseline at the left edge of the glyph. */
Tag graphicType; /* Indicates the format of the embedded graphic
* data: one of 'jpg ', 'png ' or 'tiff', or the
* special format 'dupe'. */
UnsizedArrayOf<HBUINT8>
data; /* The actual embedded graphic data. The total
* length is inferred from sequential entries in
* the glyphDataOffsets array and the fixed size
* (8 bytes) of the preceding fields. */
public:
DEFINE_SIZE_ARRAY (8, data);
};
struct SBIXStrike
{
static unsigned int get_size (unsigned num_glyphs)
{ return min_size + num_glyphs * HBUINT32::static_size; }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1));
}
hb_blob_t *get_glyph_blob (unsigned int glyph_id,
hb_blob_t *sbix_blob,
hb_tag_t file_type,
int *x_offset,
int *y_offset,
unsigned int num_glyphs,
unsigned int *strike_ppem) const
{
if (unlikely (!ppem)) return hb_blob_get_empty (); /* To get Null() object out of the way. */
unsigned int retry_count = 8;
unsigned int sbix_len = sbix_blob->length;
unsigned int strike_offset = (const char *) this - (const char *) sbix_blob->data;
assert (strike_offset < sbix_len);
retry:
if (unlikely (glyph_id >= num_glyphs ||
imageOffsetsZ[glyph_id + 1] <= imageOffsetsZ[glyph_id] ||
imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] <= SBIXGlyph::min_size ||
(unsigned int) imageOffsetsZ[glyph_id + 1] > sbix_len - strike_offset))
return hb_blob_get_empty ();
unsigned int glyph_offset = strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size;
unsigned int glyph_length = imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] - SBIXGlyph::min_size;
const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]);
if (glyph->graphicType == HB_TAG ('d','u','p','e'))
{
if (glyph_length >= 2)
{
glyph_id = *((HBUINT16 *) &glyph->data);
if (retry_count--)
goto retry;
}
return hb_blob_get_empty ();
}
if (unlikely (file_type != glyph->graphicType))
return hb_blob_get_empty ();
if (strike_ppem) *strike_ppem = ppem;
if (x_offset) *x_offset = glyph->xOffset;
if (y_offset) *y_offset = glyph->yOffset;
return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length);
}
bool subset (hb_subset_context_t *c, unsigned int available_len) const
{
TRACE_SUBSET (this);
unsigned int num_output_glyphs = c->plan->num_output_glyphs ();
auto* out = c->serializer->start_embed<SBIXStrike> ();
if (unlikely (!out)) return_trace (false);
auto snap = c->serializer->snapshot ();
if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false);
out->ppem = ppem;
out->resolution = resolution;
HBUINT32 head;
head = get_size (num_output_glyphs + 1);
bool has_glyphs = false;
for (unsigned new_gid = 0; new_gid < num_output_glyphs; new_gid++)
{
hb_codepoint_t old_gid;
if (!c->plan->old_gid_for_new_gid (new_gid, &old_gid) ||
unlikely (imageOffsetsZ[old_gid].is_null () ||
imageOffsetsZ[old_gid + 1].is_null () ||
imageOffsetsZ[old_gid + 1] <= imageOffsetsZ[old_gid] ||
imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid] <= SBIXGlyph::min_size) ||
(unsigned int) imageOffsetsZ[old_gid + 1] > available_len)
{
out->imageOffsetsZ[new_gid] = head;
continue;
}
has_glyphs = true;
unsigned int delta = imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid];
unsigned int glyph_data_length = delta - SBIXGlyph::min_size;
if (!(this+imageOffsetsZ[old_gid]).copy (c->serializer, glyph_data_length))
return_trace (false);
out->imageOffsetsZ[new_gid] = head;
head += delta;
}
if (has_glyphs)
out->imageOffsetsZ[num_output_glyphs] = head;
else
c->serializer->revert (snap);
return_trace (has_glyphs);
}
public:
HBUINT16 ppem; /* The PPEM size for which this strike was designed. */
HBUINT16 resolution; /* The device pixel density (in PPI) for which this
* strike was designed. (E.g., 96 PPI, 192 PPI.) */
protected:
UnsizedArrayOf<Offset32To<SBIXGlyph>>
imageOffsetsZ; /* Offset from the beginning of the strike data header
* to bitmap data for an individual glyph ID. */
public:
DEFINE_SIZE_ARRAY (4, imageOffsetsZ);
};
struct sbix
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_sbix;
bool has_data () const { return version; }
const SBIXStrike &get_strike (unsigned int i) const { return this+strikes[i]; }
struct accelerator_t
{
accelerator_t (hb_face_t *face)
{
table = hb_sanitize_context_t ().reference_table<sbix> (face);
num_glyphs = face->get_num_glyphs ();
}
~accelerator_t () { table.destroy (); }
bool has_data () const { return table->has_data (); }
bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents,
bool scale = true) const
{
/* We only support PNG right now, and following function checks type. */
return get_png_extents (font, glyph, extents, scale);
}
hb_blob_t *reference_png (hb_font_t *font,
hb_codepoint_t glyph_id,
int *x_offset,
int *y_offset,
unsigned int *available_ppem) const
{
return choose_strike (font).get_glyph_blob (glyph_id, table.get_blob (),
HB_TAG ('p','n','g',' '),
x_offset, y_offset,
num_glyphs, available_ppem);
}
bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
{
if (!has_data ())
return false;
int x_offset = 0, y_offset = 0;
unsigned int strike_ppem = 0;
hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
hb_glyph_extents_t extents;
hb_glyph_extents_t pixel_extents;
if (blob == hb_blob_get_empty ())
return false;
if (!hb_font_get_glyph_extents (font, glyph, &extents))
return false;
if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
return false;
bool ret = funcs->image (data,
blob,
pixel_extents.width, -pixel_extents.height,
HB_PAINT_IMAGE_FORMAT_PNG,
font->slant_xy,
&extents);
hb_blob_destroy (blob);
return ret;
}
private:
const SBIXStrike &choose_strike (hb_font_t *font) const
{
unsigned count = table->strikes.len;
if (unlikely (!count))
return Null (SBIXStrike);
unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
if (!requested_ppem)
requested_ppem = 1<<30; /* Choose largest strike. */
/* TODO Add DPI sensitivity as well? */
unsigned int best_i = 0;
unsigned int best_ppem = table->get_strike (0).ppem;
for (unsigned int i = 1; i < count; i++)
{
unsigned int ppem = (table->get_strike (i)).ppem;
if ((requested_ppem <= ppem && ppem < best_ppem) ||
(requested_ppem > best_ppem && ppem > best_ppem))
{
best_i = i;
best_ppem = ppem;
}
}
return table->get_strike (best_i);
}
struct PNGHeader
{
HBUINT8 signature[8];
struct
{
struct
{
HBUINT32 length;
Tag type;
} header;
HBUINT32 width;
HBUINT32 height;
HBUINT8 bitDepth;
HBUINT8 colorType;
HBUINT8 compressionMethod;
HBUINT8 filterMethod;
HBUINT8 interlaceMethod;
} IHDR;
public:
DEFINE_SIZE_STATIC (29);
};
bool get_png_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents,
bool scale = true) const
{
/* Following code is safe to call even without data.
* But faster to short-circuit. */
if (!has_data ())
return false;
int x_offset = 0, y_offset = 0;
unsigned int strike_ppem = 0;
hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
const PNGHeader &png = *blob->as<PNGHeader>();
if (png.IHDR.height >= 65536 || png.IHDR.width >= 65536)
{
hb_blob_destroy (blob);
return false;
}
extents->x_bearing = x_offset;
extents->y_bearing = png.IHDR.height + y_offset;
extents->width = png.IHDR.width;
extents->height = -1 * png.IHDR.height;
/* Convert to font units. */
if (strike_ppem && scale)
{
float scale = font->face->get_upem () / (float) strike_ppem;
extents->x_bearing = roundf (extents->x_bearing * scale);
extents->y_bearing = roundf (extents->y_bearing * scale);
extents->width = roundf (extents->width * scale);
extents->height = roundf (extents->height * scale);
}
if (scale)
font->scale_glyph_extents (extents);
hb_blob_destroy (blob);
return strike_ppem;
}
private:
hb_blob_ptr_t<sbix> table;
unsigned int num_glyphs;
};
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
version >= 1 &&
strikes.sanitize (c, this)));
}
bool
add_strike (hb_subset_context_t *c, unsigned i) const
{
if (strikes[i].is_null () || c->source_blob->length < (unsigned) strikes[i])
return false;
return (this+strikes[i]).subset (c, c->source_blob->length - (unsigned) strikes[i]);
}
bool serialize_strike_offsets (hb_subset_context_t *c) const
{
TRACE_SERIALIZE (this);
auto *out = c->serializer->start_embed<Array32OfOffset32To<SBIXStrike>> ();
if (unlikely (!out)) return_trace (false);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
hb_vector_t<Offset32To<SBIXStrike>*> new_strikes;
hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
for (int i = strikes.len - 1; i >= 0; --i)
{
auto* o = out->serialize_append (c->serializer);
if (unlikely (!o)) return_trace (false);
*o = 0;
auto snap = c->serializer->snapshot ();
c->serializer->push ();
bool ret = add_strike (c, i);
if (!ret)
{
c->serializer->pop_discard ();
out->pop ();
c->serializer->revert (snap);
}
else
{
objidxs.push (c->serializer->pop_pack ());
new_strikes.push (o);
}
}
for (unsigned int i = 0; i < new_strikes.length; ++i)
c->serializer->add_link (*new_strikes[i], objidxs[new_strikes.length - 1 - i]);
return_trace (true);
}
bool subset (hb_subset_context_t* c) const
{
TRACE_SUBSET (this);
sbix *sbix_prime = c->serializer->start_embed<sbix> ();
if (unlikely (!sbix_prime)) return_trace (false);
if (unlikely (!c->serializer->embed (this->version))) return_trace (false);
if (unlikely (!c->serializer->embed (this->flags))) return_trace (false);
return_trace (serialize_strike_offsets (c));
}
protected:
HBUINT16 version; /* Table version number — set to 1 */
HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines.
* Bits 2 to 15: reserved (set to 0). */
Array32OfOffset32To<SBIXStrike>
strikes; /* Offsets from the beginning of the 'sbix'
* table to data for each individual bitmap strike. */
public:
DEFINE_SIZE_ARRAY (8, strikes);
};
struct sbix_accelerator_t : sbix::accelerator_t {
sbix_accelerator_t (hb_face_t *face) : sbix::accelerator_t (face) {}
};
} /* namespace OT */
#endif /* OT_COLOR_SBIX_SBIX_HH */

View File

@ -1,151 +0,0 @@
/*
* Copyright © 2018 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#ifndef OT_COLOR_SVG_SVG_HH
#define OT_COLOR_SVG_SVG_HH
#include "../../../hb-open-type.hh"
#include "../../../hb-blob.hh"
#include "../../../hb-paint.hh"
/*
* SVG -- SVG (Scalable Vector Graphics)
* https://docs.microsoft.com/en-us/typography/opentype/spec/svg
*/
#define HB_OT_TAG_SVG HB_TAG('S','V','G',' ')
namespace OT {
struct SVGDocumentIndexEntry
{
int cmp (hb_codepoint_t g) const
{ return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; }
hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const
{
return hb_blob_create_sub_blob (svg_blob,
index_offset + (unsigned int) svgDoc,
svgDocLength);
}
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
svgDoc.sanitize (c, base, svgDocLength));
}
protected:
HBUINT16 startGlyphID; /* The first glyph ID in the range described by
* this index entry. */
HBUINT16 endGlyphID; /* The last glyph ID in the range described by
* this index entry. Must be >= startGlyphID. */
NNOffset32To<UnsizedArrayOf<HBUINT8>>
svgDoc; /* Offset from the beginning of the SVG Document Index
* to an SVG document. Must be non-zero. */
HBUINT32 svgDocLength; /* Length of the SVG document.
* Must be non-zero. */
public:
DEFINE_SIZE_STATIC (12);
};
struct SVG
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_SVG;
bool has_data () const { return svgDocEntries; }
struct accelerator_t
{
accelerator_t (hb_face_t *face)
{ table = hb_sanitize_context_t ().reference_table<SVG> (face); }
~accelerator_t () { table.destroy (); }
hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const
{
return table->get_glyph_entry (glyph_id).reference_blob (table.get_blob (),
table->svgDocEntries);
}
bool has_data () const { return table->has_data (); }
bool paint_glyph (hb_font_t *font HB_UNUSED, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
{
if (!has_data ())
return false;
hb_blob_t *blob = reference_blob_for_glyph (glyph);
if (blob == hb_blob_get_empty ())
return false;
funcs->image (data,
blob,
0, 0,
HB_PAINT_IMAGE_FORMAT_SVG,
font->slant_xy,
nullptr);
hb_blob_destroy (blob);
return true;
}
private:
hb_blob_ptr_t<SVG> table;
public:
DEFINE_SIZE_STATIC (sizeof (hb_blob_ptr_t<SVG>));
};
const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const
{ return (this+svgDocEntries).bsearch (glyph_id); }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
(this+svgDocEntries).sanitize_shallow (c)));
}
protected:
HBUINT16 version; /* Table version (starting at 0). */
Offset32To<SortedArray16Of<SVGDocumentIndexEntry>>
svgDocEntries; /* Offset (relative to the start of the SVG table) to the
* SVG Documents Index. Must be non-zero. */
/* Array of SVG Document Index Entries. */
HBUINT32 reserved; /* Set to 0. */
public:
DEFINE_SIZE_STATIC (10);
};
struct SVG_accelerator_t : SVG::accelerator_t {
SVG_accelerator_t (hb_face_t *face) : SVG::accelerator_t (face) {}
};
} /* namespace OT */
#endif /* OT_COLOR_SVG_SVG_HH */

View File

@ -1,337 +0,0 @@
/*
* Copyright © 2007,2008,2009 Red Hat, Inc.
* Copyright © 2010,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
* Google Author(s): Behdad Esfahbod, Garret Rieger
*/
#ifndef OT_LAYOUT_COMMON_COVERAGE_HH
#define OT_LAYOUT_COMMON_COVERAGE_HH
#include "../types.hh"
#include "CoverageFormat1.hh"
#include "CoverageFormat2.hh"
namespace OT {
namespace Layout {
namespace Common {
template<typename Iterator>
static inline void Coverage_serialize (hb_serialize_context_t *c,
Iterator it);
struct Coverage
{
protected:
union {
HBUINT16 format; /* Format identifier */
CoverageFormat1_3<SmallTypes> format1;
CoverageFormat2_4<SmallTypes> format2;
#ifndef HB_NO_BEYOND_64K
CoverageFormat1_3<MediumTypes>format3;
CoverageFormat2_4<MediumTypes>format4;
#endif
} u;
public:
DEFINE_SIZE_UNION (2, format);
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return_trace (false);
switch (u.format)
{
case 1: return_trace (u.format1.sanitize (c));
case 2: return_trace (u.format2.sanitize (c));
#ifndef HB_NO_BEYOND_64K
case 3: return_trace (u.format3.sanitize (c));
case 4: return_trace (u.format4.sanitize (c));
#endif
default:return_trace (true);
}
}
/* Has interface. */
unsigned operator [] (hb_codepoint_t k) const { return get (k); }
bool has (hb_codepoint_t k) const { return (*this)[k] != NOT_COVERED; }
/* Predicate. */
bool operator () (hb_codepoint_t k) const { return has (k); }
unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
unsigned int get_coverage (hb_codepoint_t glyph_id) const
{
switch (u.format) {
case 1: return u.format1.get_coverage (glyph_id);
case 2: return u.format2.get_coverage (glyph_id);
#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.get_coverage (glyph_id);
case 4: return u.format4.get_coverage (glyph_id);
#endif
default:return NOT_COVERED;
}
}
unsigned get_population () const
{
switch (u.format) {
case 1: return u.format1.get_population ();
case 2: return u.format2.get_population ();
#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.get_population ();
case 4: return u.format4.get_population ();
#endif
default:return NOT_COVERED;
}
}
template <typename Iterator,
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c, Iterator glyphs)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (this))) return_trace (false);
unsigned count = 0;
unsigned num_ranges = 0;
hb_codepoint_t last = (hb_codepoint_t) -2;
for (auto g: glyphs)
{
if (last + 1 != g)
num_ranges++;
last = g;
count++;
}
u.format = count <= num_ranges * 3 ? 1 : 2;
#ifndef HB_NO_BEYOND_64K
if (count && last > 0xFFFFu)
u.format += 2;
#endif
switch (u.format)
{
case 1: return_trace (u.format1.serialize (c, glyphs));
case 2: return_trace (u.format2.serialize (c, glyphs));
#ifndef HB_NO_BEYOND_64K
case 3: return_trace (u.format3.serialize (c, glyphs));
case 4: return_trace (u.format4.serialize (c, glyphs));
#endif
default:return_trace (false);
}
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto it =
+ iter ()
| hb_take (c->plan->source->get_num_glyphs ())
| hb_filter (c->plan->glyph_map_gsub)
| hb_map_retains_sorting (c->plan->glyph_map_gsub)
;
// Cache the iterator result as it will be iterated multiple times
// by the serialize code below.
hb_sorted_vector_t<hb_codepoint_t> glyphs (it);
Coverage_serialize (c->serializer, glyphs.iter ());
return_trace (bool (glyphs));
}
bool intersects (const hb_set_t *glyphs) const
{
switch (u.format)
{
case 1: return u.format1.intersects (glyphs);
case 2: return u.format2.intersects (glyphs);
#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.intersects (glyphs);
case 4: return u.format4.intersects (glyphs);
#endif
default:return false;
}
}
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
{
switch (u.format)
{
case 1: return u.format1.intersects_coverage (glyphs, index);
case 2: return u.format2.intersects_coverage (glyphs, index);
#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.intersects_coverage (glyphs, index);
case 4: return u.format4.intersects_coverage (glyphs, index);
#endif
default:return false;
}
}
/* Might return false if array looks unsorted.
* Used for faster rejection of corrupt data. */
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{
switch (u.format)
{
case 1: return u.format1.collect_coverage (glyphs);
case 2: return u.format2.collect_coverage (glyphs);
#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.collect_coverage (glyphs);
case 4: return u.format4.collect_coverage (glyphs);
#endif
default:return false;
}
}
template <typename IterableOut,
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
{
switch (u.format)
{
case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
#endif
default:return ;
}
}
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
{
static constexpr bool is_sorted_iterator = true;
iter_t (const Coverage &c_ = Null (Coverage))
{
hb_memset (this, 0, sizeof (*this));
format = c_.u.format;
switch (format)
{
case 1: u.format1.init (c_.u.format1); return;
case 2: u.format2.init (c_.u.format2); return;
#ifndef HB_NO_BEYOND_64K
case 3: u.format3.init (c_.u.format3); return;
case 4: u.format4.init (c_.u.format4); return;
#endif
default: return;
}
}
bool __more__ () const
{
switch (format)
{
case 1: return u.format1.__more__ ();
case 2: return u.format2.__more__ ();
#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.__more__ ();
case 4: return u.format4.__more__ ();
#endif
default:return false;
}
}
void __next__ ()
{
switch (format)
{
case 1: u.format1.__next__ (); break;
case 2: u.format2.__next__ (); break;
#ifndef HB_NO_BEYOND_64K
case 3: u.format3.__next__ (); break;
case 4: u.format4.__next__ (); break;
#endif
default: break;
}
}
typedef hb_codepoint_t __item_t__;
__item_t__ __item__ () const { return get_glyph (); }
hb_codepoint_t get_glyph () const
{
switch (format)
{
case 1: return u.format1.get_glyph ();
case 2: return u.format2.get_glyph ();
#ifndef HB_NO_BEYOND_64K
case 3: return u.format3.get_glyph ();
case 4: return u.format4.get_glyph ();
#endif
default:return 0;
}
}
bool operator != (const iter_t& o) const
{
if (unlikely (format != o.format)) return true;
switch (format)
{
case 1: return u.format1 != o.u.format1;
case 2: return u.format2 != o.u.format2;
#ifndef HB_NO_BEYOND_64K
case 3: return u.format3 != o.u.format3;
case 4: return u.format4 != o.u.format4;
#endif
default:return false;
}
}
iter_t __end__ () const
{
iter_t it = {};
it.format = format;
switch (format)
{
case 1: it.u.format1 = u.format1.__end__ (); break;
case 2: it.u.format2 = u.format2.__end__ (); break;
#ifndef HB_NO_BEYOND_64K
case 3: it.u.format3 = u.format3.__end__ (); break;
case 4: it.u.format4 = u.format4.__end__ (); break;
#endif
default: break;
}
return it;
}
private:
unsigned int format;
union {
#ifndef HB_NO_BEYOND_64K
CoverageFormat2_4<MediumTypes>::iter_t format4; /* Put this one first since it's larger; helps shut up compiler. */
CoverageFormat1_3<MediumTypes>::iter_t format3;
#endif
CoverageFormat2_4<SmallTypes>::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */
CoverageFormat1_3<SmallTypes>::iter_t format1;
} u;
};
iter_t iter () const { return iter_t (*this); }
};
template<typename Iterator>
static inline void
Coverage_serialize (hb_serialize_context_t *c,
Iterator it)
{ c->start_embed<Coverage> ()->serialize (c, it); }
}
}
}
#endif // #ifndef OT_LAYOUT_COMMON_COVERAGE_HH

View File

@ -1,133 +0,0 @@
/*
* Copyright © 2007,2008,2009 Red Hat, Inc.
* Copyright © 2010,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
* Google Author(s): Behdad Esfahbod, Garret Rieger
*/
#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
#define OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
namespace OT {
namespace Layout {
namespace Common {
#define NOT_COVERED ((unsigned int) -1)
template <typename Types>
struct CoverageFormat1_3
{
friend struct Coverage;
protected:
HBUINT16 coverageFormat; /* Format identifier--format = 1 */
SortedArray16Of<typename Types::HBGlyphID>
glyphArray; /* Array of GlyphIDs--in numerical order */
public:
DEFINE_SIZE_ARRAY (4, glyphArray);
private:
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (glyphArray.sanitize (c));
}
unsigned int get_coverage (hb_codepoint_t glyph_id) const
{
unsigned int i;
glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
return i;
}
unsigned get_population () const
{
return glyphArray.len;
}
template <typename Iterator,
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c, Iterator glyphs)
{
TRACE_SERIALIZE (this);
return_trace (glyphArray.serialize (c, glyphs));
}
bool intersects (const hb_set_t *glyphs) const
{
if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
{
for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
if (get_coverage (g) != NOT_COVERED)
return true;
return false;
}
for (const auto& g : glyphArray.as_array ())
if (glyphs->has (g))
return true;
return false;
}
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
{ return glyphs->has (glyphArray[index]); }
template <typename IterableOut,
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
{
unsigned count = glyphArray.len;
for (unsigned i = 0; i < count; i++)
if (glyphs.has (glyphArray[i]))
intersect_glyphs << glyphArray[i];
}
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{ return glyphs->add_sorted_array (glyphArray.as_array ()); }
public:
/* Older compilers need this to be public. */
struct iter_t
{
void init (const struct CoverageFormat1_3 &c_) { c = &c_; i = 0; }
bool __more__ () const { return i < c->glyphArray.len; }
void __next__ () { i++; }
hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
bool operator != (const iter_t& o) const
{ return i != o.i; }
iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; }
private:
const struct CoverageFormat1_3 *c;
unsigned int i;
};
private:
};
}
}
}
#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH

View File

@ -1,232 +0,0 @@
/*
* Copyright © 2007,2008,2009 Red Hat, Inc.
* Copyright © 2010,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
* Google Author(s): Behdad Esfahbod, Garret Rieger
*/
#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
#define OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
#include "RangeRecord.hh"
namespace OT {
namespace Layout {
namespace Common {
template <typename Types>
struct CoverageFormat2_4
{
friend struct Coverage;
protected:
HBUINT16 coverageFormat; /* Format identifier--format = 2 */
SortedArray16Of<RangeRecord<Types>>
rangeRecord; /* Array of glyph ranges--ordered by
* Start GlyphID. rangeCount entries
* long */
public:
DEFINE_SIZE_ARRAY (4, rangeRecord);
private:
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (rangeRecord.sanitize (c));
}
unsigned int get_coverage (hb_codepoint_t glyph_id) const
{
const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id);
return likely (range.first <= range.last)
? (unsigned int) range.value + (glyph_id - range.first)
: NOT_COVERED;
}
unsigned get_population () const
{
typename Types::large_int ret = 0;
for (const auto &r : rangeRecord)
ret += r.get_population ();
return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
}
template <typename Iterator,
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c, Iterator glyphs)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (this))) return_trace (false);
unsigned num_ranges = 0;
hb_codepoint_t last = (hb_codepoint_t) -2;
for (auto g: glyphs)
{
if (last + 1 != g)
num_ranges++;
last = g;
}
if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
if (!num_ranges) return_trace (true);
unsigned count = 0;
unsigned range = (unsigned) -1;
last = (hb_codepoint_t) -2;
for (auto g: glyphs)
{
if (last + 1 != g)
{
range++;
rangeRecord[range].first = g;
rangeRecord[range].value = count;
}
rangeRecord[range].last = g;
last = g;
count++;
}
return_trace (true);
}
bool intersects (const hb_set_t *glyphs) const
{
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
{
for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
if (get_coverage (g) != NOT_COVERED)
return true;
return false;
}
return hb_any (+ hb_iter (rangeRecord)
| hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
}
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
{
auto *range = rangeRecord.as_array ().bsearch (index);
if (range)
return range->intersects (*glyphs);
return false;
}
template <typename IterableOut,
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
{
/* Break out of loop for overlapping, broken, tables,
* to avoid fuzzer timouts. */
hb_codepoint_t last = 0;
for (const auto& range : rangeRecord)
{
if (unlikely (range.first < last))
break;
last = range.last;
for (hb_codepoint_t g = range.first - 1;
glyphs.next (&g) && g <= last;)
intersect_glyphs << g;
}
}
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{
for (const auto& range: rangeRecord)
if (unlikely (!range.collect_coverage (glyphs)))
return false;
return true;
}
public:
/* Older compilers need this to be public. */
struct iter_t
{
void init (const CoverageFormat2_4 &c_)
{
c = &c_;
coverage = 0;
i = 0;
j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
{
/* Broken table. Skip. */
i = c->rangeRecord.len;
j = 0;
}
}
bool __more__ () const { return i < c->rangeRecord.len; }
void __next__ ()
{
if (j >= c->rangeRecord[i].last)
{
i++;
if (__more__ ())
{
unsigned int old = coverage;
j = c->rangeRecord[i].first;
coverage = c->rangeRecord[i].value;
if (unlikely (coverage != old + 1))
{
/* Broken table. Skip. Important to avoid DoS.
* Also, our callers depend on coverage being
* consecutive and monotonically increasing,
* ie. iota(). */
i = c->rangeRecord.len;
j = 0;
return;
}
}
else
j = 0;
return;
}
coverage++;
j++;
}
hb_codepoint_t get_glyph () const { return j; }
bool operator != (const iter_t& o) const
{ return i != o.i || j != o.j; }
iter_t __end__ () const
{
iter_t it;
it.init (*c);
it.i = c->rangeRecord.len;
it.j = 0;
return it;
}
private:
const struct CoverageFormat2_4 *c;
unsigned int i, coverage;
hb_codepoint_t j;
};
private:
};
}
}
}
#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH

View File

@ -1,85 +0,0 @@
/*
* Copyright © 2007,2008,2009 Red Hat, Inc.
* Copyright © 2010,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
* Google Author(s): Behdad Esfahbod, Garret Rieger
*/
#ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
#define OT_LAYOUT_COMMON_RANGERECORD_HH
namespace OT {
namespace Layout {
namespace Common {
template <typename Types>
struct RangeRecord
{
typename Types::HBGlyphID first; /* First GlyphID in the range */
typename Types::HBGlyphID last; /* Last GlyphID in the range */
HBUINT16 value; /* Value */
DEFINE_SIZE_STATIC (2 + 2 * Types::size);
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
int cmp (hb_codepoint_t g) const
{ return g < first ? -1 : g <= last ? 0 : +1; }
unsigned get_population () const
{
if (unlikely (last < first)) return 0;
return (last - first + 1);
}
bool intersects (const hb_set_t &glyphs) const
{ return glyphs.intersects (first, last); }
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{ return glyphs->add_range (first, last); }
};
}
}
}
// TODO(garretrieger): This was previously implemented using
// DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (OT, RangeRecord, 9);
// but that only works when there is only a single namespace level.
// The macro should probably be fixed so it can work in this situation.
extern HB_INTERNAL const unsigned char _hb_Null_OT_RangeRecord[9];
template <typename Spec>
struct Null<OT::Layout::Common::RangeRecord<Spec>> {
static OT::Layout::Common::RangeRecord<Spec> const & get_null () {
return *reinterpret_cast<const OT::Layout::Common::RangeRecord<Spec> *> (_hb_Null_OT_RangeRecord);
}
};
#endif // #ifndef OT_LAYOUT_COMMON_RANGERECORD_HH

View File

@ -1,918 +0,0 @@
/*
* Copyright © 2007,2008,2009 Red Hat, Inc.
* Copyright © 2010,2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
* Google Author(s): Behdad Esfahbod
*/
#ifndef OT_LAYOUT_GDEF_GDEF_HH
#define OT_LAYOUT_GDEF_GDEF_HH
#include "../../../hb-ot-layout-common.hh"
#include "../../../hb-font.hh"
namespace OT {
/*
* Attachment List Table
*/
/* Array of contour point indices--in increasing numerical order */
struct AttachPoint : Array16Of<HBUINT16>
{
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
if (unlikely (!out)) return_trace (false);
return_trace (out->serialize (c->serializer, + iter ()));
}
};
struct AttachList
{
unsigned int get_attach_points (hb_codepoint_t glyph_id,
unsigned int start_offset,
unsigned int *point_count /* IN/OUT */,
unsigned int *point_array /* OUT */) const
{
unsigned int index = (this+coverage).get_coverage (glyph_id);
if (index == NOT_COVERED)
{
if (point_count)
*point_count = 0;
return 0;
}
const AttachPoint &points = this+attachPoint[index];
if (point_count)
{
+ points.as_array ().sub_array (start_offset, point_count)
| hb_sink (hb_array (point_array, *point_count))
;
}
return points.len;
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ hb_zip (this+coverage, attachPoint)
| hb_filter (glyphset, hb_first)
| hb_filter (subset_offset_array (c, out->attachPoint, this), hb_second)
| hb_map (hb_first)
| hb_map (glyph_map)
| hb_sink (new_coverage)
;
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
return_trace (bool (new_coverage));
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
}
protected:
Offset16To<Coverage>
coverage; /* Offset to Coverage table -- from
* beginning of AttachList table */
Array16OfOffset16To<AttachPoint>
attachPoint; /* Array of AttachPoint tables
* in Coverage Index order */
public:
DEFINE_SIZE_ARRAY (4, attachPoint);
};
/*
* Ligature Caret Table
*/
struct CaretValueFormat1
{
friend struct CaretValue;
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->embed (this);
if (unlikely (!out)) return_trace (false);
return_trace (true);
}
private:
hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
{
return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
protected:
HBUINT16 caretValueFormat; /* Format identifier--format = 1 */
FWORD coordinate; /* X or Y value, in design units */
public:
DEFINE_SIZE_STATIC (4);
};
struct CaretValueFormat2
{
friend struct CaretValue;
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->embed (this);
if (unlikely (!out)) return_trace (false);
return_trace (true);
}
private:
hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
{
hb_position_t x, y;
font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y);
return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
protected:
HBUINT16 caretValueFormat; /* Format identifier--format = 2 */
HBUINT16 caretValuePoint; /* Contour point index on glyph */
public:
DEFINE_SIZE_STATIC (4);
};
struct CaretValueFormat3
{
friend struct CaretValue;
hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction,
const VariationStore &var_store) const
{
return HB_DIRECTION_IS_HORIZONTAL (direction) ?
font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
if (unlikely (!out)) return_trace (false);
if (!c->serializer->embed (caretValueFormat)) return_trace (false);
if (!c->serializer->embed (coordinate)) return_trace (false);
unsigned varidx = (this+deviceTable).get_variation_index ();
if (c->plan->layout_variation_idx_delta_map.has (varidx))
{
int delta = hb_second (c->plan->layout_variation_idx_delta_map.get (varidx));
if (delta != 0)
{
if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))
return_trace (false);
}
}
if (c->plan->all_axes_pinned)
return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
if (!c->serializer->embed (deviceTable))
return_trace (false);
return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this, c->serializer->to_bias (out),
hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map));
}
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{ (this+deviceTable).collect_variation_indices (c); }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
}
protected:
HBUINT16 caretValueFormat; /* Format identifier--format = 3 */
FWORD coordinate; /* X or Y value, in design units */
Offset16To<Device>
deviceTable; /* Offset to Device table for X or Y
* value--from beginning of CaretValue
* table */
public:
DEFINE_SIZE_STATIC (6);
};
struct CaretValue
{
hb_position_t get_caret_value (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph_id,
const VariationStore &var_store) const
{
switch (u.format) {
case 1: return u.format1.get_caret_value (font, direction);
case 2: return u.format2.get_caret_value (font, direction, glyph_id);
case 3: return u.format3.get_caret_value (font, direction, var_store);
default:return 0;
}
}
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
TRACE_DISPATCH (this, u.format);
switch (u.format) {
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{
switch (u.format) {
case 1:
case 2:
return;
case 3:
u.format3.collect_variation_indices (c);
return;
default: return;
}
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return_trace (false);
switch (u.format) {
case 1: return_trace (u.format1.sanitize (c));
case 2: return_trace (u.format2.sanitize (c));
case 3: return_trace (u.format3.sanitize (c));
default:return_trace (true);
}
}
protected:
union {
HBUINT16 format; /* Format identifier */
CaretValueFormat1 format1;
CaretValueFormat2 format2;
CaretValueFormat3 format3;
} u;
public:
DEFINE_SIZE_UNION (2, format);
};
struct LigGlyph
{
unsigned get_lig_carets (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph_id,
const VariationStore &var_store,
unsigned start_offset,
unsigned *caret_count /* IN/OUT */,
hb_position_t *caret_array /* OUT */) const
{
if (caret_count)
{
+ carets.as_array ().sub_array (start_offset, caret_count)
| hb_map (hb_add (this))
| hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); })
| hb_sink (hb_array (caret_array, *caret_count))
;
}
return carets.len;
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ hb_iter (carets)
| hb_apply (subset_offset_array (c, out->carets, this))
;
return_trace (bool (out->carets));
}
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{
for (const Offset16To<CaretValue>& offset : carets.iter ())
(this+offset).collect_variation_indices (c);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (carets.sanitize (c, this));
}
protected:
Array16OfOffset16To<CaretValue>
carets; /* Offset array of CaretValue tables
* --from beginning of LigGlyph table
* --in increasing coordinate order */
public:
DEFINE_SIZE_ARRAY (2, carets);
};
struct LigCaretList
{
unsigned int get_lig_carets (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph_id,
const VariationStore &var_store,
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
hb_position_t *caret_array /* OUT */) const
{
unsigned int index = (this+coverage).get_coverage (glyph_id);
if (index == NOT_COVERED)
{
if (caret_count)
*caret_count = 0;
return 0;
}
const LigGlyph &lig_glyph = this+ligGlyph[index];
return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ hb_zip (this+coverage, ligGlyph)
| hb_filter (glyphset, hb_first)
| hb_filter (subset_offset_array (c, out->ligGlyph, this), hb_second)
| hb_map (hb_first)
| hb_map (glyph_map)
| hb_sink (new_coverage)
;
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
return_trace (bool (new_coverage));
}
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{
+ hb_zip (this+coverage, ligGlyph)
| hb_filter (c->glyph_set, hb_first)
| hb_map (hb_second)
| hb_map (hb_add (this))
| hb_apply ([c] (const LigGlyph& _) { _.collect_variation_indices (c); })
;
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
}
protected:
Offset16To<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of LigCaretList table */
Array16OfOffset16To<LigGlyph>
ligGlyph; /* Array of LigGlyph tables
* in Coverage Index order */
public:
DEFINE_SIZE_ARRAY (4, ligGlyph);
};
struct MarkGlyphSetsFormat1
{
bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
{ return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->format = format;
bool ret = true;
for (const Offset32To<Coverage>& offset : coverage.iter ())
{
auto *o = out->coverage.serialize_append (c->serializer);
if (unlikely (!o))
{
ret = false;
break;
}
//not using o->serialize_subset (c, offset, this, out) here because
//OTS doesn't allow null offset.
//See issue: https://github.com/khaledhosny/ots/issues/172
c->serializer->push ();
c->dispatch (this+offset);
c->serializer->add_link (*o, c->serializer->pop_pack ());
}
return_trace (ret && out->coverage.len);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (coverage.sanitize (c, this));
}
protected:
HBUINT16 format; /* Format identifier--format = 1 */
Array16Of<Offset32To<Coverage>>
coverage; /* Array of long offsets to mark set
* coverage tables */
public:
DEFINE_SIZE_ARRAY (4, coverage);
};
struct MarkGlyphSets
{
bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
{
switch (u.format) {
case 1: return u.format1.covers (set_index, glyph_id);
default:return false;
}
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
switch (u.format) {
case 1: return_trace (u.format1.subset (c));
default:return_trace (false);
}
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return_trace (false);
switch (u.format) {
case 1: return_trace (u.format1.sanitize (c));
default:return_trace (true);
}
}
protected:
union {
HBUINT16 format; /* Format identifier */
MarkGlyphSetsFormat1 format1;
} u;
public:
DEFINE_SIZE_UNION (2, format);
};
/*
* GDEF -- Glyph Definition
* https://docs.microsoft.com/en-us/typography/opentype/spec/gdef
*/
template <typename Types>
struct GDEFVersion1_2
{
friend struct GDEF;
protected:
FixedVersion<>version; /* Version of the GDEF table--currently
* 0x00010003u */
typename Types::template OffsetTo<ClassDef>
glyphClassDef; /* Offset to class definition table
* for glyph type--from beginning of
* GDEF header (may be Null) */
typename Types::template OffsetTo<AttachList>
attachList; /* Offset to list of glyphs with
* attachment points--from beginning
* of GDEF header (may be Null) */
typename Types::template OffsetTo<LigCaretList>
ligCaretList; /* Offset to list of positioning points
* for ligature carets--from beginning
* of GDEF header (may be Null) */
typename Types::template OffsetTo<ClassDef>
markAttachClassDef; /* Offset to class definition table for
* mark attachment type--from beginning
* of GDEF header (may be Null) */
typename Types::template OffsetTo<MarkGlyphSets>
markGlyphSetsDef; /* Offset to the table of mark set
* definitions--from beginning of GDEF
* header (may be NULL). Introduced
* in version 0x00010002. */
Offset32To<VariationStore>
varStore; /* Offset to the table of Item Variation
* Store--from beginning of GDEF
* header (may be NULL). Introduced
* in version 0x00010003. */
public:
DEFINE_SIZE_MIN (4 + 4 * Types::size);
unsigned int get_size () const
{
return min_size +
(version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
(version.to_int () >= 0x00010003u ? varStore.static_size : 0);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (version.sanitize (c) &&
glyphClassDef.sanitize (c, this) &&
attachList.sanitize (c, this) &&
ligCaretList.sanitize (c, this) &&
markAttachClassDef.sanitize (c, this) &&
(version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
(version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->embed (*this);
if (unlikely (!out)) return_trace (false);
bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
bool subset_markglyphsetsdef = false;
if (version.to_int () >= 0x00010002u)
{
subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
}
bool subset_varstore = false;
if (version.to_int () >= 0x00010003u)
{
if (c->plan->all_axes_pinned)
out->varStore = 0;
else
subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ());
}
if (subset_varstore)
{
out->version.minor = 3;
} else if (subset_markglyphsetsdef) {
out->version.minor = 2;
} else {
out->version.minor = 0;
}
return_trace (subset_glyphclassdef || subset_attachlist ||
subset_ligcaretlist || subset_markattachclassdef ||
(out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) ||
(out->version.to_int () >= 0x00010003u && subset_varstore));
}
};
struct GDEF
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF;
enum GlyphClasses {
UnclassifiedGlyph = 0,
BaseGlyph = 1,
LigatureGlyph = 2,
MarkGlyph = 3,
ComponentGlyph = 4
};
unsigned int get_size () const
{
switch (u.version.major) {
case 1: return u.version1.get_size ();
#ifndef HB_NO_BEYOND_64K
case 2: return u.version2.get_size ();
#endif
default: return u.version.static_size;
}
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (unlikely (!u.version.sanitize (c))) return_trace (false);
switch (u.version.major) {
case 1: return_trace (u.version1.sanitize (c));
#ifndef HB_NO_BEYOND_64K
case 2: return_trace (u.version2.sanitize (c));
#endif
default: return_trace (true);
}
}
bool subset (hb_subset_context_t *c) const
{
switch (u.version.major) {
case 1: return u.version1.subset (c);
#ifndef HB_NO_BEYOND_64K
case 2: return u.version2.subset (c);
#endif
default: return false;
}
}
bool has_glyph_classes () const
{
switch (u.version.major) {
case 1: return u.version1.glyphClassDef != 0;
#ifndef HB_NO_BEYOND_64K
case 2: return u.version2.glyphClassDef != 0;
#endif
default: return false;
}
}
const ClassDef &get_glyph_class_def () const
{
switch (u.version.major) {
case 1: return this+u.version1.glyphClassDef;
#ifndef HB_NO_BEYOND_64K
case 2: return this+u.version2.glyphClassDef;
#endif
default: return Null(ClassDef);
}
}
bool has_attach_list () const
{
switch (u.version.major) {
case 1: return u.version1.attachList != 0;
#ifndef HB_NO_BEYOND_64K
case 2: return u.version2.attachList != 0;
#endif
default: return false;
}
}
const AttachList &get_attach_list () const
{
switch (u.version.major) {
case 1: return this+u.version1.attachList;
#ifndef HB_NO_BEYOND_64K
case 2: return this+u.version2.attachList;
#endif
default: return Null(AttachList);
}
}
bool has_lig_carets () const
{
switch (u.version.major) {
case 1: return u.version1.ligCaretList != 0;
#ifndef HB_NO_BEYOND_64K
case 2: return u.version2.ligCaretList != 0;
#endif
default: return false;
}
}
const LigCaretList &get_lig_caret_list () const
{
switch (u.version.major) {
case 1: return this+u.version1.ligCaretList;
#ifndef HB_NO_BEYOND_64K
case 2: return this+u.version2.ligCaretList;
#endif
default: return Null(LigCaretList);
}
}
bool has_mark_attachment_types () const
{
switch (u.version.major) {
case 1: return u.version1.markAttachClassDef != 0;
#ifndef HB_NO_BEYOND_64K
case 2: return u.version2.markAttachClassDef != 0;
#endif
default: return false;
}
}
const ClassDef &get_mark_attach_class_def () const
{
switch (u.version.major) {
case 1: return this+u.version1.markAttachClassDef;
#ifndef HB_NO_BEYOND_64K
case 2: return this+u.version2.markAttachClassDef;
#endif
default: return Null(ClassDef);
}
}
bool has_mark_glyph_sets () const
{
switch (u.version.major) {
case 1: return u.version.to_int () >= 0x00010002u && u.version1.markGlyphSetsDef != 0;
#ifndef HB_NO_BEYOND_64K
case 2: return u.version2.markGlyphSetsDef != 0;
#endif
default: return false;
}
}
const MarkGlyphSets &get_mark_glyph_sets () const
{
switch (u.version.major) {
case 1: return u.version.to_int () >= 0x00010002u ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets);
#ifndef HB_NO_BEYOND_64K
case 2: return this+u.version2.markGlyphSetsDef;
#endif
default: return Null(MarkGlyphSets);
}
}
bool has_var_store () const
{
switch (u.version.major) {
case 1: return u.version.to_int () >= 0x00010003u && u.version1.varStore != 0;
#ifndef HB_NO_BEYOND_64K
case 2: return u.version2.varStore != 0;
#endif
default: return false;
}
}
const VariationStore &get_var_store () const
{
switch (u.version.major) {
case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(VariationStore);
#ifndef HB_NO_BEYOND_64K
case 2: return this+u.version2.varStore;
#endif
default: return Null(VariationStore);
}
}
bool has_data () const { return u.version.to_int (); }
unsigned int get_glyph_class (hb_codepoint_t glyph) const
{ return get_glyph_class_def ().get_class (glyph); }
void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
{ get_glyph_class_def ().collect_class (glyphs, klass); }
unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
{ return get_mark_attach_class_def ().get_class (glyph); }
unsigned int get_attach_points (hb_codepoint_t glyph_id,
unsigned int start_offset,
unsigned int *point_count /* IN/OUT */,
unsigned int *point_array /* OUT */) const
{ return get_attach_list ().get_attach_points (glyph_id, start_offset, point_count, point_array); }
unsigned int get_lig_carets (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph_id,
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
hb_position_t *caret_array /* OUT */) const
{ return get_lig_caret_list ().get_lig_carets (font,
direction, glyph_id, get_var_store(),
start_offset, caret_count, caret_array); }
bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
{ return get_mark_glyph_sets ().covers (set_index, glyph_id); }
/* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
* glyph class and other bits, and high 8-bit the mark attachment type (if any).
* Not to be confused with lookup_props which is very similar. */
unsigned int get_glyph_props (hb_codepoint_t glyph) const
{
unsigned int klass = get_glyph_class (glyph);
static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), "");
static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), "");
static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), "");
switch (klass) {
default: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
case BaseGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
case MarkGlyph:
klass = get_mark_attachment_type (glyph);
return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8);
}
}
HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
hb_face_t *face) const;
struct accelerator_t
{
accelerator_t (hb_face_t *face)
{
table = hb_sanitize_context_t ().reference_table<GDEF> (face);
if (unlikely (table->is_blocklisted (table.get_blob (), face)))
{
hb_blob_destroy (table.get_blob ());
table = hb_blob_get_empty ();
}
}
~accelerator_t () { table.destroy (); }
hb_blob_ptr_t<GDEF> table;
};
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{ get_lig_caret_list ().collect_variation_indices (c); }
void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map /* OUT */) const
{
if (!has_var_store ()) return;
if (layout_variation_indices->is_empty ()) return;
unsigned new_major = 0, new_minor = 0;
unsigned last_major = (layout_variation_indices->get_min ()) >> 16;
for (unsigned idx : layout_variation_indices->iter ())
{
uint16_t major = idx >> 16;
if (major >= get_var_store ().get_sub_table_count ()) break;
if (major != last_major)
{
new_minor = 0;
++new_major;
}
unsigned new_idx = (new_major << 16) + new_minor;
if (!layout_variation_idx_delta_map->has (idx))
continue;
int delta = hb_second (layout_variation_idx_delta_map->get (idx));
layout_variation_idx_delta_map->set (idx, hb_pair_t<unsigned, int> (new_idx, delta));
++new_minor;
last_major = major;
}
}
protected:
union {
FixedVersion<> version; /* Version identifier */
GDEFVersion1_2<SmallTypes> version1;
#ifndef HB_NO_BEYOND_64K
GDEFVersion1_2<MediumTypes> version2;
#endif
} u;
public:
DEFINE_SIZE_MIN (4);
};
struct GDEF_accelerator_t : GDEF::accelerator_t {
GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {}
};
} /* namespace OT */
#endif /* OT_LAYOUT_GDEF_GDEF_HH */

View File

@ -1,83 +0,0 @@
#ifndef OT_LAYOUT_GPOS_ANCHOR_HH
#define OT_LAYOUT_GPOS_ANCHOR_HH
#include "AnchorFormat1.hh"
#include "AnchorFormat2.hh"
#include "AnchorFormat3.hh"
namespace OT {
namespace Layout {
namespace GPOS_impl {
struct Anchor
{
protected:
union {
HBUINT16 format; /* Format identifier */
AnchorFormat1 format1;
AnchorFormat2 format2;
AnchorFormat3 format3;
} u;
public:
DEFINE_SIZE_UNION (2, format);
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return_trace (false);
switch (u.format) {
case 1: return_trace (u.format1.sanitize (c));
case 2: return_trace (u.format2.sanitize (c));
case 3: return_trace (u.format3.sanitize (c));
default:return_trace (true);
}
}
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
float *x, float *y) const
{
*x = *y = 0;
switch (u.format) {
case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
default: return;
}
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
switch (u.format) {
case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
case 2:
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
{
// AnchorFormat 2 just containins extra hinting information, so
// if hints are being dropped convert to format 1.
return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
}
return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
case 3: return_trace (u.format3.subset (c));
default:return_trace (false);
}
}
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{
switch (u.format) {
case 1: case 2:
return;
case 3:
u.format3.collect_variation_indices (c);
return;
default: return;
}
}
};
}
}
}
#endif // OT_LAYOUT_GPOS_ANCHOR_HH

View File

@ -1,46 +0,0 @@
#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
#define OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
namespace OT {
namespace Layout {
namespace GPOS_impl {
struct AnchorFormat1
{
protected:
HBUINT16 format; /* Format identifier--format = 1 */
FWORD xCoordinate; /* Horizontal value--in design units */
FWORD yCoordinate; /* Vertical value--in design units */
public:
DEFINE_SIZE_STATIC (6);
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
float *x, float *y) const
{
hb_font_t *font = c->font;
*x = font->em_fscale_x (xCoordinate);
*y = font->em_fscale_y (yCoordinate);
}
AnchorFormat1* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
AnchorFormat1* out = c->embed<AnchorFormat1> (this);
if (!out) return_trace (out);
out->format = 1;
return_trace (out);
}
};
}
}
}
#endif // OT_LAYOUT_GPOS_ANCHORFORMAT1_HH

View File

@ -1,58 +0,0 @@
#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
#define OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
namespace OT {
namespace Layout {
namespace GPOS_impl {
struct AnchorFormat2
{
protected:
HBUINT16 format; /* Format identifier--format = 2 */
FWORD xCoordinate; /* Horizontal value--in design units */
FWORD yCoordinate; /* Vertical value--in design units */
HBUINT16 anchorPoint; /* Index to glyph contour point */
public:
DEFINE_SIZE_STATIC (8);
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
float *x, float *y) const
{
hb_font_t *font = c->font;
#ifdef HB_NO_HINTING
*x = font->em_fscale_x (xCoordinate);
*y = font->em_fscale_y (yCoordinate);
return;
#endif
unsigned int x_ppem = font->x_ppem;
unsigned int y_ppem = font->y_ppem;
hb_position_t cx = 0, cy = 0;
bool ret;
ret = (x_ppem || y_ppem) &&
font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
*x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
*y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
}
AnchorFormat2* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
return_trace (c->embed<AnchorFormat2> (this));
}
};
}
}
}
#endif // OT_LAYOUT_GPOS_ANCHORFORMAT2_HH

View File

@ -1,100 +0,0 @@
#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
#define OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
namespace OT {
namespace Layout {
namespace GPOS_impl {
struct AnchorFormat3
{
protected:
HBUINT16 format; /* Format identifier--format = 3 */
FWORD xCoordinate; /* Horizontal value--in design units */
FWORD yCoordinate; /* Vertical value--in design units */
Offset16To<Device>
xDeviceTable; /* Offset to Device table for X
* coordinate-- from beginning of
* Anchor table (may be NULL) */
Offset16To<Device>
yDeviceTable; /* Offset to Device table for Y
* coordinate-- from beginning of
* Anchor table (may be NULL) */
public:
DEFINE_SIZE_STATIC (10);
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
}
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
float *x, float *y) const
{
hb_font_t *font = c->font;
*x = font->em_fscale_x (xCoordinate);
*y = font->em_fscale_y (yCoordinate);
if (font->x_ppem || font->num_coords)
*x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
if (font->y_ppem || font->num_coords)
*y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
if (unlikely (!out)) return_trace (false);
if (unlikely (!c->serializer->embed (format))) return_trace (false);
if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false);
if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false);
unsigned x_varidx = xDeviceTable ? (this+xDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
if (c->plan->layout_variation_idx_delta_map.has (x_varidx))
{
int delta = hb_second (c->plan->layout_variation_idx_delta_map.get (x_varidx));
if (delta != 0)
{
if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
HB_SERIALIZE_ERROR_INT_OVERFLOW))
return_trace (false);
}
}
unsigned y_varidx = yDeviceTable ? (this+yDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
if (c->plan->layout_variation_idx_delta_map.has (y_varidx))
{
int delta = hb_second (c->plan->layout_variation_idx_delta_map.get (y_varidx));
if (delta != 0)
{
if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
HB_SERIALIZE_ERROR_INT_OVERFLOW))
return_trace (false);
}
}
if (c->plan->all_axes_pinned)
return_trace (c->serializer->check_assign (out->format, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
if (!c->serializer->embed (xDeviceTable)) return_trace (false);
if (!c->serializer->embed (yDeviceTable)) return_trace (false);
out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
return_trace (out);
}
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{
(this+xDeviceTable).collect_variation_indices (c);
(this+yDeviceTable).collect_variation_indices (c);
}
};
}
}
}
#endif // OT_LAYOUT_GPOS_ANCHORFORMAT3_HH

View File

@ -1,77 +0,0 @@
#ifndef OT_LAYOUT_GPOS_ANCHORMATRIX_HH
#define OT_LAYOUT_GPOS_ANCHORMATRIX_HH
namespace OT {
namespace Layout {
namespace GPOS_impl {
struct AnchorMatrix
{
HBUINT16 rows; /* Number of rows */
UnsizedArrayOf<Offset16To<Anchor>>
matrixZ; /* Matrix of offsets to Anchor tables--
* from beginning of AnchorMatrix table */
public:
DEFINE_SIZE_ARRAY (2, matrixZ);
bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
{
TRACE_SANITIZE (this);
if (!c->check_struct (this)) return_trace (false);
if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
unsigned int count = rows * cols;
if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
for (unsigned int i = 0; i < count; i++)
if (!matrixZ[i].sanitize (c, this)) return_trace (false);
return_trace (true);
}
const Anchor& get_anchor (unsigned int row, unsigned int col,
unsigned int cols, bool *found) const
{
*found = false;
if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
*found = !matrixZ[row * cols + col].is_null ();
return this+matrixZ[row * cols + col];
}
template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
Iterator index_iter) const
{
for (unsigned i : index_iter)
(this+matrixZ[i]).collect_variation_indices (c);
}
template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
bool subset (hb_subset_context_t *c,
unsigned num_rows,
Iterator index_iter) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (this);
if (!index_iter) return_trace (false);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->rows = num_rows;
for (const unsigned i : index_iter)
{
auto *offset = c->serializer->embed (matrixZ[i]);
if (!offset) return_trace (false);
offset->serialize_subset (c, matrixZ[i], this);
}
return_trace (true);
}
};
}
}
}
#endif /* OT_LAYOUT_GPOS_ANCHORMATRIX_HH */

View File

@ -1,14 +0,0 @@
#ifndef OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
#define OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
namespace OT {
namespace Layout {
namespace GPOS_impl {
struct ChainContextPos : ChainContext {};
}
}
}
#endif /* OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH */

View File

@ -1,33 +0,0 @@
#ifndef OT_LAYOUT_GPOS_COMMON_HH
#define OT_LAYOUT_GPOS_COMMON_HH
namespace OT {
namespace Layout {
namespace GPOS_impl {
enum attach_type_t {
ATTACH_TYPE_NONE = 0X00,
/* Each attachment should be either a mark or a cursive; can't be both. */
ATTACH_TYPE_MARK = 0X01,
ATTACH_TYPE_CURSIVE = 0X02,
};
/* buffer **position** var allocations */
#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
#define attach_type() var.u8[2] /* attachment type */
/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
template<typename Iterator, typename SrcLookup>
static void SinglePos_serialize (hb_serialize_context_t *c,
const SrcLookup *src,
Iterator it,
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
bool all_axes_pinned);
}
}
}
#endif // OT_LAYOUT_GPOS_COMMON_HH

View File

@ -1,14 +0,0 @@
#ifndef OT_LAYOUT_GPOS_CONTEXTPOS_HH
#define OT_LAYOUT_GPOS_CONTEXTPOS_HH
namespace OT {
namespace Layout {
namespace GPOS_impl {
struct ContextPos : Context {};
}
}
}
#endif /* OT_LAYOUT_GPOS_CONTEXTPOS_HH */

View File

@ -1,35 +0,0 @@
#ifndef OT_LAYOUT_GPOS_CURSIVEPOS_HH
#define OT_LAYOUT_GPOS_CURSIVEPOS_HH
#include "CursivePosFormat1.hh"
namespace OT {
namespace Layout {
namespace GPOS_impl {
struct CursivePos
{
protected:
union {
HBUINT16 format; /* Format identifier */
CursivePosFormat1 format1;
} u;
public:
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
TRACE_DISPATCH (this, u.format);
switch (u.format) {
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
};
}
}
}
#endif /* OT_LAYOUT_GPOS_CURSIVEPOS_HH */

View File

@ -1,301 +0,0 @@
#ifndef OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
#define OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
#include "Anchor.hh"
namespace OT {
namespace Layout {
namespace GPOS_impl {
struct EntryExitRecord
{
friend struct CursivePosFormat1;
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
}
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
const void *src_base) const
{
(src_base+entryAnchor).collect_variation_indices (c);
(src_base+exitAnchor).collect_variation_indices (c);
}
EntryExitRecord* subset (hb_subset_context_t *c,
const void *src_base) const
{
TRACE_SERIALIZE (this);
auto *out = c->serializer->embed (this);
if (unlikely (!out)) return_trace (nullptr);
out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
return_trace (out);
}
protected:
Offset16To<Anchor>
entryAnchor; /* Offset to EntryAnchor table--from
* beginning of CursivePos
* subtable--may be NULL */
Offset16To<Anchor>
exitAnchor; /* Offset to ExitAnchor table--from
* beginning of CursivePos
* subtable--may be NULL */
public:
DEFINE_SIZE_STATIC (4);
};
static void
reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) {
int chain = pos[i].attach_chain(), type = pos[i].attach_type();
if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
return;
pos[i].attach_chain() = 0;
unsigned int j = (int) i + chain;
/* Stop if we see new parent in the chain. */
if (j == new_parent)
return;
reverse_cursive_minor_offset (pos, j, direction, new_parent);
if (HB_DIRECTION_IS_HORIZONTAL (direction))
pos[j].y_offset = -pos[i].y_offset;
else
pos[j].x_offset = -pos[i].x_offset;
pos[j].attach_chain() = -chain;
pos[j].attach_type() = type;
}
struct CursivePosFormat1
{
protected:
HBUINT16 format; /* Format identifier--format = 1 */
Offset16To<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
Array16Of<EntryExitRecord>
entryExitRecord; /* Array of EntryExit records--in
* Coverage Index order */
public:
DEFINE_SIZE_ARRAY (6, entryExitRecord);
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
}
bool intersects (const hb_set_t *glyphs) const
{ return (this+coverage).intersects (glyphs); }
void closure_lookups (hb_closure_lookups_context_t *c) const {}
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{
+ hb_zip (this+coverage, entryExitRecord)
| hb_filter (c->glyph_set, hb_first)
| hb_map (hb_second)
| hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); })
;
}
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{ if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
const Coverage &get_coverage () const { return this+coverage; }
bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
if (!this_record.entryAnchor) return_trace (false);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
unsigned unsafe_from;
if (!skippy_iter.prev (&unsafe_from))
{
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
return_trace (false);
}
const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
if (!prev_record.exitAnchor)
{
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
return_trace (false);
}
unsigned int i = skippy_iter.idx;
unsigned int j = buffer->idx;
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
"cursive attaching glyph at %u to glyph at %u",
i, j);
}
buffer->unsafe_to_break (i, j + 1);
float entry_x, entry_y, exit_x, exit_y;
(this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
(this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
hb_glyph_position_t *pos = buffer->pos;
hb_position_t d;
/* Main-direction adjustment */
switch (c->direction) {
case HB_DIRECTION_LTR:
pos[i].x_advance = roundf (exit_x) + pos[i].x_offset;
d = roundf (entry_x) + pos[j].x_offset;
pos[j].x_advance -= d;
pos[j].x_offset -= d;
break;
case HB_DIRECTION_RTL:
d = roundf (exit_x) + pos[i].x_offset;
pos[i].x_advance -= d;
pos[i].x_offset -= d;
pos[j].x_advance = roundf (entry_x) + pos[j].x_offset;
break;
case HB_DIRECTION_TTB:
pos[i].y_advance = roundf (exit_y) + pos[i].y_offset;
d = roundf (entry_y) + pos[j].y_offset;
pos[j].y_advance -= d;
pos[j].y_offset -= d;
break;
case HB_DIRECTION_BTT:
d = roundf (exit_y) + pos[i].y_offset;
pos[i].y_advance -= d;
pos[i].y_offset -= d;
pos[j].y_advance = roundf (entry_y);
break;
case HB_DIRECTION_INVALID:
default:
break;
}
/* Cross-direction adjustment */
/* We attach child to parent (think graph theory and rooted trees whereas
* the root stays on baseline and each node aligns itself against its
* parent.
*
* Optimize things for the case of RightToLeft, as that's most common in
* Arabic. */
unsigned int child = i;
unsigned int parent = j;
hb_position_t x_offset = entry_x - exit_x;
hb_position_t y_offset = entry_y - exit_y;
if (!(c->lookup_props & LookupFlag::RightToLeft))
{
unsigned int k = child;
child = parent;
parent = k;
x_offset = -x_offset;
y_offset = -y_offset;
}
/* If child was already connected to someone else, walk through its old
* chain and reverse the link direction, such that the whole tree of its
* previous connection now attaches to new parent. Watch out for case
* where new parent is on the path from old chain...
*/
reverse_cursive_minor_offset (pos, child, c->direction, parent);
pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
pos[child].attach_chain() = (int) parent - (int) child;
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
pos[child].y_offset = y_offset;
else
pos[child].x_offset = x_offset;
/* If parent was attached to child, separate them.
* https://github.com/harfbuzz/harfbuzz/issues/2469
*/
if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain()))
{
pos[parent].attach_chain() = 0;
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
pos[parent].y_offset = 0;
else
pos[parent].x_offset = 0;
}
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
"cursive attached glyph at %u to glyph at %u",
i, j);
}
buffer->idx++;
return_trace (true);
}
template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_subset_context_t *c,
Iterator it,
const void *src_base)
{
if (unlikely (!c->serializer->extend_min ((*this)))) return;
this->format = 1;
this->entryExitRecord.len = it.len ();
for (const EntryExitRecord& entry_record : + it
| hb_map (hb_second))
entry_record.subset (c, src_base);
auto glyphs =
+ it
| hb_map_retains_sorting (hb_first)
;
coverage.serialize_serialize (c->serializer, glyphs);
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
if (unlikely (!out)) return_trace (false);
auto it =
+ hb_zip (this+coverage, entryExitRecord)
| hb_filter (glyphset, hb_first)
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
{ return hb_pair (glyph_map[p.first], p.second);})
;
bool ret = bool (it);
out->serialize (c, it, this);
return_trace (ret);
}
};
}
}
}
#endif /* OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH */

View File

@ -1,17 +0,0 @@
#ifndef OT_LAYOUT_GPOS_EXTENSIONPOS_HH
#define OT_LAYOUT_GPOS_EXTENSIONPOS_HH
namespace OT {
namespace Layout {
namespace GPOS_impl {
struct ExtensionPos : Extension<ExtensionPos>
{
typedef struct PosLookupSubTable SubTable;
};
}
}
}
#endif /* OT_LAYOUT_GPOS_EXTENSIONPOS_HH */

View File

@ -1,171 +0,0 @@
#ifndef OT_LAYOUT_GPOS_GPOS_HH
#define OT_LAYOUT_GPOS_GPOS_HH
#include "../../../hb-ot-layout-common.hh"
#include "../../../hb-ot-layout-gsubgpos.hh"
#include "Common.hh"
#include "PosLookup.hh"
namespace OT {
using Layout::GPOS_impl::PosLookup;
namespace Layout {
static void
propagate_attachment_offsets (hb_glyph_position_t *pos,
unsigned int len,
unsigned int i,
hb_direction_t direction,
unsigned nesting_level = HB_MAX_NESTING_LEVEL);
/*
* GPOS -- Glyph Positioning
* https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
*/
struct GPOS : GSUBGPOS
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
using Lookup = PosLookup;
const PosLookup& get_lookup (unsigned int i) const
{ return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); }
static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
bool subset (hb_subset_context_t *c) const
{
hb_subset_layout_context_t l (c, tableTag);
return GSUBGPOS::subset<PosLookup> (&l);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (GSUBGPOS::sanitize<PosLookup> (c));
}
HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
hb_face_t *face) const;
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{
for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++)
{
if (!c->gpos_lookups->has (i)) continue;
const PosLookup &l = get_lookup (i);
l.dispatch (c);
}
}
void closure_lookups (hb_face_t *face,
const hb_set_t *glyphs,
hb_set_t *lookup_indexes /* IN/OUT */) const
{ GSUBGPOS::closure_lookups<PosLookup> (face, glyphs, lookup_indexes); }
typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
};
static void
propagate_attachment_offsets (hb_glyph_position_t *pos,
unsigned int len,
unsigned int i,
hb_direction_t direction,
unsigned nesting_level)
{
/* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
* offset of glyph they are attached to. */
int chain = pos[i].attach_chain(), type = pos[i].attach_type();
if (likely (!chain))
return;
pos[i].attach_chain() = 0;
unsigned int j = (int) i + chain;
if (unlikely (j >= len))
return;
if (unlikely (!nesting_level))
return;
propagate_attachment_offsets (pos, len, j, direction, nesting_level - 1);
assert (!!(type & GPOS_impl::ATTACH_TYPE_MARK) ^ !!(type & GPOS_impl::ATTACH_TYPE_CURSIVE));
if (type & GPOS_impl::ATTACH_TYPE_CURSIVE)
{
if (HB_DIRECTION_IS_HORIZONTAL (direction))
pos[i].y_offset += pos[j].y_offset;
else
pos[i].x_offset += pos[j].x_offset;
}
else /*if (type & GPOS_impl::ATTACH_TYPE_MARK)*/
{
pos[i].x_offset += pos[j].x_offset;
pos[i].y_offset += pos[j].y_offset;
assert (j < i);
if (HB_DIRECTION_IS_FORWARD (direction))
for (unsigned int k = j; k < i; k++) {
pos[i].x_offset -= pos[k].x_advance;
pos[i].y_offset -= pos[k].y_advance;
}
else
for (unsigned int k = j + 1; k < i + 1; k++) {
pos[i].x_offset += pos[k].x_advance;
pos[i].y_offset += pos[k].y_advance;
}
}
}
void
GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
}
void
GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
{
//_hb_buffer_assert_gsubgpos_vars (buffer);
}
void
GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
{
_hb_buffer_assert_gsubgpos_vars (buffer);
unsigned int len;
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
hb_direction_t direction = buffer->props.direction;
/* Handle attachments */
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
for (unsigned i = 0; i < len; i++)
propagate_attachment_offsets (pos, len, i, direction);
if (unlikely (font->slant))
{
for (unsigned i = 0; i < len; i++)
if (unlikely (pos[i].y_offset))
pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset);
}
}
}
struct GPOS_accelerator_t : Layout::GPOS::accelerator_t {
GPOS_accelerator_t (hb_face_t *face) : Layout::GPOS::accelerator_t (face) {}
};
}
#endif /* OT_LAYOUT_GPOS_GPOS_HH */

Some files were not shown because too many files have changed in this diff Show More