Compare commits
1 Commits
main
...
pairpos-ne
Author | SHA1 | Date |
---|---|---|
Behdad Esfahbod | 7a76222c20 |
|
@ -2,17 +2,15 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
meson --cross-file=.ci/win32-cross-file.txt \
|
meson --cross-file=.ci/win32-cross-file.txt \
|
||||||
--wrap-mode=default \
|
--wrap-mode=forcefallback \
|
||||||
-Dtests=disabled \
|
-Dtests=disabled \
|
||||||
-Dcairo=enabled \
|
-Dcairo=enabled \
|
||||||
-Dcairo:fontconfig=disabled \
|
-Dcairo:fontconfig=disabled \
|
||||||
-Dcairo:freetype=disabled \
|
|
||||||
-Dcairo:dwrite=disabled \
|
|
||||||
-Dcairo:tests=disabled \
|
|
||||||
-Dglib=enabled \
|
-Dglib=enabled \
|
||||||
-Dfreetype=disabled \
|
-Dfreetype=enabled \
|
||||||
-Dgdi=enabled \
|
-Dgdi=enabled \
|
||||||
-Ddirectwrite=enabled \
|
-Ddirectwrite=enabled \
|
||||||
|
-Dcairo=enabled \
|
||||||
win32build \
|
win32build \
|
||||||
$@
|
$@
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,15 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
meson --cross-file=.ci/win64-cross-file.txt \
|
meson --cross-file=.ci/win64-cross-file.txt \
|
||||||
--wrap-mode=default \
|
--wrap-mode=forcefallback \
|
||||||
-Dtests=disabled \
|
-Dtests=disabled \
|
||||||
-Dcairo=enabled \
|
-Dcairo=enabled \
|
||||||
-Dcairo:fontconfig=disabled \
|
-Dcairo:fontconfig=disabled \
|
||||||
-Dcairo:freetype=disabled \
|
|
||||||
-Dcairo:dwrite=disabled \
|
|
||||||
-Dcairo:tests=disabled \
|
|
||||||
-Dglib=enabled \
|
-Dglib=enabled \
|
||||||
-Dfreetype=disabled \
|
-Dfreetype=enabled \
|
||||||
-Dgdi=enabled \
|
-Dgdi=enabled \
|
||||||
-Ddirectwrite=enabled \
|
-Ddirectwrite=enabled \
|
||||||
|
-Dcairo=enabled \
|
||||||
win64build \
|
win64build \
|
||||||
$@
|
$@
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,9 @@ jobs:
|
||||||
xcode: "12.5.1"
|
xcode: "12.5.1"
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- 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 icu4c graphite2 gobject-introspection gtk-doc ninja
|
||||||
- run: pip3 install meson --upgrade
|
- 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: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson build -Dcoretext=enabled -Dgraphite=enabled -Dauto_features=enabled -Dchafa=disabled
|
||||||
- run: meson compile -Cbuild
|
- run: meson compile -Cbuild
|
||||||
- run: meson test -Cbuild --print-errorlogs
|
- run: meson test -Cbuild --print-errorlogs
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
|
@ -57,8 +57,8 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- 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: 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 build --buildtype=debugoptimized
|
||||||
- run: meson compile -Cbuild -j9
|
- run: ninja -Cbuild -j9
|
||||||
# TOOD: increase timeouts and remove --no-suite=slow
|
# 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 --num-processes=$(($(nproc)/2 + 1))
|
||||||
|
|
||||||
|
@ -69,9 +69,24 @@ jobs:
|
||||||
- checkout
|
- checkout
|
||||||
- run: apk update && apk add ragel gcc g++ glib-dev freetype-dev cairo-dev git py3-pip ninja
|
- 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: pip3 install meson==0.56.0
|
||||||
- run: meson setup build --buildtype=minsize
|
- run: meson build --buildtype=minsize
|
||||||
|
- run: ninja -Cbuild -j9
|
||||||
|
- run: meson test -Cbuild --print-errorlogs
|
||||||
|
|
||||||
|
archlinux:
|
||||||
|
docker:
|
||||||
|
- image: archlinux/base
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- 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 compile -Cbuild -j9
|
||||||
- run: meson test -Cbuild --print-errorlogs
|
- 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
|
||||||
|
|
||||||
asan-ubsan:
|
asan-ubsan:
|
||||||
docker:
|
docker:
|
||||||
|
@ -81,9 +96,8 @@ jobs:
|
||||||
- run: apt update || true
|
- 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: 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: 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: CC=clang CXX=clang++ meson build --default-library=static -Db_sanitize=address,undefined --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
|
||||||
- run: meson compile -Cbuild -j9
|
- run: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||||
- run: meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
|
||||||
|
|
||||||
tsan:
|
tsan:
|
||||||
docker:
|
docker:
|
||||||
|
@ -93,9 +107,8 @@ jobs:
|
||||||
- run: apt update || true
|
- 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: 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: 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: CC=clang CXX=clang++ meson build --default-library=static -Db_sanitize=thread --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
|
||||||
- run: meson compile -Cbuild -j9
|
- run: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||||
- run: meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
|
||||||
|
|
||||||
msan:
|
msan:
|
||||||
docker:
|
docker:
|
||||||
|
@ -106,9 +119,8 @@ jobs:
|
||||||
- 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: 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: pip3 install meson==0.56.0
|
||||||
# msan, needs --force-fallback-for=glib,freetype2 also which doesn't work yet but runs fuzzer cases at least
|
# 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: CC=clang CXX=clang++ meson 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: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||||
- run: meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
|
||||||
|
|
||||||
clang-cxx2a:
|
clang-cxx2a:
|
||||||
docker:
|
docker:
|
||||||
|
@ -123,8 +135,8 @@ jobs:
|
||||||
executor: win32-executor
|
executor: win32-executor
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build python3 python3-pip git g++-mingw-w64-i686 zip
|
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build gtk-doc-tools python3 python3-pip git g++-mingw-w64-i686 zip
|
||||||
- run: pip3 install meson==0.60.0
|
- run: pip3 install meson==0.56.0 --upgrade
|
||||||
- run: .ci/build-win32.sh
|
- run: .ci/build-win32.sh
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: harfbuzz-win32.zip
|
path: harfbuzz-win32.zip
|
||||||
|
@ -146,8 +158,8 @@ jobs:
|
||||||
executor: win64-executor
|
executor: win64-executor
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- 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: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build gtk-doc-tools python3 python3-pip git g++-mingw-w64-x86-64 zip
|
||||||
- run: pip3 install meson==0.60.0
|
- run: pip3 install meson==0.56.0 --upgrade
|
||||||
- run: bash .ci/build-win64.sh
|
- run: bash .ci/build-win64.sh
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: harfbuzz-win64.zip
|
path: harfbuzz-win64.zip
|
||||||
|
@ -186,6 +198,7 @@ workflows:
|
||||||
ignore: /.*/
|
ignore: /.*/
|
||||||
- fedora-valgrind
|
- fedora-valgrind
|
||||||
- alpine
|
- alpine
|
||||||
|
#- archlinux
|
||||||
- asan-ubsan
|
- asan-ubsan
|
||||||
- tsan
|
- tsan
|
||||||
- msan
|
- msan
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
comment: false
|
comment: off
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
status:
|
status:
|
||||||
project:
|
project:
|
||||||
default:
|
default:
|
||||||
informational: true
|
threshold: 1%
|
||||||
patch:
|
patch: off
|
||||||
default:
|
|
||||||
informational: true
|
|
||||||
|
|
|
@ -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
|
|
|
@ -1,9 +1,5 @@
|
||||||
name: CIFuzz
|
name: CIFuzz
|
||||||
on: [pull_request]
|
on: [pull_request]
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Fuzzing:
|
Fuzzing:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
@ -11,7 +11,7 @@ permissions:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-18.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
|
@ -12,60 +12,46 @@ permissions:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-18.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- uses: actions/checkout@v3
|
||||||
uses: actions/checkout@v3
|
- name: install dependencies
|
||||||
- name: Setup Ccache
|
run: sudo apt-get update && sudo apt-get install pkg-config gcc gtk-doc-tools libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python3 python3-setuptools ninja-build gobject-introspection libgirepository1.0-dev
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
- run: sudo pip3 install fonttools meson==0.56.0 gcovr==5.0
|
||||||
with:
|
- name: run
|
||||||
key: ${{ github.job }}-${{ runner.os }}-${{ runner.arch }}
|
run: meson build -Db_coverage=true --auto-features=enabled -Dgraphite=enabled -Dchafa=disabled -Dragel_subproject=true -Doptimization=2
|
||||||
- name: Install Dependencies
|
- name: ci
|
||||||
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
|
|
||||||
run: meson test --print-errorlogs -Cbuild
|
run: meson test --print-errorlogs -Cbuild
|
||||||
- name: Generate Documentations
|
|
||||||
|
- name: generate documentations
|
||||||
run: ninja -Cbuild harfbuzz-doc
|
run: ninja -Cbuild harfbuzz-doc
|
||||||
- name: Deploy Documentations
|
- name: deploy documentations
|
||||||
if: github.ref_type == 'tag'
|
if: github.ref_type == 'tag'
|
||||||
run: .ci/deploy-docs.sh
|
run: .ci/deploy-docs.sh
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||||
REVISION: ${{ github.sha }}
|
REVISION: ${{ github.sha }}
|
||||||
- name: Generate Coverage
|
|
||||||
|
# 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-xml
|
run: ninja -Cbuild coverage-xml
|
||||||
- name: Upload Coverage
|
- uses: codecov/codecov-action@v3
|
||||||
uses: codecov/codecov-action@v3
|
|
||||||
with:
|
with:
|
||||||
file: build/meson-logs/coverage.xml
|
file: build/meson-logs/coverage.xml
|
||||||
|
|
|
@ -14,47 +14,17 @@ jobs:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- uses: actions/checkout@v3
|
||||||
uses: actions/checkout@v3
|
- name: install dependencies
|
||||||
- name: Setup Ccache
|
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config freetype glib glib-utils cairo icu4c graphite2 gobject-introspection gtk-doc ninja
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
- run: pip3 install fonttools meson==0.56.0 gcovr==5.0
|
||||||
with:
|
- name: run
|
||||||
key: ${{ github.job }}-${{ runner.os }}-${{ runner.arch }}
|
run: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson build -Db_coverage=true -Dcoretext=enabled -Dgraphite=enabled -Dauto_features=enabled -Dchafa=disabled -Doptimization=2
|
||||||
- name: Install Dependencies
|
- name: ci
|
||||||
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
|
run: meson test --print-errorlogs -Cbuild
|
||||||
- name: Generate Coverage
|
|
||||||
|
- name: cov
|
||||||
run: ninja -Cbuild coverage-xml
|
run: ninja -Cbuild coverage-xml
|
||||||
- name: Upload Coverage
|
- uses: codecov/codecov-action@v3
|
||||||
uses: codecov/codecov-action@v3
|
|
||||||
with:
|
with:
|
||||||
file: build/meson-logs/coverage.xml
|
file: build/meson-logs/coverage.xml
|
||||||
|
|
|
@ -14,7 +14,6 @@ jobs:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
matrix:
|
||||||
os: [windows-2019, windows-latest]
|
os: [windows-2019, windows-latest]
|
||||||
include:
|
include:
|
||||||
|
@ -27,35 +26,33 @@ jobs:
|
||||||
name: ${{ matrix.name }}
|
name: ${{ matrix.name }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- uses: actions/checkout@v3
|
||||||
uses: actions/checkout@v3
|
- uses: actions/setup-python@v4
|
||||||
- name: Setup Ccache
|
with:
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
python-version: '3.x'
|
||||||
with:
|
- uses: ilammy/msvc-dev-cmd@v1
|
||||||
variant: sccache
|
with:
|
||||||
key: ${{ github.job }}-${{ matrix.os }}-${{ matrix.ARCH }}
|
arch : ${{ matrix.ARCH }}
|
||||||
- name: Setup Python
|
- name: Upgrade pip
|
||||||
uses: actions/setup-python@v4
|
run: |
|
||||||
with:
|
python -m pip install -U pip
|
||||||
python-version: '3.x'
|
- name: Install Dependencies
|
||||||
- name: Setup MSVC
|
run: |
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
pip install --upgrade meson ninja fonttools
|
||||||
with:
|
- name: Build
|
||||||
arch : ${{ matrix.ARCH }}
|
run: |
|
||||||
- name: Install Python Dependencies
|
# This dir contains a pkg-config which meson will happily use and later fail, so remove it
|
||||||
run: |
|
$env:path = ($env:path.Split(';') | Where-Object { $_ -ne 'C:\Strawberry\perl\bin' }) -join ';'
|
||||||
pip install --upgrade meson ninja fonttools
|
|
||||||
- name: Setup Meson
|
meson setup build `
|
||||||
run: |
|
--wrap-mode=default `
|
||||||
sccache --version
|
--buildtype=release `
|
||||||
meson setup build `
|
-Dglib=enabled `
|
||||||
--wrap-mode=forcefallback `
|
-Dfreetype=enabled `
|
||||||
--buildtype=release `
|
-Dgdi=enabled `
|
||||||
-Dglib=enabled `
|
-Ddirectwrite=enabled
|
||||||
-Dfreetype=enabled `
|
|
||||||
-Dgdi=enabled `
|
meson compile -C build
|
||||||
-Ddirectwrite=enabled
|
- name: Test
|
||||||
- name: Build
|
run: |
|
||||||
run: meson compile -Cbuild
|
meson test --print-errorlogs --suite=harfbuzz -C build
|
||||||
- name: Test
|
|
||||||
run: meson test --print-errorlogs --suite=harfbuzz -Cbuild
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ jobs:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- MSYSTEM: MINGW32
|
- MSYSTEM: MINGW32
|
||||||
|
@ -23,51 +22,47 @@ jobs:
|
||||||
MSYS2_ARCH: x86_64
|
MSYS2_ARCH: x86_64
|
||||||
name: ${{ matrix.MSYSTEM }}
|
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:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- uses: actions/checkout@v3
|
||||||
uses: actions/checkout@v3
|
- uses: msys2/setup-msys2@v2
|
||||||
- name: Setup MSYS2
|
with:
|
||||||
uses: msys2/setup-msys2@v2
|
msystem: ${{ matrix.MSYSTEM }}
|
||||||
with:
|
update: true
|
||||||
msystem: ${{ matrix.MSYSTEM }}
|
install: >-
|
||||||
update: true
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-cairo
|
||||||
install: >-
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-freetype
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-cairo
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-freetype
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc-libs
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-gettext
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc-libs
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-glib2
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gettext
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-gobject-introspection
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-glib2
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-graphite2
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gobject-introspection
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-icu
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-graphite2
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-meson
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-icu
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-ninja
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-meson
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-pkg-config
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-ninja
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-python
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-pkg-config
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-python-pip
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-python
|
mingw-w64-${{ matrix.MSYS2_ARCH }}-ragel
|
||||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-python-pip
|
- name: Install Python Dependencies
|
||||||
- name: Install Python Dependencies
|
run: |
|
||||||
run: |
|
pip install --upgrade fonttools
|
||||||
pip install --upgrade fonttools
|
- name: Build
|
||||||
- name: Setup Meson
|
run: |
|
||||||
run: |
|
meson build \
|
||||||
meson setup build \
|
--wrap-mode=nodownload \
|
||||||
--wrap-mode=nodownload \
|
--auto-features=enabled \
|
||||||
--auto-features=enabled \
|
-Ddirectwrite=enabled \
|
||||||
-Ddocs=disabled \
|
-Dgdi=enabled \
|
||||||
-Ddirectwrite=enabled \
|
-Dgraphite=enabled \
|
||||||
-Dgdi=enabled \
|
-Dchafa=disabled
|
||||||
-Dgraphite=enabled \
|
ninja -C build
|
||||||
-Dchafa=disabled
|
- name: Test
|
||||||
- name: Build
|
run: |
|
||||||
run: meson compile -Cbuild
|
meson test \
|
||||||
- name: Test
|
--print-errorlogs \
|
||||||
run: meson test --print-errorlogs --suite=harfbuzz -Cbuild
|
--suite=harfbuzz \
|
||||||
|
-C build
|
||||||
|
|
|
@ -566,7 +566,7 @@ if (HB_HAVE_INTROSPECTION)
|
||||||
# We need to account for the varying output directories
|
# We need to account for the varying output directories
|
||||||
# when we build using Visual Studio projects
|
# when we build using Visual Studio projects
|
||||||
if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
|
if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
|
||||||
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
|
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
|
||||||
else ()
|
else ()
|
||||||
set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
|
set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -816,7 +816,7 @@ if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
|
||||||
make_pkgconfig_pc_file("harfbuzz-gobject")
|
make_pkgconfig_pc_file("harfbuzz-gobject")
|
||||||
if (HB_HAVE_INTROSPECTION)
|
if (HB_HAVE_INTROSPECTION)
|
||||||
if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
|
if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
|
||||||
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
|
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
|
||||||
else ()
|
else ()
|
||||||
set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
|
set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
20
COPYING
20
COPYING
|
@ -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
|
For parts of HarfBuzz that are licensed under different licenses see individual
|
||||||
files names COPYING in subdirectories where applicable.
|
files names COPYING in subdirectories where applicable.
|
||||||
|
|
||||||
Copyright © 2010-2022 Google, Inc.
|
Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 Google, Inc.
|
||||||
Copyright © 2015-2020 Ebrahim Byagowi
|
Copyright © 2018,2019,2020 Ebrahim Byagowi
|
||||||
Copyright © 2019,2020 Facebook, Inc.
|
Copyright © 2019,2020 Facebook, Inc.
|
||||||
Copyright © 2012,2015 Mozilla Foundation
|
Copyright © 2012 Mozilla Foundation
|
||||||
Copyright © 2011 Codethink Limited
|
Copyright © 2011 Codethink Limited
|
||||||
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
||||||
Copyright © 2009 Keith Stribley
|
Copyright © 2009 Keith Stribley
|
||||||
Copyright © 2011 Martin Hosken and SIL International
|
Copyright © 2009 Martin Hosken and SIL International
|
||||||
Copyright © 2007 Chris Wilson
|
Copyright © 2007 Chris Wilson
|
||||||
Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod
|
Copyright © 2005,2006,2020,2021 Behdad Esfahbod
|
||||||
Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc.
|
Copyright © 2005 David Turner
|
||||||
Copyright © 1998-2005 David Turner and Werner Lemberg
|
Copyright © 2004,2007,2008,2009,2010 Red Hat, Inc.
|
||||||
Copyright © 2016 Igalia S.L.
|
Copyright © 1998-2004 David Turner and Werner Lemberg
|
||||||
Copyright © 2022 Matthias Clasen
|
|
||||||
Copyright © 2018,2021 Khaled Hosny
|
|
||||||
Copyright © 2018,2019,2020 Adobe, Inc
|
|
||||||
Copyright © 2013-2015 Alexei Podtelezhnikov
|
|
||||||
|
|
||||||
For full copyright notices consult the individual files in the package.
|
For full copyright notices consult the individual files in the package.
|
||||||
|
|
||||||
|
|
233
NEWS
233
NEWS
|
@ -1,236 +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
|
|
||||||
====================================
|
|
||||||
- Don’t 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
|
Overview of changes leading to 5.2.0
|
||||||
Saturday, September 17, 2022
|
Saturday, September 17, 2022
|
||||||
====================================
|
====================================
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
- [ ] 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.
|
||||||
|
|
||||||
- [ ] Search for 'XSince: REPLACEME' on the repository and replace it with the chosen version for the release, e.g. 'Since: 1.4.7'.
|
- [ ] Search for REPLACEME on the repository and replace it with the chosen version for the release.
|
||||||
|
|
||||||
- [ ] 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.
|
||||||
|
|
||||||
|
|
20
SECURITY.md
20
SECURITY.md
|
@ -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.
|
|
|
@ -1,6 +1,6 @@
|
||||||
AC_PREREQ([2.64])
|
AC_PREREQ([2.64])
|
||||||
AC_INIT([HarfBuzz],
|
AC_INIT([HarfBuzz],
|
||||||
[7.1.0],
|
[5.2.0],
|
||||||
[https://github.com/harfbuzz/harfbuzz/issues/new],
|
[https://github.com/harfbuzz/harfbuzz/issues/new],
|
||||||
[harfbuzz],
|
[harfbuzz],
|
||||||
[http://harfbuzz.org/])
|
[http://harfbuzz.org/])
|
||||||
|
@ -45,7 +45,7 @@ AC_SUBST(HB_VERSION)
|
||||||
|
|
||||||
# Libtool version
|
# Libtool version
|
||||||
m4_define([hb_version_int],
|
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
|
HB_LIBTOOL_VERSION_INFO=hb_version_int:0:hb_version_int
|
||||||
AC_SUBST(HB_LIBTOOL_VERSION_INFO)
|
AC_SUBST(HB_LIBTOOL_VERSION_INFO)
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ SCANGOBJ_OPTIONS=
|
||||||
# Extra options to supply to gtkdoc-scan.
|
# Extra options to supply to gtkdoc-scan.
|
||||||
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
|
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
|
||||||
SCAN_OPTIONS=--rebuild-types --deprecated-guards="HB_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
|
# Header files or dirs to ignore when scanning. Use base file/dir names
|
||||||
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
|
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
|
||||||
|
|
|
@ -56,9 +56,7 @@
|
||||||
<xi:include href="xml/hb-blob.xml"/>
|
<xi:include href="xml/hb-blob.xml"/>
|
||||||
<xi:include href="xml/hb-buffer.xml"/>
|
<xi:include href="xml/hb-buffer.xml"/>
|
||||||
<xi:include href="xml/hb-common.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-draw.xml"/>
|
||||||
<xi:include href="xml/hb-paint.xml"/>
|
|
||||||
<xi:include href="xml/hb-deprecated.xml"/>
|
<xi:include href="xml/hb-deprecated.xml"/>
|
||||||
<xi:include href="xml/hb-face.xml"/>
|
<xi:include href="xml/hb-face.xml"/>
|
||||||
<xi:include href="xml/hb-font.xml"/>
|
<xi:include href="xml/hb-font.xml"/>
|
||||||
|
@ -98,7 +96,6 @@
|
||||||
<xi:include href="xml/hb-uniscribe.xml"/>
|
<xi:include href="xml/hb-uniscribe.xml"/>
|
||||||
<xi:include href="xml/hb-gdi.xml"/>
|
<xi:include href="xml/hb-gdi.xml"/>
|
||||||
<xi:include href="xml/hb-directwrite.xml"/>
|
<xi:include href="xml/hb-directwrite.xml"/>
|
||||||
<xi:include href="xml/hb-cairo.xml"/>
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="style-api">
|
<chapter id="style-api">
|
||||||
|
@ -118,79 +115,75 @@
|
||||||
</chapter-->
|
</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="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-5-0-0" role="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-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-4-4-0" role="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-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-4-3-0" role="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-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-4-2-0" role="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-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-1-0" role="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-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-0-0" role="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-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-3-4-0" role="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-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-3-3-0" role="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-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-3-1-0" role="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-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-0-0" role="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-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-2-9-1" role="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-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-2-9-0" role="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-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-2-8-2" role="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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-3-3" role="1.3.3"><title>Index of new symbols in 1.3.3</title><xi:include href="xml/api-index-1.3.3.xml"><xi:fallback /></xi:include></index>
|
||||||
<index id="api-index-1-4-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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>
|
||||||
<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>
|
|
||||||
|
|
||||||
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
|
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
|
||||||
</part>
|
</part>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<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
|
and under active maintenance. This is what is used in latest
|
||||||
versions of Firefox, GNOME, ChromeOS, Chrome, LibreOffice,
|
versions of Firefox, GNOME, ChromeOS, Chrome, LibreOffice,
|
||||||
XeTeX, Android, and KDE, among other places.
|
XeTeX, Android, and KDE, among other places.
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
<SECTION>
|
|
||||||
<SUBSECTION Private>
|
<SUBSECTION Private>
|
||||||
HB_H_IN
|
HB_H_IN
|
||||||
HB_OT_H_IN
|
HB_OT_H_IN
|
||||||
|
@ -27,33 +26,33 @@ hb_blob_create_from_file
|
||||||
hb_blob_create_from_file_or_fail
|
hb_blob_create_from_file_or_fail
|
||||||
hb_blob_create_sub_blob
|
hb_blob_create_sub_blob
|
||||||
hb_blob_copy_writable_or_fail
|
hb_blob_copy_writable_or_fail
|
||||||
hb_blob_get_empty
|
|
||||||
hb_blob_reference
|
|
||||||
hb_blob_destroy
|
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
|
||||||
hb_blob_get_data_writable
|
hb_blob_get_data_writable
|
||||||
|
hb_blob_get_empty
|
||||||
hb_blob_get_length
|
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_blob_t
|
||||||
hb_memory_mode_t
|
hb_memory_mode_t
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-buffer</FILE>
|
<FILE>hb-buffer</FILE>
|
||||||
|
HB_SEGMENT_PROPERTIES_DEFAULT
|
||||||
|
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT
|
||||||
hb_buffer_create
|
hb_buffer_create
|
||||||
hb_buffer_allocation_successful
|
|
||||||
hb_buffer_create_similar
|
hb_buffer_create_similar
|
||||||
hb_buffer_get_empty
|
|
||||||
hb_buffer_reference
|
hb_buffer_reference
|
||||||
|
hb_buffer_get_empty
|
||||||
hb_buffer_destroy
|
hb_buffer_destroy
|
||||||
hb_buffer_set_user_data
|
|
||||||
hb_buffer_get_user_data
|
|
||||||
hb_buffer_reset
|
hb_buffer_reset
|
||||||
hb_buffer_clear_contents
|
hb_buffer_clear_contents
|
||||||
hb_buffer_pre_allocate
|
hb_buffer_pre_allocate
|
||||||
|
hb_buffer_allocation_successful
|
||||||
hb_buffer_add
|
hb_buffer_add
|
||||||
hb_buffer_add_codepoints
|
hb_buffer_add_codepoints
|
||||||
hb_buffer_add_utf32
|
hb_buffer_add_utf32
|
||||||
|
@ -80,14 +79,15 @@ hb_buffer_get_segment_properties
|
||||||
hb_buffer_guess_segment_properties
|
hb_buffer_guess_segment_properties
|
||||||
hb_buffer_set_unicode_funcs
|
hb_buffer_set_unicode_funcs
|
||||||
hb_buffer_get_unicode_funcs
|
hb_buffer_get_unicode_funcs
|
||||||
|
hb_buffer_set_user_data
|
||||||
|
hb_buffer_get_user_data
|
||||||
hb_buffer_get_glyph_infos
|
hb_buffer_get_glyph_infos
|
||||||
hb_glyph_info_get_glyph_flags
|
|
||||||
hb_buffer_get_glyph_positions
|
hb_buffer_get_glyph_positions
|
||||||
hb_buffer_has_positions
|
hb_buffer_has_positions
|
||||||
hb_buffer_set_invisible_glyph
|
|
||||||
hb_buffer_get_invisible_glyph
|
hb_buffer_get_invisible_glyph
|
||||||
hb_buffer_set_not_found_glyph
|
hb_buffer_set_invisible_glyph
|
||||||
hb_buffer_get_not_found_glyph
|
hb_buffer_get_not_found_glyph
|
||||||
|
hb_buffer_set_not_found_glyph
|
||||||
hb_buffer_set_replacement_codepoint
|
hb_buffer_set_replacement_codepoint
|
||||||
hb_buffer_get_replacement_codepoint
|
hb_buffer_get_replacement_codepoint
|
||||||
hb_buffer_normalize_glyphs
|
hb_buffer_normalize_glyphs
|
||||||
|
@ -106,11 +106,9 @@ hb_segment_properties_equal
|
||||||
hb_segment_properties_hash
|
hb_segment_properties_hash
|
||||||
hb_segment_properties_overlay
|
hb_segment_properties_overlay
|
||||||
hb_buffer_diff
|
hb_buffer_diff
|
||||||
hb_buffer_message_func_t
|
|
||||||
hb_buffer_set_message_func
|
hb_buffer_set_message_func
|
||||||
HB_SEGMENT_PROPERTIES_DEFAULT
|
|
||||||
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT
|
|
||||||
hb_buffer_t
|
hb_buffer_t
|
||||||
|
hb_glyph_info_get_glyph_flags
|
||||||
hb_glyph_info_t
|
hb_glyph_info_t
|
||||||
hb_glyph_flags_t
|
hb_glyph_flags_t
|
||||||
hb_glyph_position_t
|
hb_glyph_position_t
|
||||||
|
@ -121,25 +119,18 @@ hb_segment_properties_t
|
||||||
hb_buffer_serialize_format_t
|
hb_buffer_serialize_format_t
|
||||||
hb_buffer_serialize_flags_t
|
hb_buffer_serialize_flags_t
|
||||||
hb_buffer_diff_flags_t
|
hb_buffer_diff_flags_t
|
||||||
|
hb_buffer_message_func_t
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-common</FILE>
|
<FILE>hb-common</FILE>
|
||||||
HB_TAG
|
|
||||||
HB_UNTAG
|
|
||||||
hb_tag_from_string
|
hb_tag_from_string
|
||||||
hb_tag_to_string
|
hb_tag_to_string
|
||||||
hb_direction_from_string
|
hb_direction_from_string
|
||||||
hb_direction_to_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_from_iso15924_tag
|
||||||
hb_script_to_iso15924_tag
|
|
||||||
hb_script_from_string
|
hb_script_from_string
|
||||||
|
hb_script_to_iso15924_tag
|
||||||
hb_script_get_horizontal_direction
|
hb_script_get_horizontal_direction
|
||||||
hb_language_from_string
|
hb_language_from_string
|
||||||
hb_language_to_string
|
hb_language_to_string
|
||||||
|
@ -161,9 +152,17 @@ hb_position_t
|
||||||
hb_tag_t
|
hb_tag_t
|
||||||
hb_script_t
|
hb_script_t
|
||||||
hb_user_data_key_t
|
hb_user_data_key_t
|
||||||
|
HB_TAG
|
||||||
HB_TAG_NONE
|
HB_TAG_NONE
|
||||||
HB_TAG_MAX
|
HB_TAG_MAX
|
||||||
HB_TAG_MAX_SIGNED
|
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_LANGUAGE_INVALID
|
||||||
HB_FEATURE_GLOBAL_END
|
HB_FEATURE_GLOBAL_END
|
||||||
HB_FEATURE_GLOBAL_START
|
HB_FEATURE_GLOBAL_START
|
||||||
|
@ -180,35 +179,20 @@ uint16_t
|
||||||
uint32_t
|
uint32_t
|
||||||
uint64_t
|
uint64_t
|
||||||
uint8_t
|
uint8_t
|
||||||
|
<SUBSECTION Private>
|
||||||
HB_EXTERN
|
HB_EXTERN
|
||||||
HB_DEPRECATED
|
HB_DEPRECATED
|
||||||
HB_DEPRECATED_FOR
|
HB_DEPRECATED_FOR
|
||||||
</SECTION>
|
</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>
|
<SECTION>
|
||||||
<FILE>hb-draw</FILE>
|
<FILE>hb-draw</FILE>
|
||||||
|
hb_draw_funcs_t
|
||||||
hb_draw_funcs_create
|
hb_draw_funcs_create
|
||||||
hb_draw_funcs_get_empty
|
|
||||||
hb_draw_funcs_reference
|
|
||||||
hb_draw_funcs_destroy
|
hb_draw_funcs_destroy
|
||||||
hb_draw_funcs_set_user_data
|
hb_draw_funcs_reference
|
||||||
hb_draw_funcs_get_user_data
|
|
||||||
hb_draw_funcs_make_immutable
|
|
||||||
hb_draw_funcs_is_immutable
|
hb_draw_funcs_is_immutable
|
||||||
|
hb_draw_funcs_make_immutable
|
||||||
hb_draw_move_to_func_t
|
hb_draw_move_to_func_t
|
||||||
hb_draw_funcs_set_move_to_func
|
hb_draw_funcs_set_move_to_func
|
||||||
hb_draw_line_to_func_t
|
hb_draw_line_to_func_t
|
||||||
|
@ -219,79 +203,13 @@ hb_draw_cubic_to_func_t
|
||||||
hb_draw_funcs_set_cubic_to_func
|
hb_draw_funcs_set_cubic_to_func
|
||||||
hb_draw_close_path_func_t
|
hb_draw_close_path_func_t
|
||||||
hb_draw_funcs_set_close_path_func
|
hb_draw_funcs_set_close_path_func
|
||||||
|
hb_draw_state_t
|
||||||
|
HB_DRAW_STATE_DEFAULT
|
||||||
hb_draw_move_to
|
hb_draw_move_to
|
||||||
hb_draw_line_to
|
hb_draw_line_to
|
||||||
hb_draw_quadratic_to
|
hb_draw_quadratic_to
|
||||||
hb_draw_cubic_to
|
hb_draw_cubic_to
|
||||||
hb_draw_close_path
|
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>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
|
@ -346,29 +264,27 @@ hb_face_count
|
||||||
hb_face_t
|
hb_face_t
|
||||||
hb_face_create
|
hb_face_create
|
||||||
hb_face_create_for_tables
|
hb_face_create_for_tables
|
||||||
hb_face_get_empty
|
|
||||||
hb_face_reference
|
|
||||||
hb_face_destroy
|
hb_face_destroy
|
||||||
hb_face_set_user_data
|
hb_face_get_empty
|
||||||
hb_face_get_user_data
|
|
||||||
hb_face_make_immutable
|
|
||||||
hb_face_is_immutable
|
|
||||||
hb_face_get_table_tags
|
hb_face_get_table_tags
|
||||||
hb_face_set_glyph_count
|
|
||||||
hb_face_get_glyph_count
|
hb_face_get_glyph_count
|
||||||
hb_face_set_index
|
|
||||||
hb_face_get_index
|
hb_face_get_index
|
||||||
hb_face_set_upem
|
|
||||||
hb_face_get_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_blob
|
||||||
hb_face_reference_table
|
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_unicodes
|
||||||
hb_face_collect_nominal_glyph_mapping
|
|
||||||
hb_face_collect_variation_selectors
|
hb_face_collect_variation_selectors
|
||||||
hb_face_collect_variation_unicodes
|
hb_face_collect_variation_unicodes
|
||||||
hb_face_builder_create
|
hb_face_builder_create
|
||||||
hb_face_builder_add_table
|
hb_face_builder_add_table
|
||||||
hb_face_builder_sort_tables
|
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
|
@ -376,124 +292,113 @@ hb_face_builder_sort_tables
|
||||||
hb_font_add_glyph_origin_for_direction
|
hb_font_add_glyph_origin_for_direction
|
||||||
hb_font_create
|
hb_font_create
|
||||||
hb_font_create_sub_font
|
hb_font_create_sub_font
|
||||||
hb_font_get_empty
|
|
||||||
hb_font_reference
|
|
||||||
hb_font_destroy
|
hb_font_destroy
|
||||||
hb_font_set_user_data
|
hb_font_funcs_create
|
||||||
hb_font_get_user_data
|
hb_font_funcs_destroy
|
||||||
hb_font_make_immutable
|
hb_font_funcs_get_empty
|
||||||
hb_font_is_immutable
|
hb_font_funcs_get_user_data
|
||||||
hb_font_set_face
|
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_shape_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_face
|
||||||
hb_font_get_glyph
|
hb_font_get_glyph
|
||||||
hb_font_get_glyph_advance_for_direction
|
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_for_direction
|
||||||
|
hb_font_get_glyph_advances_func_t
|
||||||
hb_font_get_glyph_contour_point
|
hb_font_get_glyph_contour_point
|
||||||
hb_font_get_glyph_contour_point_for_origin
|
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
|
||||||
hb_font_get_glyph_extents_for_origin
|
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
|
||||||
|
hb_font_get_glyph_from_name_func_t
|
||||||
hb_font_get_glyph_h_advance
|
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_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_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_h_origin
|
||||||
hb_font_get_glyph_v_origin
|
hb_font_get_glyph_h_origin_func_t
|
||||||
hb_font_get_glyph_origin_for_direction
|
hb_font_get_glyph_kerning_for_direction
|
||||||
|
hb_font_get_glyph_kerning_func_t
|
||||||
hb_font_get_glyph_name
|
hb_font_get_glyph_name
|
||||||
|
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_shape
|
hb_font_get_glyph_shape
|
||||||
hb_font_draw_glyph
|
hb_font_get_glyph_shape_func_t
|
||||||
hb_font_paint_glyph
|
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
|
||||||
|
hb_font_get_nominal_glyph_func_t
|
||||||
hb_font_get_nominal_glyphs
|
hb_font_get_nominal_glyphs
|
||||||
hb_font_get_variation_glyph
|
hb_font_get_nominal_glyphs_func_t
|
||||||
hb_font_set_parent
|
|
||||||
hb_font_get_parent
|
hb_font_get_parent
|
||||||
hb_font_set_ppem
|
|
||||||
hb_font_get_ppem
|
hb_font_get_ppem
|
||||||
hb_font_set_ptem
|
|
||||||
hb_font_get_ptem
|
hb_font_get_ptem
|
||||||
hb_font_set_scale
|
|
||||||
hb_font_get_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_get_synthetic_slant
|
||||||
hb_font_set_variations
|
hb_font_get_user_data
|
||||||
hb_font_set_variation
|
hb_font_get_variation_glyph
|
||||||
HB_FONT_NO_VAR_NAMED_INSTANCE
|
hb_font_get_variation_glyph_func_t
|
||||||
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_get_var_coords_design
|
||||||
hb_font_set_var_coords_normalized
|
|
||||||
hb_font_get_var_coords_normalized
|
hb_font_get_var_coords_normalized
|
||||||
hb_font_glyph_from_string
|
hb_font_glyph_from_string
|
||||||
hb_font_glyph_to_string
|
hb_font_glyph_to_string
|
||||||
|
hb_font_is_immutable
|
||||||
|
hb_font_make_immutable
|
||||||
hb_font_get_serial
|
hb_font_get_serial
|
||||||
hb_font_changed
|
hb_font_changed
|
||||||
|
hb_font_reference
|
||||||
|
hb_font_set_face
|
||||||
hb_font_set_funcs
|
hb_font_set_funcs
|
||||||
hb_font_set_funcs_data
|
hb_font_set_funcs_data
|
||||||
|
hb_font_set_parent
|
||||||
|
hb_font_set_ppem
|
||||||
|
hb_font_set_ptem
|
||||||
|
hb_font_set_scale
|
||||||
|
hb_font_set_synthetic_slant
|
||||||
|
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_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_font_t
|
||||||
hb_reference_table_func_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_extents_func_t
|
||||||
hb_font_get_font_h_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_get_font_v_extents_func_t
|
||||||
hb_font_funcs_set_font_v_extents_func
|
|
||||||
hb_font_get_h_extents
|
hb_font_get_h_extents
|
||||||
hb_font_get_v_extents
|
hb_font_get_v_extents
|
||||||
hb_font_get_extents_for_direction
|
|
||||||
hb_font_extents_t
|
hb_font_extents_t
|
||||||
hb_glyph_extents_t
|
hb_glyph_extents_t
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
@ -544,33 +449,30 @@ hb_icu_script_to_script
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-map</FILE>
|
<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_VALUE_INVALID
|
||||||
|
hb_map_allocation_successful
|
||||||
|
hb_map_clear
|
||||||
|
hb_map_copy
|
||||||
|
hb_map_create
|
||||||
|
hb_map_del
|
||||||
|
hb_map_destroy
|
||||||
|
hb_map_get
|
||||||
|
hb_map_get_empty
|
||||||
|
hb_map_get_population
|
||||||
|
hb_map_is_equal
|
||||||
|
hb_map_get_user_data
|
||||||
|
hb_map_has
|
||||||
|
hb_map_hash
|
||||||
|
hb_map_is_empty
|
||||||
|
hb_map_reference
|
||||||
|
hb_map_set
|
||||||
|
hb_map_set_user_data
|
||||||
hb_map_t
|
hb_map_t
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-ot-color</FILE>
|
<FILE>hb-ot-color</FILE>
|
||||||
|
hb_color_t
|
||||||
HB_COLOR
|
HB_COLOR
|
||||||
hb_color_get_alpha
|
hb_color_get_alpha
|
||||||
hb_color_get_blue
|
hb_color_get_blue
|
||||||
|
@ -580,19 +482,16 @@ hb_ot_color_glyph_get_layers
|
||||||
hb_ot_color_glyph_reference_png
|
hb_ot_color_glyph_reference_png
|
||||||
hb_ot_color_glyph_reference_svg
|
hb_ot_color_glyph_reference_svg
|
||||||
hb_ot_color_has_layers
|
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_palettes
|
||||||
hb_ot_color_has_png
|
hb_ot_color_has_png
|
||||||
hb_ot_color_has_svg
|
hb_ot_color_has_svg
|
||||||
|
hb_ot_color_layer_t
|
||||||
hb_ot_color_palette_color_get_name_id
|
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_colors
|
||||||
hb_ot_color_palette_get_count
|
hb_ot_color_palette_get_count
|
||||||
hb_ot_color_palette_get_flags
|
hb_ot_color_palette_get_flags
|
||||||
hb_ot_color_palette_get_name_id
|
hb_ot_color_palette_get_name_id
|
||||||
hb_color_t
|
|
||||||
hb_ot_color_layer_t
|
|
||||||
hb_ot_color_palette_flags_t
|
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
|
@ -602,21 +501,35 @@ hb_ot_font_set_funcs
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-ot-name</FILE>
|
<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_list_names
|
||||||
hb_ot_name_get_utf16
|
hb_ot_name_get_utf16
|
||||||
hb_ot_name_get_utf32
|
hb_ot_name_get_utf32
|
||||||
hb_ot_name_get_utf8
|
hb_ot_name_get_utf8
|
||||||
hb_ot_name_id_t
|
|
||||||
hb_ot_name_id_predefined_t
|
|
||||||
hb_ot_name_entry_t
|
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-ot-layout</FILE>
|
<FILE>hb-ot-layout</FILE>
|
||||||
|
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_language
|
||||||
hb_ot_tag_to_script
|
hb_ot_tag_to_script
|
||||||
hb_ot_tags_from_script_and_language
|
hb_ot_tags_from_script_and_language
|
||||||
hb_ot_tags_to_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
|
||||||
|
HB_OT_LAYOUT_NO_VARIATIONS_INDEX
|
||||||
|
HB_OT_TAG_BASE
|
||||||
|
HB_OT_TAG_GDEF
|
||||||
|
HB_OT_TAG_GPOS
|
||||||
|
HB_OT_TAG_GSUB
|
||||||
|
HB_OT_TAG_JSTF
|
||||||
|
hb_ot_layout_baseline_tag_t
|
||||||
hb_ot_layout_collect_lookups
|
hb_ot_layout_collect_lookups
|
||||||
hb_ot_layout_collect_features
|
hb_ot_layout_collect_features
|
||||||
hb_ot_layout_feature_get_characters
|
hb_ot_layout_feature_get_characters
|
||||||
|
@ -631,6 +544,7 @@ hb_ot_layout_get_glyph_class
|
||||||
hb_ot_layout_get_glyphs_in_class
|
hb_ot_layout_get_glyphs_in_class
|
||||||
hb_ot_layout_get_ligature_carets
|
hb_ot_layout_get_ligature_carets
|
||||||
hb_ot_layout_get_size_params
|
hb_ot_layout_get_size_params
|
||||||
|
hb_ot_layout_glyph_class_t
|
||||||
hb_ot_layout_has_glyph_classes
|
hb_ot_layout_has_glyph_classes
|
||||||
hb_ot_layout_has_positioning
|
hb_ot_layout_has_positioning
|
||||||
hb_ot_layout_has_substitution
|
hb_ot_layout_has_substitution
|
||||||
|
@ -640,14 +554,12 @@ hb_ot_layout_language_get_feature_tags
|
||||||
hb_ot_layout_language_get_required_feature
|
hb_ot_layout_language_get_required_feature
|
||||||
hb_ot_layout_lookup_collect_glyphs
|
hb_ot_layout_lookup_collect_glyphs
|
||||||
hb_ot_layout_lookup_get_glyph_alternates
|
hb_ot_layout_lookup_get_glyph_alternates
|
||||||
hb_ot_layout_lookup_get_optical_bound
|
|
||||||
hb_ot_layout_lookup_substitute_closure
|
hb_ot_layout_lookup_substitute_closure
|
||||||
hb_ot_layout_lookups_substitute_closure
|
hb_ot_layout_lookups_substitute_closure
|
||||||
hb_ot_layout_lookup_would_substitute
|
hb_ot_layout_lookup_would_substitute
|
||||||
hb_ot_layout_script_find_language
|
hb_ot_layout_script_find_language
|
||||||
hb_ot_layout_script_get_language_tags
|
hb_ot_layout_script_get_language_tags
|
||||||
hb_ot_layout_script_select_language
|
hb_ot_layout_script_select_language
|
||||||
hb_ot_layout_script_select_language2
|
|
||||||
hb_ot_layout_table_find_feature_variations
|
hb_ot_layout_table_find_feature_variations
|
||||||
hb_ot_layout_table_get_feature_tags
|
hb_ot_layout_table_get_feature_tags
|
||||||
hb_ot_layout_table_get_script_tags
|
hb_ot_layout_table_get_script_tags
|
||||||
|
@ -655,25 +567,18 @@ hb_ot_layout_table_get_lookup_count
|
||||||
hb_ot_layout_table_select_script
|
hb_ot_layout_table_select_script
|
||||||
hb_ot_shape_plan_collect_lookups
|
hb_ot_shape_plan_collect_lookups
|
||||||
hb_ot_layout_language_get_required_feature_index
|
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_LAYOUT_DEFAULT_LANGUAGE_INDEX
|
|
||||||
HB_OT_LAYOUT_NO_FEATURE_INDEX
|
|
||||||
HB_OT_LAYOUT_NO_SCRIPT_INDEX
|
|
||||||
HB_OT_LAYOUT_NO_VARIATIONS_INDEX
|
|
||||||
HB_OT_TAG_BASE
|
|
||||||
HB_OT_TAG_GDEF
|
|
||||||
HB_OT_TAG_GPOS
|
|
||||||
HB_OT_TAG_GSUB
|
|
||||||
HB_OT_TAG_JSTF
|
|
||||||
hb_ot_layout_baseline_tag_t
|
|
||||||
hb_ot_layout_glyph_class_t
|
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-ot-math</FILE>
|
<FILE>hb-ot-math</FILE>
|
||||||
|
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
|
||||||
hb_ot_math_has_data
|
hb_ot_math_has_data
|
||||||
hb_ot_math_get_constant
|
hb_ot_math_get_constant
|
||||||
hb_ot_math_get_glyph_italics_correction
|
hb_ot_math_get_glyph_italics_correction
|
||||||
|
@ -684,31 +589,23 @@ hb_ot_math_is_glyph_extended_shape
|
||||||
hb_ot_math_get_glyph_variants
|
hb_ot_math_get_glyph_variants
|
||||||
hb_ot_math_get_min_connector_overlap
|
hb_ot_math_get_min_connector_overlap
|
||||||
hb_ot_math_get_glyph_assembly
|
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>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-ot-meta</FILE>
|
<FILE>hb-ot-meta</FILE>
|
||||||
|
hb_ot_meta_tag_t
|
||||||
hb_ot_meta_get_entry_tags
|
hb_ot_meta_get_entry_tags
|
||||||
hb_ot_meta_reference_entry
|
hb_ot_meta_reference_entry
|
||||||
hb_ot_meta_tag_t
|
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-ot-metrics</FILE>
|
<FILE>hb-ot-metrics</FILE>
|
||||||
|
hb_ot_metrics_tag_t
|
||||||
hb_ot_metrics_get_position
|
hb_ot_metrics_get_position
|
||||||
hb_ot_metrics_get_position_with_fallback
|
hb_ot_metrics_get_position_with_fallback
|
||||||
hb_ot_metrics_get_variation
|
hb_ot_metrics_get_variation
|
||||||
hb_ot_metrics_get_x_variation
|
hb_ot_metrics_get_x_variation
|
||||||
hb_ot_metrics_get_y_variation
|
hb_ot_metrics_get_y_variation
|
||||||
hb_ot_metrics_tag_t
|
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
|
@ -718,7 +615,14 @@ hb_ot_shape_glyphs_closure
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-ot-var</FILE>
|
<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_has_data
|
||||||
|
hb_ot_var_axis_flags_t
|
||||||
|
hb_ot_var_axis_info_t
|
||||||
hb_ot_var_find_axis_info
|
hb_ot_var_find_axis_info
|
||||||
hb_ot_var_get_axis_count
|
hb_ot_var_get_axis_count
|
||||||
hb_ot_var_get_axis_infos
|
hb_ot_var_get_axis_infos
|
||||||
|
@ -728,44 +632,31 @@ hb_ot_var_named_instance_get_postscript_name_id
|
||||||
hb_ot_var_named_instance_get_design_coords
|
hb_ot_var_named_instance_get_design_coords
|
||||||
hb_ot_var_normalize_variations
|
hb_ot_var_normalize_variations
|
||||||
hb_ot_var_normalize_coords
|
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>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-set</FILE>
|
<FILE>hb-set</FILE>
|
||||||
hb_set_create
|
HB_SET_VALUE_INVALID
|
||||||
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_add
|
hb_set_add
|
||||||
hb_set_add_range
|
hb_set_add_range
|
||||||
hb_set_add_sorted_array
|
hb_set_add_sorted_array
|
||||||
|
hb_set_allocation_successful
|
||||||
|
hb_set_copy
|
||||||
|
hb_set_clear
|
||||||
|
hb_set_create
|
||||||
hb_set_del
|
hb_set_del
|
||||||
hb_set_del_range
|
hb_set_del_range
|
||||||
|
hb_set_destroy
|
||||||
|
hb_set_get_empty
|
||||||
hb_set_get_max
|
hb_set_get_max
|
||||||
hb_set_get_min
|
hb_set_get_min
|
||||||
hb_set_get_population
|
hb_set_get_population
|
||||||
hb_set_is_empty
|
hb_set_get_user_data
|
||||||
|
hb_set_has
|
||||||
hb_set_hash
|
hb_set_hash
|
||||||
hb_set_subtract
|
|
||||||
hb_set_intersect
|
hb_set_intersect
|
||||||
hb_set_union
|
|
||||||
hb_set_symmetric_difference
|
|
||||||
hb_set_invert
|
hb_set_invert
|
||||||
hb_set_is_inverted
|
hb_set_is_empty
|
||||||
hb_set_is_equal
|
hb_set_is_equal
|
||||||
hb_set_is_subset
|
hb_set_is_subset
|
||||||
hb_set_next
|
hb_set_next
|
||||||
|
@ -773,15 +664,19 @@ hb_set_next_range
|
||||||
hb_set_next_many
|
hb_set_next_many
|
||||||
hb_set_previous
|
hb_set_previous
|
||||||
hb_set_previous_range
|
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_t
|
||||||
|
hb_set_union
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-shape</FILE>
|
<FILE>hb-shape</FILE>
|
||||||
hb_shape
|
hb_shape
|
||||||
hb_shape_full
|
hb_shape_full
|
||||||
hb_shape_justify
|
|
||||||
hb_shape_list_shapers
|
hb_shape_list_shapers
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
@ -791,50 +686,50 @@ hb_shape_plan_create
|
||||||
hb_shape_plan_create_cached
|
hb_shape_plan_create_cached
|
||||||
hb_shape_plan_create2
|
hb_shape_plan_create2
|
||||||
hb_shape_plan_create_cached2
|
hb_shape_plan_create_cached2
|
||||||
hb_shape_plan_get_empty
|
|
||||||
hb_shape_plan_reference
|
|
||||||
hb_shape_plan_destroy
|
hb_shape_plan_destroy
|
||||||
hb_shape_plan_set_user_data
|
|
||||||
hb_shape_plan_get_user_data
|
|
||||||
hb_shape_plan_execute
|
hb_shape_plan_execute
|
||||||
|
hb_shape_plan_get_empty
|
||||||
hb_shape_plan_get_shaper
|
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
|
hb_shape_plan_t
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-unicode</FILE>
|
<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_MAX
|
||||||
|
hb_unicode_combining_class
|
||||||
|
hb_unicode_combining_class_func_t
|
||||||
hb_unicode_combining_class_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_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>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
|
@ -846,13 +741,13 @@ hb_uniscribe_font_get_logfontw
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-version</FILE>
|
<FILE>hb-version</FILE>
|
||||||
HB_VERSION_ATLEAST
|
HB_VERSION_ATLEAST
|
||||||
hb_version
|
|
||||||
hb_version_atleast
|
|
||||||
hb_version_string
|
|
||||||
HB_VERSION_MAJOR
|
HB_VERSION_MAJOR
|
||||||
HB_VERSION_MICRO
|
HB_VERSION_MICRO
|
||||||
HB_VERSION_MINOR
|
HB_VERSION_MINOR
|
||||||
HB_VERSION_STRING
|
HB_VERSION_STRING
|
||||||
|
hb_version
|
||||||
|
hb_version_atleast
|
||||||
|
hb_version_string
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
|
@ -863,19 +758,20 @@ hb_style_get_value
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>hb-subset</FILE>
|
<FILE>hb-subset</FILE>
|
||||||
|
hb_subset_flags_t
|
||||||
|
hb_subset_input_t
|
||||||
|
hb_subset_sets_t
|
||||||
|
hb_subset_plan_t
|
||||||
hb_subset_input_create_or_fail
|
hb_subset_input_create_or_fail
|
||||||
hb_subset_input_reference
|
hb_subset_input_reference
|
||||||
hb_subset_input_destroy
|
hb_subset_input_destroy
|
||||||
hb_subset_input_set_user_data
|
hb_subset_input_set_user_data
|
||||||
hb_subset_input_get_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_get_flags
|
||||||
|
hb_subset_input_set_flags
|
||||||
hb_subset_input_unicode_set
|
hb_subset_input_unicode_set
|
||||||
hb_subset_input_glyph_set
|
hb_subset_input_glyph_set
|
||||||
hb_subset_input_set
|
hb_subset_input_set
|
||||||
hb_subset_input_pin_axis_location
|
|
||||||
hb_subset_input_pin_axis_to_default
|
|
||||||
hb_subset_or_fail
|
hb_subset_or_fail
|
||||||
hb_subset_plan_create_or_fail
|
hb_subset_plan_create_or_fail
|
||||||
hb_subset_plan_reference
|
hb_subset_plan_reference
|
||||||
|
@ -886,28 +782,8 @@ hb_subset_plan_execute_or_fail
|
||||||
hb_subset_plan_unicode_to_old_glyph_mapping
|
hb_subset_plan_unicode_to_old_glyph_mapping
|
||||||
hb_subset_plan_new_to_old_glyph_mapping
|
hb_subset_plan_new_to_old_glyph_mapping
|
||||||
hb_subset_plan_old_to_new_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>
|
<SUBSECTION Private>
|
||||||
hb_link_t
|
hb_link_t
|
||||||
hb_object_t
|
hb_object_t
|
||||||
hb_subset_repack_or_fail
|
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
|
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
|
@ -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()
|
if not find_program('gtkdoc-scan', required: get_option('docs')).found()
|
||||||
message('Not building documentation as gtk-doc was not found')
|
message('Not building documentation as gtk-doc was not found')
|
||||||
subdir_done()
|
subdir_done()
|
||||||
|
@ -36,7 +41,6 @@ html_images = [
|
||||||
]
|
]
|
||||||
|
|
||||||
ignore_headers = [
|
ignore_headers = [
|
||||||
'hb-features.h',
|
|
||||||
'hb-gobject.h',
|
'hb-gobject.h',
|
||||||
'hb-gobject-enums.h',
|
'hb-gobject-enums.h',
|
||||||
'hb-gobject-enums-tmp.h',
|
'hb-gobject-enums-tmp.h',
|
||||||
|
@ -49,7 +53,7 @@ gnome.gtkdoc('harfbuzz',
|
||||||
meson.current_build_dir() / '..' / 'src',
|
meson.current_build_dir() / '..' / 'src',
|
||||||
],
|
],
|
||||||
scan_args: ['--deprecated-guards=HB_DISABLE_DEPRECATED',
|
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',
|
mkdb_args: ['--source-suffixes=h,cc',
|
||||||
'--xml-mode',
|
'--xml-mode',
|
||||||
|
@ -59,6 +63,4 @@ gnome.gtkdoc('harfbuzz',
|
||||||
html_assets: html_images,
|
html_assets: html_images,
|
||||||
ignore_headers: ignore_headers,
|
ignore_headers: ignore_headers,
|
||||||
dependencies: [libharfbuzz_dep],
|
dependencies: [libharfbuzz_dep],
|
||||||
install: true,
|
install: true)
|
||||||
check: get_option('doc_tests'),
|
|
||||||
)
|
|
||||||
|
|
|
@ -23,11 +23,11 @@ Offset overflows can happen for a variety of reasons and require different strat
|
||||||
for more flexibility in the ordering.
|
for more flexibility in the ordering.
|
||||||
* In GSUB/GPOS overflows from Lookup subtables can be resolved by changing the Lookup to an extension
|
* 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.
|
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.
|
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
|
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.
|
which attempt a combination of the above strategies to attempt to find a non-overflowing configuration.
|
||||||
|
|
||||||
The harfbuzz subsetting library
|
The harfbuzz subsetting library
|
||||||
[includes a repacking algorithm](https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-repacker.hh)
|
[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
|
which is used to resolve offset overflows that are present in the subsetted tables it produces. This
|
||||||
|
@ -47,22 +47,16 @@ There's four key pieces to the harfbuzz approach:
|
||||||
|
|
||||||
* [Topological sorting algorithm](https://en.wikipedia.org/wiki/Topological_sorting): an algorithm
|
* [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.
|
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
|
* 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
|
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
|
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
|
to calculate the final position of each subtable and then check if any offsets to it will
|
||||||
overflow.
|
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
|
* Offset resolution strategies: given a particular occurrence of an overflow these strategies
|
||||||
modify the graph to attempt to resolve the overflow.
|
modify the graph to attempt to resolve the overflow.
|
||||||
|
|
||||||
# High Level Algorithm
|
# High Level Algorithm
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -70,7 +64,6 @@ def repack(graph):
|
||||||
graph.topological_sort()
|
graph.topological_sort()
|
||||||
|
|
||||||
if (graph.will_overflow())
|
if (graph.will_overflow())
|
||||||
preprocess(graph)
|
|
||||||
assign_spaces(graph)
|
assign_spaces(graph)
|
||||||
graph.topological_sort()
|
graph.topological_sort()
|
||||||
|
|
||||||
|
@ -92,7 +85,7 @@ The harfbuzz repacker uses two different algorithms for topological sorting:
|
||||||
Kahn's algorithm is approximately twice as fast as the shortest distance sort so that is attempted
|
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
|
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.
|
sort will be used for all subsequent topological sorting operations.
|
||||||
|
|
||||||
## Shortest Distance Sort
|
## Shortest Distance Sort
|
||||||
|
|
||||||
This algorithm orders the nodes based on total distance to each node. Nodes with a shorter distance
|
This algorithm orders the nodes based on total distance to each node. Nodes with a shorter distance
|
||||||
|
@ -120,7 +113,7 @@ operations:
|
||||||
* The number of incoming edges to each node is cached. This is required by the Kahn's algorithm
|
* 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
|
portion of both sorts. Where possible when the graph is modified we manually update the cached
|
||||||
edge counts of affected nodes.
|
edge counts of affected nodes.
|
||||||
|
|
||||||
* The distance to each node is cached. Where possible when the graph is modified we manually update
|
* The distance to each node is cached. Where possible when the graph is modified we manually update
|
||||||
the cached distances of any affected nodes.
|
the cached distances of any affected nodes.
|
||||||
|
|
||||||
|
@ -192,37 +185,6 @@ The assign_spaces() step in the high level algorithm is responsible for identify
|
||||||
subgraphs and assigning unique spaces to each one. More information on the space assignment can be
|
subgraphs and assigning unique spaces to each one. More information on the space assignment can be
|
||||||
found in the next section.
|
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
|
# Offset Resolution Strategies
|
||||||
|
|
||||||
|
@ -242,13 +204,13 @@ and then assign each such subgraph to a unique non-zero space. The algorithm is
|
||||||
|
|
||||||
a. Pick a node `n` in set `S` then perform an undirected graph traversal and find the set `Q` of
|
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`.
|
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
|
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.
|
to disconnect it from space 0.
|
||||||
|
|
||||||
d. Remove all nodes in `Q` from `S` and assign all nodes in `Q` to `next_space`.
|
d. Remove all nodes in `Q` from `S` and assign all nodes in `Q` to `next_space`.
|
||||||
|
|
||||||
|
|
||||||
c. Increment `next_space` by one.
|
c. Increment `next_space` by one.
|
||||||
|
|
||||||
|
|
||||||
|
@ -264,31 +226,40 @@ of the overflowing link:
|
||||||
|
|
||||||
* If the overflowing offset is pointing to a subtable with more than one incoming edge: duplicate
|
* 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.
|
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
|
* 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
|
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.
|
children will be ordered closer to the parent.
|
||||||
|
|
||||||
# Test Cases
|
# Test Cases
|
||||||
|
|
||||||
The harfbuzz repacker has tests defined using generic graphs: https://github.com/harfbuzz/harfbuzz/blob/main/src/test-repacker.cc
|
The harfbuzz repacker has tests defined using generic graphs: https://github.com/harfbuzz/harfbuzz/blob/main/src/test-repacker.cc
|
||||||
|
|
||||||
# Future Improvements
|
# Future Improvements
|
||||||
|
|
||||||
Currently for GPOS tables the repacker implementation is sufficient to handle both subsetting and the
|
The above resolution strategies are not sufficient to resolve all overflows. For example consider
|
||||||
general case of font compilation repacking. However for GSUB the repacker is only sufficient for
|
the case where a single subtable is 65k and the graph structure requires an offset to point over it.
|
||||||
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
|
The current harfbuzz implementation is suitable for the vast majority of subsetting related overflows.
|
||||||
to support the general case:
|
Subsetting related overflows are typically easy to solve since all subsets are derived from a font
|
||||||
|
that was originally overflow free. A more general purpose version of the algorithm suitable for font
|
||||||
* Extension demotion: currently extension promotion is supported but in some cases if the non-extension
|
creation purposes will likely need some additional offset resolution strategies:
|
||||||
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
|
* 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
|
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
|
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.
|
priority should be increased or the parent's priority decreased.
|
||||||
|
|
||||||
|
* Many subtables can be split into two smaller subtables without impacting the overall functionality.
|
||||||
|
This should be done when an overflow is the result of a very large table which can't be moved
|
||||||
|
to avoid offsets pointing over it.
|
||||||
|
|
||||||
|
* Lookup subtables in GSUB/GPOS can be upgraded to extension lookups which uses a 32 bit offset.
|
||||||
|
Overflows from a Lookup subtable to it's child should be resolved by converting to an extension
|
||||||
|
lookup.
|
||||||
|
|
||||||
|
Once additional resolution strategies are added to the algorithm it's likely that we'll need to
|
||||||
|
switch to using a [backtracking algorithm](https://en.wikipedia.org/wiki/Backtracking) to explore
|
||||||
|
the various combinations of resolution strategies until a non-overflowing combination is found. This
|
||||||
|
will require the ability to restore the graph to an earlier state. It's likely that using a stack
|
||||||
|
of undoable resolution commands could be used to accomplish this.
|
||||||
|
|
|
@ -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%
|
|
|
@ -182,7 +182,8 @@
|
||||||
</para>
|
</para>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>
|
<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>
|
||||||
<para>
|
<para>
|
||||||
The distinguishing feature of level 0 behavior is that, at
|
The distinguishing feature of level 0 behavior is that, at
|
||||||
|
@ -193,7 +194,7 @@
|
||||||
as well as the <emphasis>Zero Width Joiner</emphasis> and
|
as well as the <emphasis>Zero Width Joiner</emphasis> and
|
||||||
<emphasis>Zero Width Non-Joiner</emphasis> code points, are
|
<emphasis>Zero Width Non-Joiner</emphasis> code points, are
|
||||||
assigned the cluster value of the closest preceding code
|
assigned the cluster value of the closest preceding code
|
||||||
point from <emphasis>different</emphasis> category.
|
point from <emphasis>different</emphasis> category.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
In essence, whenever a base character is followed by a mark
|
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
|
url="https://www.unicode.org/reports/tr29/#Regex_Definitions">Unicode
|
||||||
Technical Report 29</ulink>.
|
Technical Report 29</ulink>.
|
||||||
</para>
|
</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>
|
<para>
|
||||||
Client programs can specify level 0 behavior for a buffer by
|
Client programs can specify level 0 behavior for a buffer by
|
||||||
setting its <literal>cluster_level</literal> to
|
setting its <literal>cluster_level</literal> to
|
||||||
|
@ -224,13 +220,13 @@
|
||||||
implement backward compatibility with the old HarfBuzz.
|
implement backward compatibility with the old HarfBuzz.
|
||||||
</para>
|
</para>
|
||||||
<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
|
clusters of marks and other modifier code points with the
|
||||||
preceding "base" code point's cluster. By preserving the
|
preceding "base" code point's cluster. By preserving the
|
||||||
separate cluster values of these marks and modifier code
|
separate cluster values of these marks and modifier code
|
||||||
points, script shapers can perform additional operations
|
points, script shapers can perform additional operations
|
||||||
that might lead to improved results (for example, coloring
|
that might lead to improved results (for example, reordering
|
||||||
mark glyphs differently than their base).
|
a sequence of marks).
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Client programs can specify level 1 behavior for a buffer by
|
Client programs can specify level 1 behavior for a buffer by
|
||||||
|
@ -246,7 +242,7 @@
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
This difference can be seen most clearly when HarfBuzz processes
|
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
|
and level 1, ligatures and glyph decomposition both involve
|
||||||
merging clusters; in level 2, neither of these operations
|
merging clusters; in level 2, neither of these operations
|
||||||
triggers a merge.
|
triggers a merge.
|
||||||
|
@ -263,7 +259,7 @@
|
||||||
assign initial cluster values in a buffer by reusing the indices
|
assign initial cluster values in a buffer by reusing the indices
|
||||||
of the code points in the input text. This gives a sequence of
|
of the code points in the input text. This gives a sequence of
|
||||||
cluster values that is monotonically increasing (for example,
|
cluster values that is monotonically increasing (for example,
|
||||||
0,1,2,3,4).
|
0,1,2,3,4).
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
It is not <emphasis>required</emphasis> that the cluster values
|
It is not <emphasis>required</emphasis> that the cluster values
|
||||||
|
@ -318,7 +314,7 @@
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="a-clustering-example-for-levels-0-and-1">
|
<section id="a-clustering-example-for-levels-0-and-1">
|
||||||
<title>A clustering example for levels 0 and 1</title>
|
<title>A clustering example for levels 0 and 1</title>
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
shaping. The typeface must be set to a specific point size in
|
shaping. The typeface must be set to a specific point size in
|
||||||
order for some details (such as hinting) to work. In addition,
|
order for some details (such as hinting) to work. In addition,
|
||||||
if the font file in question is an OpenType Variable Font, then
|
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.
|
named instance) in order to get the output you need.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
|
@ -256,18 +256,6 @@
|
||||||
<para>
|
<para>
|
||||||
<function>hb_font_get_glyph_from_name_func_t</function>: returns
|
<function>hb_font_get_glyph_from_name_func_t</function>: returns
|
||||||
the glyph index that corresponds to a given glyph name.
|
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>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
@ -387,6 +375,20 @@
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</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">
|
<section id="fonts-and-faces-variable">
|
||||||
<title>Working with OpenType Variable Fonts</title>
|
<title>Working with OpenType Variable Fonts</title>
|
||||||
<para>
|
<para>
|
||||||
|
@ -453,66 +455,13 @@
|
||||||
range actually implemented in the font's variation axis. After
|
range actually implemented in the font's variation axis. After
|
||||||
all, a font might only provide lighter-than-regular weights, and
|
all, a font might only provide lighter-than-regular weights, and
|
||||||
setting a heavier value on the <literal>wght</literal> axis will
|
setting a heavier value on the <literal>wght</literal> axis will
|
||||||
not change that.
|
not change that.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Once your variation settings are specified on your font object,
|
Once your variation settings are specified on your font object,
|
||||||
however, shaping with a variable font is just like shaping a
|
however, shaping with a variable font is just like shaping a
|
||||||
static font.
|
static font.
|
||||||
</para>
|
</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>
|
</section>
|
||||||
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -174,9 +174,7 @@
|
||||||
<para>
|
<para>
|
||||||
HarfBuzz provides integration points with FreeType at the
|
HarfBuzz provides integration points with FreeType at the
|
||||||
face-object and font-object level and for the font-functions
|
face-object and font-object level and for the font-functions
|
||||||
virtual-method structure of a font object. These functions
|
virtual-method structure of a font object. To use the
|
||||||
make it easy for clients that use FreeType for rasterization
|
|
||||||
or font-loading, to use HarfBuzz for shaping. To use the
|
|
||||||
FreeType-integration API, include the
|
FreeType-integration API, include the
|
||||||
<filename>hb-ft.h</filename> header.
|
<filename>hb-ft.h</filename> header.
|
||||||
</para>
|
</para>
|
||||||
|
@ -310,49 +308,7 @@
|
||||||
it when it is unneeded.
|
it when it is unneeded.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</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">
|
<section id="integration-uniscribe">
|
||||||
<title>Uniscribe integration</title>
|
<title>Uniscribe integration</title>
|
||||||
<para>
|
<para>
|
||||||
|
|
119
meson.build
119
meson.build
|
@ -1,9 +1,8 @@
|
||||||
project('harfbuzz', 'c', 'cpp',
|
project('harfbuzz', 'c', 'cpp',
|
||||||
meson_version: '>= 0.55.0',
|
meson_version: '>= 0.55.0',
|
||||||
version: '7.1.0',
|
version: '5.2.0',
|
||||||
default_options: [
|
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-exceptions also anyway
|
||||||
'cpp_rtti=false', # Just to support msvc, we are passing -fno-rtti also anyway
|
|
||||||
'cpp_std=c++11',
|
'cpp_std=c++11',
|
||||||
'wrap_mode=nofallback', # Use --wrap-mode=default to revert, https://github.com/harfbuzz/harfbuzz/pull/2548
|
'wrap_mode=nofallback', # Use --wrap-mode=default to revert, https://github.com/harfbuzz/harfbuzz/pull/2548
|
||||||
],
|
],
|
||||||
|
@ -15,7 +14,7 @@ hb_version_minor = hb_version_arr[1].to_int()
|
||||||
hb_version_micro = hb_version_arr[2].to_int()
|
hb_version_micro = hb_version_arr[2].to_int()
|
||||||
|
|
||||||
# libtool versioning
|
# 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)
|
hb_libtool_version_info = '@0@:0:@0@'.format(hb_version_int)
|
||||||
|
|
||||||
pkgmod = import('pkgconfig')
|
pkgmod = import('pkgconfig')
|
||||||
|
@ -28,12 +27,17 @@ if cpp.get_argument_syntax() == 'msvc'
|
||||||
# If a warning is harmless but hard to fix, use '/woXXXX' so it's shown once
|
# 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
|
# NOTE: Only add warnings here if you are sure they're spurious
|
||||||
msvc_args = [
|
msvc_args = [
|
||||||
|
'/wd4018', # implicit signed/unsigned conversion
|
||||||
|
'/wd4146', # unary minus on unsigned (beware INT_MIN)
|
||||||
'/wd4244', # lossy type conversion (e.g. double -> int)
|
'/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
|
cpp.get_supported_arguments(['/utf-8']), # set the input encoding to utf-8
|
||||||
]
|
]
|
||||||
add_project_arguments(msvc_args, language: ['c', 'cpp'])
|
add_project_arguments(msvc_args, language: ['c', 'cpp'])
|
||||||
# Disable SAFESEH with MSVC for libs that use external deps that are built with MinGW
|
# Disable SAFESEH with MSVC for libs that use external deps that are built with MinGW
|
||||||
# noseh_link_args = ['/SAFESEH:NO']
|
# noseh_link_args = ['/SAFESEH:NO']
|
||||||
|
# disable exception handling
|
||||||
|
add_project_arguments(['/EHs-', '/EHc-'], language: 'cpp')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
add_project_link_arguments(cpp.get_supported_link_arguments([
|
add_project_link_arguments(cpp.get_supported_link_arguments([
|
||||||
|
@ -79,35 +83,20 @@ check_funcs = [
|
||||||
|
|
||||||
m_dep = cpp.find_library('m', required: false)
|
m_dep = cpp.find_library('m', required: false)
|
||||||
|
|
||||||
if meson.version().version_compare('>=0.60.0')
|
|
||||||
# pkg-config: freetype2, cmake: Freetype
|
# Try pkgconfig name
|
||||||
freetype_dep = dependency('freetype2', 'Freetype',
|
freetype_dep = dependency('freetype2', required: false)
|
||||||
|
if not freetype_dep.found()
|
||||||
|
# Try cmake name
|
||||||
|
freetype_dep = dependency('freetype', required: false)
|
||||||
|
endif
|
||||||
|
if not freetype_dep.found()
|
||||||
|
# Subproject fallback, `allow_fallback: true` means the fallback will be
|
||||||
|
# tried even if the freetype option is set to `auto`.
|
||||||
|
freetype_dep = dependency('freetype2',
|
||||||
required: get_option('freetype'),
|
required: get_option('freetype'),
|
||||||
default_options: ['harfbuzz=disabled'],
|
default_options: ['harfbuzz=disabled'],
|
||||||
allow_fallback: true)
|
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
|
|
||||||
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
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
glib_dep = dependency('glib-2.0', required: get_option('glib'))
|
glib_dep = dependency('glib-2.0', required: get_option('glib'))
|
||||||
|
@ -115,36 +104,18 @@ gobject_dep = dependency('gobject-2.0', required: get_option('gobject'))
|
||||||
graphite2_dep = dependency('graphite2', required: get_option('graphite2'))
|
graphite2_dep = dependency('graphite2', required: get_option('graphite2'))
|
||||||
graphite_dep = dependency('graphite2', required: get_option('graphite'))
|
graphite_dep = dependency('graphite2', required: get_option('graphite'))
|
||||||
|
|
||||||
if meson.version().version_compare('>=0.60.0')
|
# Try pkgconfig name
|
||||||
# pkg-config: icu-uc, cmake: ICU but with components
|
icu_dep = dependency('icu-uc', required: false)
|
||||||
icu_dep = dependency('icu-uc', 'ICU',
|
if not icu_dep.found()
|
||||||
components: 'uc',
|
# Try cmake name
|
||||||
required: get_option('icu'),
|
icu_dep = dependency('ICU',
|
||||||
default_options: ['harfbuzz=disabled'],
|
required: false,
|
||||||
allow_fallback: true)
|
components: 'uc',
|
||||||
else
|
method: 'cmake')
|
||||||
# painful hack to handle multiple dependencies but also respect options
|
endif
|
||||||
icu_opt = get_option('icu')
|
if not icu_dep.found()
|
||||||
# we want to handle enabled manually after fallbacks, but also handle disabled normally
|
# Subproject fallback if icu option is enabled
|
||||||
if icu_opt.enabled()
|
icu_dep = dependency('icu-uc', required: get_option('icu'))
|
||||||
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'))
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if icu_dep.found() and icu_dep.type_name() == 'pkgconfig'
|
if icu_dep.found() and icu_dep.type_name() == 'pkgconfig'
|
||||||
|
@ -177,8 +148,7 @@ if not get_option('cairo').disabled()
|
||||||
# harfbuzz support disabled, so when cairo will lookup freetype2 dependency
|
# harfbuzz support disabled, so when cairo will lookup freetype2 dependency
|
||||||
# it will be forced to use that one.
|
# it will be forced to use that one.
|
||||||
cairo_dep = dependency('cairo', required: get_option('cairo'))
|
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: get_option('cairo'))
|
||||||
cairo_ft_dep = dependency('cairo-ft', required: cairo_ft_required)
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -205,19 +175,10 @@ endif
|
||||||
|
|
||||||
if cairo_dep.found()
|
if cairo_dep.found()
|
||||||
conf.set('HAVE_CAIRO', 1)
|
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'
|
if cairo_dep.type_name() == 'internal'
|
||||||
foreach func: check_cairo_funcs
|
conf.set('HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC', 1)
|
||||||
name = func[0]
|
|
||||||
conf.set('HAVE_@0@'.format(name.to_upper()), 1)
|
|
||||||
endforeach
|
|
||||||
else
|
else
|
||||||
check_funcs += check_cairo_funcs
|
check_funcs += [['cairo_user_font_face_set_render_color_glyph_func', {'deps': cairo_dep}]]
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -373,10 +334,7 @@ foreach check : check_funcs
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
subdir('src')
|
subdir('src')
|
||||||
|
subdir('util')
|
||||||
if not get_option('utilities').disabled()
|
|
||||||
subdir('util')
|
|
||||||
endif
|
|
||||||
|
|
||||||
if not get_option('tests').disabled()
|
if not get_option('tests').disabled()
|
||||||
subdir('test')
|
subdir('test')
|
||||||
|
@ -392,9 +350,6 @@ endif
|
||||||
|
|
||||||
configure_file(output: 'config.h', configuration: conf)
|
configure_file(output: 'config.h', configuration: conf)
|
||||||
|
|
||||||
alias_target('lib', libharfbuzz)
|
|
||||||
alias_target('libs', libharfbuzz, libharfbuzz_subset)
|
|
||||||
|
|
||||||
build_summary = {
|
build_summary = {
|
||||||
'Directories':
|
'Directories':
|
||||||
{'prefix': get_option('prefix'),
|
{'prefix': get_option('prefix'),
|
||||||
|
@ -409,8 +364,7 @@ build_summary = {
|
||||||
'ICU': conf.get('HAVE_ICU', 0) == 1,
|
'ICU': conf.get('HAVE_ICU', 0) == 1,
|
||||||
},
|
},
|
||||||
'Font callbacks (the more the merrier)':
|
'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':
|
'Dependencies used for command-line utilities':
|
||||||
{'Cairo': conf.get('HAVE_CAIRO', 0) == 1,
|
{'Cairo': conf.get('HAVE_CAIRO', 0) == 1,
|
||||||
|
@ -427,7 +381,6 @@ build_summary = {
|
||||||
'Other features':
|
'Other features':
|
||||||
{'Documentation': conf.get('HAVE_GTK_DOC', 0) == 1,
|
{'Documentation': conf.get('HAVE_GTK_DOC', 0) == 1,
|
||||||
'GObject bindings': conf.get('HAVE_GOBJECT', 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,
|
'Introspection': conf.get('HAVE_INTROSPECTION', 0) == 1,
|
||||||
'Experimental APIs': conf.get('HB_EXPERIMENTAL_API', 0) == 1,
|
'Experimental APIs': conf.get('HB_EXPERIMENTAL_API', 0) == 1,
|
||||||
},
|
},
|
||||||
|
|
|
@ -29,10 +29,6 @@ option('introspection', type: 'feature', value: 'auto', yield: true,
|
||||||
description: 'Generate gobject-introspection bindings (.gir/.typelib files)')
|
description: 'Generate gobject-introspection bindings (.gir/.typelib files)')
|
||||||
option('docs', type: 'feature', value: 'auto', yield: true,
|
option('docs', type: 'feature', value: 'auto', yield: true,
|
||||||
description: 'Generate documentation with gtk-doc')
|
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',
|
option('benchmark', type: 'feature', value: 'disabled',
|
||||||
description: 'Enable benchmark tests')
|
description: 'Enable benchmark tests')
|
||||||
|
|
|
@ -163,7 +163,7 @@ static void BM_Font (benchmark::State &state,
|
||||||
hb_draw_funcs_t *draw_funcs = _draw_funcs_create ();
|
hb_draw_funcs_t *draw_funcs = _draw_funcs_create ();
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
for (unsigned gid = 0; gid < num_glyphs; ++gid)
|
for (unsigned gid = 0; gid < num_glyphs; ++gid)
|
||||||
hb_font_draw_glyph (font, gid, draw_funcs, nullptr);
|
hb_font_get_glyph_shape (font, gid, draw_funcs, nullptr);
|
||||||
break;
|
break;
|
||||||
hb_draw_funcs_destroy (draw_funcs);
|
hb_draw_funcs_destroy (draw_funcs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,18 +27,10 @@ struct test_input_t
|
||||||
"perf/texts/fa-thelittleprince.txt",
|
"perf/texts/fa-thelittleprince.txt",
|
||||||
false},
|
false},
|
||||||
|
|
||||||
{"perf/fonts/NotoNastaliqUrdu-Regular.ttf",
|
|
||||||
"perf/texts/fa-words.txt",
|
|
||||||
false},
|
|
||||||
|
|
||||||
{"perf/fonts/Amiri-Regular.ttf",
|
{"perf/fonts/Amiri-Regular.ttf",
|
||||||
"perf/texts/fa-thelittleprince.txt",
|
"perf/texts/fa-thelittleprince.txt",
|
||||||
false},
|
false},
|
||||||
|
|
||||||
{SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf",
|
|
||||||
"perf/texts/hi-words.txt",
|
|
||||||
false},
|
|
||||||
|
|
||||||
{"perf/fonts/Roboto-Regular.ttf",
|
{"perf/fonts/Roboto-Regular.ttf",
|
||||||
"perf/texts/en-thelittleprince.txt",
|
"perf/texts/en-thelittleprince.txt",
|
||||||
false},
|
false},
|
||||||
|
|
|
@ -54,19 +54,18 @@ static inline unsigned int ARRAY_LEN (const Type (&)[n]) { return n; }
|
||||||
struct test_input_t
|
struct test_input_t
|
||||||
{
|
{
|
||||||
const char *font_path;
|
const char *font_path;
|
||||||
unsigned max_subset_size;
|
const unsigned max_subset_size;
|
||||||
const axis_location_t *instance_opts;
|
const axis_location_t *instance_opts;
|
||||||
unsigned num_instance_opts;
|
const unsigned num_instance_opts;
|
||||||
} default_tests[] =
|
} tests[] =
|
||||||
{
|
{
|
||||||
{SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf", 1000, nullptr, 0},
|
{SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf", 4000, nullptr, 0},
|
||||||
{SUBSET_FONT_BASE_PATH "Amiri-Regular.ttf", 4096, nullptr, 0},
|
{SUBSET_FONT_BASE_PATH "Amiri-Regular.ttf", 4000, nullptr, 0},
|
||||||
{SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf", 1400, nullptr, 0},
|
{SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf", 1000, nullptr, 0},
|
||||||
{SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf", 1000, 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 "Mplus1p-Regular.ttf", 10000, nullptr, 0},
|
||||||
{SUBSET_FONT_BASE_PATH "SourceHanSans-Regular_subset.otf", 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 "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 "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)},
|
{SUBSET_FONT_BASE_PATH "RobotoFlex-Variable.ttf", 900, _roboto_flex_instance_opts, ARRAY_LEN (_roboto_flex_instance_opts)},
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -74,10 +73,6 @@ struct test_input_t
|
||||||
#endif
|
#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,
|
void AddCodepoints(const hb_set_t* codepoints_in_font,
|
||||||
unsigned subset_size,
|
unsigned subset_size,
|
||||||
hb_subset_input_t* input)
|
hb_subset_input_t* input)
|
||||||
|
@ -102,52 +97,24 @@ void AddGlyphs(unsigned num_glyphs_in_font,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 */
|
/* benchmark for subsetting a font */
|
||||||
static void BM_subset (benchmark::State &state,
|
static void BM_subset (benchmark::State &state,
|
||||||
operation_t operation,
|
operation_t operation,
|
||||||
const test_input_t &test_input,
|
const test_input_t &test_input)
|
||||||
bool hinting)
|
|
||||||
{
|
{
|
||||||
unsigned subset_size = state.range(0);
|
unsigned subset_size = state.range(0);
|
||||||
|
|
||||||
hb_face_t *face = nullptr;
|
hb_face_t *face;
|
||||||
|
|
||||||
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);
|
hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
|
||||||
assert (blob);
|
assert (blob);
|
||||||
face = hb_face_create (blob, 0);
|
face = hb_face_create (blob, 0);
|
||||||
hb_blob_destroy (blob);
|
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 ();
|
hb_subset_input_t* input = hb_subset_input_create_or_fail ();
|
||||||
assert (input);
|
assert (input);
|
||||||
|
|
||||||
if (!hinting)
|
|
||||||
hb_subset_input_set_flags (input, HB_SUBSET_FLAGS_NO_HINTING);
|
|
||||||
|
|
||||||
switch (operation)
|
switch (operation)
|
||||||
{
|
{
|
||||||
case subset_codepoints:
|
case subset_codepoints:
|
||||||
|
@ -167,6 +134,7 @@ static void BM_subset (benchmark::State &state,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case instance:
|
case instance:
|
||||||
|
#ifdef HB_EXPERIMENTAL_API
|
||||||
{
|
{
|
||||||
hb_set_t* all_codepoints = hb_set_create ();
|
hb_set_t* all_codepoints = hb_set_create ();
|
||||||
hb_face_collect_unicodes (face, all_codepoints);
|
hb_face_collect_unicodes (face, all_codepoints);
|
||||||
|
@ -178,6 +146,7 @@ static void BM_subset (benchmark::State &state,
|
||||||
test_input.instance_opts[i].axis_tag,
|
test_input.instance_opts[i].axis_tag,
|
||||||
test_input.instance_opts[i].axis_value);
|
test_input.instance_opts[i].axis_value);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +163,6 @@ static void BM_subset (benchmark::State &state,
|
||||||
|
|
||||||
static void test_subset (operation_t op,
|
static void test_subset (operation_t op,
|
||||||
const char *op_name,
|
const char *op_name,
|
||||||
bool hinting,
|
|
||||||
benchmark::TimeUnit time_unit,
|
benchmark::TimeUnit time_unit,
|
||||||
const test_input_t &test_input)
|
const test_input_t &test_input)
|
||||||
{
|
{
|
||||||
|
@ -203,57 +171,36 @@ static void test_subset (operation_t op,
|
||||||
|
|
||||||
char name[1024] = "BM_subset/";
|
char name[1024] = "BM_subset/";
|
||||||
strcat (name, op_name);
|
strcat (name, op_name);
|
||||||
strcat (name, "/");
|
strcat (name, strrchr (test_input.font_path, '/'));
|
||||||
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)
|
benchmark::RegisterBenchmark (name, BM_subset, op, test_input)
|
||||||
->Range(10, test_input.max_subset_size)
|
->Range(10, test_input.max_subset_size)
|
||||||
->Unit(time_unit);
|
->Unit(time_unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_operation (operation_t op,
|
static void test_operation (operation_t op,
|
||||||
const char *op_name,
|
const char *op_name,
|
||||||
const test_input_t *tests,
|
|
||||||
unsigned num_tests,
|
|
||||||
benchmark::TimeUnit time_unit)
|
benchmark::TimeUnit time_unit)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < num_tests; i++)
|
for (auto& test_input : tests)
|
||||||
{
|
{
|
||||||
auto& test_input = tests[i];
|
test_subset (op, op_name, time_unit, test_input);
|
||||||
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)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
benchmark::Initialize(&argc, argv);
|
#define TEST_OPERATION(op, time_unit) test_operation (op, #op, time_unit)
|
||||||
|
|
||||||
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_glyphs, benchmark::kMillisecond);
|
||||||
TEST_OPERATION (subset_codepoints, benchmark::kMillisecond);
|
TEST_OPERATION (subset_codepoints, benchmark::kMillisecond);
|
||||||
|
#ifdef HB_EXPERIMENTAL_API
|
||||||
TEST_OPERATION (instance, benchmark::kMillisecond);
|
TEST_OPERATION (instance, benchmark::kMillisecond);
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef TEST_OPERATION
|
#undef TEST_OPERATION
|
||||||
|
|
||||||
|
benchmark::Initialize(&argc, argv);
|
||||||
benchmark::RunSpecifiedBenchmarks();
|
benchmark::RunSpecifiedBenchmarks();
|
||||||
benchmark::Shutdown();
|
benchmark::Shutdown();
|
||||||
|
|
||||||
if (tests != default_tests)
|
|
||||||
free (tests);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
10000
perf/texts/fa-words.txt
10000
perf/texts/fa-words.txt
File diff suppressed because it is too large
Load Diff
10000
perf/texts/hi-words.txt
10000
perf/texts/hi-words.txt
File diff suppressed because it is too large
Load Diff
|
@ -47,9 +47,6 @@ HBLIBS += $(GLIB_LIBS)
|
||||||
HBDEPS += $(GLIB_DEPS)
|
HBDEPS += $(GLIB_DEPS)
|
||||||
HBSOURCES += $(HB_GLIB_sources)
|
HBSOURCES += $(HB_GLIB_sources)
|
||||||
HBHEADERS += $(HB_GLIB_headers)
|
HBHEADERS += $(HB_GLIB_headers)
|
||||||
HB_HAS_GLIB_DEF = define HB_HAS_GLIB 1
|
|
||||||
else
|
|
||||||
HB_HAS_GLIB_DEF = undef HB_HAS_GLIB
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_FREETYPE
|
if HAVE_FREETYPE
|
||||||
|
@ -58,9 +55,6 @@ HBLIBS += $(FREETYPE_LIBS)
|
||||||
HBDEPS += $(FREETYPE_DEPS)
|
HBDEPS += $(FREETYPE_DEPS)
|
||||||
HBSOURCES += $(HB_FT_sources)
|
HBSOURCES += $(HB_FT_sources)
|
||||||
HBHEADERS += $(HB_FT_headers)
|
HBHEADERS += $(HB_FT_headers)
|
||||||
HB_HAS_FREETYPE_DEF = define HB_HAS_FREETYPE 1
|
|
||||||
else
|
|
||||||
HB_HAS_FREETYPE_DEF = undef HB_HAS_FREETYPE
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_GRAPHITE2
|
if HAVE_GRAPHITE2
|
||||||
|
@ -69,9 +63,6 @@ HBLIBS += $(GRAPHITE2_LIBS)
|
||||||
HBDEPS += $(GRAPHITE2_DEPS)
|
HBDEPS += $(GRAPHITE2_DEPS)
|
||||||
HBSOURCES += $(HB_GRAPHITE2_sources)
|
HBSOURCES += $(HB_GRAPHITE2_sources)
|
||||||
HBHEADERS += $(HB_GRAPHITE2_headers)
|
HBHEADERS += $(HB_GRAPHITE2_headers)
|
||||||
HB_HAS_GRAPHITE_DEF = define HB_HAS_GRAPHITE 1
|
|
||||||
else
|
|
||||||
HB_HAS_GRAPHITE_DEF = undef HB_HAS_GRAPHITE
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_UNISCRIBE
|
if HAVE_UNISCRIBE
|
||||||
|
@ -79,9 +70,6 @@ HBCFLAGS += $(UNISCRIBE_CFLAGS)
|
||||||
HBNONPCLIBS += $(UNISCRIBE_LIBS)
|
HBNONPCLIBS += $(UNISCRIBE_LIBS)
|
||||||
HBSOURCES += $(HB_UNISCRIBE_sources)
|
HBSOURCES += $(HB_UNISCRIBE_sources)
|
||||||
HBHEADERS += $(HB_UNISCRIBE_headers)
|
HBHEADERS += $(HB_UNISCRIBE_headers)
|
||||||
HB_HAS_UNISCRIBE_DEF = define HB_HAS_UNISCRIBE 1
|
|
||||||
else
|
|
||||||
HB_HAS_UNISCRIBE_DEF = undef HB_HAS_UNISCRIBE
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_DIRECTWRITE
|
if HAVE_DIRECTWRITE
|
||||||
|
@ -89,9 +77,6 @@ HBCFLAGS += $(DIRECTWRITE_CXXFLAGS)
|
||||||
HBNONPCLIBS += $(DIRECTWRITE_LIBS)
|
HBNONPCLIBS += $(DIRECTWRITE_LIBS)
|
||||||
HBSOURCES += $(HB_DIRECTWRITE_sources)
|
HBSOURCES += $(HB_DIRECTWRITE_sources)
|
||||||
HBHEADERS += $(HB_DIRECTWRITE_headers)
|
HBHEADERS += $(HB_DIRECTWRITE_headers)
|
||||||
HB_HAS_DIRECTWRITE_DEF = define HB_HAS_DIRECTWRITE 1
|
|
||||||
else
|
|
||||||
HB_HAS_DIRECTWRITE_DEF = undef HB_HAS_DIRECTWRITE
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_GDI
|
if HAVE_GDI
|
||||||
|
@ -99,9 +84,6 @@ HBCFLAGS += $(GDI_CXXFLAGS)
|
||||||
HBNONPCLIBS += $(GDI_LIBS)
|
HBNONPCLIBS += $(GDI_LIBS)
|
||||||
HBSOURCES += $(HB_GDI_sources)
|
HBSOURCES += $(HB_GDI_sources)
|
||||||
HBHEADERS += $(HB_GDI_headers)
|
HBHEADERS += $(HB_GDI_headers)
|
||||||
HB_HAS_GDI_DEF = define HB_HAS_GDI 1
|
|
||||||
else
|
|
||||||
HB_HAS_GDI_DEF = undef HB_HAS_GDI
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_CORETEXT
|
if HAVE_CORETEXT
|
||||||
|
@ -109,9 +91,6 @@ HBCFLAGS += $(CORETEXT_CFLAGS)
|
||||||
HBNONPCLIBS += $(CORETEXT_LIBS)
|
HBNONPCLIBS += $(CORETEXT_LIBS)
|
||||||
HBSOURCES += $(HB_CORETEXT_sources)
|
HBSOURCES += $(HB_CORETEXT_sources)
|
||||||
HBHEADERS += $(HB_CORETEXT_headers)
|
HBHEADERS += $(HB_CORETEXT_headers)
|
||||||
HB_HAS_CORETEXT_DEF = define HB_HAS_CORETEXT 1
|
|
||||||
else
|
|
||||||
HB_HAS_CORETEXT_DEF = undef HB_HAS_CORETEXT
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,8 +114,6 @@ export_symbols = -export-symbols harfbuzz.def
|
||||||
harfbuzz_def_dependency = harfbuzz.def
|
harfbuzz_def_dependency = harfbuzz.def
|
||||||
export_symbols_subset = -export-symbols harfbuzz-subset.def
|
export_symbols_subset = -export-symbols harfbuzz-subset.def
|
||||||
harfbuzz_subset_def_dependency = 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
|
export_symbols_icu = -export-symbols harfbuzz-icu.def
|
||||||
harfbuzz_icu_def_dependency = harfbuzz-icu.def
|
harfbuzz_icu_def_dependency = harfbuzz-icu.def
|
||||||
export_symbols_gobject = -export-symbols harfbuzz-gobject.def
|
export_symbols_gobject = -export-symbols harfbuzz-gobject.def
|
||||||
|
@ -170,7 +147,7 @@ pkgconfigdir = $(libdir)/pkgconfig
|
||||||
pkgconfig_DATA = harfbuzz.pc
|
pkgconfig_DATA = harfbuzz.pc
|
||||||
cmakedir = $(libdir)/cmake/harfbuzz
|
cmakedir = $(libdir)/cmake/harfbuzz
|
||||||
cmake_DATA = harfbuzz-config.cmake
|
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
|
lib_LTLIBRARIES += libharfbuzz-subset.la
|
||||||
libharfbuzz_subset_la_LINK = $(chosen_linker) $(libharfbuzz_subset_la_LDFLAGS)
|
libharfbuzz_subset_la_LINK = $(chosen_linker) $(libharfbuzz_subset_la_LDFLAGS)
|
||||||
|
@ -195,24 +172,12 @@ harfbuzz-subset.cc: Makefile.sources
|
||||||
|| ($(RM) $(srcdir)/harfbuzz-subset.cc; false)
|
|| ($(RM) $(srcdir)/harfbuzz-subset.cc; false)
|
||||||
BUILT_SOURCES += harfbuzz-subset.cc
|
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
|
||||||
if HAVE_ICU_BUILTIN
|
if HAVE_ICU_BUILTIN
|
||||||
HBCFLAGS += $(ICU_CFLAGS)
|
HBCFLAGS += $(ICU_CFLAGS)
|
||||||
HBLIBS += $(ICU_LIBS)
|
HBLIBS += $(ICU_LIBS)
|
||||||
HBSOURCES += $(HB_ICU_sources)
|
HBSOURCES += $(HB_ICU_sources)
|
||||||
HBHEADERS += $(HB_ICU_headers)
|
HBHEADERS += $(HB_ICU_headers)
|
||||||
HB_HAS_ICU_DEF = define HB_HAS_ICU 1
|
|
||||||
else
|
else
|
||||||
lib_LTLIBRARIES += libharfbuzz-icu.la
|
lib_LTLIBRARIES += libharfbuzz-icu.la
|
||||||
libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
|
libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
|
||||||
|
@ -222,7 +187,6 @@ libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la
|
||||||
EXTRA_libharfbuzz_icu_la_DEPENDENCIES = $(harfbuzz_icu_def_dependency)
|
EXTRA_libharfbuzz_icu_la_DEPENDENCIES = $(harfbuzz_icu_def_dependency)
|
||||||
pkginclude_HEADERS += $(HB_ICU_headers)
|
pkginclude_HEADERS += $(HB_ICU_headers)
|
||||||
pkgconfig_DATA += harfbuzz-icu.pc
|
pkgconfig_DATA += harfbuzz-icu.pc
|
||||||
HB_HAS_ICU_DEF = undef HB_HAS_ICU
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
EXTRA_DIST += harfbuzz-icu.pc.in
|
EXTRA_DIST += harfbuzz-icu.pc.in
|
||||||
|
@ -254,9 +218,6 @@ hb-gobject-enums.%: hb-gobject-enums.%.tmpl $(HBHEADERS)
|
||||||
--template $^ | \
|
--template $^ | \
|
||||||
sed 's/_t_get_type/_get_type/g; s/_T (/ (/g' > "$@" \
|
sed 's/_t_get_type/_get_type/g; s/_T (/ (/g' > "$@" \
|
||||||
|| ($(RM) "$@"; false)
|
|| ($(RM) "$@"; false)
|
||||||
HB_HAS_GOBJECT_DEF = define HB_HAS_GOBJECT 1
|
|
||||||
else
|
|
||||||
HB_HAS_GOBJECT_DEF = undef HB_HAS_GOBJECT
|
|
||||||
endif
|
endif
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
harfbuzz-gobject.pc.in \
|
harfbuzz-gobject.pc.in \
|
||||||
|
@ -265,27 +226,6 @@ EXTRA_DIST += \
|
||||||
$(NULL)
|
$(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
|
%.pc: %.pc.in $(top_builddir)/config.status
|
||||||
$(AM_V_GEN) \
|
$(AM_V_GEN) \
|
||||||
$(SED) -e 's@%prefix%@$(prefix)@g' \
|
$(SED) -e 's@%prefix%@$(prefix)@g' \
|
||||||
|
@ -312,8 +252,6 @@ harfbuzz.def: $(HBHEADERS)
|
||||||
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
|
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
|
||||||
harfbuzz-subset.def: $(HB_SUBSET_headers)
|
harfbuzz-subset.def: $(HB_SUBSET_headers)
|
||||||
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
|
$(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)
|
harfbuzz-icu.def: $(HB_ICU_headers)
|
||||||
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
|
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
|
||||||
harfbuzz-gobject.def: $(HB_GOBJECT_headers)
|
harfbuzz-gobject.def: $(HB_GOBJECT_headers)
|
||||||
|
@ -382,7 +320,6 @@ noinst_PROGRAMS = \
|
||||||
test-ot-name \
|
test-ot-name \
|
||||||
test-ot-glyphname \
|
test-ot-glyphname \
|
||||||
test-gpos-size-params \
|
test-gpos-size-params \
|
||||||
test-gsub-get-alternates \
|
|
||||||
test-gsub-would-substitute \
|
test-gsub-would-substitute \
|
||||||
test-use-table \
|
test-use-table \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
@ -420,10 +357,6 @@ test_gpos_size_params_SOURCES = test-gpos-size-params.cc
|
||||||
test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
|
test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
|
||||||
test_gpos_size_params_LDADD = libharfbuzz.la $(HBLIBS)
|
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_SOURCES = test-gsub-would-substitute.cc
|
||||||
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
|
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
|
||||||
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
||||||
|
@ -435,7 +368,6 @@ COMPILED_TESTS = \
|
||||||
test-iter \
|
test-iter \
|
||||||
test-machinery \
|
test-machinery \
|
||||||
test-map \
|
test-map \
|
||||||
test-multimap \
|
|
||||||
test-number \
|
test-number \
|
||||||
test-ot-tag \
|
test-ot-tag \
|
||||||
test-priority-queue \
|
test-priority-queue \
|
||||||
|
@ -475,10 +407,6 @@ test_map_SOURCES = test-map.cc hb-static.cc
|
||||||
test_map_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
test_map_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||||
test_map_LDADD = $(COMPILED_TESTS_LDADD)
|
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_number_SOURCES = test-number.cc hb-number.cc
|
test_number_SOURCES = test-number.cc hb-number.cc
|
||||||
test_number_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
test_number_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||||
test_number_LDADD = $(COMPILED_TESTS_LDADD)
|
test_number_LDADD = $(COMPILED_TESTS_LDADD)
|
||||||
|
|
|
@ -42,19 +42,16 @@ HB_BASE_sources = \
|
||||||
hb-draw.hh \
|
hb-draw.hh \
|
||||||
hb-face.cc \
|
hb-face.cc \
|
||||||
hb-face.hh \
|
hb-face.hh \
|
||||||
hb-face-builder.cc \
|
|
||||||
hb-fallback-shape.cc \
|
hb-fallback-shape.cc \
|
||||||
hb-font.cc \
|
hb-font.cc \
|
||||||
hb-font.hh \
|
hb-font.hh \
|
||||||
hb-iter.hh \
|
hb-iter.hh \
|
||||||
hb-kern.hh \
|
hb-kern.hh \
|
||||||
hb-limits.hh \
|
|
||||||
hb-machinery.hh \
|
hb-machinery.hh \
|
||||||
hb-map.cc \
|
hb-map.cc \
|
||||||
hb-map.hh \
|
hb-map.hh \
|
||||||
hb-meta.hh \
|
hb-meta.hh \
|
||||||
hb-ms-feature-ranges.hh \
|
hb-ms-feature-ranges.hh \
|
||||||
hb-multimap.hh \
|
|
||||||
hb-mutex.hh \
|
hb-mutex.hh \
|
||||||
hb-null.hh \
|
hb-null.hh \
|
||||||
hb-number.cc \
|
hb-number.cc \
|
||||||
|
@ -69,6 +66,11 @@ HB_BASE_sources = \
|
||||||
hb-ot-cff2-table.cc \
|
hb-ot-cff2-table.cc \
|
||||||
hb-ot-cff2-table.hh \
|
hb-ot-cff2-table.hh \
|
||||||
hb-ot-cmap-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-color.cc \
|
||||||
hb-ot-face-table-list.hh \
|
hb-ot-face-table-list.hh \
|
||||||
hb-ot-face.cc \
|
hb-ot-face.cc \
|
||||||
|
@ -85,18 +87,7 @@ HB_BASE_sources = \
|
||||||
hb-ot-layout-common.hh \
|
hb-ot-layout-common.hh \
|
||||||
hb-ot-layout-gdef-table.hh \
|
hb-ot-layout-gdef-table.hh \
|
||||||
hb-ot-layout-gpos-table.hh \
|
hb-ot-layout-gpos-table.hh \
|
||||||
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 \
|
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.hh \
|
||||||
OT/glyf/glyf-helpers.hh \
|
OT/glyf/glyf-helpers.hh \
|
||||||
OT/glyf/loca.hh \
|
OT/glyf/loca.hh \
|
||||||
|
@ -104,17 +95,13 @@ HB_BASE_sources = \
|
||||||
OT/glyf/Glyph.hh \
|
OT/glyf/Glyph.hh \
|
||||||
OT/glyf/GlyphHeader.hh \
|
OT/glyf/GlyphHeader.hh \
|
||||||
OT/glyf/SimpleGlyph.hh \
|
OT/glyf/SimpleGlyph.hh \
|
||||||
OT/glyf/coord-setter.hh \
|
|
||||||
OT/glyf/composite-iter.hh \
|
|
||||||
OT/glyf/CompositeGlyph.hh \
|
OT/glyf/CompositeGlyph.hh \
|
||||||
OT/glyf/VarCompositeGlyph.hh \
|
|
||||||
OT/glyf/SubsetGlyph.hh \
|
OT/glyf/SubsetGlyph.hh \
|
||||||
OT/Layout/types.hh \
|
OT/Layout/types.hh \
|
||||||
OT/Layout/Common/Coverage.hh \
|
OT/Layout/Common/Coverage.hh \
|
||||||
OT/Layout/Common/CoverageFormat1.hh \
|
OT/Layout/Common/CoverageFormat1.hh \
|
||||||
OT/Layout/Common/CoverageFormat2.hh \
|
OT/Layout/Common/CoverageFormat2.hh \
|
||||||
OT/Layout/Common/RangeRecord.hh \
|
OT/Layout/Common/RangeRecord.hh \
|
||||||
OT/Layout/GDEF/GDEF.hh \
|
|
||||||
OT/Layout/GPOS/AnchorFormat1.hh \
|
OT/Layout/GPOS/AnchorFormat1.hh \
|
||||||
OT/Layout/GPOS/AnchorFormat2.hh \
|
OT/Layout/GPOS/AnchorFormat2.hh \
|
||||||
OT/Layout/GPOS/AnchorFormat3.hh \
|
OT/Layout/GPOS/AnchorFormat3.hh \
|
||||||
|
@ -169,7 +156,6 @@ HB_BASE_sources = \
|
||||||
OT/Layout/GSUB/SingleSubst.hh \
|
OT/Layout/GSUB/SingleSubst.hh \
|
||||||
OT/Layout/GSUB/SubstLookup.hh \
|
OT/Layout/GSUB/SubstLookup.hh \
|
||||||
OT/Layout/GSUB/SubstLookupSubTable.hh \
|
OT/Layout/GSUB/SubstLookupSubTable.hh \
|
||||||
OT/name/name.hh \
|
|
||||||
hb-ot-layout-gsubgpos.hh \
|
hb-ot-layout-gsubgpos.hh \
|
||||||
hb-ot-layout-jstf-table.hh \
|
hb-ot-layout-jstf-table.hh \
|
||||||
hb-ot-layout.cc \
|
hb-ot-layout.cc \
|
||||||
|
@ -225,7 +211,6 @@ HB_BASE_sources = \
|
||||||
hb-ot-tag.cc \
|
hb-ot-tag.cc \
|
||||||
hb-ot-var-avar-table.hh \
|
hb-ot-var-avar-table.hh \
|
||||||
hb-ot-var-common.hh \
|
hb-ot-var-common.hh \
|
||||||
hb-ot-var-cvar-table.hh \
|
|
||||||
hb-ot-var-fvar-table.hh \
|
hb-ot-var-fvar-table.hh \
|
||||||
hb-ot-var-gvar-table.hh \
|
hb-ot-var-gvar-table.hh \
|
||||||
hb-ot-var-hvar-table.hh \
|
hb-ot-var-hvar-table.hh \
|
||||||
|
@ -261,8 +246,7 @@ HB_BASE_sources = \
|
||||||
|
|
||||||
HB_BASE_RAGEL_GENERATED_sources = \
|
HB_BASE_RAGEL_GENERATED_sources = \
|
||||||
hb-buffer-deserialize-json.hh \
|
hb-buffer-deserialize-json.hh \
|
||||||
hb-buffer-deserialize-text-glyphs.hh \
|
hb-buffer-deserialize-text.hh \
|
||||||
hb-buffer-deserialize-text-unicode.hh \
|
|
||||||
hb-number-parser.hh \
|
hb-number-parser.hh \
|
||||||
hb-ot-shaper-indic-machine.hh \
|
hb-ot-shaper-indic-machine.hh \
|
||||||
hb-ot-shaper-khmer-machine.hh \
|
hb-ot-shaper-khmer-machine.hh \
|
||||||
|
@ -271,8 +255,7 @@ HB_BASE_RAGEL_GENERATED_sources = \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
HB_BASE_RAGEL_sources = \
|
HB_BASE_RAGEL_sources = \
|
||||||
hb-buffer-deserialize-json.rl \
|
hb-buffer-deserialize-json.rl \
|
||||||
hb-buffer-deserialize-text-glyphs.rl \
|
hb-buffer-deserialize-text.rl \
|
||||||
hb-buffer-deserialize-text-unicode.rl \
|
|
||||||
hb-number-parser.rl \
|
hb-number-parser.rl \
|
||||||
hb-ot-shaper-indic-machine.rl \
|
hb-ot-shaper-indic-machine.rl \
|
||||||
hb-ot-shaper-khmer-machine.rl \
|
hb-ot-shaper-khmer-machine.rl \
|
||||||
|
@ -303,7 +286,6 @@ HB_BASE_headers = \
|
||||||
hb-ot-shape.h \
|
hb-ot-shape.h \
|
||||||
hb-ot-var.h \
|
hb-ot-var.h \
|
||||||
hb-ot.h \
|
hb-ot.h \
|
||||||
hb-paint.h \
|
|
||||||
hb-set.h \
|
hb-set.h \
|
||||||
hb-shape-plan.h \
|
hb-shape-plan.h \
|
||||||
hb-shape.h \
|
hb-shape.h \
|
||||||
|
@ -315,7 +297,7 @@ HB_BASE_headers = \
|
||||||
|
|
||||||
# Optional Sources and Headers with external deps
|
# 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_FT_headers = hb-ft.h
|
||||||
|
|
||||||
HB_GLIB_sources = hb-glib.cc
|
HB_GLIB_sources = hb-glib.cc
|
||||||
|
@ -348,6 +330,7 @@ HB_SUBSET_sources = \
|
||||||
hb-number.hh \
|
hb-number.hh \
|
||||||
hb-ot-cff1-table.cc \
|
hb-ot-cff1-table.cc \
|
||||||
hb-ot-cff2-table.cc \
|
hb-ot-cff2-table.cc \
|
||||||
|
hb-ot-color-colrv1-closure.hh \
|
||||||
hb-ot-post-table-v2subset.hh \
|
hb-ot-post-table-v2subset.hh \
|
||||||
hb-static.cc \
|
hb-static.cc \
|
||||||
hb-subset-cff-common.cc \
|
hb-subset-cff-common.cc \
|
||||||
|
@ -358,8 +341,6 @@ HB_SUBSET_sources = \
|
||||||
hb-subset-cff2.hh \
|
hb-subset-cff2.hh \
|
||||||
hb-subset-input.cc \
|
hb-subset-input.cc \
|
||||||
hb-subset-input.hh \
|
hb-subset-input.hh \
|
||||||
hb-subset-instancer-solver.cc \
|
|
||||||
hb-subset-accelerator.hh \
|
|
||||||
hb-subset-plan.cc \
|
hb-subset-plan.cc \
|
||||||
hb-subset-plan.hh \
|
hb-subset-plan.hh \
|
||||||
hb-subset-repacker.cc \
|
hb-subset-repacker.cc \
|
||||||
|
@ -376,7 +357,6 @@ HB_SUBSET_sources = \
|
||||||
graph/markbasepos-graph.hh \
|
graph/markbasepos-graph.hh \
|
||||||
graph/split-helpers.hh \
|
graph/split-helpers.hh \
|
||||||
graph/serialize.hh \
|
graph/serialize.hh \
|
||||||
OT/Color/COLR/colrv1-closure.hh \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
HB_SUBSET_headers = \
|
HB_SUBSET_headers = \
|
||||||
|
@ -384,16 +364,6 @@ HB_SUBSET_headers = \
|
||||||
hb-subset-repacker.h \
|
hb-subset-repacker.h \
|
||||||
$(NULL)
|
$(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
|
HB_GOBJECT_DIST_sources = hb-gobject-structs.cc
|
||||||
HB_GOBJECT_DIST_headers = hb-gobject.h hb-gobject-structs.h
|
HB_GOBJECT_DIST_headers = hb-gobject.h hb-gobject-structs.h
|
||||||
HB_GOBJECT_ENUM_sources = hb-gobject-enums.cc
|
HB_GOBJECT_ENUM_sources = hb-gobject-enums.cc
|
||||||
|
|
|
@ -49,7 +49,7 @@ struct Coverage
|
||||||
HBUINT16 format; /* Format identifier */
|
HBUINT16 format; /* Format identifier */
|
||||||
CoverageFormat1_3<SmallTypes> format1;
|
CoverageFormat1_3<SmallTypes> format1;
|
||||||
CoverageFormat2_4<SmallTypes> format2;
|
CoverageFormat2_4<SmallTypes> format2;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
CoverageFormat1_3<MediumTypes>format3;
|
CoverageFormat1_3<MediumTypes>format3;
|
||||||
CoverageFormat2_4<MediumTypes>format4;
|
CoverageFormat2_4<MediumTypes>format4;
|
||||||
#endif
|
#endif
|
||||||
|
@ -65,7 +65,7 @@ struct Coverage
|
||||||
{
|
{
|
||||||
case 1: return_trace (u.format1.sanitize (c));
|
case 1: return_trace (u.format1.sanitize (c));
|
||||||
case 2: return_trace (u.format2.sanitize (c));
|
case 2: return_trace (u.format2.sanitize (c));
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return_trace (u.format3.sanitize (c));
|
case 3: return_trace (u.format3.sanitize (c));
|
||||||
case 4: return_trace (u.format4.sanitize (c));
|
case 4: return_trace (u.format4.sanitize (c));
|
||||||
#endif
|
#endif
|
||||||
|
@ -74,8 +74,10 @@ struct Coverage
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Has interface. */
|
/* Has interface. */
|
||||||
unsigned operator [] (hb_codepoint_t k) const { return get (k); }
|
static constexpr unsigned SENTINEL = NOT_COVERED;
|
||||||
bool has (hb_codepoint_t k) const { return (*this)[k] != NOT_COVERED; }
|
typedef unsigned int value_t;
|
||||||
|
value_t operator [] (hb_codepoint_t k) const { return get (k); }
|
||||||
|
bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
|
||||||
/* Predicate. */
|
/* Predicate. */
|
||||||
bool operator () (hb_codepoint_t k) const { return has (k); }
|
bool operator () (hb_codepoint_t k) const { return has (k); }
|
||||||
|
|
||||||
|
@ -85,7 +87,7 @@ struct Coverage
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return u.format1.get_coverage (glyph_id);
|
case 1: return u.format1.get_coverage (glyph_id);
|
||||||
case 2: return u.format2.get_coverage (glyph_id);
|
case 2: return u.format2.get_coverage (glyph_id);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return u.format3.get_coverage (glyph_id);
|
case 3: return u.format3.get_coverage (glyph_id);
|
||||||
case 4: return u.format4.get_coverage (glyph_id);
|
case 4: return u.format4.get_coverage (glyph_id);
|
||||||
#endif
|
#endif
|
||||||
|
@ -98,7 +100,7 @@ struct Coverage
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return u.format1.get_population ();
|
case 1: return u.format1.get_population ();
|
||||||
case 2: return u.format2.get_population ();
|
case 2: return u.format2.get_population ();
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return u.format3.get_population ();
|
case 3: return u.format3.get_population ();
|
||||||
case 4: return u.format4.get_population ();
|
case 4: return u.format4.get_population ();
|
||||||
#endif
|
#endif
|
||||||
|
@ -125,7 +127,7 @@ struct Coverage
|
||||||
}
|
}
|
||||||
u.format = count <= num_ranges * 3 ? 1 : 2;
|
u.format = count <= num_ranges * 3 ? 1 : 2;
|
||||||
|
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
if (count && last > 0xFFFFu)
|
if (count && last > 0xFFFFu)
|
||||||
u.format += 2;
|
u.format += 2;
|
||||||
#endif
|
#endif
|
||||||
|
@ -134,7 +136,7 @@ struct Coverage
|
||||||
{
|
{
|
||||||
case 1: return_trace (u.format1.serialize (c, glyphs));
|
case 1: return_trace (u.format1.serialize (c, glyphs));
|
||||||
case 2: return_trace (u.format2.serialize (c, glyphs));
|
case 2: return_trace (u.format2.serialize (c, glyphs));
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return_trace (u.format3.serialize (c, glyphs));
|
case 3: return_trace (u.format3.serialize (c, glyphs));
|
||||||
case 4: return_trace (u.format4.serialize (c, glyphs));
|
case 4: return_trace (u.format4.serialize (c, glyphs));
|
||||||
#endif
|
#endif
|
||||||
|
@ -147,7 +149,6 @@ struct Coverage
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto it =
|
auto it =
|
||||||
+ iter ()
|
+ iter ()
|
||||||
| hb_take (c->plan->source->get_num_glyphs ())
|
|
||||||
| hb_filter (c->plan->glyph_map_gsub)
|
| hb_filter (c->plan->glyph_map_gsub)
|
||||||
| hb_map_retains_sorting (c->plan->glyph_map_gsub)
|
| hb_map_retains_sorting (c->plan->glyph_map_gsub)
|
||||||
;
|
;
|
||||||
|
@ -165,7 +166,7 @@ struct Coverage
|
||||||
{
|
{
|
||||||
case 1: return u.format1.intersects (glyphs);
|
case 1: return u.format1.intersects (glyphs);
|
||||||
case 2: return u.format2.intersects (glyphs);
|
case 2: return u.format2.intersects (glyphs);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return u.format3.intersects (glyphs);
|
case 3: return u.format3.intersects (glyphs);
|
||||||
case 4: return u.format4.intersects (glyphs);
|
case 4: return u.format4.intersects (glyphs);
|
||||||
#endif
|
#endif
|
||||||
|
@ -178,7 +179,7 @@ struct Coverage
|
||||||
{
|
{
|
||||||
case 1: return u.format1.intersects_coverage (glyphs, index);
|
case 1: return u.format1.intersects_coverage (glyphs, index);
|
||||||
case 2: return u.format2.intersects_coverage (glyphs, index);
|
case 2: return u.format2.intersects_coverage (glyphs, index);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return u.format3.intersects_coverage (glyphs, index);
|
case 3: return u.format3.intersects_coverage (glyphs, index);
|
||||||
case 4: return u.format4.intersects_coverage (glyphs, index);
|
case 4: return u.format4.intersects_coverage (glyphs, index);
|
||||||
#endif
|
#endif
|
||||||
|
@ -195,7 +196,7 @@ struct Coverage
|
||||||
{
|
{
|
||||||
case 1: return u.format1.collect_coverage (glyphs);
|
case 1: return u.format1.collect_coverage (glyphs);
|
||||||
case 2: return u.format2.collect_coverage (glyphs);
|
case 2: return u.format2.collect_coverage (glyphs);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return u.format3.collect_coverage (glyphs);
|
case 3: return u.format3.collect_coverage (glyphs);
|
||||||
case 4: return u.format4.collect_coverage (glyphs);
|
case 4: return u.format4.collect_coverage (glyphs);
|
||||||
#endif
|
#endif
|
||||||
|
@ -211,7 +212,7 @@ struct Coverage
|
||||||
{
|
{
|
||||||
case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
|
case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
|
||||||
case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
|
case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
|
case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
|
||||||
case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
|
case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
|
||||||
#endif
|
#endif
|
||||||
|
@ -224,13 +225,13 @@ struct Coverage
|
||||||
static constexpr bool is_sorted_iterator = true;
|
static constexpr bool is_sorted_iterator = true;
|
||||||
iter_t (const Coverage &c_ = Null (Coverage))
|
iter_t (const Coverage &c_ = Null (Coverage))
|
||||||
{
|
{
|
||||||
hb_memset (this, 0, sizeof (*this));
|
memset (this, 0, sizeof (*this));
|
||||||
format = c_.u.format;
|
format = c_.u.format;
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case 1: u.format1.init (c_.u.format1); return;
|
case 1: u.format1.init (c_.u.format1); return;
|
||||||
case 2: u.format2.init (c_.u.format2); return;
|
case 2: u.format2.init (c_.u.format2); return;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: u.format3.init (c_.u.format3); return;
|
case 3: u.format3.init (c_.u.format3); return;
|
||||||
case 4: u.format4.init (c_.u.format4); return;
|
case 4: u.format4.init (c_.u.format4); return;
|
||||||
#endif
|
#endif
|
||||||
|
@ -243,7 +244,7 @@ struct Coverage
|
||||||
{
|
{
|
||||||
case 1: return u.format1.__more__ ();
|
case 1: return u.format1.__more__ ();
|
||||||
case 2: return u.format2.__more__ ();
|
case 2: return u.format2.__more__ ();
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return u.format3.__more__ ();
|
case 3: return u.format3.__more__ ();
|
||||||
case 4: return u.format4.__more__ ();
|
case 4: return u.format4.__more__ ();
|
||||||
#endif
|
#endif
|
||||||
|
@ -256,7 +257,7 @@ struct Coverage
|
||||||
{
|
{
|
||||||
case 1: u.format1.__next__ (); break;
|
case 1: u.format1.__next__ (); break;
|
||||||
case 2: u.format2.__next__ (); break;
|
case 2: u.format2.__next__ (); break;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: u.format3.__next__ (); break;
|
case 3: u.format3.__next__ (); break;
|
||||||
case 4: u.format4.__next__ (); break;
|
case 4: u.format4.__next__ (); break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -272,7 +273,7 @@ struct Coverage
|
||||||
{
|
{
|
||||||
case 1: return u.format1.get_glyph ();
|
case 1: return u.format1.get_glyph ();
|
||||||
case 2: return u.format2.get_glyph ();
|
case 2: return u.format2.get_glyph ();
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return u.format3.get_glyph ();
|
case 3: return u.format3.get_glyph ();
|
||||||
case 4: return u.format4.get_glyph ();
|
case 4: return u.format4.get_glyph ();
|
||||||
#endif
|
#endif
|
||||||
|
@ -286,7 +287,7 @@ struct Coverage
|
||||||
{
|
{
|
||||||
case 1: return u.format1 != o.u.format1;
|
case 1: return u.format1 != o.u.format1;
|
||||||
case 2: return u.format2 != o.u.format2;
|
case 2: return u.format2 != o.u.format2;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return u.format3 != o.u.format3;
|
case 3: return u.format3 != o.u.format3;
|
||||||
case 4: return u.format4 != o.u.format4;
|
case 4: return u.format4 != o.u.format4;
|
||||||
#endif
|
#endif
|
||||||
|
@ -301,7 +302,7 @@ struct Coverage
|
||||||
{
|
{
|
||||||
case 1: it.u.format1 = u.format1.__end__ (); break;
|
case 1: it.u.format1 = u.format1.__end__ (); break;
|
||||||
case 2: it.u.format2 = u.format2.__end__ (); break;
|
case 2: it.u.format2 = u.format2.__end__ (); break;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: it.u.format3 = u.format3.__end__ (); break;
|
case 3: it.u.format3 = u.format3.__end__ (); break;
|
||||||
case 4: it.u.format4 = u.format4.__end__ (); break;
|
case 4: it.u.format4 = u.format4.__end__ (); break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -313,7 +314,7 @@ struct Coverage
|
||||||
private:
|
private:
|
||||||
unsigned int format;
|
unsigned int format;
|
||||||
union {
|
union {
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
CoverageFormat2_4<MediumTypes>::iter_t format4; /* Put this one first since it's larger; helps shut up compiler. */
|
CoverageFormat2_4<MediumTypes>::iter_t format4; /* Put this one first since it's larger; helps shut up compiler. */
|
||||||
CoverageFormat1_3<MediumTypes>::iter_t format3;
|
CoverageFormat1_3<MediumTypes>::iter_t format3;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -77,14 +77,7 @@ struct CoverageFormat1_3
|
||||||
|
|
||||||
bool intersects (const hb_set_t *glyphs) const
|
bool intersects (const hb_set_t *glyphs) const
|
||||||
{
|
{
|
||||||
if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
|
/* TODO Speed up, using hb_set_next() and bsearch()? */
|
||||||
{
|
|
||||||
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 ())
|
for (const auto& g : glyphArray.as_array ())
|
||||||
if (glyphs->has (g))
|
if (glyphs->has (g))
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -80,6 +80,8 @@ struct CoverageFormat2_4
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||||
|
|
||||||
|
/* TODO(iter) Write more efficiently? */
|
||||||
|
|
||||||
unsigned num_ranges = 0;
|
unsigned num_ranges = 0;
|
||||||
hb_codepoint_t last = (hb_codepoint_t) -2;
|
hb_codepoint_t last = (hb_codepoint_t) -2;
|
||||||
for (auto g: glyphs)
|
for (auto g: glyphs)
|
||||||
|
@ -113,22 +115,26 @@ struct CoverageFormat2_4
|
||||||
|
|
||||||
bool intersects (const hb_set_t *glyphs) const
|
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)
|
return hb_any (+ hb_iter (rangeRecord)
|
||||||
| hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
|
| hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
|
||||||
}
|
}
|
||||||
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||||
{
|
{
|
||||||
auto *range = rangeRecord.as_array ().bsearch (index);
|
auto cmp = [] (const void *pk, const void *pr) -> int
|
||||||
if (range)
|
{
|
||||||
return range->intersects (*glyphs);
|
unsigned index = * (const unsigned *) pk;
|
||||||
|
const RangeRecord<Types> &range = * (const RangeRecord<Types> *) pr;
|
||||||
|
if (index < range.value) return -1;
|
||||||
|
if (index > (unsigned int) range.value + (range.last - range.first)) return +1;
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto arr = rangeRecord.as_array ();
|
||||||
|
unsigned idx;
|
||||||
|
if (hb_bsearch_impl (&idx, index,
|
||||||
|
arr.arrayZ, arr.length, sizeof (arr[0]),
|
||||||
|
(int (*)(const void *_key, const void *_item)) cmp))
|
||||||
|
return arr.arrayZ[idx].intersects (*glyphs);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,14 +142,9 @@ struct CoverageFormat2_4
|
||||||
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
|
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
|
||||||
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
|
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)
|
for (const auto& range : rangeRecord)
|
||||||
{
|
{
|
||||||
if (unlikely (range.first < last))
|
hb_codepoint_t last = range.last;
|
||||||
break;
|
|
||||||
last = range.last;
|
|
||||||
for (hb_codepoint_t g = range.first - 1;
|
for (hb_codepoint_t g = range.first - 1;
|
||||||
glyphs.next (&g) && g <= last;)
|
glyphs.next (&g) && g <= last;)
|
||||||
intersect_glyphs << g;
|
intersect_glyphs << g;
|
||||||
|
|
|
@ -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 */
|
|
|
@ -51,9 +51,9 @@ struct AnchorFormat3
|
||||||
if (unlikely (!c->serializer->embed (yCoordinate))) 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;
|
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))
|
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));
|
int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (x_varidx));
|
||||||
if (delta != 0)
|
if (delta != 0)
|
||||||
{
|
{
|
||||||
if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
|
if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
|
||||||
|
@ -63,9 +63,9 @@ struct AnchorFormat3
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned y_varidx = yDeviceTable ? (this+yDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
|
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))
|
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));
|
int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (y_varidx));
|
||||||
if (delta != 0)
|
if (delta != 0)
|
||||||
{
|
{
|
||||||
if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
|
if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
|
||||||
|
@ -80,8 +80,8 @@ struct AnchorFormat3
|
||||||
if (!c->serializer->embed (xDeviceTable)) return_trace (false);
|
if (!c->serializer->embed (xDeviceTable)) return_trace (false);
|
||||||
if (!c->serializer->embed (yDeviceTable)) 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->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);
|
out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map);
|
||||||
return_trace (out);
|
return_trace (out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@ struct CursivePos
|
||||||
template <typename context_t, typename ...Ts>
|
template <typename context_t, typename ...Ts>
|
||||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
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);
|
TRACE_DISPATCH (this, u.format);
|
||||||
|
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||||
default:return_trace (c->default_return_value ());
|
default:return_trace (c->default_return_value ());
|
||||||
|
|
|
@ -143,7 +143,7 @@ struct CursivePosFormat1
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"cursive attaching glyph at %u to glyph at %u",
|
"cursive attaching glyph at %d to glyph at %d",
|
||||||
i, j);
|
i, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ struct CursivePosFormat1
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"cursive attached glyph at %u to glyph at %u",
|
"cursive attached glyph at %d to glyph at %d",
|
||||||
i, j);
|
i, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct GPOS : GSUBGPOS
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
hb_subset_layout_context_t l (c, tableTag);
|
hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features);
|
||||||
return GSUBGPOS::subset<PosLookup> (&l);
|
return GSUBGPOS::subset<PosLookup> (&l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"attaching mark glyph at %u to glyph at %u",
|
"attaching mark glyph at %d to glyph at %d",
|
||||||
c->buffer->idx, glyph_pos);
|
c->buffer->idx, glyph_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"attached mark glyph at %u to glyph at %u",
|
"attached mark glyph at %d to glyph at %d",
|
||||||
c->buffer->idx, glyph_pos);
|
c->buffer->idx, glyph_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ struct MarkBasePos
|
||||||
union {
|
union {
|
||||||
HBUINT16 format; /* Format identifier */
|
HBUINT16 format; /* Format identifier */
|
||||||
MarkBasePosFormat1_2<SmallTypes> format1;
|
MarkBasePosFormat1_2<SmallTypes> format1;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
MarkBasePosFormat1_2<MediumTypes> format2;
|
MarkBasePosFormat1_2<MediumTypes> format2;
|
||||||
#endif
|
#endif
|
||||||
} u;
|
} u;
|
||||||
|
@ -22,11 +22,11 @@ struct MarkBasePos
|
||||||
template <typename context_t, typename ...Ts>
|
template <typename context_t, typename ...Ts>
|
||||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
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);
|
TRACE_DISPATCH (this, u.format);
|
||||||
|
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||||
#endif
|
#endif
|
||||||
default:return_trace (c->default_return_value ());
|
default:return_trace (c->default_return_value ());
|
||||||
|
|
|
@ -90,25 +90,6 @@ struct MarkBasePosFormat1_2
|
||||||
|
|
||||||
const Coverage &get_coverage () const { return this+markCoverage; }
|
const Coverage &get_coverage () const { return this+markCoverage; }
|
||||||
|
|
||||||
static inline bool accept (hb_buffer_t *buffer, unsigned idx)
|
|
||||||
{
|
|
||||||
/* We only want to attach to the first of a MultipleSubst sequence.
|
|
||||||
* https://github.com/harfbuzz/harfbuzz/issues/740
|
|
||||||
* Reject others...
|
|
||||||
* ...but stop if we find a mark in the MultipleSubst sequence:
|
|
||||||
* https://github.com/harfbuzz/harfbuzz/issues/1020 */
|
|
||||||
return !_hb_glyph_info_multiplied (&buffer->info[idx]) ||
|
|
||||||
0 == _hb_glyph_info_get_lig_comp (&buffer->info[idx]) ||
|
|
||||||
(idx == 0 ||
|
|
||||||
_hb_glyph_info_is_mark (&buffer->info[idx - 1]) ||
|
|
||||||
!_hb_glyph_info_multiplied (&buffer->info[idx - 1]) ||
|
|
||||||
_hb_glyph_info_get_lig_id (&buffer->info[idx]) !=
|
|
||||||
_hb_glyph_info_get_lig_id (&buffer->info[idx - 1]) ||
|
|
||||||
_hb_glyph_info_get_lig_comp (&buffer->info[idx]) !=
|
|
||||||
_hb_glyph_info_get_lig_comp (&buffer->info[idx - 1]) + 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool apply (hb_ot_apply_context_t *c) const
|
bool apply (hb_ot_apply_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_APPLY (this);
|
TRACE_APPLY (this);
|
||||||
|
@ -116,54 +97,48 @@ struct MarkBasePosFormat1_2
|
||||||
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
|
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
|
||||||
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
||||||
|
|
||||||
/* Now we search backwards for a non-mark glyph.
|
/* Now we search backwards for a non-mark glyph */
|
||||||
* We don't use skippy_iter.prev() to avoid O(n^2) behavior. */
|
|
||||||
|
|
||||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||||
|
skippy_iter.reset (buffer->idx, 1);
|
||||||
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
|
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
|
||||||
|
do {
|
||||||
if (c->last_base_until > buffer->idx)
|
unsigned unsafe_from;
|
||||||
{
|
if (!skippy_iter.prev (&unsafe_from))
|
||||||
c->last_base_until = 0;
|
|
||||||
c->last_base = -1;
|
|
||||||
}
|
|
||||||
unsigned j;
|
|
||||||
for (j = buffer->idx; j > c->last_base_until; j--)
|
|
||||||
{
|
|
||||||
auto match = skippy_iter.match (buffer->info[j - 1]);
|
|
||||||
if (match == skippy_iter.MATCH)
|
|
||||||
{
|
{
|
||||||
// https://github.com/harfbuzz/harfbuzz/issues/4124
|
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
|
||||||
if (!accept (buffer, j - 1) &&
|
return_trace (false);
|
||||||
NOT_COVERED == (this+baseCoverage).get_coverage (buffer->info[j - 1].codepoint))
|
|
||||||
match = skippy_iter.SKIP;
|
|
||||||
}
|
}
|
||||||
if (match == skippy_iter.MATCH)
|
|
||||||
{
|
|
||||||
c->last_base = (signed) j - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c->last_base_until = buffer->idx;
|
|
||||||
if (c->last_base == -1)
|
|
||||||
{
|
|
||||||
buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1);
|
|
||||||
return_trace (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned idx = (unsigned) c->last_base;
|
/* We only want to attach to the first of a MultipleSubst sequence.
|
||||||
|
* https://github.com/harfbuzz/harfbuzz/issues/740
|
||||||
|
* Reject others...
|
||||||
|
* ...but stop if we find a mark in the MultipleSubst sequence:
|
||||||
|
* https://github.com/harfbuzz/harfbuzz/issues/1020 */
|
||||||
|
if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
|
||||||
|
0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
|
||||||
|
(skippy_iter.idx == 0 ||
|
||||||
|
_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
|
||||||
|
!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx - 1]) ||
|
||||||
|
_hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
|
||||||
|
_hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
|
||||||
|
_hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
|
||||||
|
_hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
|
||||||
|
))
|
||||||
|
break;
|
||||||
|
skippy_iter.reject ();
|
||||||
|
} while (true);
|
||||||
|
|
||||||
/* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
|
/* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
|
||||||
//if (!_hb_glyph_info_is_base_glyph (&buffer->info[idx])) { return_trace (false); }
|
//if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
|
||||||
|
|
||||||
unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[idx].codepoint);
|
unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
|
||||||
if (base_index == NOT_COVERED)
|
if (base_index == NOT_COVERED)
|
||||||
{
|
{
|
||||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, idx));
|
return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
|
|
@ -13,7 +13,7 @@ struct MarkLigPos
|
||||||
union {
|
union {
|
||||||
HBUINT16 format; /* Format identifier */
|
HBUINT16 format; /* Format identifier */
|
||||||
MarkLigPosFormat1_2<SmallTypes> format1;
|
MarkLigPosFormat1_2<SmallTypes> format1;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
MarkLigPosFormat1_2<MediumTypes> format2;
|
MarkLigPosFormat1_2<MediumTypes> format2;
|
||||||
#endif
|
#endif
|
||||||
} u;
|
} u;
|
||||||
|
@ -22,11 +22,11 @@ struct MarkLigPos
|
||||||
template <typename context_t, typename ...Ts>
|
template <typename context_t, typename ...Ts>
|
||||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
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);
|
TRACE_DISPATCH (this, u.format);
|
||||||
|
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||||
#endif
|
#endif
|
||||||
default:return_trace (c->default_return_value ());
|
default:return_trace (c->default_return_value ());
|
||||||
|
|
|
@ -100,41 +100,24 @@ struct MarkLigPosFormat1_2
|
||||||
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
||||||
|
|
||||||
/* Now we search backwards for a non-mark glyph */
|
/* Now we search backwards for a non-mark glyph */
|
||||||
|
|
||||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||||
|
skippy_iter.reset (buffer->idx, 1);
|
||||||
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
|
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
|
||||||
|
unsigned unsafe_from;
|
||||||
if (c->last_base_until > buffer->idx)
|
if (!skippy_iter.prev (&unsafe_from))
|
||||||
{
|
{
|
||||||
c->last_base_until = 0;
|
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
|
||||||
c->last_base = -1;
|
|
||||||
}
|
|
||||||
unsigned j;
|
|
||||||
for (j = buffer->idx; j > c->last_base_until; j--)
|
|
||||||
{
|
|
||||||
auto match = skippy_iter.match (buffer->info[j - 1]);
|
|
||||||
if (match == skippy_iter.MATCH)
|
|
||||||
{
|
|
||||||
c->last_base = (signed) j - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c->last_base_until = buffer->idx;
|
|
||||||
if (c->last_base == -1)
|
|
||||||
{
|
|
||||||
buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1);
|
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned idx = (unsigned) c->last_base;
|
|
||||||
|
|
||||||
/* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
|
/* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
|
||||||
//if (!_hb_glyph_info_is_ligature (&buffer->info[idx])) { return_trace (false); }
|
//if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
|
||||||
|
|
||||||
unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[idx].codepoint);
|
unsigned int j = skippy_iter.idx;
|
||||||
|
unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
|
||||||
if (lig_index == NOT_COVERED)
|
if (lig_index == NOT_COVERED)
|
||||||
{
|
{
|
||||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +128,7 @@ struct MarkLigPosFormat1_2
|
||||||
unsigned int comp_count = lig_attach.rows;
|
unsigned int comp_count = lig_attach.rows;
|
||||||
if (unlikely (!comp_count))
|
if (unlikely (!comp_count))
|
||||||
{
|
{
|
||||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +137,7 @@ struct MarkLigPosFormat1_2
|
||||||
* can directly use the component index. If not, we attach the mark
|
* can directly use the component index. If not, we attach the mark
|
||||||
* glyph to the last component of the ligature. */
|
* glyph to the last component of the ligature. */
|
||||||
unsigned int comp_index;
|
unsigned int comp_index;
|
||||||
unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[idx]);
|
unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
|
||||||
unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
|
unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
|
||||||
unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
|
unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
|
||||||
if (lig_id && lig_id == mark_id && mark_comp > 0)
|
if (lig_id && lig_id == mark_id && mark_comp > 0)
|
||||||
|
@ -162,7 +145,7 @@ struct MarkLigPosFormat1_2
|
||||||
else
|
else
|
||||||
comp_index = comp_count - 1;
|
comp_index = comp_count - 1;
|
||||||
|
|
||||||
return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, idx));
|
return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
|
|
@ -13,7 +13,7 @@ struct MarkMarkPos
|
||||||
union {
|
union {
|
||||||
HBUINT16 format; /* Format identifier */
|
HBUINT16 format; /* Format identifier */
|
||||||
MarkMarkPosFormat1_2<SmallTypes> format1;
|
MarkMarkPosFormat1_2<SmallTypes> format1;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
MarkMarkPosFormat1_2<MediumTypes> format2;
|
MarkMarkPosFormat1_2<MediumTypes> format2;
|
||||||
#endif
|
#endif
|
||||||
} u;
|
} u;
|
||||||
|
@ -22,11 +22,11 @@ struct MarkMarkPos
|
||||||
template <typename context_t, typename ...Ts>
|
template <typename context_t, typename ...Ts>
|
||||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
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);
|
TRACE_DISPATCH (this, u.format);
|
||||||
|
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||||
#endif
|
#endif
|
||||||
default:return_trace (c->default_return_value ());
|
default:return_trace (c->default_return_value ());
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct PairPos
|
||||||
HBUINT16 format; /* Format identifier */
|
HBUINT16 format; /* Format identifier */
|
||||||
PairPosFormat1_3<SmallTypes> format1;
|
PairPosFormat1_3<SmallTypes> format1;
|
||||||
PairPosFormat2_4<SmallTypes> format2;
|
PairPosFormat2_4<SmallTypes> format2;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
PairPosFormat1_3<MediumTypes> format3;
|
PairPosFormat1_3<MediumTypes> format3;
|
||||||
PairPosFormat2_4<MediumTypes> format4;
|
PairPosFormat2_4<MediumTypes> format4;
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,12 +25,12 @@ struct PairPos
|
||||||
template <typename context_t, typename ...Ts>
|
template <typename context_t, typename ...Ts>
|
||||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
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);
|
TRACE_DISPATCH (this, u.format);
|
||||||
|
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
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 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||||
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
|
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,7 +43,7 @@ struct PairPosFormat1_3
|
||||||
{
|
{
|
||||||
valueFormat,
|
valueFormat,
|
||||||
len1,
|
len1,
|
||||||
PairSet::get_size (len1, len2)
|
1 + len1 + len2
|
||||||
};
|
};
|
||||||
|
|
||||||
return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
|
return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
|
||||||
|
@ -51,21 +51,8 @@ struct PairPosFormat1_3
|
||||||
|
|
||||||
bool intersects (const hb_set_t *glyphs) const
|
bool intersects (const hb_set_t *glyphs) const
|
||||||
{
|
{
|
||||||
auto &cov = this+coverage;
|
|
||||||
|
|
||||||
if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
|
|
||||||
{
|
|
||||||
for (hb_codepoint_t g : glyphs->iter())
|
|
||||||
{
|
|
||||||
unsigned i = cov.get_coverage (g);
|
|
||||||
if ((this+pairSet[i]).intersects (glyphs, valueFormat))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
+ hb_zip (cov, pairSet)
|
+ hb_zip (this+coverage, pairSet)
|
||||||
| hb_filter (*glyphs, hb_first)
|
| hb_filter (*glyphs, hb_first)
|
||||||
| hb_map (hb_second)
|
| hb_map (hb_second)
|
||||||
| hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_)
|
| hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_)
|
||||||
|
@ -177,21 +164,19 @@ struct PairPosFormat1_3
|
||||||
|
|
||||||
hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
|
hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
|
||||||
{
|
{
|
||||||
unsigned record_size = PairSet::get_size (valueFormat);
|
unsigned len1 = valueFormat[0].get_len ();
|
||||||
|
unsigned len2 = valueFormat[1].get_len ();
|
||||||
|
unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
|
||||||
|
|
||||||
unsigned format1 = 0;
|
unsigned format1 = 0;
|
||||||
unsigned format2 = 0;
|
unsigned format2 = 0;
|
||||||
for (const auto & _ :
|
for (const auto & _ :
|
||||||
+ hb_zip (this+coverage, pairSet)
|
+ hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
|
||||||
| hb_filter (glyphset, hb_first)
|
|
||||||
| hb_map (hb_second)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
const PairSet& set = (this + _);
|
const PairSet& set = (this + _);
|
||||||
const PairValueRecord *record = &set.firstPairValueRecord;
|
const PairValueRecord *record = &set.firstPairValueRecord;
|
||||||
|
|
||||||
unsigned count = set.len;
|
for (unsigned i = 0; i < set.len; i++)
|
||||||
for (unsigned i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
if (record->intersects (glyphset))
|
if (record->intersects (glyphset))
|
||||||
{
|
{
|
||||||
|
@ -200,9 +185,6 @@ struct PairPosFormat1_3
|
||||||
}
|
}
|
||||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format1 == valueFormat[0] && format2 == valueFormat[1])
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return hb_pair (format1, format2);
|
return hb_pair (format1, format2);
|
||||||
|
|
|
@ -49,7 +49,7 @@ struct PairPosFormat2_4
|
||||||
|
|
||||||
unsigned int len1 = valueFormat1.get_len ();
|
unsigned int len1 = valueFormat1.get_len ();
|
||||||
unsigned int len2 = valueFormat2.get_len ();
|
unsigned int len2 = valueFormat2.get_len ();
|
||||||
unsigned int stride = HBUINT16::static_size * (len1 + len2);
|
unsigned int stride = len1 + len2;
|
||||||
unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
|
unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
|
||||||
unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
|
unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
|
||||||
return_trace (c->check_range ((const void *) values,
|
return_trace (c->check_range ((const void *) values,
|
||||||
|
@ -220,25 +220,17 @@ struct PairPosFormat2_4
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"try kerning glyphs at %u,%u",
|
"kerning glyphs at %d,%d",
|
||||||
c->buffer->idx, skippy_iter.idx);
|
c->buffer->idx, skippy_iter.idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
|
applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
|
||||||
applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
|
applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
|
||||||
|
|
||||||
if (applied_first || applied_second)
|
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
|
||||||
{
|
|
||||||
c->buffer->message (c->font,
|
|
||||||
"kerned glyphs at %u,%u",
|
|
||||||
c->buffer->idx, skippy_iter.idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"tried kerning glyphs at %u,%u",
|
"kerned glyphs at %d,%d",
|
||||||
c->buffer->idx, skippy_iter.idx);
|
c->buffer->idx, skippy_iter.idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,13 +241,6 @@ struct PairPosFormat2_4
|
||||||
boring:
|
boring:
|
||||||
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
|
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
|
||||||
|
|
||||||
if (len2)
|
|
||||||
{
|
|
||||||
skippy_iter.idx++;
|
|
||||||
// https://github.com/harfbuzz/harfbuzz/issues/3824
|
|
||||||
// https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
|
|
||||||
buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->idx = skippy_iter.idx;
|
buffer->idx = skippy_iter.idx;
|
||||||
|
|
||||||
|
@ -298,8 +283,8 @@ struct PairPosFormat2_4
|
||||||
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
|
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
|
||||||
{
|
{
|
||||||
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
|
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
|
||||||
valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], &c->plan->layout_variation_idx_delta_map);
|
valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], c->plan->layout_variation_idx_delta_map);
|
||||||
valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], &c->plan->layout_variation_idx_delta_map);
|
valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], c->plan->layout_variation_idx_delta_map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +307,6 @@ struct PairPosFormat2_4
|
||||||
{
|
{
|
||||||
unsigned len1 = valueFormat1.get_len ();
|
unsigned len1 = valueFormat1.get_len ();
|
||||||
unsigned len2 = valueFormat2.get_len ();
|
unsigned len2 = valueFormat2.get_len ();
|
||||||
unsigned record_size = len1 + len2;
|
|
||||||
|
|
||||||
unsigned format1 = 0;
|
unsigned format1 = 0;
|
||||||
unsigned format2 = 0;
|
unsigned format2 = 0;
|
||||||
|
@ -331,13 +315,10 @@ struct PairPosFormat2_4
|
||||||
{
|
{
|
||||||
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
|
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
|
||||||
{
|
{
|
||||||
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_size;
|
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
|
||||||
format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
|
format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
|
||||||
format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
|
format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format1 == valueFormat1 && format2 == valueFormat2)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return hb_pair (format1, format2);
|
return hb_pair (format1, format2);
|
||||||
|
|
|
@ -24,22 +24,11 @@ struct PairSet
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_MIN (2);
|
DEFINE_SIZE_MIN (2);
|
||||||
|
|
||||||
static unsigned get_size (unsigned len1, unsigned len2)
|
|
||||||
{
|
|
||||||
return Types::HBGlyphID::static_size + Value::static_size * (len1 + len2);
|
|
||||||
}
|
|
||||||
static unsigned get_size (const ValueFormat valueFormats[2])
|
|
||||||
{
|
|
||||||
unsigned len1 = valueFormats[0].get_len ();
|
|
||||||
unsigned len2 = valueFormats[1].get_len ();
|
|
||||||
return get_size (len1, len2);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sanitize_closure_t
|
struct sanitize_closure_t
|
||||||
{
|
{
|
||||||
const ValueFormat *valueFormats;
|
const ValueFormat *valueFormats;
|
||||||
unsigned int len1; /* valueFormats[0].get_len() */
|
unsigned int len1; /* valueFormats[0].get_len() */
|
||||||
unsigned int stride; /* bytes */
|
unsigned int stride; /* 1 + len1 + len2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
|
bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
|
||||||
|
@ -48,6 +37,7 @@ struct PairSet
|
||||||
if (!(c->check_struct (this)
|
if (!(c->check_struct (this)
|
||||||
&& c->check_range (&firstPairValueRecord,
|
&& c->check_range (&firstPairValueRecord,
|
||||||
len,
|
len,
|
||||||
|
HBUINT16::static_size,
|
||||||
closure->stride))) return_trace (false);
|
closure->stride))) return_trace (false);
|
||||||
|
|
||||||
unsigned int count = len;
|
unsigned int count = len;
|
||||||
|
@ -59,7 +49,9 @@ struct PairSet
|
||||||
bool intersects (const hb_set_t *glyphs,
|
bool intersects (const hb_set_t *glyphs,
|
||||||
const ValueFormat *valueFormats) const
|
const ValueFormat *valueFormats) const
|
||||||
{
|
{
|
||||||
unsigned record_size = get_size (valueFormats);
|
unsigned int len1 = valueFormats[0].get_len ();
|
||||||
|
unsigned int len2 = valueFormats[1].get_len ();
|
||||||
|
unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
|
||||||
|
|
||||||
const PairValueRecord *record = &firstPairValueRecord;
|
const PairValueRecord *record = &firstPairValueRecord;
|
||||||
unsigned int count = len;
|
unsigned int count = len;
|
||||||
|
@ -75,7 +67,9 @@ struct PairSet
|
||||||
void collect_glyphs (hb_collect_glyphs_context_t *c,
|
void collect_glyphs (hb_collect_glyphs_context_t *c,
|
||||||
const ValueFormat *valueFormats) const
|
const ValueFormat *valueFormats) const
|
||||||
{
|
{
|
||||||
unsigned record_size = get_size (valueFormats);
|
unsigned int len1 = valueFormats[0].get_len ();
|
||||||
|
unsigned int len2 = valueFormats[1].get_len ();
|
||||||
|
unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
|
||||||
|
|
||||||
const PairValueRecord *record = &firstPairValueRecord;
|
const PairValueRecord *record = &firstPairValueRecord;
|
||||||
c->input->add_array (&record->secondGlyph, len, record_size);
|
c->input->add_array (&record->secondGlyph, len, record_size);
|
||||||
|
@ -84,7 +78,9 @@ struct PairSet
|
||||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||||
const ValueFormat *valueFormats) const
|
const ValueFormat *valueFormats) const
|
||||||
{
|
{
|
||||||
unsigned record_size = get_size (valueFormats);
|
unsigned len1 = valueFormats[0].get_len ();
|
||||||
|
unsigned len2 = valueFormats[1].get_len ();
|
||||||
|
unsigned record_size = HBUINT16::static_size * (1 + len1 + len2);
|
||||||
|
|
||||||
const PairValueRecord *record = &firstPairValueRecord;
|
const PairValueRecord *record = &firstPairValueRecord;
|
||||||
unsigned count = len;
|
unsigned count = len;
|
||||||
|
@ -105,7 +101,7 @@ struct PairSet
|
||||||
hb_buffer_t *buffer = c->buffer;
|
hb_buffer_t *buffer = c->buffer;
|
||||||
unsigned int len1 = valueFormats[0].get_len ();
|
unsigned int len1 = valueFormats[0].get_len ();
|
||||||
unsigned int len2 = valueFormats[1].get_len ();
|
unsigned int len2 = valueFormats[1].get_len ();
|
||||||
unsigned record_size = get_size (len1, len2);
|
unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
|
||||||
|
|
||||||
const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
|
const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
|
||||||
&firstPairValueRecord,
|
&firstPairValueRecord,
|
||||||
|
@ -116,39 +112,23 @@ struct PairSet
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"try kerning glyphs at %u,%u",
|
"kerning glyphs at %d,%d",
|
||||||
c->buffer->idx, pos);
|
c->buffer->idx, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
|
bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
|
||||||
bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
|
bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
|
||||||
|
|
||||||
if (applied_first || applied_second)
|
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
|
||||||
{
|
|
||||||
c->buffer->message (c->font,
|
|
||||||
"kerned glyphs at %u,%u",
|
|
||||||
c->buffer->idx, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"tried kerning glyphs at %u,%u",
|
"kerned glyphs at %d,%d",
|
||||||
c->buffer->idx, pos);
|
c->buffer->idx, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (applied_first || applied_second)
|
if (applied_first || applied_second)
|
||||||
buffer->unsafe_to_break (buffer->idx, pos + 1);
|
buffer->unsafe_to_break (buffer->idx, pos + 1);
|
||||||
|
|
||||||
if (len2)
|
|
||||||
{
|
|
||||||
pos++;
|
|
||||||
// https://github.com/harfbuzz/harfbuzz/issues/3824
|
|
||||||
// https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
|
|
||||||
buffer->unsafe_to_break (buffer->idx, pos + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->idx = pos;
|
buffer->idx = pos;
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
@ -172,7 +152,7 @@ struct PairSet
|
||||||
|
|
||||||
unsigned len1 = valueFormats[0].get_len ();
|
unsigned len1 = valueFormats[0].get_len ();
|
||||||
unsigned len2 = valueFormats[1].get_len ();
|
unsigned len2 = valueFormats[1].get_len ();
|
||||||
unsigned record_size = get_size (len1, len2);
|
unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
|
||||||
|
|
||||||
typename PairValueRecord::context_t context =
|
typename PairValueRecord::context_t context =
|
||||||
{
|
{
|
||||||
|
@ -181,7 +161,7 @@ struct PairSet
|
||||||
newFormats,
|
newFormats,
|
||||||
len1,
|
len1,
|
||||||
&glyph_map,
|
&glyph_map,
|
||||||
&c->plan->layout_variation_idx_delta_map
|
c->plan->layout_variation_idx_delta_map
|
||||||
};
|
};
|
||||||
|
|
||||||
const PairValueRecord *record = &firstPairValueRecord;
|
const PairValueRecord *record = &firstPairValueRecord;
|
||||||
|
|
|
@ -72,8 +72,8 @@ struct SinglePos
|
||||||
template <typename context_t, typename ...Ts>
|
template <typename context_t, typename ...Ts>
|
||||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
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);
|
TRACE_DISPATCH (this, u.format);
|
||||||
|
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
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 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||||
|
|
|
@ -28,15 +28,7 @@ struct SinglePosFormat1
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
return_trace (c->check_struct (this) &&
|
return_trace (c->check_struct (this) &&
|
||||||
coverage.sanitize (c, this) &&
|
coverage.sanitize (c, this) &&
|
||||||
/* The coverage table may use a range to represent a set
|
|
||||||
* of glyphs, which means a small number of bytes can
|
|
||||||
* generate a large glyph set. Manually modify the
|
|
||||||
* sanitizer max ops to take this into account.
|
|
||||||
*
|
|
||||||
* Note: This check *must* be right after coverage sanitize. */
|
|
||||||
c->check_ops ((this + coverage).get_population () >> 1) &&
|
|
||||||
valueFormat.sanitize_value (c, this, values));
|
valueFormat.sanitize_value (c, this, values));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intersects (const hb_set_t *glyphs) const
|
bool intersects (const hb_set_t *glyphs) const
|
||||||
|
@ -71,7 +63,7 @@ struct SinglePosFormat1
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"positioning glyph at %u",
|
"positioning glyph at %d",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +72,7 @@ struct SinglePosFormat1
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"positioned glyph at %u",
|
"positioned glyph at %d",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,24 +80,6 @@ struct SinglePosFormat1
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
position_single (hb_font_t *font,
|
|
||||||
hb_direction_t direction,
|
|
||||||
hb_codepoint_t gid,
|
|
||||||
hb_glyph_position_t &pos) const
|
|
||||||
{
|
|
||||||
unsigned int index = (this+coverage).get_coverage (gid);
|
|
||||||
if (likely (index == NOT_COVERED)) return false;
|
|
||||||
|
|
||||||
/* This is ugly... */
|
|
||||||
hb_buffer_t buffer;
|
|
||||||
buffer.props.direction = direction;
|
|
||||||
OT::hb_ot_apply_context_t c (1, font, &buffer);
|
|
||||||
|
|
||||||
valueFormat.apply_value (&c, this, values, pos);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Iterator,
|
template<typename Iterator,
|
||||||
typename SrcLookup,
|
typename SrcLookup,
|
||||||
hb_requires (hb_is_iterator (Iterator))>
|
hb_requires (hb_is_iterator (Iterator))>
|
||||||
|
@ -152,7 +126,7 @@ struct SinglePosFormat1
|
||||||
;
|
;
|
||||||
|
|
||||||
bool ret = bool (it);
|
bool ret = bool (it);
|
||||||
SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
|
SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
|
||||||
return_trace (ret);
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -68,12 +68,12 @@ struct SinglePosFormat2
|
||||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||||
|
|
||||||
if (unlikely (index >= valueCount)) return_trace (false);
|
if (likely (index >= valueCount)) return_trace (false);
|
||||||
|
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"positioning glyph at %u",
|
"positioning glyph at %d",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ struct SinglePosFormat2
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"positioned glyph at %u",
|
"positioned glyph at %d",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,28 +92,6 @@ struct SinglePosFormat2
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
position_single (hb_font_t *font,
|
|
||||||
hb_direction_t direction,
|
|
||||||
hb_codepoint_t gid,
|
|
||||||
hb_glyph_position_t &pos) const
|
|
||||||
{
|
|
||||||
unsigned int index = (this+coverage).get_coverage (gid);
|
|
||||||
if (likely (index == NOT_COVERED)) return false;
|
|
||||||
if (unlikely (index >= valueCount)) return false;
|
|
||||||
|
|
||||||
/* This is ugly... */
|
|
||||||
hb_buffer_t buffer;
|
|
||||||
buffer.props.direction = direction;
|
|
||||||
OT::hb_ot_apply_context_t c (1, font, &buffer);
|
|
||||||
|
|
||||||
valueFormat.apply_value (&c, this,
|
|
||||||
&values[index * valueFormat.get_len ()],
|
|
||||||
pos);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Iterator,
|
template<typename Iterator,
|
||||||
typename SrcLookup,
|
typename SrcLookup,
|
||||||
hb_requires (hb_is_iterator (Iterator))>
|
hb_requires (hb_is_iterator (Iterator))>
|
||||||
|
@ -163,7 +141,7 @@ struct SinglePosFormat2
|
||||||
;
|
;
|
||||||
|
|
||||||
bool ret = bool (it);
|
bool ret = bool (it);
|
||||||
SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
|
SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
|
||||||
return_trace (ret);
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -371,7 +371,7 @@ struct ValueFormat : HBUINT16
|
||||||
for (unsigned int i = 0; i < count; i++) {
|
for (unsigned int i = 0; i < count; i++) {
|
||||||
if (!sanitize_value_devices (c, base, values))
|
if (!sanitize_value_devices (c, base, values))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
values = &StructAtOffset<const Value> (values, stride);
|
values += stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
|
|
|
@ -61,7 +61,7 @@ struct AlternateSet
|
||||||
{
|
{
|
||||||
c->buffer->sync_so_far ();
|
c->buffer->sync_so_far ();
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replacing glyph at %u (alternate substitution)",
|
"replacing glyph at %d (alternate substitution)",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,8 +70,8 @@ struct AlternateSet
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replaced glyph at %u (alternate substitution)",
|
"replaced glyph at %d (alternate substitution)",
|
||||||
c->buffer->idx - 1u);
|
c->buffer->idx - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
|
@ -84,7 +84,7 @@ struct AlternateSet
|
||||||
{
|
{
|
||||||
if (alternates.len && alternate_count)
|
if (alternates.len && alternate_count)
|
||||||
{
|
{
|
||||||
+ alternates.as_array ().sub_array (start_offset, alternate_count)
|
+ alternates.sub_array (start_offset, alternate_count)
|
||||||
| hb_sink (hb_array (alternate_glyphs, *alternate_count))
|
| hb_sink (hb_array (alternate_glyphs, *alternate_count))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct AlternateSubst
|
||||||
union {
|
union {
|
||||||
HBUINT16 format; /* Format identifier */
|
HBUINT16 format; /* Format identifier */
|
||||||
AlternateSubstFormat1_2<SmallTypes> format1;
|
AlternateSubstFormat1_2<SmallTypes> format1;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
AlternateSubstFormat1_2<MediumTypes> format2;
|
AlternateSubstFormat1_2<MediumTypes> format2;
|
||||||
#endif
|
#endif
|
||||||
} u;
|
} u;
|
||||||
|
@ -23,11 +23,11 @@ struct AlternateSubst
|
||||||
template <typename context_t, typename ...Ts>
|
template <typename context_t, typename ...Ts>
|
||||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
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);
|
TRACE_DISPATCH (this, u.format);
|
||||||
|
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||||
#endif
|
#endif
|
||||||
default:return_trace (c->default_return_value ());
|
default:return_trace (c->default_return_value ());
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct GSUB : GSUBGPOS
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
hb_subset_layout_context_t l (c, tableTag);
|
hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
|
||||||
return GSUBGPOS::subset<SubstLookup> (&l);
|
return GSUBGPOS::subset<SubstLookup> (&l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,6 @@ struct Ligature
|
||||||
bool intersects (const hb_set_t *glyphs) const
|
bool intersects (const hb_set_t *glyphs) const
|
||||||
{ return hb_all (component, glyphs); }
|
{ return hb_all (component, glyphs); }
|
||||||
|
|
||||||
bool intersects_lig_glyph (const hb_set_t *glyphs) const
|
|
||||||
{ return glyphs->has(ligGlyph); }
|
|
||||||
|
|
||||||
void closure (hb_closure_context_t *c) const
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
if (!intersects (c->glyphs)) return;
|
if (!intersects (c->glyphs)) return;
|
||||||
|
@ -72,7 +69,7 @@ struct Ligature
|
||||||
{
|
{
|
||||||
c->buffer->sync_so_far ();
|
c->buffer->sync_so_far ();
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replacing glyph at %u (ligature substitution)",
|
"replacing glyph at %d (ligature substitution)",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +78,8 @@ struct Ligature
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replaced glyph at %u (ligature substitution)",
|
"replaced glyph at %d (ligature substitution)",
|
||||||
c->buffer->idx - 1u);
|
c->buffer->idx - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
|
@ -121,7 +118,7 @@ struct Ligature
|
||||||
match_positions[i] += delta;
|
match_positions[i] += delta;
|
||||||
if (i)
|
if (i)
|
||||||
*p++ = ',';
|
*p++ = ',';
|
||||||
snprintf (p, sizeof(buf) - (p - buf), "%u", match_positions[i]);
|
sprintf (p, "%u", match_positions[i]);
|
||||||
p += strlen(p);
|
p += strlen(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +138,7 @@ struct Ligature
|
||||||
{
|
{
|
||||||
c->buffer->sync_so_far ();
|
c->buffer->sync_so_far ();
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"ligated glyph at %u",
|
"ligated glyph at %d",
|
||||||
pos);
|
pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,18 +34,6 @@ struct LigatureSet
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intersects_lig_glyph (const hb_set_t *glyphs) const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
+ hb_iter (ligature)
|
|
||||||
| hb_map (hb_add (this))
|
|
||||||
| hb_map ([glyphs] (const Ligature<Types> &_) {
|
|
||||||
return _.intersects_lig_glyph (glyphs) && _.intersects (glyphs);
|
|
||||||
})
|
|
||||||
| hb_any
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void closure (hb_closure_context_t *c) const
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
+ hb_iter (ligature)
|
+ hb_iter (ligature)
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct LigatureSubst
|
||||||
union {
|
union {
|
||||||
HBUINT16 format; /* Format identifier */
|
HBUINT16 format; /* Format identifier */
|
||||||
LigatureSubstFormat1_2<SmallTypes> format1;
|
LigatureSubstFormat1_2<SmallTypes> format1;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
LigatureSubstFormat1_2<MediumTypes> format2;
|
LigatureSubstFormat1_2<MediumTypes> format2;
|
||||||
#endif
|
#endif
|
||||||
} u;
|
} u;
|
||||||
|
@ -23,11 +23,11 @@ struct LigatureSubst
|
||||||
template <typename context_t, typename ...Ts>
|
template <typename context_t, typename ...Ts>
|
||||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
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);
|
TRACE_DISPATCH (this, u.format);
|
||||||
|
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||||
#endif
|
#endif
|
||||||
default:return_trace (c->default_return_value ());
|
default:return_trace (c->default_return_value ());
|
||||||
|
|
|
@ -130,7 +130,7 @@ struct LigatureSubstFormat1_2
|
||||||
+ hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
|
+ hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
|
||||||
| hb_filter (glyphset, hb_first)
|
| hb_filter (glyphset, hb_first)
|
||||||
| hb_filter ([&] (const LigatureSet<Types>& _) {
|
| hb_filter ([&] (const LigatureSet<Types>& _) {
|
||||||
return _.intersects_lig_glyph (&glyphset);
|
return _.intersects (&glyphset);
|
||||||
}, hb_second)
|
}, hb_second)
|
||||||
| hb_map (hb_first)
|
| hb_map (hb_first)
|
||||||
| hb_sink (new_coverage);
|
| hb_sink (new_coverage);
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct MultipleSubst
|
||||||
union {
|
union {
|
||||||
HBUINT16 format; /* Format identifier */
|
HBUINT16 format; /* Format identifier */
|
||||||
MultipleSubstFormat1_2<SmallTypes> format1;
|
MultipleSubstFormat1_2<SmallTypes> format1;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
MultipleSubstFormat1_2<MediumTypes> format2;
|
MultipleSubstFormat1_2<MediumTypes> format2;
|
||||||
#endif
|
#endif
|
||||||
} u;
|
} u;
|
||||||
|
@ -24,11 +24,11 @@ struct MultipleSubst
|
||||||
template <typename context_t, typename ...Ts>
|
template <typename context_t, typename ...Ts>
|
||||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
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);
|
TRACE_DISPATCH (this, u.format);
|
||||||
|
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||||
#endif
|
#endif
|
||||||
default:return_trace (c->default_return_value ());
|
default:return_trace (c->default_return_value ());
|
||||||
|
|
|
@ -20,8 +20,8 @@ struct ReverseChainSingleSubst
|
||||||
template <typename context_t, typename ...Ts>
|
template <typename context_t, typename ...Ts>
|
||||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
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);
|
TRACE_DISPATCH (this, u.format);
|
||||||
|
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||||
default:return_trace (c->default_return_value ());
|
default:return_trace (c->default_return_value ());
|
||||||
|
|
|
@ -135,7 +135,7 @@ struct ReverseChainSingleSubstFormat1
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replacing glyph at %u (reverse chaining substitution)",
|
"replacing glyph at %d (reverse chaining substitution)",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ struct ReverseChainSingleSubstFormat1
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replaced glyph at %u (reverse chaining substitution)",
|
"replaced glyph at %d (reverse chaining substitution)",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ struct Sequence
|
||||||
{
|
{
|
||||||
c->buffer->sync_so_far ();
|
c->buffer->sync_so_far ();
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replacing glyph at %u (multiple substitution)",
|
"replacing glyph at %d (multiple substitution)",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,8 +53,8 @@ struct Sequence
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replaced glyph at %u (multiple subtitution)",
|
"replaced glyph at %d (multiple subtitution)",
|
||||||
c->buffer->idx - 1u);
|
c->buffer->idx - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
|
@ -67,7 +67,7 @@ struct Sequence
|
||||||
{
|
{
|
||||||
c->buffer->sync_so_far ();
|
c->buffer->sync_so_far ();
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"deleting glyph at %u (multiple substitution)",
|
"deleting glyph at %d (multiple substitution)",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ struct Sequence
|
||||||
{
|
{
|
||||||
c->buffer->sync_so_far ();
|
c->buffer->sync_so_far ();
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"deleted glyph at %u (multiple substitution)",
|
"deleted glyph at %d (multiple substitution)",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ struct Sequence
|
||||||
{
|
{
|
||||||
c->buffer->sync_so_far ();
|
c->buffer->sync_so_far ();
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"multiplying glyph at %u",
|
"multiplying glyph at %d",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ struct Sequence
|
||||||
{
|
{
|
||||||
if (buf < p)
|
if (buf < p)
|
||||||
*p++ = ',';
|
*p++ = ',';
|
||||||
snprintf (p, sizeof(buf) - (p - buf), "%u", i);
|
sprintf (p, "%u", i);
|
||||||
p += strlen(p);
|
p += strlen(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ struct SingleSubst
|
||||||
HBUINT16 format; /* Format identifier */
|
HBUINT16 format; /* Format identifier */
|
||||||
SingleSubstFormat1_3<SmallTypes> format1;
|
SingleSubstFormat1_3<SmallTypes> format1;
|
||||||
SingleSubstFormat2_4<SmallTypes> format2;
|
SingleSubstFormat2_4<SmallTypes> format2;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
SingleSubstFormat1_3<MediumTypes> format3;
|
SingleSubstFormat1_3<MediumTypes> format3;
|
||||||
SingleSubstFormat2_4<MediumTypes> format4;
|
SingleSubstFormat2_4<MediumTypes> format4;
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,12 +27,12 @@ struct SingleSubst
|
||||||
template <typename context_t, typename ...Ts>
|
template <typename context_t, typename ...Ts>
|
||||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
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);
|
TRACE_DISPATCH (this, u.format);
|
||||||
|
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
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 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||||
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
|
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
|
||||||
#endif
|
#endif
|
||||||
|
@ -55,7 +55,7 @@ struct SingleSubst
|
||||||
format = 1;
|
format = 1;
|
||||||
hb_codepoint_t mask = 0xFFFFu;
|
hb_codepoint_t mask = 0xFFFFu;
|
||||||
|
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
if (+ glyphs
|
if (+ glyphs
|
||||||
| hb_map_retains_sorting (hb_first)
|
| hb_map_retains_sorting (hb_first)
|
||||||
| hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; }))
|
| hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; }))
|
||||||
|
@ -78,7 +78,7 @@ struct SingleSubst
|
||||||
| hb_map_retains_sorting (hb_first),
|
| hb_map_retains_sorting (hb_first),
|
||||||
delta));
|
delta));
|
||||||
case 2: return_trace (u.format2.serialize (c, glyphs));
|
case 2: return_trace (u.format2.serialize (c, glyphs));
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: return_trace (u.format3.serialize (c,
|
case 3: return_trace (u.format3.serialize (c,
|
||||||
+ glyphs
|
+ glyphs
|
||||||
| hb_map_retains_sorting (hb_first),
|
| hb_map_retains_sorting (hb_first),
|
||||||
|
|
|
@ -25,15 +25,7 @@ struct SingleSubstFormat1_3
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
return_trace (c->check_struct (this) &&
|
return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
|
||||||
coverage.sanitize (c, this) &&
|
|
||||||
/* The coverage table may use a range to represent a set
|
|
||||||
* of glyphs, which means a small number of bytes can
|
|
||||||
* generate a large glyph set. Manually modify the
|
|
||||||
* sanitizer max ops to take this into account.
|
|
||||||
*
|
|
||||||
* Note: This check *must* be right after coverage sanitize. */
|
|
||||||
c->check_ops ((this + coverage).get_population () >> 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_codepoint_t get_mask () const
|
hb_codepoint_t get_mask () const
|
||||||
|
@ -65,7 +57,7 @@ struct SingleSubstFormat1_3
|
||||||
hb_codepoint_t max_before = intersection.get_max ();
|
hb_codepoint_t max_before = intersection.get_max ();
|
||||||
hb_codepoint_t min_after = (min_before + d) & mask;
|
hb_codepoint_t min_after = (min_before + d) & mask;
|
||||||
hb_codepoint_t max_after = (max_before + d) & mask;
|
hb_codepoint_t max_after = (max_before + d) & mask;
|
||||||
if (intersection.get_population () == max_before - min_before + 1 &&
|
if (pop >= max_before - min_before &&
|
||||||
((min_before <= min_after && min_after <= max_before) ||
|
((min_before <= min_after && min_after <= max_before) ||
|
||||||
(min_before <= max_after && max_after <= max_before)))
|
(min_before <= max_after && max_after <= max_before)))
|
||||||
return;
|
return;
|
||||||
|
@ -95,34 +87,6 @@ struct SingleSubstFormat1_3
|
||||||
bool would_apply (hb_would_apply_context_t *c) const
|
bool would_apply (hb_would_apply_context_t *c) const
|
||||||
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
|
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
|
||||||
|
|
||||||
unsigned
|
|
||||||
get_glyph_alternates (hb_codepoint_t glyph_id,
|
|
||||||
unsigned start_offset,
|
|
||||||
unsigned *alternate_count /* IN/OUT. May be NULL. */,
|
|
||||||
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
|
|
||||||
{
|
|
||||||
unsigned int index = (this+coverage).get_coverage (glyph_id);
|
|
||||||
if (likely (index == NOT_COVERED))
|
|
||||||
{
|
|
||||||
if (alternate_count)
|
|
||||||
*alternate_count = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alternate_count && *alternate_count)
|
|
||||||
{
|
|
||||||
hb_codepoint_t d = deltaGlyphID;
|
|
||||||
hb_codepoint_t mask = get_mask ();
|
|
||||||
|
|
||||||
glyph_id = (glyph_id + d) & mask;
|
|
||||||
|
|
||||||
*alternate_glyphs = glyph_id;
|
|
||||||
*alternate_count = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool apply (hb_ot_apply_context_t *c) const
|
bool apply (hb_ot_apply_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_APPLY (this);
|
TRACE_APPLY (this);
|
||||||
|
@ -139,7 +103,7 @@ struct SingleSubstFormat1_3
|
||||||
{
|
{
|
||||||
c->buffer->sync_so_far ();
|
c->buffer->sync_so_far ();
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replacing glyph at %u (single substitution)",
|
"replacing glyph at %d (single substitution)",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,8 +112,8 @@ struct SingleSubstFormat1_3
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replaced glyph at %u (single substitution)",
|
"replaced glyph at %d (single substitution)",
|
||||||
c->buffer->idx - 1u);
|
c->buffer->idx - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
|
|
|
@ -36,24 +36,8 @@ struct SingleSubstFormat2_4
|
||||||
|
|
||||||
void closure (hb_closure_context_t *c) const
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
auto &cov = this+coverage;
|
+ hb_zip (this+coverage, substitute)
|
||||||
auto &glyph_set = c->parent_active_glyphs ();
|
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||||
|
|
||||||
if (substitute.len > glyph_set.get_population () * 4)
|
|
||||||
{
|
|
||||||
for (auto g : glyph_set)
|
|
||||||
{
|
|
||||||
unsigned i = cov.get_coverage (g);
|
|
||||||
if (i == NOT_COVERED || i >= substitute.len)
|
|
||||||
continue;
|
|
||||||
c->output->add (substitute.arrayZ[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ hb_zip (cov, substitute)
|
|
||||||
| hb_filter (glyph_set, hb_first)
|
|
||||||
| hb_map (hb_second)
|
| hb_map (hb_second)
|
||||||
| hb_sink (c->output)
|
| hb_sink (c->output)
|
||||||
;
|
;
|
||||||
|
@ -75,31 +59,6 @@ struct SingleSubstFormat2_4
|
||||||
bool would_apply (hb_would_apply_context_t *c) const
|
bool would_apply (hb_would_apply_context_t *c) const
|
||||||
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
|
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
|
||||||
|
|
||||||
unsigned
|
|
||||||
get_glyph_alternates (hb_codepoint_t glyph_id,
|
|
||||||
unsigned start_offset,
|
|
||||||
unsigned *alternate_count /* IN/OUT. May be NULL. */,
|
|
||||||
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
|
|
||||||
{
|
|
||||||
unsigned int index = (this+coverage).get_coverage (glyph_id);
|
|
||||||
if (likely (index == NOT_COVERED))
|
|
||||||
{
|
|
||||||
if (alternate_count)
|
|
||||||
*alternate_count = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alternate_count && *alternate_count)
|
|
||||||
{
|
|
||||||
glyph_id = substitute[index];
|
|
||||||
|
|
||||||
*alternate_glyphs = glyph_id;
|
|
||||||
*alternate_count = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool apply (hb_ot_apply_context_t *c) const
|
bool apply (hb_ot_apply_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_APPLY (this);
|
TRACE_APPLY (this);
|
||||||
|
@ -112,7 +71,7 @@ struct SingleSubstFormat2_4
|
||||||
{
|
{
|
||||||
c->buffer->sync_so_far ();
|
c->buffer->sync_so_far ();
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replacing glyph at %u (single substitution)",
|
"replacing glyph at %d (single substitution)",
|
||||||
c->buffer->idx);
|
c->buffer->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,8 +80,8 @@ struct SingleSubstFormat2_4
|
||||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||||
{
|
{
|
||||||
c->buffer->message (c->font,
|
c->buffer->message (c->font,
|
||||||
"replaced glyph at %u (single substitution)",
|
"replaced glyph at %d (single substitution)",
|
||||||
c->buffer->idx - 1u);
|
c->buffer->idx - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
|
|
||||||
#include "../../hb-open-type.hh"
|
#include "../../hb-open-type.hh"
|
||||||
#include "composite-iter.hh"
|
|
||||||
|
|
||||||
|
|
||||||
namespace OT {
|
namespace OT {
|
||||||
|
@ -87,34 +86,27 @@ struct CompositeGlyphRecord
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void transform_points (contour_point_vector_t &points,
|
void transform_points (contour_point_vector_t &points) const
|
||||||
const float (&matrix)[4],
|
|
||||||
const contour_point_t &trans) const
|
|
||||||
{
|
|
||||||
if (scaled_offsets ())
|
|
||||||
{
|
|
||||||
points.translate (trans);
|
|
||||||
points.transform (matrix);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
points.transform (matrix);
|
|
||||||
points.translate (trans);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool get_points (contour_point_vector_t &points) const
|
|
||||||
{
|
{
|
||||||
float matrix[4];
|
float matrix[4];
|
||||||
contour_point_t trans;
|
contour_point_t trans;
|
||||||
get_transformation (matrix, trans);
|
if (get_transformation (matrix, trans))
|
||||||
if (unlikely (!points.resize (points.length + 1))) return false;
|
{
|
||||||
points[points.length - 1] = trans;
|
if (scaled_offsets ())
|
||||||
return true;
|
{
|
||||||
|
points.translate (trans);
|
||||||
|
points.transform (matrix);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
points.transform (matrix);
|
||||||
|
points.translate (trans);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned compile_with_point (const contour_point_t &point,
|
unsigned compile_with_deltas (const contour_point_t &p_delta,
|
||||||
char *out) const
|
char *out) const
|
||||||
{
|
{
|
||||||
const HBINT8 *p = &StructAfter<const HBINT8> (flags);
|
const HBINT8 *p = &StructAfter<const HBINT8> (flags);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BEYOND_64K
|
||||||
|
@ -128,29 +120,30 @@ struct CompositeGlyphRecord
|
||||||
unsigned len_before_val = (const char *)p - (const char *)this;
|
unsigned len_before_val = (const char *)p - (const char *)this;
|
||||||
if (flags & ARG_1_AND_2_ARE_WORDS)
|
if (flags & ARG_1_AND_2_ARE_WORDS)
|
||||||
{
|
{
|
||||||
// no overflow, copy value
|
// no overflow, copy and update value with deltas
|
||||||
hb_memcpy (out, this, len);
|
memcpy (out, this, len);
|
||||||
|
|
||||||
|
const HBINT16 *px = reinterpret_cast<const HBINT16 *> (p);
|
||||||
HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
|
HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
|
||||||
o[0] = roundf (point.x);
|
o[0] = px[0] + roundf (p_delta.x);
|
||||||
o[1] = roundf (point.y);
|
o[1] = px[1] + roundf (p_delta.y);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int new_x = roundf (point.x);
|
int new_x = p[0] + roundf (p_delta.x);
|
||||||
int new_y = roundf (point.y);
|
int new_y = p[1] + roundf (p_delta.y);
|
||||||
if (new_x <= 127 && new_x >= -128 &&
|
if (new_x <= 127 && new_x >= -128 &&
|
||||||
new_y <= 127 && new_y >= -128)
|
new_y <= 127 && new_y >= -128)
|
||||||
{
|
{
|
||||||
hb_memcpy (out, this, len);
|
memcpy (out, this, len);
|
||||||
HBINT8 *o = reinterpret_cast<HBINT8 *> (out + len_before_val);
|
HBINT8 *o = reinterpret_cast<HBINT8 *> (out + len_before_val);
|
||||||
o[0] = new_x;
|
o[0] = new_x;
|
||||||
o[1] = new_y;
|
o[1] = new_y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// new point value has an int8 overflow
|
// int8 overflows after deltas applied
|
||||||
hb_memcpy (out, this, len_before_val);
|
memcpy (out, this, len_before_val);
|
||||||
|
|
||||||
//update flags
|
//update flags
|
||||||
CompositeGlyphRecord *o = reinterpret_cast<CompositeGlyphRecord *> (out);
|
CompositeGlyphRecord *o = reinterpret_cast<CompositeGlyphRecord *> (out);
|
||||||
|
@ -159,14 +152,14 @@ struct CompositeGlyphRecord
|
||||||
|
|
||||||
HBINT16 new_value;
|
HBINT16 new_value;
|
||||||
new_value = new_x;
|
new_value = new_x;
|
||||||
hb_memcpy (out, &new_value, HBINT16::static_size);
|
memcpy (out, &new_value, HBINT16::static_size);
|
||||||
out += HBINT16::static_size;
|
out += HBINT16::static_size;
|
||||||
|
|
||||||
new_value = new_y;
|
new_value = new_y;
|
||||||
hb_memcpy (out, &new_value, HBINT16::static_size);
|
memcpy (out, &new_value, HBINT16::static_size);
|
||||||
out += HBINT16::static_size;
|
out += HBINT16::static_size;
|
||||||
|
|
||||||
hb_memcpy (out, p+2, len - len_before_val - 2);
|
memcpy (out, p+2, len - len_before_val - 2);
|
||||||
len += 2;
|
len += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,7 +170,6 @@ struct CompositeGlyphRecord
|
||||||
bool scaled_offsets () const
|
bool scaled_offsets () const
|
||||||
{ return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
|
{ return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
|
||||||
|
|
||||||
public:
|
|
||||||
bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
|
bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
|
||||||
{
|
{
|
||||||
matrix[0] = matrix[3] = 1.f;
|
matrix[0] = matrix[3] = 1.f;
|
||||||
|
@ -232,6 +224,7 @@ struct CompositeGlyphRecord
|
||||||
return tx || ty;
|
return tx || ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
hb_codepoint_t get_gid () const
|
hb_codepoint_t get_gid () const
|
||||||
{
|
{
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BEYOND_64K
|
||||||
|
@ -252,27 +245,6 @@ struct CompositeGlyphRecord
|
||||||
StructAfter<HBGlyphID16> (flags) = gid;
|
StructAfter<HBGlyphID16> (flags) = gid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HB_NO_BEYOND_64K
|
|
||||||
void lower_gid_24_to_16 ()
|
|
||||||
{
|
|
||||||
hb_codepoint_t gid = get_gid ();
|
|
||||||
if (!(flags & GID_IS_24BIT) || gid > 0xFFFFu)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Lower the flag and move the rest of the struct down. */
|
|
||||||
|
|
||||||
unsigned size = get_size ();
|
|
||||||
char *end = (char *) this + size;
|
|
||||||
char *p = &StructAfter<char> (flags);
|
|
||||||
p += HBGlyphID24::static_size;
|
|
||||||
|
|
||||||
flags = flags & ~GID_IS_24BIT;
|
|
||||||
set_gid (gid);
|
|
||||||
|
|
||||||
memmove (p - HBGlyphID24::static_size + HBGlyphID16::static_size, p, end - p);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HBUINT16 flags;
|
HBUINT16 flags;
|
||||||
HBUINT24 pad;
|
HBUINT24 pad;
|
||||||
|
@ -280,7 +252,55 @@ struct CompositeGlyphRecord
|
||||||
DEFINE_SIZE_MIN (4);
|
DEFINE_SIZE_MIN (4);
|
||||||
};
|
};
|
||||||
|
|
||||||
using composite_iter_t = composite_iter_tmpl<CompositeGlyphRecord>;
|
struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphRecord &>
|
||||||
|
{
|
||||||
|
typedef const CompositeGlyphRecord *__item_t__;
|
||||||
|
composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
|
||||||
|
glyph (glyph_), current (nullptr), current_size (0)
|
||||||
|
{
|
||||||
|
set_current (current_);
|
||||||
|
}
|
||||||
|
|
||||||
|
composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
|
||||||
|
|
||||||
|
item_t __item__ () const { return *current; }
|
||||||
|
bool __more__ () const { return current; }
|
||||||
|
void __next__ ()
|
||||||
|
{
|
||||||
|
if (!current->has_more ()) { current = nullptr; return; }
|
||||||
|
|
||||||
|
set_current (&StructAtOffset<CompositeGlyphRecord> (current, current_size));
|
||||||
|
}
|
||||||
|
composite_iter_t __end__ () const { return composite_iter_t (); }
|
||||||
|
bool operator != (const composite_iter_t& o) const
|
||||||
|
{ return current != o.current; }
|
||||||
|
|
||||||
|
|
||||||
|
void set_current (__item_t__ current_)
|
||||||
|
{
|
||||||
|
if (!glyph.check_range (current_, CompositeGlyphRecord::min_size))
|
||||||
|
{
|
||||||
|
current = nullptr;
|
||||||
|
current_size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned size = current_->get_size ();
|
||||||
|
if (!glyph.check_range (current_, size))
|
||||||
|
{
|
||||||
|
current = nullptr;
|
||||||
|
current_size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current_;
|
||||||
|
current_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
hb_bytes_t glyph;
|
||||||
|
__item_t__ current;
|
||||||
|
unsigned current_size;
|
||||||
|
};
|
||||||
|
|
||||||
struct CompositeGlyph
|
struct CompositeGlyph
|
||||||
{
|
{
|
||||||
|
@ -331,7 +351,7 @@ struct CompositeGlyph
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compile_bytes_with_deltas (const hb_bytes_t &source_bytes,
|
bool compile_bytes_with_deltas (const hb_bytes_t &source_bytes,
|
||||||
const contour_point_vector_t &points_with_deltas,
|
const contour_point_vector_t &deltas,
|
||||||
hb_bytes_t &dest_bytes /* OUT */)
|
hb_bytes_t &dest_bytes /* OUT */)
|
||||||
{
|
{
|
||||||
if (source_bytes.length <= GlyphHeader::static_size ||
|
if (source_bytes.length <= GlyphHeader::static_size ||
|
||||||
|
@ -346,7 +366,7 @@ struct CompositeGlyph
|
||||||
/* try to allocate more memories than source glyph bytes
|
/* try to allocate more memories than source glyph bytes
|
||||||
* in case that there might be an overflow for int8 value
|
* in case that there might be an overflow for int8 value
|
||||||
* and we would need to use int16 instead */
|
* and we would need to use int16 instead */
|
||||||
char *o = (char *) hb_calloc (source_len * 2, sizeof (char));
|
char *o = (char *) hb_calloc (source_len + source_len/2, sizeof (char));
|
||||||
if (unlikely (!o)) return false;
|
if (unlikely (!o)) return false;
|
||||||
|
|
||||||
const CompositeGlyphRecord *c = reinterpret_cast<const CompositeGlyphRecord *> (source_bytes.arrayZ + GlyphHeader::static_size);
|
const CompositeGlyphRecord *c = reinterpret_cast<const CompositeGlyphRecord *> (source_bytes.arrayZ + GlyphHeader::static_size);
|
||||||
|
@ -356,21 +376,18 @@ struct CompositeGlyph
|
||||||
unsigned i = 0, source_comp_len = 0;
|
unsigned i = 0, source_comp_len = 0;
|
||||||
for (const auto &component : it)
|
for (const auto &component : it)
|
||||||
{
|
{
|
||||||
/* last 4 points in points_with_deltas are phantom points and should not be included */
|
/* last 4 points in deltas are phantom points and should not be included */
|
||||||
if (i >= points_with_deltas.length - 4) {
|
if (i >= deltas.length - 4) return false;
|
||||||
free (o);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned comp_len = component.get_size ();
|
unsigned comp_len = component.get_size ();
|
||||||
if (component.is_anchored ())
|
if (component.is_anchored ())
|
||||||
{
|
{
|
||||||
hb_memcpy (p, &component, comp_len);
|
memcpy (p, &component, comp_len);
|
||||||
p += comp_len;
|
p += comp_len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned new_len = component.compile_with_point (points_with_deltas[i], p);
|
unsigned new_len = component.compile_with_deltas (deltas[i], p);
|
||||||
p += new_len;
|
p += new_len;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
@ -381,7 +398,7 @@ struct CompositeGlyph
|
||||||
if (source_len > source_comp_len)
|
if (source_len > source_comp_len)
|
||||||
{
|
{
|
||||||
unsigned instr_len = source_len - source_comp_len;
|
unsigned instr_len = source_len - source_comp_len;
|
||||||
hb_memcpy (p, (const char *)c + source_comp_len, instr_len);
|
memcpy (p, (const char *)c + source_comp_len, instr_len);
|
||||||
p += instr_len;
|
p += instr_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
#include "GlyphHeader.hh"
|
#include "GlyphHeader.hh"
|
||||||
#include "SimpleGlyph.hh"
|
#include "SimpleGlyph.hh"
|
||||||
#include "CompositeGlyph.hh"
|
#include "CompositeGlyph.hh"
|
||||||
#include "VarCompositeGlyph.hh"
|
|
||||||
#include "coord-setter.hh"
|
|
||||||
|
|
||||||
|
|
||||||
namespace OT {
|
namespace OT {
|
||||||
|
@ -29,14 +27,7 @@ enum phantom_point_index_t
|
||||||
|
|
||||||
struct Glyph
|
struct Glyph
|
||||||
{
|
{
|
||||||
enum glyph_type_t {
|
enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
|
||||||
EMPTY,
|
|
||||||
SIMPLE,
|
|
||||||
COMPOSITE,
|
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
|
||||||
VAR_COMPOSITE,
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
composite_iter_t get_composite_iterator () const
|
composite_iter_t get_composite_iterator () const
|
||||||
|
@ -44,25 +35,12 @@ struct Glyph
|
||||||
if (type != COMPOSITE) return composite_iter_t ();
|
if (type != COMPOSITE) return composite_iter_t ();
|
||||||
return CompositeGlyph (*header, bytes).iter ();
|
return CompositeGlyph (*header, bytes).iter ();
|
||||||
}
|
}
|
||||||
var_composite_iter_t get_var_composite_iterator () const
|
|
||||||
{
|
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
|
||||||
if (type != VAR_COMPOSITE) return var_composite_iter_t ();
|
|
||||||
return VarCompositeGlyph (*header, bytes).iter ();
|
|
||||||
#else
|
|
||||||
return var_composite_iter_t ();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
const hb_bytes_t trim_padding () const
|
const hb_bytes_t trim_padding () const
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
|
||||||
case VAR_COMPOSITE: return VarCompositeGlyph (*header, bytes).trim_padding ();
|
|
||||||
#endif
|
|
||||||
case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
|
case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
|
||||||
case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
|
case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
|
||||||
case EMPTY: return bytes;
|
|
||||||
default: return bytes;
|
default: return bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,72 +48,53 @@ struct Glyph
|
||||||
void drop_hints ()
|
void drop_hints ()
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
|
||||||
case VAR_COMPOSITE: return; // No hinting
|
|
||||||
#endif
|
|
||||||
case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
|
case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
|
||||||
case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
|
case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
|
||||||
case EMPTY: return;
|
default: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_overlaps_flag ()
|
void set_overlaps_flag ()
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
|
||||||
case VAR_COMPOSITE: return; // No overlaps flag
|
|
||||||
#endif
|
|
||||||
case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
|
case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
|
||||||
case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
|
case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
|
||||||
case EMPTY: return;
|
default: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
|
void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
|
||||||
case VAR_COMPOSITE: return; // No hinting
|
|
||||||
#endif
|
|
||||||
case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
|
case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
|
||||||
case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
|
case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
|
||||||
case EMPTY: return;
|
default: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_mtx (const hb_subset_plan_t *plan,
|
void update_mtx (const hb_subset_plan_t *plan,
|
||||||
int xMin, int xMax,
|
int xMin, int yMax,
|
||||||
int yMin, int yMax,
|
|
||||||
const contour_point_vector_t &all_points) const
|
const contour_point_vector_t &all_points) const
|
||||||
{
|
{
|
||||||
hb_codepoint_t new_gid = 0;
|
hb_codepoint_t new_gid = 0;
|
||||||
if (!plan->new_gid_for_old_gid (gid, &new_gid))
|
if (!plan->new_gid_for_old_gid (gid, &new_gid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (type != EMPTY)
|
|
||||||
{
|
|
||||||
plan->bounds_width_map.set (new_gid, xMax - xMin);
|
|
||||||
plan->bounds_height_map.set (new_gid, yMax - yMin);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned len = all_points.length;
|
unsigned len = all_points.length;
|
||||||
float leftSideX = all_points[len - 4].x;
|
float leftSideX = all_points[len - 4].x;
|
||||||
float rightSideX = all_points[len - 3].x;
|
float rightSideX = all_points[len - 3].x;
|
||||||
float topSideY = all_points[len - 2].y;
|
float topSideY = all_points[len - 2].y;
|
||||||
float bottomSideY = all_points[len - 1].y;
|
float bottomSideY = all_points[len - 1].y;
|
||||||
|
|
||||||
signed hori_aw = roundf (rightSideX - leftSideX);
|
int hori_aw = roundf (rightSideX - leftSideX);
|
||||||
if (hori_aw < 0) hori_aw = 0;
|
if (hori_aw < 0) hori_aw = 0;
|
||||||
int lsb = roundf (xMin - leftSideX);
|
int lsb = roundf (xMin - leftSideX);
|
||||||
plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
|
plan->hmtx_map->set (new_gid, hb_pair (hori_aw, lsb));
|
||||||
//flag value should be computed using non-empty glyphs
|
|
||||||
if (type != EMPTY && lsb != xMin)
|
|
||||||
plan->head_maxp_info.allXMinIsLsb = false;
|
|
||||||
|
|
||||||
signed vert_aw = roundf (topSideY - bottomSideY);
|
int vert_aw = roundf (topSideY - bottomSideY);
|
||||||
if (vert_aw < 0) vert_aw = 0;
|
if (vert_aw < 0) vert_aw = 0;
|
||||||
int tsb = roundf (topSideY - yMax);
|
int tsb = roundf (topSideY - yMax);
|
||||||
plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
|
plan->vmtx_map->set (new_gid, hb_pair (vert_aw, tsb));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compile_header_bytes (const hb_subset_plan_t *plan,
|
bool compile_header_bytes (const hb_subset_plan_t *plan,
|
||||||
|
@ -143,57 +102,40 @@ struct Glyph
|
||||||
hb_bytes_t &dest_bytes /* OUT */) const
|
hb_bytes_t &dest_bytes /* OUT */) const
|
||||||
{
|
{
|
||||||
GlyphHeader *glyph_header = nullptr;
|
GlyphHeader *glyph_header = nullptr;
|
||||||
if (!plan->pinned_at_default && type != EMPTY && all_points.length >= 4)
|
if (all_points.length > 4)
|
||||||
{
|
{
|
||||||
glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
|
glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
|
||||||
if (unlikely (!glyph_header)) return false;
|
if (unlikely (!glyph_header)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float xMin = 0, xMax = 0;
|
int xMin, xMax;
|
||||||
float yMin = 0, yMax = 0;
|
xMin = xMax = roundf (all_points[0].x);
|
||||||
if (all_points.length > 4)
|
|
||||||
{
|
int yMin, yMax;
|
||||||
xMin = xMax = all_points[0].x;
|
yMin = yMax = roundf (all_points[0].y);
|
||||||
yMin = yMax = all_points[0].y;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 1; i < all_points.length - 4; i++)
|
for (unsigned i = 1; i < all_points.length - 4; i++)
|
||||||
{
|
{
|
||||||
float x = all_points[i].x;
|
float rounded_x = roundf (all_points[i].x);
|
||||||
float y = all_points[i].y;
|
float rounded_y = roundf (all_points[i].y);
|
||||||
xMin = hb_min (xMin, x);
|
xMin = hb_min (xMin, rounded_x);
|
||||||
xMax = hb_max (xMax, x);
|
xMax = hb_max (xMax, rounded_x);
|
||||||
yMin = hb_min (yMin, y);
|
yMin = hb_min (yMin, rounded_y);
|
||||||
yMax = hb_max (yMax, y);
|
yMax = hb_max (yMax, rounded_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_mtx (plan, roundf (xMin), roundf (xMax), roundf (yMin), roundf (yMax), all_points);
|
update_mtx (plan, xMin, yMax, all_points);
|
||||||
|
|
||||||
int rounded_xMin = roundf (xMin);
|
|
||||||
int rounded_xMax = roundf (xMax);
|
|
||||||
int rounded_yMin = roundf (yMin);
|
|
||||||
int rounded_yMax = roundf (yMax);
|
|
||||||
|
|
||||||
if (type != EMPTY)
|
/*for empty glyphs: all_points only include phantom points.
|
||||||
{
|
*just update metrics and then return */
|
||||||
plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, rounded_xMin);
|
if (all_points.length == 4)
|
||||||
plan->head_maxp_info.yMin = hb_min (plan->head_maxp_info.yMin, rounded_yMin);
|
|
||||||
plan->head_maxp_info.xMax = hb_max (plan->head_maxp_info.xMax, rounded_xMax);
|
|
||||||
plan->head_maxp_info.yMax = hb_max (plan->head_maxp_info.yMax, rounded_yMax);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* when pinned at default, no need to compile glyph header
|
|
||||||
* and for empty glyphs: all_points only include phantom points.
|
|
||||||
* just update metrics and then return */
|
|
||||||
if (!glyph_header)
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
glyph_header->numberOfContours = header->numberOfContours;
|
glyph_header->numberOfContours = header->numberOfContours;
|
||||||
|
glyph_header->xMin = xMin;
|
||||||
glyph_header->xMin = rounded_xMin;
|
glyph_header->yMin = yMin;
|
||||||
glyph_header->yMin = rounded_yMin;
|
glyph_header->xMax = xMax;
|
||||||
glyph_header->xMax = rounded_xMax;
|
glyph_header->yMax = yMax;
|
||||||
glyph_header->yMax = rounded_yMax;
|
|
||||||
|
|
||||||
dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size);
|
dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size);
|
||||||
return true;
|
return true;
|
||||||
|
@ -203,74 +145,33 @@ struct Glyph
|
||||||
hb_font_t *font,
|
hb_font_t *font,
|
||||||
const glyf_accelerator_t &glyf,
|
const glyf_accelerator_t &glyf,
|
||||||
hb_bytes_t &dest_start, /* IN/OUT */
|
hb_bytes_t &dest_start, /* IN/OUT */
|
||||||
hb_bytes_t &dest_end /* OUT */)
|
hb_bytes_t &dest_end /* OUT */) const
|
||||||
{
|
{
|
||||||
contour_point_vector_t all_points, points_with_deltas;
|
contour_point_vector_t all_points, deltas;
|
||||||
unsigned composite_contours = 0;
|
get_points (font, glyf, all_points, &deltas, false);
|
||||||
head_maxp_info_t *head_maxp_info_p = &plan->head_maxp_info;
|
|
||||||
unsigned *composite_contours_p = &composite_contours;
|
|
||||||
|
|
||||||
// don't compute head/maxp values when glyph has no contours(type is EMPTY)
|
switch (type) {
|
||||||
// also ignore .notdef glyph when --notdef-outline is not enabled
|
case COMPOSITE:
|
||||||
if (type == EMPTY ||
|
if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
|
||||||
(gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)))
|
deltas,
|
||||||
{
|
dest_end))
|
||||||
head_maxp_info_p = nullptr;
|
return false;
|
||||||
composite_contours_p = nullptr;
|
break;
|
||||||
}
|
case SIMPLE:
|
||||||
|
if (!SimpleGlyph (*header, bytes).compile_bytes_with_deltas (all_points,
|
||||||
if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
|
plan->flags & HB_SUBSET_FLAGS_NO_HINTING,
|
||||||
return false;
|
dest_end))
|
||||||
|
return false;
|
||||||
// .notdef, set type to empty so we only update metrics and don't compile bytes for
|
break;
|
||||||
// it
|
default:
|
||||||
if (gid == 0 &&
|
/* set empty bytes for empty glyph
|
||||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
* do not use source glyph's pointers */
|
||||||
{
|
|
||||||
type = EMPTY;
|
|
||||||
dest_start = hb_bytes_t ();
|
dest_start = hb_bytes_t ();
|
||||||
dest_end = hb_bytes_t ();
|
dest_end = hb_bytes_t ();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//dont compile bytes when pinned at default, just recalculate bounds
|
return compile_header_bytes (plan, all_points, dest_start);
|
||||||
if (!plan->pinned_at_default)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
|
||||||
case VAR_COMPOSITE:
|
|
||||||
// TODO
|
|
||||||
dest_end = hb_bytes_t ();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case COMPOSITE:
|
|
||||||
if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
|
|
||||||
points_with_deltas,
|
|
||||||
dest_end))
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
case SIMPLE:
|
|
||||||
if (!SimpleGlyph (*header, bytes).compile_bytes_with_deltas (all_points,
|
|
||||||
plan->flags & HB_SUBSET_FLAGS_NO_HINTING,
|
|
||||||
dest_end))
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
case EMPTY:
|
|
||||||
/* set empty bytes for empty glyph
|
|
||||||
* do not use source glyph's pointers */
|
|
||||||
dest_start = hb_bytes_t ();
|
|
||||||
dest_end = hb_bytes_t ();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!compile_header_bytes (plan, all_points, dest_start))
|
|
||||||
{
|
|
||||||
dest_end.fini ();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -280,69 +181,39 @@ struct Glyph
|
||||||
template <typename accelerator_t>
|
template <typename accelerator_t>
|
||||||
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
||||||
contour_point_vector_t &all_points /* OUT */,
|
contour_point_vector_t &all_points /* OUT */,
|
||||||
contour_point_vector_t *points_with_deltas = nullptr, /* OUT */
|
contour_point_vector_t *deltas = nullptr, /* OUT */
|
||||||
head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
|
|
||||||
unsigned *composite_contours = nullptr, /* OUT */
|
|
||||||
bool shift_points_hori = true,
|
|
||||||
bool use_my_metrics = true,
|
bool use_my_metrics = true,
|
||||||
bool phantom_only = false,
|
bool phantom_only = false,
|
||||||
hb_array_t<int> coords = hb_array_t<int> (),
|
unsigned int depth = 0) const
|
||||||
unsigned int depth = 0,
|
|
||||||
unsigned *edge_count = nullptr) const
|
|
||||||
{
|
{
|
||||||
if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
|
if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
|
||||||
unsigned stack_edge_count = 0;
|
|
||||||
if (!edge_count) edge_count = &stack_edge_count;
|
|
||||||
if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false;
|
|
||||||
(*edge_count)++;
|
|
||||||
|
|
||||||
if (head_maxp_info)
|
|
||||||
{
|
|
||||||
head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!coords)
|
|
||||||
coords = hb_array (font->coords, font->num_coords);
|
|
||||||
|
|
||||||
contour_point_vector_t stack_points;
|
contour_point_vector_t stack_points;
|
||||||
bool inplace = type == SIMPLE && all_points.length == 0;
|
bool inplace = type == SIMPLE && all_points.length == 0;
|
||||||
/* Load into all_points if it's empty, as an optimization. */
|
/* Load into all_points if it's empty, as an optimization. */
|
||||||
contour_point_vector_t &points = inplace ? all_points : stack_points;
|
contour_point_vector_t &points = inplace ? all_points : stack_points;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SIMPLE:
|
|
||||||
if (depth == 0 && head_maxp_info)
|
|
||||||
head_maxp_info->maxContours = hb_max (head_maxp_info->maxContours, (unsigned) header->numberOfContours);
|
|
||||||
if (depth > 0 && composite_contours)
|
|
||||||
*composite_contours += (unsigned) header->numberOfContours;
|
|
||||||
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
case COMPOSITE:
|
case COMPOSITE:
|
||||||
{
|
{
|
||||||
for (auto &item : get_composite_iterator ())
|
/* pseudo component points for each component in composite glyph */
|
||||||
if (unlikely (!item.get_points (points))) return false;
|
unsigned num_points = hb_len (CompositeGlyph (*header, bytes).iter ());
|
||||||
|
if (unlikely (!points.resize (num_points))) return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
case SIMPLE:
|
||||||
case VAR_COMPOSITE:
|
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
|
||||||
{
|
return false;
|
||||||
for (auto &item : get_var_composite_iterator ())
|
|
||||||
if (unlikely (!item.get_points (points))) return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
case EMPTY:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init phantom points */
|
/* Init phantom points */
|
||||||
if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
|
if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
|
||||||
hb_array_t<contour_point_t> phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
|
hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
|
||||||
{
|
{
|
||||||
int lsb = 0;
|
int lsb = 0;
|
||||||
int h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
|
int h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
|
||||||
(int) header->xMin - lsb : 0;
|
(int) header->xMin - lsb : 0;
|
||||||
HB_UNUSED int tsb = 0;
|
int tsb = 0;
|
||||||
int v_orig = (int) header->yMax +
|
int v_orig = (int) header->yMax +
|
||||||
#ifndef HB_NO_VERTICAL
|
#ifndef HB_NO_VERTICAL
|
||||||
((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb)
|
((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb)
|
||||||
|
@ -359,29 +230,35 @@ struct Glyph
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
phantoms[PHANTOM_LEFT].x = h_delta;
|
phantoms[PHANTOM_LEFT].x = h_delta;
|
||||||
phantoms[PHANTOM_RIGHT].x = (int) h_adv + h_delta;
|
phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
|
||||||
phantoms[PHANTOM_TOP].y = v_orig;
|
phantoms[PHANTOM_TOP].y = v_orig;
|
||||||
phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
|
phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (deltas != nullptr && depth == 0 && type == COMPOSITE)
|
||||||
|
{
|
||||||
|
if (unlikely (!deltas->resize (points.length))) return false;
|
||||||
|
for (unsigned i = 0 ; i < points.length; i++)
|
||||||
|
deltas->arrayZ[i] = points.arrayZ[i];
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
glyf_accelerator.gvar->apply_deltas_to_points (gid,
|
glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
|
||||||
coords,
|
|
||||||
points.as_array ());
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
|
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
|
||||||
// with child glyphs' points
|
// with child glyphs' points
|
||||||
if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE)
|
if (deltas != nullptr && depth == 0 && type == COMPOSITE)
|
||||||
{
|
{
|
||||||
if (unlikely (!points_with_deltas->resize (points.length))) return false;
|
for (unsigned i = 0 ; i < points.length; i++)
|
||||||
points_with_deltas->copy_vector (points);
|
{
|
||||||
|
deltas->arrayZ[i].x = points.arrayZ[i].x - deltas->arrayZ[i].x;
|
||||||
|
deltas->arrayZ[i].y = points.arrayZ[i].y - deltas->arrayZ[i].y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SIMPLE:
|
case SIMPLE:
|
||||||
if (depth == 0 && head_maxp_info)
|
|
||||||
head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, points.length - 4);
|
|
||||||
if (!inplace)
|
if (!inplace)
|
||||||
all_points.extend (points.as_array ());
|
all_points.extend (points.as_array ());
|
||||||
break;
|
break;
|
||||||
|
@ -393,18 +270,8 @@ struct Glyph
|
||||||
{
|
{
|
||||||
comp_points.reset ();
|
comp_points.reset ();
|
||||||
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
||||||
.get_points (font,
|
.get_points (font, glyf_accelerator, comp_points,
|
||||||
glyf_accelerator,
|
deltas, use_my_metrics, phantom_only, depth + 1)))
|
||||||
comp_points,
|
|
||||||
points_with_deltas,
|
|
||||||
head_maxp_info,
|
|
||||||
composite_contours,
|
|
||||||
shift_points_hori,
|
|
||||||
use_my_metrics,
|
|
||||||
phantom_only,
|
|
||||||
coords,
|
|
||||||
depth + 1,
|
|
||||||
edge_count)))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
||||||
|
@ -412,12 +279,11 @@ struct Glyph
|
||||||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||||
|
|
||||||
float matrix[4];
|
/* Apply component transformation & translation */
|
||||||
contour_point_t default_trans;
|
item.transform_points (comp_points);
|
||||||
item.get_transformation (matrix, default_trans);
|
|
||||||
|
|
||||||
/* Apply component transformation & translation (with deltas applied) */
|
/* Apply translation from gvar */
|
||||||
item.transform_points (comp_points, matrix, points[comp_index]);
|
comp_points.translate (points[comp_index]);
|
||||||
|
|
||||||
if (item.is_anchored ())
|
if (item.is_anchored ())
|
||||||
{
|
{
|
||||||
|
@ -433,80 +299,18 @@ struct Glyph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT));
|
all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
|
||||||
|
|
||||||
if (all_points.length > HB_GLYF_MAX_POINTS)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
comp_index++;
|
comp_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head_maxp_info && depth == 0)
|
|
||||||
{
|
|
||||||
if (composite_contours)
|
|
||||||
head_maxp_info->maxCompositeContours = hb_max (head_maxp_info->maxCompositeContours, *composite_contours);
|
|
||||||
head_maxp_info->maxCompositePoints = hb_max (head_maxp_info->maxCompositePoints, all_points.length);
|
|
||||||
head_maxp_info->maxComponentElements = hb_max (head_maxp_info->maxComponentElements, comp_index);
|
|
||||||
}
|
|
||||||
all_points.extend (phantoms);
|
all_points.extend (phantoms);
|
||||||
} break;
|
} break;
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
default:
|
||||||
case VAR_COMPOSITE:
|
|
||||||
{
|
|
||||||
contour_point_vector_t comp_points;
|
|
||||||
hb_array_t<contour_point_t> points_left = points.as_array ();
|
|
||||||
for (auto &item : get_var_composite_iterator ())
|
|
||||||
{
|
|
||||||
hb_array_t<contour_point_t> record_points = points_left.sub_array (0, item.get_num_points ());
|
|
||||||
|
|
||||||
comp_points.reset ();
|
|
||||||
|
|
||||||
auto component_coords = coords;
|
|
||||||
if (item.is_reset_unspecified_axes ())
|
|
||||||
component_coords = hb_array<int> ();
|
|
||||||
|
|
||||||
coord_setter_t coord_setter (component_coords);
|
|
||||||
item.set_variations (coord_setter, record_points);
|
|
||||||
|
|
||||||
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
|
||||||
.get_points (font,
|
|
||||||
glyf_accelerator,
|
|
||||||
comp_points,
|
|
||||||
points_with_deltas,
|
|
||||||
head_maxp_info,
|
|
||||||
nullptr,
|
|
||||||
shift_points_hori,
|
|
||||||
use_my_metrics,
|
|
||||||
phantom_only,
|
|
||||||
coord_setter.get_coords (),
|
|
||||||
depth + 1,
|
|
||||||
edge_count)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Apply component transformation */
|
|
||||||
item.transform_points (record_points, comp_points);
|
|
||||||
|
|
||||||
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
|
||||||
if (use_my_metrics && item.is_use_my_metrics ())
|
|
||||||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
|
||||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
|
||||||
|
|
||||||
all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT));
|
|
||||||
|
|
||||||
if (all_points.length > HB_GLYF_MAX_POINTS)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
points_left += item.get_num_points ();
|
|
||||||
}
|
|
||||||
all_points.extend (phantoms);
|
all_points.extend (phantoms);
|
||||||
} break;
|
|
||||||
#endif
|
|
||||||
case EMPTY:
|
|
||||||
all_points.extend (phantoms);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth == 0 && shift_points_hori) /* Apply at top level */
|
if (depth == 0) /* Apply at top level */
|
||||||
{
|
{
|
||||||
/* Undocumented rasterizer behavior:
|
/* Undocumented rasterizer behavior:
|
||||||
* Shift points horizontally by the updated left side bearing
|
* Shift points horizontally by the updated left side bearing
|
||||||
|
@ -527,26 +331,15 @@ struct Glyph
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_bytes_t get_bytes () const { return bytes; }
|
hb_bytes_t get_bytes () const { return bytes; }
|
||||||
glyph_type_t get_type () const { return type; }
|
|
||||||
const GlyphHeader *get_header () const { return header; }
|
|
||||||
|
|
||||||
Glyph () : bytes (),
|
Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
|
||||||
header (bytes.as<GlyphHeader> ()),
|
hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_),
|
||||||
gid (-1),
|
header (bytes.as<GlyphHeader> ()),
|
||||||
type(EMPTY)
|
gid (gid_)
|
||||||
{}
|
|
||||||
|
|
||||||
Glyph (hb_bytes_t bytes_,
|
|
||||||
hb_codepoint_t gid_ = (unsigned) -1) : bytes (bytes_),
|
|
||||||
header (bytes.as<GlyphHeader> ()),
|
|
||||||
gid (gid_)
|
|
||||||
{
|
{
|
||||||
int num_contours = header->numberOfContours;
|
int num_contours = header->numberOfContours;
|
||||||
if (unlikely (num_contours == 0)) type = EMPTY;
|
if (unlikely (num_contours == 0)) type = EMPTY;
|
||||||
else if (num_contours > 0) type = SIMPLE;
|
else if (num_contours > 0) type = SIMPLE;
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
|
||||||
else if (num_contours == -2) type = VAR_COMPOSITE;
|
|
||||||
#endif
|
|
||||||
else type = COMPOSITE; /* negative numbers */
|
else type = COMPOSITE; /* negative numbers */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,7 +347,7 @@ struct Glyph
|
||||||
hb_bytes_t bytes;
|
hb_bytes_t bytes;
|
||||||
const GlyphHeader *header;
|
const GlyphHeader *header;
|
||||||
hb_codepoint_t gid;
|
hb_codepoint_t gid;
|
||||||
glyph_type_t type;
|
unsigned type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,10 @@ struct GlyphHeader
|
||||||
/* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
|
/* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
|
||||||
int lsb = hb_min (xMin, xMax);
|
int lsb = hb_min (xMin, xMax);
|
||||||
(void) glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb);
|
(void) glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb);
|
||||||
extents->x_bearing = lsb;
|
extents->x_bearing = font->em_scale_x (lsb);
|
||||||
extents->y_bearing = hb_max (yMin, yMax);
|
extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax));
|
||||||
extents->width = hb_max (xMin, xMax) - hb_min (xMin, xMax);
|
extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax));
|
||||||
extents->height = hb_min (yMin, yMax) - hb_max (yMin, yMax);
|
extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax));
|
||||||
|
|
||||||
font->scale_glyph_extents (extents);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ struct SimpleGlyph
|
||||||
FLAG_X_SAME = 0x10,
|
FLAG_X_SAME = 0x10,
|
||||||
FLAG_Y_SAME = 0x20,
|
FLAG_Y_SAME = 0x20,
|
||||||
FLAG_OVERLAP_SIMPLE = 0x40,
|
FLAG_OVERLAP_SIMPLE = 0x40,
|
||||||
FLAG_CUBIC = 0x80
|
FLAG_RESERVED2 = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
const GlyphHeader &header;
|
const GlyphHeader &header;
|
||||||
|
@ -34,11 +34,6 @@ struct SimpleGlyph
|
||||||
unsigned int length (unsigned int instruction_len) const
|
unsigned int length (unsigned int instruction_len) const
|
||||||
{ return instruction_len_offset () + 2 + instruction_len; }
|
{ return instruction_len_offset () + 2 + instruction_len; }
|
||||||
|
|
||||||
bool has_instructions_length () const
|
|
||||||
{
|
|
||||||
return instruction_len_offset () + 2 <= bytes.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int instructions_length () const
|
unsigned int instructions_length () const
|
||||||
{
|
{
|
||||||
unsigned int instruction_length_offset = instruction_len_offset ();
|
unsigned int instruction_length_offset = instruction_len_offset ();
|
||||||
|
@ -99,7 +94,6 @@ struct SimpleGlyph
|
||||||
/* zero instruction length */
|
/* zero instruction length */
|
||||||
void drop_hints ()
|
void drop_hints ()
|
||||||
{
|
{
|
||||||
if (!has_instructions_length ()) return;
|
|
||||||
GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
|
GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
|
||||||
(HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
|
(HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
|
||||||
}
|
}
|
||||||
|
@ -138,8 +132,8 @@ struct SimpleGlyph
|
||||||
if (unlikely (p + 1 > end)) return false;
|
if (unlikely (p + 1 > end)) return false;
|
||||||
unsigned int repeat_count = *p++;
|
unsigned int repeat_count = *p++;
|
||||||
unsigned stop = hb_min (i + repeat_count, count);
|
unsigned stop = hb_min (i + repeat_count, count);
|
||||||
for (; i < stop; i++)
|
for (; i < stop;)
|
||||||
points_.arrayZ[i].flag = flag;
|
points_.arrayZ[i++].flag = flag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -190,7 +184,7 @@ struct SimpleGlyph
|
||||||
if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours]))) return false;
|
if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours]))) return false;
|
||||||
unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
|
unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
|
||||||
|
|
||||||
points_.alloc (num_points + 4, true); // Allocate for phantom points, to avoid a possible copy
|
points_.alloc (num_points + 4); // Allocate for phantom points, to avoid a possible copy
|
||||||
if (!points_.resize (num_points)) return false;
|
if (!points_.resize (num_points)) return false;
|
||||||
if (phantom_only) return true;
|
if (phantom_only) return true;
|
||||||
|
|
||||||
|
@ -229,34 +223,33 @@ struct SimpleGlyph
|
||||||
if (value > 0) flag |= same_flag;
|
if (value > 0) flag |= same_flag;
|
||||||
else value = -value;
|
else value = -value;
|
||||||
|
|
||||||
coords.arrayZ[coords.length++] = (uint8_t) value;
|
coords.push ((uint8_t)value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int16_t val = value;
|
int16_t val = value;
|
||||||
coords.arrayZ[coords.length++] = val >> 8;
|
coords.push (val >> 8);
|
||||||
coords.arrayZ[coords.length++] = val & 0xff;
|
coords.push (val & 0xff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void encode_flag (uint8_t &flag,
|
static void encode_flag (uint8_t &flag,
|
||||||
uint8_t &repeat,
|
uint8_t &repeat,
|
||||||
uint8_t lastflag,
|
uint8_t &lastflag,
|
||||||
hb_vector_t<uint8_t> &flags /* OUT */)
|
hb_vector_t<uint8_t> &flags /* OUT */)
|
||||||
{
|
{
|
||||||
if (flag == lastflag && repeat != 255)
|
if (flag == lastflag && repeat != 255)
|
||||||
{
|
{
|
||||||
repeat++;
|
repeat = repeat + 1;
|
||||||
if (repeat == 1)
|
if (repeat == 1)
|
||||||
{
|
{
|
||||||
/* We know there's room. */
|
flags.push(flag);
|
||||||
flags.arrayZ[flags.length++] = flag;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned len = flags.length;
|
unsigned len = flags.length;
|
||||||
flags.arrayZ[len-2] = flag | FLAG_REPEAT;
|
flags[len-2] = flag | FLAG_REPEAT;
|
||||||
flags.arrayZ[len-1] = repeat;
|
flags[len-1] = repeat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -264,6 +257,7 @@ struct SimpleGlyph
|
||||||
repeat = 0;
|
repeat = 0;
|
||||||
flags.push (flag);
|
flags.push (flag);
|
||||||
}
|
}
|
||||||
|
lastflag = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compile_bytes_with_deltas (const contour_point_vector_t &all_points,
|
bool compile_bytes_with_deltas (const contour_point_vector_t &all_points,
|
||||||
|
@ -275,30 +269,33 @@ struct SimpleGlyph
|
||||||
dest_bytes = hb_bytes_t ();
|
dest_bytes = hb_bytes_t ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
//convert absolute values to relative values
|
||||||
unsigned num_points = all_points.length - 4;
|
unsigned num_points = all_points.length - 4;
|
||||||
|
hb_vector_t<hb_pair_t<int, int>> deltas;
|
||||||
hb_vector_t<uint8_t> flags, x_coords, y_coords;
|
deltas.resize (num_points);
|
||||||
if (unlikely (!flags.alloc (num_points, true))) return false;
|
|
||||||
if (unlikely (!x_coords.alloc (2*num_points, true))) return false;
|
|
||||||
if (unlikely (!y_coords.alloc (2*num_points, true))) return false;
|
|
||||||
|
|
||||||
uint8_t lastflag = 255, repeat = 0;
|
|
||||||
int prev_x = 0, prev_y = 0;
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < num_points; i++)
|
for (unsigned i = 0; i < num_points; i++)
|
||||||
{
|
{
|
||||||
uint8_t flag = all_points.arrayZ[i].flag;
|
deltas[i].first = i == 0 ? roundf (all_points[i].x) : roundf (all_points[i].x) - roundf (all_points[i-1].x);
|
||||||
|
deltas[i].second = i == 0 ? roundf (all_points[i].y) : roundf (all_points[i].y) - roundf (all_points[i-1].y);
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_vector_t<uint8_t> flags, x_coords, y_coords;
|
||||||
|
flags.alloc (num_points);
|
||||||
|
x_coords.alloc (2*num_points);
|
||||||
|
y_coords.alloc (2*num_points);
|
||||||
|
|
||||||
|
uint8_t lastflag = 0, repeat = 0;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < num_points; i++)
|
||||||
|
{
|
||||||
|
uint8_t flag = all_points[i].flag;
|
||||||
flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE;
|
flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE;
|
||||||
|
|
||||||
int cur_x = roundf (all_points.arrayZ[i].x);
|
encode_coord (deltas[i].first, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
|
||||||
int cur_y = roundf (all_points.arrayZ[i].y);
|
encode_coord (deltas[i].second, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
|
||||||
encode_coord (cur_x - prev_x, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
|
if (i == 0) lastflag = flag + 1; //make lastflag != flag for the first point
|
||||||
encode_coord (cur_y - prev_y, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
|
|
||||||
encode_flag (flag, repeat, lastflag, flags);
|
encode_flag (flag, repeat, lastflag, flags);
|
||||||
|
|
||||||
prev_x = cur_x;
|
|
||||||
prev_y = cur_y;
|
|
||||||
lastflag = flag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned len_before_instrs = 2 * header.numberOfContours + 2;
|
unsigned len_before_instrs = 2 * header.numberOfContours + 2;
|
||||||
|
@ -308,29 +305,29 @@ struct SimpleGlyph
|
||||||
if (!no_hinting)
|
if (!no_hinting)
|
||||||
total_len += len_instrs;
|
total_len += len_instrs;
|
||||||
|
|
||||||
char *p = (char *) hb_malloc (total_len);
|
char *p = (char *) hb_calloc (total_len, sizeof (char));
|
||||||
if (unlikely (!p)) return false;
|
if (unlikely (!p)) return false;
|
||||||
|
|
||||||
const char *src = bytes.arrayZ + GlyphHeader::static_size;
|
const char *src = bytes.arrayZ + GlyphHeader::static_size;
|
||||||
char *cur = p;
|
char *cur = p;
|
||||||
hb_memcpy (p, src, len_before_instrs);
|
memcpy (p, src, len_before_instrs);
|
||||||
|
|
||||||
cur += len_before_instrs;
|
cur += len_before_instrs;
|
||||||
src += len_before_instrs;
|
src += len_before_instrs;
|
||||||
|
|
||||||
if (!no_hinting)
|
if (!no_hinting)
|
||||||
{
|
{
|
||||||
hb_memcpy (cur, src, len_instrs);
|
memcpy (cur, src, len_instrs);
|
||||||
cur += len_instrs;
|
cur += len_instrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_memcpy (cur, flags.arrayZ, flags.length);
|
memcpy (cur, flags.arrayZ, flags.length);
|
||||||
cur += flags.length;
|
cur += flags.length;
|
||||||
|
|
||||||
hb_memcpy (cur, x_coords.arrayZ, x_coords.length);
|
memcpy (cur, x_coords.arrayZ, x_coords.length);
|
||||||
cur += x_coords.length;
|
cur += x_coords.length;
|
||||||
|
|
||||||
hb_memcpy (cur, y_coords.arrayZ, y_coords.length);
|
memcpy (cur, y_coords.arrayZ, y_coords.length);
|
||||||
|
|
||||||
dest_bytes = hb_bytes_t (p, total_len);
|
dest_bytes = hb_bytes_t (p, total_len);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -14,27 +14,22 @@ namespace glyf_impl {
|
||||||
|
|
||||||
struct SubsetGlyph
|
struct SubsetGlyph
|
||||||
{
|
{
|
||||||
|
hb_codepoint_t new_gid;
|
||||||
hb_codepoint_t old_gid;
|
hb_codepoint_t old_gid;
|
||||||
Glyph source_glyph;
|
Glyph source_glyph;
|
||||||
hb_bytes_t dest_start; /* region of source_glyph to copy first */
|
hb_bytes_t dest_start; /* region of source_glyph to copy first */
|
||||||
hb_bytes_t dest_end; /* region of source_glyph to copy second */
|
hb_bytes_t dest_end; /* region of source_glyph to copy second */
|
||||||
bool allocated;
|
|
||||||
|
|
||||||
bool serialize (hb_serialize_context_t *c,
|
bool serialize (hb_serialize_context_t *c,
|
||||||
bool use_short_loca,
|
bool use_short_loca,
|
||||||
const hb_subset_plan_t *plan)
|
const hb_subset_plan_t *plan) const
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
|
|
||||||
hb_bytes_t dest_glyph = dest_start.copy (c);
|
hb_bytes_t dest_glyph = dest_start.copy (c);
|
||||||
hb_bytes_t end_copy = dest_end.copy (c);
|
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
|
||||||
if (!end_copy.arrayZ || !dest_glyph.arrayZ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + end_copy.length);
|
|
||||||
unsigned int pad_length = use_short_loca ? padding () : 0;
|
unsigned int pad_length = use_short_loca ? padding () : 0;
|
||||||
DEBUG_MSG (SUBSET, nullptr, "serialize %u byte glyph, width %u pad %u", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
|
DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
|
||||||
|
|
||||||
HBUINT8 pad;
|
HBUINT8 pad;
|
||||||
pad = 0;
|
pad = 0;
|
||||||
|
@ -46,68 +41,13 @@ struct SubsetGlyph
|
||||||
|
|
||||||
if (unlikely (!dest_glyph.length)) return_trace (true);
|
if (unlikely (!dest_glyph.length)) return_trace (true);
|
||||||
|
|
||||||
/* update components gids. */
|
/* update components gids */
|
||||||
for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
|
for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
|
||||||
{
|
{
|
||||||
hb_codepoint_t new_gid;
|
hb_codepoint_t new_gid;
|
||||||
if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
|
if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
|
||||||
const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid);
|
const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid);
|
||||||
}
|
}
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
|
||||||
for (auto &_ : Glyph (dest_glyph).get_var_composite_iterator ())
|
|
||||||
{
|
|
||||||
hb_codepoint_t new_gid;
|
|
||||||
if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
|
|
||||||
const_cast<VarCompositeGlyphRecord &> (_).set_gid (new_gid);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HB_NO_BEYOND_64K
|
|
||||||
auto it = Glyph (dest_glyph).get_composite_iterator ();
|
|
||||||
if (it)
|
|
||||||
{
|
|
||||||
/* lower GID24 to GID16 in components if possible.
|
|
||||||
*
|
|
||||||
* TODO: VarComposite. Not as critical, since VarComposite supports
|
|
||||||
* gid24 from the first version. */
|
|
||||||
char *p = it ? (char *) &*it : nullptr;
|
|
||||||
char *q = p;
|
|
||||||
const char *end = dest_glyph.arrayZ + dest_glyph.length;
|
|
||||||
while (it)
|
|
||||||
{
|
|
||||||
auto &rec = const_cast<CompositeGlyphRecord &> (*it);
|
|
||||||
++it;
|
|
||||||
|
|
||||||
q += rec.get_size ();
|
|
||||||
|
|
||||||
rec.lower_gid_24_to_16 ();
|
|
||||||
|
|
||||||
unsigned size = rec.get_size ();
|
|
||||||
|
|
||||||
memmove (p, &rec, size);
|
|
||||||
|
|
||||||
p += size;
|
|
||||||
}
|
|
||||||
memmove (p, q, end - q);
|
|
||||||
p += end - q;
|
|
||||||
|
|
||||||
/* We want to shorten the glyph, but we can't do that without
|
|
||||||
* updating the length in the loca table, which is already
|
|
||||||
* written out :-(. So we just fill the rest of the glyph with
|
|
||||||
* harmless instructions, since that's what they will be
|
|
||||||
* interpreted as.
|
|
||||||
*
|
|
||||||
* Should move the lowering to _populate_subset_glyphs() to
|
|
||||||
* fix this issue. */
|
|
||||||
|
|
||||||
hb_memset (p, 0x7A /* TrueType instruction ROFF; harmless */, end - p);
|
|
||||||
p += end - p;
|
|
||||||
dest_glyph = hb_bytes_t (dest_glyph.arrayZ, p - (char *) dest_glyph.arrayZ);
|
|
||||||
|
|
||||||
// TODO: Padding; & trim serialized bytes.
|
|
||||||
// TODO: Update length in loca. Ugh.
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||||
Glyph (dest_glyph).drop_hints ();
|
Glyph (dest_glyph).drop_hints ();
|
||||||
|
@ -121,18 +61,12 @@ struct SubsetGlyph
|
||||||
bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
|
bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
|
||||||
hb_font_t *font,
|
hb_font_t *font,
|
||||||
const glyf_accelerator_t &glyf)
|
const glyf_accelerator_t &glyf)
|
||||||
{
|
{ return source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end); }
|
||||||
allocated = source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end);
|
|
||||||
return allocated;
|
|
||||||
}
|
|
||||||
|
|
||||||
void free_compiled_bytes ()
|
void free_compiled_bytes ()
|
||||||
{
|
{
|
||||||
if (likely (allocated)) {
|
dest_start.fini ();
|
||||||
allocated = false;
|
dest_end.fini ();
|
||||||
dest_start.fini ();
|
|
||||||
dest_end.fini ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void drop_hints_bytes ()
|
void drop_hints_bytes ()
|
||||||
|
|
|
@ -1,369 +0,0 @@
|
||||||
#ifndef OT_GLYF_VARCOMPOSITEGLYPH_HH
|
|
||||||
#define OT_GLYF_VARCOMPOSITEGLYPH_HH
|
|
||||||
|
|
||||||
|
|
||||||
#include "../../hb-open-type.hh"
|
|
||||||
#include "coord-setter.hh"
|
|
||||||
|
|
||||||
|
|
||||||
namespace OT {
|
|
||||||
namespace glyf_impl {
|
|
||||||
|
|
||||||
|
|
||||||
struct VarCompositeGlyphRecord
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
enum var_composite_glyph_flag_t
|
|
||||||
{
|
|
||||||
USE_MY_METRICS = 0x0001,
|
|
||||||
AXIS_INDICES_ARE_SHORT = 0x0002,
|
|
||||||
UNIFORM_SCALE = 0x0004,
|
|
||||||
HAVE_TRANSLATE_X = 0x0008,
|
|
||||||
HAVE_TRANSLATE_Y = 0x0010,
|
|
||||||
HAVE_ROTATION = 0x0020,
|
|
||||||
HAVE_SCALE_X = 0x0040,
|
|
||||||
HAVE_SCALE_Y = 0x0080,
|
|
||||||
HAVE_SKEW_X = 0x0100,
|
|
||||||
HAVE_SKEW_Y = 0x0200,
|
|
||||||
HAVE_TCENTER_X = 0x0400,
|
|
||||||
HAVE_TCENTER_Y = 0x0800,
|
|
||||||
GID_IS_24BIT = 0x1000,
|
|
||||||
AXES_HAVE_VARIATION = 0x2000,
|
|
||||||
RESET_UNSPECIFIED_AXES = 0x4000,
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
unsigned int get_size () const
|
|
||||||
{
|
|
||||||
unsigned int size = min_size;
|
|
||||||
|
|
||||||
unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 4 : 3;
|
|
||||||
size += numAxes * axis_width;
|
|
||||||
|
|
||||||
// gid
|
|
||||||
size += 2;
|
|
||||||
if (flags & GID_IS_24BIT) size += 1;
|
|
||||||
|
|
||||||
if (flags & HAVE_TRANSLATE_X) size += 2;
|
|
||||||
if (flags & HAVE_TRANSLATE_Y) size += 2;
|
|
||||||
if (flags & HAVE_ROTATION) size += 2;
|
|
||||||
if (flags & HAVE_SCALE_X) size += 2;
|
|
||||||
if (flags & HAVE_SCALE_Y) size += 2;
|
|
||||||
if (flags & HAVE_SKEW_X) size += 2;
|
|
||||||
if (flags & HAVE_SKEW_Y) size += 2;
|
|
||||||
if (flags & HAVE_TCENTER_X) size += 2;
|
|
||||||
if (flags & HAVE_TCENTER_Y) size += 2;
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_more () const { return true; }
|
|
||||||
|
|
||||||
bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
|
|
||||||
bool is_reset_unspecified_axes () const { return flags & RESET_UNSPECIFIED_AXES; }
|
|
||||||
|
|
||||||
hb_codepoint_t get_gid () const
|
|
||||||
{
|
|
||||||
if (flags & GID_IS_24BIT)
|
|
||||||
return StructAfter<const HBGlyphID24> (numAxes);
|
|
||||||
else
|
|
||||||
return StructAfter<const HBGlyphID16> (numAxes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_gid (hb_codepoint_t gid)
|
|
||||||
{
|
|
||||||
if (flags & GID_IS_24BIT)
|
|
||||||
StructAfter<HBGlyphID24> (numAxes) = gid;
|
|
||||||
else
|
|
||||||
StructAfter<HBGlyphID16> (numAxes) = gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned get_numAxes () const
|
|
||||||
{
|
|
||||||
return numAxes;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned get_num_points () const
|
|
||||||
{
|
|
||||||
unsigned num = 0;
|
|
||||||
if (flags & AXES_HAVE_VARIATION) num += numAxes;
|
|
||||||
if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) num++;
|
|
||||||
if (flags & HAVE_ROTATION) num++;
|
|
||||||
if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) num++;
|
|
||||||
if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) num++;
|
|
||||||
if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) num++;
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
void transform_points (hb_array_t<contour_point_t> record_points,
|
|
||||||
contour_point_vector_t &points) const
|
|
||||||
{
|
|
||||||
float matrix[4];
|
|
||||||
contour_point_t trans;
|
|
||||||
|
|
||||||
get_transformation_from_points (record_points, matrix, trans);
|
|
||||||
|
|
||||||
points.transform (matrix);
|
|
||||||
points.translate (trans);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void transform (float (&matrix)[4], contour_point_t &trans,
|
|
||||||
float (other)[6])
|
|
||||||
{
|
|
||||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L268
|
|
||||||
float xx1 = other[0];
|
|
||||||
float xy1 = other[1];
|
|
||||||
float yx1 = other[2];
|
|
||||||
float yy1 = other[3];
|
|
||||||
float dx1 = other[4];
|
|
||||||
float dy1 = other[5];
|
|
||||||
float xx2 = matrix[0];
|
|
||||||
float xy2 = matrix[1];
|
|
||||||
float yx2 = matrix[2];
|
|
||||||
float yy2 = matrix[3];
|
|
||||||
float dx2 = trans.x;
|
|
||||||
float dy2 = trans.y;
|
|
||||||
|
|
||||||
matrix[0] = xx1*xx2 + xy1*yx2;
|
|
||||||
matrix[1] = xx1*xy2 + xy1*yy2;
|
|
||||||
matrix[2] = yx1*xx2 + yy1*yx2;
|
|
||||||
matrix[3] = yx1*xy2 + yy1*yy2;
|
|
||||||
trans.x = xx2*dx1 + yx2*dy1 + dx2;
|
|
||||||
trans.y = xy2*dx1 + yy2*dy1 + dy2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void translate (float (&matrix)[4], contour_point_t &trans,
|
|
||||||
float translateX, float translateY)
|
|
||||||
{
|
|
||||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L213
|
|
||||||
float other[6] = {1.f, 0.f, 0.f, 1.f, translateX, translateY};
|
|
||||||
transform (matrix, trans, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void scale (float (&matrix)[4], contour_point_t &trans,
|
|
||||||
float scaleX, float scaleY)
|
|
||||||
{
|
|
||||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L224
|
|
||||||
float other[6] = {scaleX, 0.f, 0.f, scaleY, 0.f, 0.f};
|
|
||||||
transform (matrix, trans, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rotate (float (&matrix)[4], contour_point_t &trans,
|
|
||||||
float rotation)
|
|
||||||
{
|
|
||||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
|
|
||||||
rotation = rotation * HB_PI;
|
|
||||||
float c = cosf (rotation);
|
|
||||||
float s = sinf (rotation);
|
|
||||||
float other[6] = {c, s, -s, c, 0.f, 0.f};
|
|
||||||
transform (matrix, trans, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void skew (float (&matrix)[4], contour_point_t &trans,
|
|
||||||
float skewX, float skewY)
|
|
||||||
{
|
|
||||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
|
|
||||||
skewX = skewX * HB_PI;
|
|
||||||
skewY = skewY * HB_PI;
|
|
||||||
float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f};
|
|
||||||
transform (matrix, trans, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool get_points (contour_point_vector_t &points) const
|
|
||||||
{
|
|
||||||
float translateX = 0.f;
|
|
||||||
float translateY = 0.f;
|
|
||||||
float rotation = 0.f;
|
|
||||||
float scaleX = 1.f * (1 << 10);
|
|
||||||
float scaleY = 1.f * (1 << 10);
|
|
||||||
float skewX = 0.f;
|
|
||||||
float skewY = 0.f;
|
|
||||||
float tCenterX = 0.f;
|
|
||||||
float tCenterY = 0.f;
|
|
||||||
|
|
||||||
if (unlikely (!points.resize (points.length + get_num_points ()))) return false;
|
|
||||||
|
|
||||||
unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
|
|
||||||
unsigned axes_size = numAxes * axis_width;
|
|
||||||
|
|
||||||
const F2DOT14 *q = (const F2DOT14 *) (axes_size +
|
|
||||||
(flags & GID_IS_24BIT ? 3 : 2) +
|
|
||||||
&StructAfter<const HBUINT8> (numAxes));
|
|
||||||
|
|
||||||
hb_array_t<contour_point_t> rec_points = points.as_array ().sub_array (points.length - get_num_points ());
|
|
||||||
|
|
||||||
unsigned count = numAxes;
|
|
||||||
if (flags & AXES_HAVE_VARIATION)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < count; i++)
|
|
||||||
rec_points[i].x = q++->to_int ();
|
|
||||||
rec_points += count;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
q += count;
|
|
||||||
|
|
||||||
const HBUINT16 *p = (const HBUINT16 *) q;
|
|
||||||
|
|
||||||
if (flags & HAVE_TRANSLATE_X) translateX = * (const FWORD *) p++;
|
|
||||||
if (flags & HAVE_TRANSLATE_Y) translateY = * (const FWORD *) p++;
|
|
||||||
if (flags & HAVE_ROTATION) rotation = ((const F4DOT12 *) p++)->to_int ();
|
|
||||||
if (flags & HAVE_SCALE_X) scaleX = ((const F6DOT10 *) p++)->to_int ();
|
|
||||||
if (flags & HAVE_SCALE_Y) scaleY = ((const F6DOT10 *) p++)->to_int ();
|
|
||||||
if (flags & HAVE_SKEW_X) skewX = ((const F4DOT12 *) p++)->to_int ();
|
|
||||||
if (flags & HAVE_SKEW_Y) skewY = ((const F4DOT12 *) p++)->to_int ();
|
|
||||||
if (flags & HAVE_TCENTER_X) tCenterX = * (const FWORD *) p++;
|
|
||||||
if (flags & HAVE_TCENTER_Y) tCenterY = * (const FWORD *) p++;
|
|
||||||
|
|
||||||
if ((flags & UNIFORM_SCALE) && !(flags & HAVE_SCALE_Y))
|
|
||||||
scaleY = scaleX;
|
|
||||||
|
|
||||||
if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
|
|
||||||
{
|
|
||||||
rec_points[0].x = translateX;
|
|
||||||
rec_points[0].y = translateY;
|
|
||||||
rec_points++;
|
|
||||||
}
|
|
||||||
if (flags & HAVE_ROTATION)
|
|
||||||
{
|
|
||||||
rec_points[0].x = rotation;
|
|
||||||
rec_points++;
|
|
||||||
}
|
|
||||||
if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y))
|
|
||||||
{
|
|
||||||
rec_points[0].x = scaleX;
|
|
||||||
rec_points[0].y = scaleY;
|
|
||||||
rec_points++;
|
|
||||||
}
|
|
||||||
if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y))
|
|
||||||
{
|
|
||||||
rec_points[0].x = skewX;
|
|
||||||
rec_points[0].y = skewY;
|
|
||||||
rec_points++;
|
|
||||||
}
|
|
||||||
if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
|
|
||||||
{
|
|
||||||
rec_points[0].x = tCenterX;
|
|
||||||
rec_points[0].y = tCenterY;
|
|
||||||
rec_points++;
|
|
||||||
}
|
|
||||||
assert (!rec_points);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_transformation_from_points (hb_array_t<contour_point_t> rec_points,
|
|
||||||
float (&matrix)[4], contour_point_t &trans) const
|
|
||||||
{
|
|
||||||
if (flags & AXES_HAVE_VARIATION)
|
|
||||||
rec_points += numAxes;
|
|
||||||
|
|
||||||
matrix[0] = matrix[3] = 1.f;
|
|
||||||
matrix[1] = matrix[2] = 0.f;
|
|
||||||
trans.init (0.f, 0.f);
|
|
||||||
|
|
||||||
float translateX = 0.f;
|
|
||||||
float translateY = 0.f;
|
|
||||||
float rotation = 0.f;
|
|
||||||
float scaleX = 1.f;
|
|
||||||
float scaleY = 1.f;
|
|
||||||
float skewX = 0.f;
|
|
||||||
float skewY = 0.f;
|
|
||||||
float tCenterX = 0.f;
|
|
||||||
float tCenterY = 0.f;
|
|
||||||
|
|
||||||
if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
|
|
||||||
{
|
|
||||||
translateX = rec_points[0].x;
|
|
||||||
translateY = rec_points[0].y;
|
|
||||||
rec_points++;
|
|
||||||
}
|
|
||||||
if (flags & HAVE_ROTATION)
|
|
||||||
{
|
|
||||||
rotation = rec_points[0].x / (1 << 12);
|
|
||||||
rec_points++;
|
|
||||||
}
|
|
||||||
if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y))
|
|
||||||
{
|
|
||||||
scaleX = rec_points[0].x / (1 << 10);
|
|
||||||
scaleY = rec_points[0].y / (1 << 10);
|
|
||||||
rec_points++;
|
|
||||||
}
|
|
||||||
if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y))
|
|
||||||
{
|
|
||||||
skewX = rec_points[0].x / (1 << 12);
|
|
||||||
skewY = rec_points[0].y / (1 << 12);
|
|
||||||
rec_points++;
|
|
||||||
}
|
|
||||||
if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
|
|
||||||
{
|
|
||||||
tCenterX = rec_points[0].x;
|
|
||||||
tCenterY = rec_points[0].y;
|
|
||||||
rec_points++;
|
|
||||||
}
|
|
||||||
assert (!rec_points);
|
|
||||||
|
|
||||||
translate (matrix, trans, translateX + tCenterX, translateY + tCenterY);
|
|
||||||
rotate (matrix, trans, rotation);
|
|
||||||
scale (matrix, trans, scaleX, scaleY);
|
|
||||||
skew (matrix, trans, -skewX, skewY);
|
|
||||||
translate (matrix, trans, -tCenterX, -tCenterY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_variations (coord_setter_t &setter,
|
|
||||||
hb_array_t<contour_point_t> rec_points) const
|
|
||||||
{
|
|
||||||
bool have_variations = flags & AXES_HAVE_VARIATION;
|
|
||||||
unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
|
|
||||||
|
|
||||||
const HBUINT8 *p = (const HBUINT8 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2));
|
|
||||||
const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2));
|
|
||||||
|
|
||||||
const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes)));
|
|
||||||
|
|
||||||
unsigned count = numAxes;
|
|
||||||
for (unsigned i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
unsigned axis_index = axis_width == 1 ? (unsigned) *p++ : (unsigned) *q++;
|
|
||||||
|
|
||||||
signed v = have_variations ? rec_points[i].x : a++->to_int ();
|
|
||||||
|
|
||||||
v = hb_clamp (v, -(1<<14), (1<<14));
|
|
||||||
setter[axis_index] = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
HBUINT16 flags;
|
|
||||||
HBUINT8 numAxes;
|
|
||||||
public:
|
|
||||||
DEFINE_SIZE_MIN (3);
|
|
||||||
};
|
|
||||||
|
|
||||||
using var_composite_iter_t = composite_iter_tmpl<VarCompositeGlyphRecord>;
|
|
||||||
|
|
||||||
struct VarCompositeGlyph
|
|
||||||
{
|
|
||||||
const GlyphHeader &header;
|
|
||||||
hb_bytes_t bytes;
|
|
||||||
VarCompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
|
|
||||||
header (header_), bytes (bytes_) {}
|
|
||||||
|
|
||||||
var_composite_iter_t iter () const
|
|
||||||
{ return var_composite_iter_t (bytes, &StructAfter<VarCompositeGlyphRecord, GlyphHeader> (header)); }
|
|
||||||
|
|
||||||
const hb_bytes_t trim_padding () const
|
|
||||||
{
|
|
||||||
unsigned length = GlyphHeader::static_size;
|
|
||||||
for (auto &comp : iter ())
|
|
||||||
length += comp.get_size ();
|
|
||||||
return bytes.sub_array (0, length);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace glyf_impl */
|
|
||||||
} /* namespace OT */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* OT_GLYF_VARCOMPOSITEGLYPH_HH */
|
|
|
@ -1,68 +0,0 @@
|
||||||
#ifndef OT_GLYF_COMPOSITE_ITER_HH
|
|
||||||
#define OT_GLYF_COMPOSITE_ITER_HH
|
|
||||||
|
|
||||||
|
|
||||||
#include "../../hb.hh"
|
|
||||||
|
|
||||||
|
|
||||||
namespace OT {
|
|
||||||
namespace glyf_impl {
|
|
||||||
|
|
||||||
|
|
||||||
template <typename CompositeGlyphRecord>
|
|
||||||
struct composite_iter_tmpl : hb_iter_with_fallback_t<composite_iter_tmpl<CompositeGlyphRecord>,
|
|
||||||
const CompositeGlyphRecord &>
|
|
||||||
{
|
|
||||||
typedef const CompositeGlyphRecord *__item_t__;
|
|
||||||
composite_iter_tmpl (hb_bytes_t glyph_, __item_t__ current_) :
|
|
||||||
glyph (glyph_), current (nullptr), current_size (0)
|
|
||||||
{
|
|
||||||
set_current (current_);
|
|
||||||
}
|
|
||||||
|
|
||||||
composite_iter_tmpl () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
|
|
||||||
|
|
||||||
const CompositeGlyphRecord & __item__ () const { return *current; }
|
|
||||||
bool __more__ () const { return current; }
|
|
||||||
void __next__ ()
|
|
||||||
{
|
|
||||||
if (!current->has_more ()) { current = nullptr; return; }
|
|
||||||
|
|
||||||
set_current (&StructAtOffset<CompositeGlyphRecord> (current, current_size));
|
|
||||||
}
|
|
||||||
composite_iter_tmpl __end__ () const { return composite_iter_tmpl (); }
|
|
||||||
bool operator != (const composite_iter_tmpl& o) const
|
|
||||||
{ return current != o.current; }
|
|
||||||
|
|
||||||
|
|
||||||
void set_current (__item_t__ current_)
|
|
||||||
{
|
|
||||||
if (!glyph.check_range (current_, CompositeGlyphRecord::min_size))
|
|
||||||
{
|
|
||||||
current = nullptr;
|
|
||||||
current_size = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unsigned size = current_->get_size ();
|
|
||||||
if (!glyph.check_range (current_, size))
|
|
||||||
{
|
|
||||||
current = nullptr;
|
|
||||||
current_size = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
current = current_;
|
|
||||||
current_size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
hb_bytes_t glyph;
|
|
||||||
__item_t__ current;
|
|
||||||
unsigned current_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace glyf_impl */
|
|
||||||
} /* namespace OT */
|
|
||||||
|
|
||||||
#endif /* OT_GLYF_COMPOSITE_ITER_HH */
|
|
|
@ -1,34 +0,0 @@
|
||||||
#ifndef OT_GLYF_COORD_SETTER_HH
|
|
||||||
#define OT_GLYF_COORD_SETTER_HH
|
|
||||||
|
|
||||||
|
|
||||||
#include "../../hb.hh"
|
|
||||||
|
|
||||||
|
|
||||||
namespace OT {
|
|
||||||
namespace glyf_impl {
|
|
||||||
|
|
||||||
|
|
||||||
struct coord_setter_t
|
|
||||||
{
|
|
||||||
coord_setter_t (hb_array_t<int> coords) :
|
|
||||||
coords (coords) {}
|
|
||||||
|
|
||||||
int& operator [] (unsigned idx)
|
|
||||||
{
|
|
||||||
if (coords.length < idx + 1)
|
|
||||||
coords.resize (idx + 1);
|
|
||||||
return coords[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_array_t<int> get_coords ()
|
|
||||||
{ return coords.as_array (); }
|
|
||||||
|
|
||||||
hb_vector_t<int> coords;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace glyf_impl */
|
|
||||||
} /* namespace OT */
|
|
||||||
|
|
||||||
#endif /* OT_GLYF_COORD_SETTER_HH */
|
|
|
@ -25,7 +25,7 @@ _write_loca (IteratorIn&& it, bool short_offsets, IteratorOut&& dest)
|
||||||
| hb_map ([=, &offset] (unsigned int padded_size)
|
| hb_map ([=, &offset] (unsigned int padded_size)
|
||||||
{
|
{
|
||||||
offset += padded_size;
|
offset += padded_size;
|
||||||
DEBUG_MSG (SUBSET, nullptr, "loca entry offset %u", offset);
|
DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset);
|
||||||
return offset >> right_shift;
|
return offset >> right_shift;
|
||||||
})
|
})
|
||||||
| hb_sink (dest)
|
| hb_sink (dest)
|
||||||
|
@ -44,20 +44,6 @@ _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
|
||||||
|
|
||||||
head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
|
head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
|
||||||
head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
|
head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
|
||||||
if (plan->normalized_coords)
|
|
||||||
{
|
|
||||||
head_prime->xMin = plan->head_maxp_info.xMin;
|
|
||||||
head_prime->xMax = plan->head_maxp_info.xMax;
|
|
||||||
head_prime->yMin = plan->head_maxp_info.yMin;
|
|
||||||
head_prime->yMax = plan->head_maxp_info.yMax;
|
|
||||||
|
|
||||||
unsigned orig_flag = head_prime->flags;
|
|
||||||
if (plan->head_maxp_info.allXMinIsLsb)
|
|
||||||
orig_flag |= 1 << 1;
|
|
||||||
else
|
|
||||||
orig_flag &= ~(1 << 1);
|
|
||||||
head_prime->flags = orig_flag;
|
|
||||||
}
|
|
||||||
bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
|
bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
|
||||||
|
|
||||||
hb_blob_destroy (head_prime_blob);
|
hb_blob_destroy (head_prime_blob);
|
||||||
|
@ -75,7 +61,7 @@ _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_s
|
||||||
|
|
||||||
if (unlikely (!loca_prime_data)) return false;
|
if (unlikely (!loca_prime_data)) return false;
|
||||||
|
|
||||||
DEBUG_MSG (SUBSET, nullptr, "loca entry_size %u num_offsets %u size %u",
|
DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d",
|
||||||
entry_size, num_offsets, entry_size * num_offsets);
|
entry_size, num_offsets, entry_size * num_offsets);
|
||||||
|
|
||||||
if (use_short_loca)
|
if (use_short_loca)
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "../../hb-ot-hmtx-table.hh"
|
#include "../../hb-ot-hmtx-table.hh"
|
||||||
#include "../../hb-ot-var-gvar-table.hh"
|
#include "../../hb-ot-var-gvar-table.hh"
|
||||||
#include "../../hb-draw.hh"
|
#include "../../hb-draw.hh"
|
||||||
#include "../../hb-paint.hh"
|
|
||||||
|
|
||||||
#include "glyf-helpers.hh"
|
#include "glyf-helpers.hh"
|
||||||
#include "Glyph.hh"
|
#include "Glyph.hh"
|
||||||
|
@ -31,12 +30,6 @@ struct glyf
|
||||||
|
|
||||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
|
static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
|
||||||
|
|
||||||
static bool has_valid_glyf_format(const hb_face_t* face)
|
|
||||||
{
|
|
||||||
const OT::head &head = *face->table.head;
|
|
||||||
return head.indexToLocFormat <= 1 && head.glyphDataFormat <= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
|
bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -52,11 +45,8 @@ struct glyf
|
||||||
const hb_subset_plan_t *plan)
|
const hb_subset_plan_t *plan)
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
|
|
||||||
unsigned init_len = c->length ();
|
unsigned init_len = c->length ();
|
||||||
for (auto &_ : it)
|
for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
|
||||||
if (unlikely (!_.serialize (c, use_short_loca, plan)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* As a special case when all glyph in the font are empty, add a zero byte
|
/* As a special case when all glyph in the font are empty, add a zero byte
|
||||||
* to the table, so that OTS doesn’t reject it, and to make the table work
|
* to the table, so that OTS doesn’t reject it, and to make the table work
|
||||||
|
@ -78,82 +68,53 @@ struct glyf
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
|
|
||||||
if (!has_valid_glyf_format (c->plan->source)) {
|
|
||||||
// glyf format is unknown don't attempt to subset it.
|
|
||||||
DEBUG_MSG (SUBSET, nullptr,
|
|
||||||
"unkown glyf format, dropping from subset.");
|
|
||||||
return_trace (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
glyf *glyf_prime = c->serializer->start_embed <glyf> ();
|
glyf *glyf_prime = c->serializer->start_embed <glyf> ();
|
||||||
if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
|
if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
|
||||||
|
|
||||||
hb_font_t *font = nullptr;
|
|
||||||
if (c->plan->normalized_coords)
|
|
||||||
{
|
|
||||||
font = _create_font_for_instancing (c->plan);
|
|
||||||
if (unlikely (!font)) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_vector_t<unsigned> padded_offsets;
|
|
||||||
unsigned num_glyphs = c->plan->num_output_glyphs ();
|
|
||||||
if (unlikely (!padded_offsets.resize (num_glyphs)))
|
|
||||||
{
|
|
||||||
hb_font_destroy (font);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
|
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
|
||||||
if (!_populate_subset_glyphs (c->plan, font, glyphs))
|
_populate_subset_glyphs (c->plan, &glyphs);
|
||||||
{
|
|
||||||
hb_font_destroy (font);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (font)
|
if (!c->plan->pinned_at_default)
|
||||||
hb_font_destroy (font);
|
_compile_subset_glyphs_with_deltas (c->plan, &glyphs);
|
||||||
|
|
||||||
unsigned max_offset = 0;
|
auto padded_offsets =
|
||||||
for (unsigned i = 0; i < num_glyphs; i++)
|
+ hb_iter (glyphs)
|
||||||
{
|
| hb_map (&glyf_impl::SubsetGlyph::padded_size)
|
||||||
padded_offsets[i] = glyphs[i].padded_size ();
|
;
|
||||||
max_offset += padded_offsets[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool use_short_loca = false;
|
unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
|
||||||
if (likely (!c->plan->force_long_loca))
|
bool use_short_loca = max_offset < 0x1FFFF;
|
||||||
use_short_loca = max_offset < 0x1FFFF;
|
|
||||||
|
|
||||||
|
|
||||||
|
glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
|
||||||
if (!use_short_loca) {
|
if (!use_short_loca) {
|
||||||
for (unsigned i = 0; i < num_glyphs; i++)
|
padded_offsets =
|
||||||
padded_offsets[i] = glyphs[i].length ();
|
+ hb_iter (glyphs)
|
||||||
|
| hb_map (&glyf_impl::SubsetGlyph::length)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan);
|
|
||||||
if (c->plan->normalized_coords && !c->plan->pinned_at_default)
|
|
||||||
_free_compiled_subset_glyphs (glyphs);
|
|
||||||
|
|
||||||
if (!result) return false;
|
|
||||||
|
|
||||||
|
if (!c->plan->pinned_at_default)
|
||||||
|
_free_compiled_subset_glyphs (&glyphs);
|
||||||
if (unlikely (c->serializer->in_error ())) return_trace (false);
|
if (unlikely (c->serializer->in_error ())) return_trace (false);
|
||||||
|
|
||||||
return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan,
|
return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan,
|
||||||
padded_offsets.iter (),
|
padded_offsets,
|
||||||
use_short_loca)));
|
use_short_loca)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
||||||
hb_font_t *font,
|
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
|
||||||
hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const;
|
|
||||||
|
void
|
||||||
|
_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
|
||||||
|
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
|
||||||
|
|
||||||
hb_font_t *
|
void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> *glyphs) const
|
||||||
_create_font_for_instancing (const hb_subset_plan_t *plan) const;
|
|
||||||
|
|
||||||
void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs) const
|
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < glyphs.length; i++)
|
for (auto _ : *glyphs)
|
||||||
glyphs[i].free_compiled_bytes ();
|
_.free_compiled_bytes ();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -181,7 +142,7 @@ struct glyf_accelerator_t
|
||||||
vmtx = nullptr;
|
vmtx = nullptr;
|
||||||
#endif
|
#endif
|
||||||
const OT::head &head = *face->table.head;
|
const OT::head &head = *face->table.head;
|
||||||
if (!glyf::has_valid_glyf_format (face))
|
if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
|
||||||
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
|
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
|
||||||
return;
|
return;
|
||||||
short_offset = 0 == head.indexToLocFormat;
|
short_offset = 0 == head.indexToLocFormat;
|
||||||
|
@ -219,7 +180,7 @@ struct glyf_accelerator_t
|
||||||
contour_point_vector_t all_points;
|
contour_point_vector_t all_points;
|
||||||
|
|
||||||
bool phantom_only = !consumer.is_consuming_contour_points ();
|
bool phantom_only = !consumer.is_consuming_contour_points ();
|
||||||
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only)))
|
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, phantom_only)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (consumer.is_consuming_contour_points ())
|
if (consumer.is_consuming_contour_points ())
|
||||||
|
@ -241,8 +202,6 @@ struct glyf_accelerator_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
struct points_aggregator_t
|
struct points_aggregator_t
|
||||||
{
|
{
|
||||||
|
@ -275,14 +234,19 @@ struct glyf_accelerator_t
|
||||||
extents->y_bearing = 0;
|
extents->y_bearing = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (scaled)
|
||||||
|
{
|
||||||
|
extents->x_bearing = font->em_scalef_x (min_x);
|
||||||
|
extents->width = font->em_scalef_x (max_x) - extents->x_bearing;
|
||||||
|
extents->y_bearing = font->em_scalef_y (max_y);
|
||||||
|
extents->height = font->em_scalef_y (min_y) - extents->y_bearing;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
extents->x_bearing = roundf (min_x);
|
extents->x_bearing = roundf (min_x);
|
||||||
extents->width = roundf (max_x - extents->x_bearing);
|
extents->width = roundf (max_x - extents->x_bearing);
|
||||||
extents->y_bearing = roundf (max_y);
|
extents->y_bearing = roundf (max_y);
|
||||||
extents->height = roundf (min_y - extents->y_bearing);
|
extents->height = roundf (min_y - extents->y_bearing);
|
||||||
|
|
||||||
if (scaled)
|
|
||||||
font->scale_glyph_extents (extents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,6 +270,7 @@ struct glyf_accelerator_t
|
||||||
contour_point_t *get_phantoms_sink () { return phantoms; }
|
contour_point_t *get_phantoms_sink () { return phantoms; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
unsigned
|
unsigned
|
||||||
get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
|
get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
|
||||||
{
|
{
|
||||||
|
@ -347,15 +312,6 @@ struct glyf_accelerator_t
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool get_leading_bearing_without_var_unscaled (hb_codepoint_t gid, bool is_vertical, int *lsb) const
|
|
||||||
{
|
|
||||||
if (unlikely (gid >= num_glyphs)) return false;
|
|
||||||
if (is_vertical) return false; // TODO Humm, what to do here?
|
|
||||||
|
|
||||||
*lsb = glyph_for_gid (gid).get_header ()->xMin;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
|
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
|
||||||
{
|
{
|
||||||
|
@ -368,15 +324,6 @@ struct glyf_accelerator_t
|
||||||
return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents);
|
return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
|
|
||||||
{
|
|
||||||
funcs->push_clip_glyph (data, gid, font);
|
|
||||||
funcs->color (data, true, foreground);
|
|
||||||
funcs->pop_clip (data);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const glyf_impl::Glyph
|
const glyf_impl::Glyph
|
||||||
glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
|
glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
|
||||||
{
|
{
|
||||||
|
@ -425,65 +372,48 @@ struct glyf_accelerator_t
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline void
|
||||||
glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
||||||
hb_font_t *font,
|
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
|
||||||
hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const
|
|
||||||
{
|
{
|
||||||
OT::glyf_accelerator_t glyf (plan->source);
|
OT::glyf_accelerator_t glyf (plan->source);
|
||||||
unsigned num_glyphs = plan->num_output_glyphs ();
|
|
||||||
if (!glyphs.resize (num_glyphs)) return false;
|
|
||||||
|
|
||||||
for (auto p : plan->glyph_map->iter ())
|
+ hb_range (plan->num_output_glyphs ())
|
||||||
{
|
| hb_map ([&] (hb_codepoint_t new_gid)
|
||||||
unsigned new_gid = p.second;
|
{
|
||||||
glyf_impl::SubsetGlyph& subset_glyph = glyphs.arrayZ[new_gid];
|
glyf_impl::SubsetGlyph subset_glyph = {0};
|
||||||
subset_glyph.old_gid = p.first;
|
subset_glyph.new_gid = new_gid;
|
||||||
|
|
||||||
if (unlikely (new_gid == 0 &&
|
/* should never fail: all old gids should be mapped */
|
||||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) &&
|
if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
|
||||||
!plan->normalized_coords)
|
return subset_glyph;
|
||||||
subset_glyph.source_glyph = glyf_impl::Glyph ();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If plan has an accelerator, the preprocessing step already trimmed glyphs.
|
|
||||||
* Don't trim them again! */
|
|
||||||
subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, !plan->accelerator);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
if (new_gid == 0 &&
|
||||||
subset_glyph.drop_hints_bytes ();
|
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||||
else
|
subset_glyph.source_glyph = glyf_impl::Glyph ();
|
||||||
subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
|
else
|
||||||
|
subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
|
||||||
if (font)
|
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||||
{
|
subset_glyph.drop_hints_bytes ();
|
||||||
if (unlikely (!subset_glyph.compile_bytes_with_deltas (plan, font, glyf)))
|
else
|
||||||
{
|
subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
|
||||||
// when pinned at default, only bounds are updated, thus no need to free
|
return subset_glyph;
|
||||||
if (!plan->pinned_at_default)
|
})
|
||||||
_free_compiled_subset_glyphs (glyphs);
|
| hb_sink (glyphs)
|
||||||
return false;
|
;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline hb_font_t *
|
inline void
|
||||||
glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
|
glyf::_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
|
||||||
|
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
|
||||||
{
|
{
|
||||||
|
OT::glyf_accelerator_t glyf (plan->source);
|
||||||
hb_font_t *font = hb_font_create (plan->source);
|
hb_font_t *font = hb_font_create (plan->source);
|
||||||
if (unlikely (font == hb_font_get_empty ())) return nullptr;
|
|
||||||
|
|
||||||
hb_vector_t<hb_variation_t> vars;
|
hb_vector_t<hb_variation_t> vars;
|
||||||
if (unlikely (!vars.alloc (plan->user_axes_location.get_population (), true)))
|
vars.alloc (plan->user_axes_location->get_population ());
|
||||||
{
|
|
||||||
hb_font_destroy (font);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto _ : plan->user_axes_location)
|
for (auto _ : *plan->user_axes_location)
|
||||||
{
|
{
|
||||||
hb_variation_t var;
|
hb_variation_t var;
|
||||||
var.tag = _.first;
|
var.tag = _.first;
|
||||||
|
@ -491,10 +421,11 @@ glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
|
||||||
vars.push (var);
|
vars.push (var);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
|
||||||
hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ());
|
for (auto& subset_glyph : *glyphs)
|
||||||
#endif
|
const_cast<glyf_impl::SubsetGlyph &> (subset_glyph).compile_bytes_with_deltas (plan, font, glyf);
|
||||||
return font;
|
|
||||||
|
hb_font_destroy (font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,29 +26,22 @@ struct path_builder_t
|
||||||
|
|
||||||
optional_point_t lerp (optional_point_t p, float t)
|
optional_point_t lerp (optional_point_t p, float t)
|
||||||
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
|
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
|
||||||
} first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2;
|
} first_oncurve, first_offcurve, last_offcurve;
|
||||||
|
|
||||||
path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
|
path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
|
||||||
{
|
{
|
||||||
font = font_;
|
font = font_;
|
||||||
draw_session = &draw_session_;
|
draw_session = &draw_session_;
|
||||||
first_oncurve = first_offcurve = first_offcurve2 = last_offcurve = last_offcurve2 = optional_point_t ();
|
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
|
/* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
|
||||||
See also:
|
See also:
|
||||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
|
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
|
||||||
* https://stackoverflow.com/a/20772557
|
* https://stackoverflow.com/a/20772557 */
|
||||||
*
|
|
||||||
* Cubic support added. */
|
|
||||||
void consume_point (const contour_point_t &point)
|
void consume_point (const contour_point_t &point)
|
||||||
{
|
{
|
||||||
bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
|
bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
|
||||||
#ifdef HB_NO_CUBIC_GLYF
|
|
||||||
bool is_cubic = false;
|
|
||||||
#else
|
|
||||||
bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
|
|
||||||
#endif
|
|
||||||
optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
|
optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
|
||||||
if (!first_oncurve)
|
if (!first_oncurve)
|
||||||
{
|
{
|
||||||
|
@ -59,12 +52,7 @@ struct path_builder_t
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (is_cubic && !first_offcurve2)
|
if (first_offcurve)
|
||||||
{
|
|
||||||
first_offcurve2 = first_offcurve;
|
|
||||||
first_offcurve = p;
|
|
||||||
}
|
|
||||||
else if (first_offcurve)
|
|
||||||
{
|
{
|
||||||
optional_point_t mid = first_offcurve.lerp (p, .5f);
|
optional_point_t mid = first_offcurve.lerp (p, .5f);
|
||||||
first_oncurve = mid;
|
first_oncurve = mid;
|
||||||
|
@ -81,41 +69,16 @@ struct path_builder_t
|
||||||
{
|
{
|
||||||
if (is_on_curve)
|
if (is_on_curve)
|
||||||
{
|
{
|
||||||
if (last_offcurve2)
|
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||||
{
|
p.x, p.y);
|
||||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
|
||||||
last_offcurve.x, last_offcurve.y,
|
|
||||||
p.x, p.y);
|
|
||||||
last_offcurve2 = optional_point_t ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
|
||||||
p.x, p.y);
|
|
||||||
last_offcurve = optional_point_t ();
|
last_offcurve = optional_point_t ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (is_cubic && !last_offcurve2)
|
optional_point_t mid = last_offcurve.lerp (p, .5f);
|
||||||
{
|
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||||
last_offcurve2 = last_offcurve;
|
mid.x, mid.y);
|
||||||
last_offcurve = p;
|
last_offcurve = p;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
optional_point_t mid = last_offcurve.lerp (p, .5f);
|
|
||||||
|
|
||||||
if (is_cubic)
|
|
||||||
{
|
|
||||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
|
||||||
last_offcurve.x, last_offcurve.y,
|
|
||||||
mid.x, mid.y);
|
|
||||||
last_offcurve2 = optional_point_t ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
|
||||||
mid.x, mid.y);
|
|
||||||
last_offcurve = p;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -131,40 +94,19 @@ struct path_builder_t
|
||||||
{
|
{
|
||||||
if (first_offcurve && last_offcurve)
|
if (first_offcurve && last_offcurve)
|
||||||
{
|
{
|
||||||
optional_point_t mid = last_offcurve.lerp (first_offcurve2 ?
|
optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
|
||||||
first_offcurve2 :
|
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||||
first_offcurve, .5f);
|
mid.x, mid.y);
|
||||||
if (last_offcurve2)
|
|
||||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
|
||||||
last_offcurve.x, last_offcurve.y,
|
|
||||||
mid.x, mid.y);
|
|
||||||
else
|
|
||||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
|
||||||
mid.x, mid.y);
|
|
||||||
last_offcurve = optional_point_t ();
|
last_offcurve = optional_point_t ();
|
||||||
|
/* now check the rest */
|
||||||
}
|
}
|
||||||
/* now check the rest */
|
|
||||||
|
|
||||||
if (first_offcurve && first_oncurve)
|
if (first_offcurve && first_oncurve)
|
||||||
{
|
draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
|
||||||
if (first_offcurve2)
|
first_oncurve.x, first_oncurve.y);
|
||||||
draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
|
|
||||||
first_offcurve.x, first_offcurve.y,
|
|
||||||
first_oncurve.x, first_oncurve.y);
|
|
||||||
else
|
|
||||||
draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
|
|
||||||
first_oncurve.x, first_oncurve.y);
|
|
||||||
}
|
|
||||||
else if (last_offcurve && first_oncurve)
|
else if (last_offcurve && first_oncurve)
|
||||||
{
|
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||||
if (last_offcurve2)
|
first_oncurve.x, first_oncurve.y);
|
||||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
|
||||||
last_offcurve.x, last_offcurve.y,
|
|
||||||
first_oncurve.x, first_oncurve.y);
|
|
||||||
else
|
|
||||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
|
||||||
first_oncurve.x, first_oncurve.y);
|
|
||||||
}
|
|
||||||
else if (first_oncurve)
|
else if (first_oncurve)
|
||||||
draw_session->line_to (first_oncurve.x, first_oncurve.y);
|
draw_session->line_to (first_oncurve.x, first_oncurve.y);
|
||||||
else if (first_offcurve)
|
else if (first_offcurve)
|
||||||
|
@ -175,7 +117,7 @@ struct path_builder_t
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Getting ready for the next contour */
|
/* Getting ready for the next contour */
|
||||||
first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
|
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
|
||||||
draw_session->close_path ();
|
draw_session->close_path ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,589 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright © 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.
|
|
||||||
*
|
|
||||||
* Google Author(s): Behdad Esfahbod
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OT_NAME_NAME_HH
|
|
||||||
#define OT_NAME_NAME_HH
|
|
||||||
|
|
||||||
#include "../../hb-open-type.hh"
|
|
||||||
#include "../../hb-ot-name-language.hh"
|
|
||||||
#include "../../hb-aat-layout.hh"
|
|
||||||
#include "../../hb-utf.hh"
|
|
||||||
|
|
||||||
|
|
||||||
namespace OT {
|
|
||||||
|
|
||||||
template <typename in_utf_t, typename out_utf_t>
|
|
||||||
inline unsigned int
|
|
||||||
hb_ot_name_convert_utf (hb_bytes_t bytes,
|
|
||||||
unsigned int *text_size /* IN/OUT */,
|
|
||||||
typename out_utf_t::codepoint_t *text /* OUT */)
|
|
||||||
{
|
|
||||||
unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t);
|
|
||||||
const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ;
|
|
||||||
const typename in_utf_t::codepoint_t *src_end = src + src_len;
|
|
||||||
|
|
||||||
typename out_utf_t::codepoint_t *dst = text;
|
|
||||||
|
|
||||||
hb_codepoint_t unicode;
|
|
||||||
const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
|
|
||||||
|
|
||||||
if (text_size && *text_size)
|
|
||||||
{
|
|
||||||
(*text_size)--; /* Save room for NUL-termination. */
|
|
||||||
const typename out_utf_t::codepoint_t *dst_end = text + *text_size;
|
|
||||||
|
|
||||||
while (src < src_end && dst < dst_end)
|
|
||||||
{
|
|
||||||
const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
|
|
||||||
typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
|
|
||||||
if (dst_next == dst)
|
|
||||||
break; /* Out-of-room. */
|
|
||||||
|
|
||||||
dst = dst_next;
|
|
||||||
src = src_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
*text_size = dst - text;
|
|
||||||
*dst = 0; /* NUL-terminate. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Accumulate length of rest. */
|
|
||||||
unsigned int dst_len = dst - text;
|
|
||||||
while (src < src_end)
|
|
||||||
{
|
|
||||||
src = in_utf_t::next (src, src_end, &unicode, replacement);
|
|
||||||
dst_len += out_utf_t::encode_len (unicode);
|
|
||||||
}
|
|
||||||
return dst_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define entry_score var.u16[0]
|
|
||||||
#define entry_index var.u16[1]
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* name -- Naming
|
|
||||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/name
|
|
||||||
*/
|
|
||||||
#define HB_OT_TAG_name HB_TAG('n','a','m','e')
|
|
||||||
|
|
||||||
#define UNSUPPORTED 42
|
|
||||||
|
|
||||||
struct NameRecord
|
|
||||||
{
|
|
||||||
hb_language_t language (hb_face_t *face) const
|
|
||||||
{
|
|
||||||
#ifndef HB_NO_OT_NAME_LANGUAGE
|
|
||||||
unsigned int p = platformID;
|
|
||||||
unsigned int l = languageID;
|
|
||||||
|
|
||||||
if (p == 3)
|
|
||||||
return _hb_ot_name_language_for_ms_code (l);
|
|
||||||
|
|
||||||
if (p == 1)
|
|
||||||
return _hb_ot_name_language_for_mac_code (l);
|
|
||||||
|
|
||||||
#ifndef HB_NO_OT_NAME_LANGUAGE_AAT
|
|
||||||
if (p == 0)
|
|
||||||
return face->table.ltag->get_language (l);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
return HB_LANGUAGE_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t score () const
|
|
||||||
{
|
|
||||||
/* Same order as in cmap::find_best_subtable(). */
|
|
||||||
unsigned int p = platformID;
|
|
||||||
unsigned int e = encodingID;
|
|
||||||
|
|
||||||
/* 32-bit. */
|
|
||||||
if (p == 3 && e == 10) return 0;
|
|
||||||
if (p == 0 && e == 6) return 1;
|
|
||||||
if (p == 0 && e == 4) return 2;
|
|
||||||
|
|
||||||
/* 16-bit. */
|
|
||||||
if (p == 3 && e == 1) return 3;
|
|
||||||
if (p == 0 && e == 3) return 4;
|
|
||||||
if (p == 0 && e == 2) return 5;
|
|
||||||
if (p == 0 && e == 1) return 6;
|
|
||||||
if (p == 0 && e == 0) return 7;
|
|
||||||
|
|
||||||
/* Symbol. */
|
|
||||||
if (p == 3 && e == 0) return 8;
|
|
||||||
|
|
||||||
/* We treat all Mac Latin names as ASCII only. */
|
|
||||||
if (p == 1 && e == 0) return 10; /* 10 is magic number :| */
|
|
||||||
|
|
||||||
return UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NameRecord* copy (hb_serialize_context_t *c, const void *base
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
, const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides
|
|
||||||
#endif
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
TRACE_SERIALIZE (this);
|
|
||||||
HB_UNUSED auto snap = c->snapshot ();
|
|
||||||
auto *out = c->embed (this);
|
|
||||||
if (unlikely (!out)) return_trace (nullptr);
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
hb_ot_name_record_ids_t record_ids (platformID, encodingID, languageID, nameID);
|
|
||||||
hb_bytes_t* name_bytes;
|
|
||||||
|
|
||||||
if (name_table_overrides->has (record_ids, &name_bytes)) {
|
|
||||||
hb_bytes_t encoded_bytes = *name_bytes;
|
|
||||||
char *name_str_utf16_be = nullptr;
|
|
||||||
|
|
||||||
if (platformID != 1)
|
|
||||||
{
|
|
||||||
unsigned text_size = hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, nullptr, nullptr);
|
|
||||||
|
|
||||||
text_size++; // needs to consider NULL terminator for use in hb_ot_name_convert_utf()
|
|
||||||
unsigned byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
|
|
||||||
name_str_utf16_be = (char *) hb_calloc (byte_len, 1);
|
|
||||||
if (!name_str_utf16_be)
|
|
||||||
{
|
|
||||||
c->revert (snap);
|
|
||||||
return_trace (nullptr);
|
|
||||||
}
|
|
||||||
hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, &text_size,
|
|
||||||
(hb_utf16_be_t::codepoint_t *) name_str_utf16_be);
|
|
||||||
|
|
||||||
unsigned encoded_byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
|
|
||||||
if (!encoded_byte_len || !c->check_assign (out->length, encoded_byte_len, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
|
|
||||||
c->revert (snap);
|
|
||||||
hb_free (name_str_utf16_be);
|
|
||||||
return_trace (nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
encoded_bytes = hb_bytes_t (name_str_utf16_be, encoded_byte_len);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// mac platform, copy the UTF-8 string(all ascii characters) as is
|
|
||||||
if (!c->check_assign (out->length, encoded_bytes.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
|
|
||||||
c->revert (snap);
|
|
||||||
return_trace (nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out->offset = 0;
|
|
||||||
c->push ();
|
|
||||||
encoded_bytes.copy (c);
|
|
||||||
c->add_link (out->offset, c->pop_pack (), hb_serialize_context_t::Tail, 0);
|
|
||||||
hb_free (name_str_utf16_be);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
out->offset.serialize_copy (c, offset, base, 0, hb_serialize_context_t::Tail, length);
|
|
||||||
}
|
|
||||||
return_trace (out);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isUnicode () const
|
|
||||||
{
|
|
||||||
unsigned int p = platformID;
|
|
||||||
unsigned int e = encodingID;
|
|
||||||
|
|
||||||
return (p == 0 ||
|
|
||||||
(p == 3 && (e == 0 || e == 1 || e == 10)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmp (const void *pa, const void *pb)
|
|
||||||
{
|
|
||||||
const NameRecord *a = (const NameRecord *)pa;
|
|
||||||
const NameRecord *b = (const NameRecord *)pb;
|
|
||||||
|
|
||||||
if (a->platformID != b->platformID)
|
|
||||||
return a->platformID - b->platformID;
|
|
||||||
|
|
||||||
if (a->encodingID != b->encodingID)
|
|
||||||
return a->encodingID - b->encodingID;
|
|
||||||
|
|
||||||
if (a->languageID != b->languageID)
|
|
||||||
return a->languageID - b->languageID;
|
|
||||||
|
|
||||||
if (a->nameID != b->nameID)
|
|
||||||
return a->nameID - b->nameID;
|
|
||||||
|
|
||||||
if (a->length != b->length)
|
|
||||||
return a->length - b->length;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
|
||||||
{
|
|
||||||
TRACE_SANITIZE (this);
|
|
||||||
return_trace (c->check_struct (this) && offset.sanitize (c, base, length));
|
|
||||||
}
|
|
||||||
|
|
||||||
HBUINT16 platformID; /* Platform ID. */
|
|
||||||
HBUINT16 encodingID; /* Platform-specific encoding ID. */
|
|
||||||
HBUINT16 languageID; /* Language ID. */
|
|
||||||
HBUINT16 nameID; /* Name ID. */
|
|
||||||
HBUINT16 length; /* String length (in bytes). */
|
|
||||||
NNOffset16To<UnsizedArrayOf<HBUINT8>>
|
|
||||||
offset; /* String offset from start of storage area (in bytes). */
|
|
||||||
public:
|
|
||||||
DEFINE_SIZE_STATIC (12);
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
_hb_ot_name_entry_cmp_key (const void *pa, const void *pb, bool exact)
|
|
||||||
{
|
|
||||||
const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
|
|
||||||
const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
|
|
||||||
|
|
||||||
/* Compare by name_id, then language. */
|
|
||||||
|
|
||||||
if (a->name_id != b->name_id)
|
|
||||||
return a->name_id - b->name_id;
|
|
||||||
|
|
||||||
if (a->language == b->language) return 0;
|
|
||||||
if (!a->language) return -1;
|
|
||||||
if (!b->language) return +1;
|
|
||||||
|
|
||||||
const char *astr = hb_language_to_string (a->language);
|
|
||||||
const char *bstr = hb_language_to_string (b->language);
|
|
||||||
|
|
||||||
signed c = strcmp (astr, bstr);
|
|
||||||
|
|
||||||
// 'a' is the user request, and 'b' is string in the font.
|
|
||||||
// If eg. user asks for "en-us" and font has "en", approve.
|
|
||||||
if (!exact && c &&
|
|
||||||
hb_language_matches (b->language, a->language))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
_hb_ot_name_entry_cmp (const void *pa, const void *pb)
|
|
||||||
{
|
|
||||||
/* Compare by name_id, then language, then score, then index. */
|
|
||||||
|
|
||||||
int v = _hb_ot_name_entry_cmp_key (pa, pb, true);
|
|
||||||
if (v)
|
|
||||||
return v;
|
|
||||||
|
|
||||||
const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
|
|
||||||
const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
|
|
||||||
|
|
||||||
if (a->entry_score != b->entry_score)
|
|
||||||
return a->entry_score - b->entry_score;
|
|
||||||
|
|
||||||
if (a->entry_index != b->entry_index)
|
|
||||||
return a->entry_index - b->entry_index;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct name
|
|
||||||
{
|
|
||||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_name;
|
|
||||||
|
|
||||||
unsigned int get_size () const
|
|
||||||
{ return min_size + count * nameRecordZ.item_size; }
|
|
||||||
|
|
||||||
template <typename Iterator,
|
|
||||||
hb_requires (hb_is_source_of (Iterator, const NameRecord &))>
|
|
||||||
bool serialize (hb_serialize_context_t *c,
|
|
||||||
Iterator it,
|
|
||||||
const void *src_string_pool
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
, const hb_vector_t<hb_ot_name_record_ids_t>& insert_name_records
|
|
||||||
, const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
TRACE_SERIALIZE (this);
|
|
||||||
|
|
||||||
if (unlikely (!c->extend_min ((*this)))) return_trace (false);
|
|
||||||
|
|
||||||
unsigned total_count = it.len ()
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
+ insert_name_records.length
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
this->format = 0;
|
|
||||||
if (!c->check_assign (this->count, total_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
NameRecord *name_records = (NameRecord *) hb_calloc (total_count, NameRecord::static_size);
|
|
||||||
if (unlikely (!name_records)) return_trace (false);
|
|
||||||
|
|
||||||
hb_array_t<NameRecord> records (name_records, total_count);
|
|
||||||
|
|
||||||
for (const NameRecord& record : it)
|
|
||||||
{
|
|
||||||
hb_memcpy (name_records, &record, NameRecord::static_size);
|
|
||||||
name_records++;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
for (unsigned i = 0; i < insert_name_records.length; i++)
|
|
||||||
{
|
|
||||||
const hb_ot_name_record_ids_t& ids = insert_name_records[i];
|
|
||||||
NameRecord record;
|
|
||||||
record.platformID = ids.platform_id;
|
|
||||||
record.encodingID = ids.encoding_id;
|
|
||||||
record.languageID = ids.language_id;
|
|
||||||
record.nameID = ids.name_id;
|
|
||||||
record.length = 0; // handled in NameRecord copy()
|
|
||||||
record.offset = 0;
|
|
||||||
memcpy (name_records, &record, NameRecord::static_size);
|
|
||||||
name_records++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
records.qsort ();
|
|
||||||
|
|
||||||
c->copy_all (records,
|
|
||||||
src_string_pool
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
, name_table_overrides
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
hb_free (records.arrayZ);
|
|
||||||
|
|
||||||
|
|
||||||
if (unlikely (c->ran_out_of_room ())) return_trace (false);
|
|
||||||
|
|
||||||
this->stringOffset = c->length ();
|
|
||||||
|
|
||||||
return_trace (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
|
||||||
{
|
|
||||||
TRACE_SUBSET (this);
|
|
||||||
|
|
||||||
name *name_prime = c->serializer->start_embed<name> ();
|
|
||||||
if (unlikely (!name_prime)) return_trace (false);
|
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides =
|
|
||||||
&c->plan->name_table_overrides;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto it =
|
|
||||||
+ nameRecordZ.as_array (count)
|
|
||||||
| hb_filter (c->plan->name_ids, &NameRecord::nameID)
|
|
||||||
| hb_filter (c->plan->name_languages, &NameRecord::languageID)
|
|
||||||
| hb_filter ([&] (const NameRecord& namerecord) {
|
|
||||||
return
|
|
||||||
(c->plan->flags & HB_SUBSET_FLAGS_NAME_LEGACY)
|
|
||||||
|| namerecord.isUnicode ();
|
|
||||||
})
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
| hb_filter ([&] (const NameRecord& namerecord) {
|
|
||||||
if (name_table_overrides->is_empty ())
|
|
||||||
return true;
|
|
||||||
hb_ot_name_record_ids_t rec_ids (namerecord.platformID,
|
|
||||||
namerecord.encodingID,
|
|
||||||
namerecord.languageID,
|
|
||||||
namerecord.nameID);
|
|
||||||
|
|
||||||
hb_bytes_t *p;
|
|
||||||
if (name_table_overrides->has (rec_ids, &p) &&
|
|
||||||
(*p).length == 0)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
hb_hashmap_t<hb_ot_name_record_ids_t, unsigned> retained_name_record_ids;
|
|
||||||
for (const NameRecord& rec : it)
|
|
||||||
{
|
|
||||||
hb_ot_name_record_ids_t rec_ids (rec.platformID,
|
|
||||||
rec.encodingID,
|
|
||||||
rec.languageID,
|
|
||||||
rec.nameID);
|
|
||||||
retained_name_record_ids.set (rec_ids, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_vector_t<hb_ot_name_record_ids_t> insert_name_records;
|
|
||||||
if (!name_table_overrides->is_empty ())
|
|
||||||
{
|
|
||||||
if (unlikely (!insert_name_records.alloc (name_table_overrides->get_population (), true)))
|
|
||||||
return_trace (false);
|
|
||||||
for (const auto& record_ids : name_table_overrides->keys ())
|
|
||||||
{
|
|
||||||
if (name_table_overrides->get (record_ids).length == 0)
|
|
||||||
continue;
|
|
||||||
if (retained_name_record_ids.has (record_ids))
|
|
||||||
continue;
|
|
||||||
insert_name_records.push (record_ids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (name_prime->serialize (c->serializer, it,
|
|
||||||
std::addressof (this + stringOffset)
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
|
||||||
, insert_name_records
|
|
||||||
, name_table_overrides
|
|
||||||
#endif
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sanitize_records (hb_sanitize_context_t *c) const
|
|
||||||
{
|
|
||||||
TRACE_SANITIZE (this);
|
|
||||||
const void *string_pool = (this+stringOffset).arrayZ;
|
|
||||||
return_trace (nameRecordZ.sanitize (c, count, string_pool));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
|
||||||
{
|
|
||||||
TRACE_SANITIZE (this);
|
|
||||||
return_trace (c->check_struct (this) &&
|
|
||||||
likely (format == 0 || format == 1) &&
|
|
||||||
c->check_array (nameRecordZ.arrayZ, count) &&
|
|
||||||
c->check_range (this, stringOffset) &&
|
|
||||||
sanitize_records (c));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct accelerator_t
|
|
||||||
{
|
|
||||||
accelerator_t (hb_face_t *face)
|
|
||||||
{
|
|
||||||
this->table = hb_sanitize_context_t ().reference_table<name> (face);
|
|
||||||
assert (this->table.get_length () >= this->table->stringOffset);
|
|
||||||
this->pool = (const char *) (const void *) (this->table+this->table->stringOffset);
|
|
||||||
this->pool_len = this->table.get_length () - this->table->stringOffset;
|
|
||||||
const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ,
|
|
||||||
this->table->count);
|
|
||||||
|
|
||||||
this->names.alloc (all_names.length, true);
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < all_names.length; i++)
|
|
||||||
{
|
|
||||||
hb_ot_name_entry_t *entry = this->names.push ();
|
|
||||||
|
|
||||||
entry->name_id = all_names[i].nameID;
|
|
||||||
entry->language = all_names[i].language (face);
|
|
||||||
entry->entry_score = all_names[i].score ();
|
|
||||||
entry->entry_index = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->names.qsort (_hb_ot_name_entry_cmp);
|
|
||||||
/* Walk and pick best only for each name_id,language pair,
|
|
||||||
* while dropping unsupported encodings. */
|
|
||||||
unsigned int j = 0;
|
|
||||||
for (unsigned int i = 0; i < this->names.length; i++)
|
|
||||||
{
|
|
||||||
if (this->names[i].entry_score == UNSUPPORTED ||
|
|
||||||
this->names[i].language == HB_LANGUAGE_INVALID)
|
|
||||||
continue;
|
|
||||||
if (i &&
|
|
||||||
this->names[i - 1].name_id == this->names[i].name_id &&
|
|
||||||
this->names[i - 1].language == this->names[i].language)
|
|
||||||
continue;
|
|
||||||
this->names[j++] = this->names[i];
|
|
||||||
}
|
|
||||||
this->names.resize (j);
|
|
||||||
}
|
|
||||||
~accelerator_t ()
|
|
||||||
{
|
|
||||||
this->table.destroy ();
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_index (hb_ot_name_id_t name_id,
|
|
||||||
hb_language_t language,
|
|
||||||
unsigned int *width=nullptr) const
|
|
||||||
{
|
|
||||||
const hb_ot_name_entry_t key = {name_id, {0}, language};
|
|
||||||
const hb_ot_name_entry_t *entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
|
|
||||||
this->names.length,
|
|
||||||
sizeof (hb_ot_name_entry_t),
|
|
||||||
_hb_ot_name_entry_cmp_key,
|
|
||||||
true);
|
|
||||||
|
|
||||||
if (!entry)
|
|
||||||
{
|
|
||||||
entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
|
|
||||||
this->names.length,
|
|
||||||
sizeof (hb_ot_name_entry_t),
|
|
||||||
_hb_ot_name_entry_cmp_key,
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!entry)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (width)
|
|
||||||
*width = entry->entry_score < 10 ? 2 : 1;
|
|
||||||
|
|
||||||
return entry->entry_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_bytes_t get_name (unsigned int idx) const
|
|
||||||
{
|
|
||||||
const hb_array_t<const NameRecord> all_names (table->nameRecordZ.arrayZ, table->count);
|
|
||||||
const NameRecord &record = all_names[idx];
|
|
||||||
const hb_bytes_t string_pool (pool, pool_len);
|
|
||||||
return string_pool.sub_array (record.offset, record.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const char *pool;
|
|
||||||
unsigned int pool_len;
|
|
||||||
public:
|
|
||||||
hb_blob_ptr_t<name> table;
|
|
||||||
hb_vector_t<hb_ot_name_entry_t> names;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
/* We only implement format 0 for now. */
|
|
||||||
HBUINT16 format; /* Format selector (=0/1). */
|
|
||||||
HBUINT16 count; /* Number of name records. */
|
|
||||||
NNOffset16To<UnsizedArrayOf<HBUINT8>>
|
|
||||||
stringOffset; /* Offset to start of string storage (from start of table). */
|
|
||||||
UnsizedArrayOf<NameRecord>
|
|
||||||
nameRecordZ; /* The name records where count is the number of records. */
|
|
||||||
public:
|
|
||||||
DEFINE_SIZE_ARRAY (6, nameRecordZ);
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef entry_index
|
|
||||||
#undef entry_score
|
|
||||||
|
|
||||||
struct name_accelerator_t : name::accelerator_t {
|
|
||||||
name_accelerator_t (hb_face_t *face) : name::accelerator_t (face) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace OT */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* OT_NAME_NAME_HH */
|
|
|
@ -19,7 +19,7 @@ stat = 0
|
||||||
tested = False
|
tested = False
|
||||||
|
|
||||||
# harfbuzz-icu links to libstdc++ because icu does.
|
# harfbuzz-icu links to libstdc++ because icu does.
|
||||||
for soname in ['harfbuzz', 'harfbuzz-subset', 'harfbuzz-gobject', 'harfbuzz-cairo']:
|
for soname in ['harfbuzz', 'harfbuzz-subset', 'harfbuzz-gobject']:
|
||||||
for suffix in ['so', 'dylib']:
|
for suffix in ['so', 'dylib']:
|
||||||
so = os.path.join (libs, 'lib%s.%s' % (soname, suffix))
|
so = os.path.join (libs, 'lib%s.%s' % (soname, suffix))
|
||||||
if not os.path.exists (so): continue
|
if not os.path.exists (so): continue
|
||||||
|
|
|
@ -22,7 +22,7 @@ cxxfilt = shutil.which ('c++filt')
|
||||||
tested = False
|
tested = False
|
||||||
stat = 0
|
stat = 0
|
||||||
|
|
||||||
for soname in ['harfbuzz', 'harfbuzz-subset', 'harfbuzz-icu', 'harfbuzz-gobject', 'harfbuzz-cairo']:
|
for soname in ['harfbuzz', 'harfbuzz-subset', 'harfbuzz-icu', 'harfbuzz-gobject']:
|
||||||
for suffix in ['so', 'dylib']:
|
for suffix in ['so', 'dylib']:
|
||||||
so = os.path.join (builddir, libs, 'lib%s.%s' % (soname, suffix))
|
so = os.path.join (builddir, libs, 'lib%s.%s' % (soname, suffix))
|
||||||
if not os.path.exists (so): continue
|
if not os.path.exists (so): continue
|
||||||
|
@ -31,7 +31,7 @@ for soname in ['harfbuzz', 'harfbuzz-subset', 'harfbuzz-icu', 'harfbuzz-gobject'
|
||||||
symprefix = '_' if suffix == 'dylib' else ''
|
symprefix = '_' if suffix == 'dylib' else ''
|
||||||
|
|
||||||
EXPORTED_SYMBOLS = [s.split ()[2]
|
EXPORTED_SYMBOLS = [s.split ()[2]
|
||||||
for s in re.findall (r'^.+ [BCDGIRSTu] .+$', subprocess.check_output (nm.split() + [so]).decode ('utf-8'), re.MULTILINE)
|
for s in re.findall (r'^.+ [BCDGIRST] .+$', subprocess.check_output (nm.split() + [so]).decode ('utf-8'), re.MULTILINE)
|
||||||
if not re.match (r'.* %s(%s)\b' % (symprefix, IGNORED_SYMBOLS), s)]
|
if not re.match (r'.* %s(%s)\b' % (symprefix, IGNORED_SYMBOLS), s)]
|
||||||
|
|
||||||
# run again c++filt also if is available
|
# run again c++filt also if is available
|
||||||
|
|
|
@ -19,10 +19,9 @@ symbols = sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re
|
||||||
if '--experimental-api' not in sys.argv:
|
if '--experimental-api' not in sys.argv:
|
||||||
# Move these to harfbuzz-sections.txt when got stable
|
# Move these to harfbuzz-sections.txt when got stable
|
||||||
experimental_symbols = \
|
experimental_symbols = \
|
||||||
"""hb_shape_justify
|
"""hb_subset_repack_or_fail
|
||||||
hb_subset_repack_or_fail
|
hb_subset_input_pin_axis_location
|
||||||
hb_subset_input_override_name_table
|
hb_subset_input_pin_axis_to_default""".splitlines ()
|
||||||
""".splitlines ()
|
|
||||||
symbols = [x for x in symbols if x not in experimental_symbols]
|
symbols = [x for x in symbols if x not in experimental_symbols]
|
||||||
symbols = "\n".join (symbols)
|
symbols = "\n".join (symbols)
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,6 @@ categories = {
|
||||||
'PLACEHOLDER',
|
'PLACEHOLDER',
|
||||||
'DOTTEDCIRCLE',
|
'DOTTEDCIRCLE',
|
||||||
'RS',
|
'RS',
|
||||||
'MPst',
|
|
||||||
'Repha',
|
'Repha',
|
||||||
'Ra',
|
'Ra',
|
||||||
'CM',
|
'CM',
|
||||||
|
@ -169,6 +168,8 @@ category_map = {
|
||||||
'Vowel' : 'V',
|
'Vowel' : 'V',
|
||||||
'Vowel_Dependent' : 'M',
|
'Vowel_Dependent' : 'M',
|
||||||
'Vowel_Independent' : 'V',
|
'Vowel_Independent' : 'V',
|
||||||
|
'Dotted_Circle' : 'DOTTEDCIRCLE', # Ours, not Unicode's
|
||||||
|
'Ra' : 'Ra', # Ours, not Unicode's
|
||||||
}
|
}
|
||||||
position_map = {
|
position_map = {
|
||||||
'Not_Applicable' : 'END',
|
'Not_Applicable' : 'END',
|
||||||
|
@ -239,9 +240,6 @@ category_overrides = {
|
||||||
0x0953: 'SM',
|
0x0953: 'SM',
|
||||||
0x0954: 'SM',
|
0x0954: 'SM',
|
||||||
|
|
||||||
# U+0A40 GURMUKHI VOWEL SIGN II may be preceded by U+0A02 GURMUKHI SIGN BINDI.
|
|
||||||
0x0A40: 'MPst',
|
|
||||||
|
|
||||||
# The following act like consonants.
|
# The following act like consonants.
|
||||||
0x0A72: 'C',
|
0x0A72: 'C',
|
||||||
0x0A73: 'C',
|
0x0A73: 'C',
|
||||||
|
@ -442,7 +440,7 @@ for k,new_cat in category_overrides.items():
|
||||||
indic_data[k] = (new_cat, pos, unicode_data[2][k])
|
indic_data[k] = (new_cat, pos, unicode_data[2][k])
|
||||||
|
|
||||||
# We only expect position for certain types
|
# We only expect position for certain types
|
||||||
positioned_categories = ('CM', 'SM', 'RS', 'H', 'M', 'MPst')
|
positioned_categories = ('CM', 'SM', 'RS', 'H', 'M')
|
||||||
for k, (cat, pos, block) in indic_data.items():
|
for k, (cat, pos, block) in indic_data.items():
|
||||||
if cat not in positioned_categories:
|
if cat not in positioned_categories:
|
||||||
pos = 'END'
|
pos = 'END'
|
||||||
|
@ -452,12 +450,11 @@ for k, (cat, pos, block) in indic_data.items():
|
||||||
|
|
||||||
# Keep in sync with CONSONANT_FLAGS in the shaper
|
# Keep in sync with CONSONANT_FLAGS in the shaper
|
||||||
consonant_categories = ('C', 'CS', 'Ra','CM', 'V', 'PLACEHOLDER', 'DOTTEDCIRCLE')
|
consonant_categories = ('C', 'CS', 'Ra','CM', 'V', 'PLACEHOLDER', 'DOTTEDCIRCLE')
|
||||||
matra_categories = ('M', 'MPst')
|
|
||||||
smvd_categories = ('SM', 'VD', 'A', 'Symbol')
|
smvd_categories = ('SM', 'VD', 'A', 'Symbol')
|
||||||
for k, (cat, pos, block) in indic_data.items():
|
for k, (cat, pos, block) in indic_data.items():
|
||||||
if cat in consonant_categories:
|
if cat in consonant_categories:
|
||||||
pos = 'BASE_C'
|
pos = 'BASE_C'
|
||||||
elif cat in matra_categories:
|
elif cat == 'M':
|
||||||
if block.startswith('Khmer') or block.startswith('Myanmar'):
|
if block.startswith('Khmer') or block.startswith('Myanmar'):
|
||||||
cat = position_to_category(pos)
|
cat = position_to_category(pos)
|
||||||
else:
|
else:
|
||||||
|
@ -637,7 +634,7 @@ for u in uu:
|
||||||
end = (end-1)//8*8 + 7
|
end = (end-1)//8*8 + 7
|
||||||
|
|
||||||
if start != last + 1:
|
if start != last + 1:
|
||||||
if start - last <= 1+16*2:
|
if start - last <= 1+16*3:
|
||||||
print_block (None, last+1, start-1, indic_data)
|
print_block (None, last+1, start-1, indic_data)
|
||||||
else:
|
else:
|
||||||
if last >= 0:
|
if last >= 0:
|
||||||
|
@ -694,6 +691,6 @@ print ('#endif')
|
||||||
print ()
|
print ()
|
||||||
print ("/* == End of generated table == */")
|
print ("/* == End of generated table == */")
|
||||||
|
|
||||||
# Maintain at least 50% occupancy in the table */
|
# Maintain at least 30% occupancy in the table */
|
||||||
if occupancy < 50:
|
if occupancy < 30:
|
||||||
raise Exception ("Table too sparse, please investigate: ", occupancy)
|
raise Exception ("Table too sparse, please investigate: ", occupancy)
|
||||||
|
|
|
@ -25,28 +25,14 @@ hb_common_h = 'hb-common.h' if len (sys.argv) < 3 else sys.argv[2]
|
||||||
|
|
||||||
logging.info('Preparing data tables...')
|
logging.info('Preparing data tables...')
|
||||||
|
|
||||||
|
|
||||||
# This is how the data is encoded:
|
|
||||||
#
|
|
||||||
# General_Category (gc), Canonical_Combining_Class (ccc),
|
|
||||||
# and Script (sc) are encoded as integers.
|
|
||||||
#
|
|
||||||
# Mirroring character (bmg) is encoded as difference from
|
|
||||||
# the original character.
|
|
||||||
#
|
|
||||||
# Composition & Decomposition (dm) are encoded elaborately,
|
|
||||||
# as discussed below.
|
|
||||||
|
|
||||||
gc = [u['gc'] for u in ucd]
|
gc = [u['gc'] for u in ucd]
|
||||||
ccc = [int(u['ccc']) for u in ucd]
|
ccc = [int(u['ccc']) for u in ucd]
|
||||||
bmg = [int(v, 16) - int(u) if v else 0 for u,v in enumerate(u['bmg'] for u in ucd)]
|
bmg = [int(v, 16) - int(u) if v else 0 for u,v in enumerate(u['bmg'] for u in ucd)]
|
||||||
|
#gc_ccc_non0 = set((cat,klass) for cat,klass in zip(gc,ccc) if klass)
|
||||||
|
#gc_bmg_non0 = set((cat,mirr) for cat,mirr in zip(gc, bmg) if mirr)
|
||||||
|
|
||||||
sc = [u['sc'] for u in ucd]
|
sc = [u['sc'] for u in ucd]
|
||||||
|
|
||||||
|
|
||||||
# Prepare Compose / Decompose data
|
|
||||||
#
|
|
||||||
# This code is very dense. See hb_ucd_compose() / hb_ucd_decompose() for the logic.
|
|
||||||
|
|
||||||
dm = {i:tuple(int(v, 16) for v in u['dm'].split()) for i,u in enumerate(ucd)
|
dm = {i:tuple(int(v, 16) for v in u['dm'].split()) for i,u in enumerate(ucd)
|
||||||
if u['dm'] != '#' and u['dt'] == 'can' and not (0xAC00 <= i < 0xAC00+11172)}
|
if u['dm'] != '#' and u['dt'] == 'can' and not (0xAC00 <= i < 0xAC00+11172)}
|
||||||
ce = {i for i,u in enumerate(ucd) if u['Comp_Ex'] == 'Y'}
|
ce = {i for i,u in enumerate(ucd) if u['Comp_Ex'] == 'Y'}
|
||||||
|
@ -77,9 +63,6 @@ dm_order = {None: 0}
|
||||||
dm_order.update(dm1_order)
|
dm_order.update(dm1_order)
|
||||||
dm_order.update(dm2_order)
|
dm_order.update(dm2_order)
|
||||||
|
|
||||||
|
|
||||||
# Prepare General_Category / Script mapping arrays
|
|
||||||
|
|
||||||
gc_order = dict()
|
gc_order = dict()
|
||||||
for i,v in enumerate(('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu',
|
for i,v in enumerate(('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu',
|
||||||
'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf',
|
'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf',
|
||||||
|
@ -100,18 +83,10 @@ for line in open(hb_common_h):
|
||||||
sc_order[i] = tag
|
sc_order[i] = tag
|
||||||
sc_array.append(name)
|
sc_array.append(name)
|
||||||
|
|
||||||
|
DEFAULT = 3
|
||||||
|
COMPACT = 5
|
||||||
|
SLOPPY = 9
|
||||||
|
|
||||||
# Write out main data
|
|
||||||
|
|
||||||
DEFAULT = 'DEFAULT'
|
|
||||||
COMPACT = 'COMPACT'
|
|
||||||
SLOPPY = 'SLOPPY'
|
|
||||||
|
|
||||||
compression_level = {
|
|
||||||
DEFAULT: 5,
|
|
||||||
COMPACT: 9,
|
|
||||||
SLOPPY: 9,
|
|
||||||
}
|
|
||||||
|
|
||||||
logging.info('Generating output...')
|
logging.info('Generating output...')
|
||||||
print("/* == Start of generated table == */")
|
print("/* == Start of generated table == */")
|
||||||
|
@ -129,9 +104,6 @@ print()
|
||||||
print('#include "hb.hh"')
|
print('#include "hb.hh"')
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
# Write mapping data
|
|
||||||
|
|
||||||
code = packTab.Code('_hb_ucd')
|
code = packTab.Code('_hb_ucd')
|
||||||
sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array)
|
sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array)
|
||||||
dm1_p0_array, _ = code.addArray('uint16_t', 'dm1_p0_map', dm1_p0_array)
|
dm1_p0_array, _ = code.addArray('uint16_t', 'dm1_p0_map', dm1_p0_array)
|
||||||
|
@ -148,24 +120,18 @@ datasets = [
|
||||||
('dm', dm, None, dm_order),
|
('dm', dm, None, dm_order),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
for compression in (DEFAULT, COMPACT, SLOPPY):
|
||||||
# Write main data
|
|
||||||
|
|
||||||
for step in (DEFAULT, COMPACT, SLOPPY):
|
|
||||||
compression = compression_level[step]
|
|
||||||
logging.info(' Compression=%d:' % compression)
|
logging.info(' Compression=%d:' % compression)
|
||||||
print()
|
print()
|
||||||
if step == DEFAULT:
|
if compression == DEFAULT:
|
||||||
print('#ifndef HB_OPTIMIZE_SIZE')
|
print('#ifndef HB_OPTIMIZE_SIZE')
|
||||||
elif step == COMPACT:
|
elif compression == COMPACT:
|
||||||
print('#elif !defined(HB_NO_UCD_UNASSIGNED)')
|
print('#elif !defined(HB_NO_UCD_UNASSIGNED)')
|
||||||
elif step == SLOPPY:
|
|
||||||
print('#else')
|
|
||||||
else:
|
else:
|
||||||
assert False
|
print('#else')
|
||||||
print()
|
print()
|
||||||
|
|
||||||
if step == SLOPPY:
|
if compression == SLOPPY:
|
||||||
for i in range(len(gc)):
|
for i in range(len(gc)):
|
||||||
if (i % 128) and gc[i] == 'Cn':
|
if (i % 128) and gc[i] == 'Cn':
|
||||||
gc[i] = gc[i - 1]
|
gc[i] = gc[i - 1]
|
||||||
|
@ -191,7 +157,6 @@ for step in (DEFAULT, COMPACT, SLOPPY):
|
||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
print('#endif')
|
print('#endif')
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# flake8: noqa: F821
|
# flake8: noqa: F821
|
||||||
|
|
||||||
import logging
|
|
||||||
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
|
|
||||||
|
|
||||||
"""usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
|
"""usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
|
||||||
|
|
||||||
Input files:
|
Input files:
|
||||||
|
@ -137,7 +134,6 @@ property_names = [
|
||||||
'Number_Joiner',
|
'Number_Joiner',
|
||||||
'Number',
|
'Number',
|
||||||
'Brahmi_Joining_Number',
|
'Brahmi_Joining_Number',
|
||||||
'Symbol_Modifier',
|
|
||||||
'Hieroglyph',
|
'Hieroglyph',
|
||||||
'Hieroglyph_Joiner',
|
'Hieroglyph_Joiner',
|
||||||
'Hieroglyph_Segment_Begin',
|
'Hieroglyph_Segment_Begin',
|
||||||
|
@ -218,7 +214,8 @@ def is_CONS_MED(U, UISC, UDI, UGC, AJT):
|
||||||
return (UISC == Consonant_Medial and UGC != Lo or
|
return (UISC == Consonant_Medial and UGC != Lo or
|
||||||
UISC == Consonant_Initial_Postfixed)
|
UISC == Consonant_Initial_Postfixed)
|
||||||
def is_CONS_MOD(U, UISC, UDI, UGC, AJT):
|
def is_CONS_MOD(U, UISC, UDI, UGC, AJT):
|
||||||
return UISC in [Nukta, Gemination_Mark, Consonant_Killer]
|
return (UISC in [Nukta, Gemination_Mark, Consonant_Killer] and
|
||||||
|
not is_SYM_MOD(U, UISC, UDI, UGC, AJT))
|
||||||
def is_CONS_SUB(U, UISC, UDI, UGC, AJT):
|
def is_CONS_SUB(U, UISC, UDI, UGC, AJT):
|
||||||
return UISC == Consonant_Subjoined and UGC != Lo
|
return UISC == Consonant_Subjoined and UGC != Lo
|
||||||
def is_CONS_WITH_STACKER(U, UISC, UDI, UGC, AJT):
|
def is_CONS_WITH_STACKER(U, UISC, UDI, UGC, AJT):
|
||||||
|
@ -260,7 +257,7 @@ def is_SAKOT(U, UISC, UDI, UGC, AJT):
|
||||||
# Split off of HALANT
|
# Split off of HALANT
|
||||||
return U == 0x1A60
|
return U == 0x1A60
|
||||||
def is_SYM_MOD(U, UISC, UDI, UGC, AJT):
|
def is_SYM_MOD(U, UISC, UDI, UGC, AJT):
|
||||||
return UISC == Symbol_Modifier
|
return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73]
|
||||||
def is_VOWEL(U, UISC, UDI, UGC, AJT):
|
def is_VOWEL(U, UISC, UDI, UGC, AJT):
|
||||||
return (UISC == Pure_Killer or
|
return (UISC == Pure_Killer or
|
||||||
UGC != Lo and UISC in [Vowel, Vowel_Dependent])
|
UGC != Lo and UISC in [Vowel, Vowel_Dependent])
|
||||||
|
@ -362,6 +359,9 @@ def map_to_use(data):
|
||||||
# TODO: These don't have UISC assigned in Unicode 13.0.0, but have UIPC
|
# TODO: These don't have UISC assigned in Unicode 13.0.0, but have UIPC
|
||||||
if 0x0F18 <= U <= 0x0F19 or 0x0F3E <= U <= 0x0F3F: UISC = Vowel_Dependent
|
if 0x0F18 <= U <= 0x0F19 or 0x0F3E <= U <= 0x0F3F: UISC = Vowel_Dependent
|
||||||
|
|
||||||
|
# TODO: https://github.com/harfbuzz/harfbuzz/pull/627
|
||||||
|
if 0x1BF2 <= U <= 0x1BF3: UISC = Nukta; UIPC = Bottom
|
||||||
|
|
||||||
# TODO: U+1CED should only be allowed after some of
|
# TODO: U+1CED should only be allowed after some of
|
||||||
# the nasalization marks, maybe only for U+1CE9..U+1CF1.
|
# the nasalization marks, maybe only for U+1CE9..U+1CF1.
|
||||||
if U == 0x1CED: UISC = Tone_Mark
|
if U == 0x1CED: UISC = Tone_Mark
|
||||||
|
@ -372,9 +372,23 @@ def map_to_use(data):
|
||||||
|
|
||||||
# Resolve Indic_Positional_Category
|
# Resolve Indic_Positional_Category
|
||||||
|
|
||||||
|
# TODO: These should die, but have UIPC in Unicode 13.0.0
|
||||||
|
if U in [0x953, 0x954]: UIPC = Not_Applicable
|
||||||
|
|
||||||
|
# TODO: These are not in USE's override list that we have, nor are they in Unicode 13.0.0
|
||||||
|
if 0xA926 <= U <= 0xA92A: UIPC = Top
|
||||||
# TODO: https://github.com/harfbuzz/harfbuzz/pull/1037
|
# TODO: https://github.com/harfbuzz/harfbuzz/pull/1037
|
||||||
# and https://github.com/harfbuzz/harfbuzz/issues/1631
|
# and https://github.com/harfbuzz/harfbuzz/issues/1631
|
||||||
if U in [0x11302, 0x11303, 0x114C1]: UIPC = Top
|
if U in [0x11302, 0x11303, 0x114C1]: UIPC = Top
|
||||||
|
if 0x1CF8 <= U <= 0x1CF9: UIPC = Top
|
||||||
|
|
||||||
|
# TODO: https://github.com/harfbuzz/harfbuzz/issues/3550
|
||||||
|
if U == 0x10A38: UIPC = Bottom
|
||||||
|
|
||||||
|
# TODO: https://github.com/harfbuzz/harfbuzz/pull/982
|
||||||
|
# also https://github.com/harfbuzz/harfbuzz/issues/1012
|
||||||
|
if 0x1112A <= U <= 0x1112B: UIPC = Top
|
||||||
|
if 0x11131 <= U <= 0x11132: UIPC = Top
|
||||||
|
|
||||||
assert (UIPC in [Not_Applicable, Visual_Order_Left] or U == 0x0F7F or
|
assert (UIPC in [Not_Applicable, Visual_Order_Left] or U == 0x0F7F or
|
||||||
USE in use_positions), "%s %s %s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UDI, UGC, AJT)
|
USE in use_positions), "%s %s %s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UDI, UGC, AJT)
|
||||||
|
@ -468,29 +482,10 @@ print ("")
|
||||||
|
|
||||||
import packTab
|
import packTab
|
||||||
data = {u:v[0] for u,v in use_data.items()}
|
data = {u:v[0] for u,v in use_data.items()}
|
||||||
|
code = packTab.Code('hb_use')
|
||||||
DEFAULT = 5
|
sol = packTab.pack_table(data, compression=5, default='O')
|
||||||
COMPACT = 9
|
sol.genCode(code, f'get_category')
|
||||||
for compression in (DEFAULT, COMPACT):
|
code.print_c(linkage='static inline')
|
||||||
|
|
||||||
logging.info(' Compression=%d:' % compression)
|
|
||||||
print()
|
|
||||||
if compression == DEFAULT:
|
|
||||||
print('#ifndef HB_OPTIMIZE_SIZE')
|
|
||||||
elif compression == COMPACT:
|
|
||||||
print('#else')
|
|
||||||
else:
|
|
||||||
assert False
|
|
||||||
print()
|
|
||||||
|
|
||||||
code = packTab.Code('hb_use')
|
|
||||||
sol = packTab.pack_table(data, compression=compression, default='O')
|
|
||||||
logging.info(' FullCost=%d' % (sol.fullCost))
|
|
||||||
sol.genCode(code, f'get_category')
|
|
||||||
code.print_c(linkage='static inline')
|
|
||||||
print ()
|
|
||||||
|
|
||||||
print('#endif')
|
|
||||||
|
|
||||||
print ()
|
print ()
|
||||||
for k in sorted(use_mapping.keys()):
|
for k in sorted(use_mapping.keys()):
|
||||||
|
|
|
@ -112,7 +112,7 @@ struct ClassDef : public OT::ClassDef
|
||||||
{
|
{
|
||||||
case 1: return ((ClassDefFormat1*)this)->sanitize (vertex);
|
case 1: return ((ClassDefFormat1*)this)->sanitize (vertex);
|
||||||
case 2: return ((ClassDefFormat2*)this)->sanitize (vertex);
|
case 2: return ((ClassDefFormat2*)this)->sanitize (vertex);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
// Not currently supported
|
// Not currently supported
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
|
|
|
@ -136,7 +136,7 @@ struct Coverage : public OT::Layout::Common::Coverage
|
||||||
{
|
{
|
||||||
case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
|
case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
|
||||||
case 2: return ((CoverageFormat2*)this)->sanitize (vertex);
|
case 2: return ((CoverageFormat2*)this)->sanitize (vertex);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
// Not currently supported
|
// Not currently supported
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
|
|
|
@ -49,50 +49,6 @@ struct graph_t
|
||||||
unsigned end = 0;
|
unsigned end = 0;
|
||||||
unsigned priority = 0;
|
unsigned priority = 0;
|
||||||
|
|
||||||
|
|
||||||
bool link_positions_valid (unsigned num_objects, bool removed_nil)
|
|
||||||
{
|
|
||||||
hb_set_t assigned_bytes;
|
|
||||||
for (const auto& l : obj.real_links)
|
|
||||||
{
|
|
||||||
if (l.objidx >= num_objects
|
|
||||||
|| (removed_nil && !l.objidx))
|
|
||||||
{
|
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
|
||||||
"Invalid graph. Invalid object index.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned start = l.position;
|
|
||||||
unsigned end = start + l.width - 1;
|
|
||||||
|
|
||||||
if (unlikely (l.width < 2 || l.width > 4))
|
|
||||||
{
|
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
|
||||||
"Invalid graph. Invalid link width.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely (end >= table_size ()))
|
|
||||||
{
|
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
|
||||||
"Invalid graph. Link position is out of bounds.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely (assigned_bytes.intersects (start, end)))
|
|
||||||
{
|
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
|
||||||
"Invalid graph. Found offsets whose positions overlap.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
assigned_bytes.add_range (start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
return !assigned_bytes.in_error ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void normalize ()
|
void normalize ()
|
||||||
{
|
{
|
||||||
obj.real_links.qsort ();
|
obj.real_links.qsort ();
|
||||||
|
@ -123,7 +79,7 @@ struct graph_t
|
||||||
while (a || b)
|
while (a || b)
|
||||||
{
|
{
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||||
" 0x%x %s 0x%x", (unsigned) *a, (*a == *b) ? "==" : "!=", (unsigned) *b);
|
" 0x%x %s 0x%x", *a, (*a == *b) ? "==" : "!=", *b);
|
||||||
a++;
|
a++;
|
||||||
b++;
|
b++;
|
||||||
}
|
}
|
||||||
|
@ -176,7 +132,7 @@ struct graph_t
|
||||||
for (unsigned i = 0; i < parents.length; i++)
|
for (unsigned i = 0; i < parents.length; i++)
|
||||||
{
|
{
|
||||||
if (parents[i] != parent_index) continue;
|
if (parents[i] != parent_index) continue;
|
||||||
parents.remove_unordered (i);
|
parents.remove (i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,7 +148,7 @@ struct graph_t
|
||||||
if ((obj.head + link.position) != offset)
|
if ((obj.head + link.position) != offset)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
obj.real_links.remove_unordered (i);
|
obj.real_links.remove (i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,6 +286,8 @@ struct graph_t
|
||||||
vertices_scratch_.alloc (objects.length);
|
vertices_scratch_.alloc (objects.length);
|
||||||
for (unsigned i = 0; i < objects.length; i++)
|
for (unsigned i = 0; i < objects.length; i++)
|
||||||
{
|
{
|
||||||
|
// TODO(grieger): check all links point to valid objects.
|
||||||
|
|
||||||
// If this graph came from a serialization buffer object 0 is the
|
// If this graph came from a serialization buffer object 0 is the
|
||||||
// nil object. We don't need it for our purposes here so drop it.
|
// nil object. We don't need it for our purposes here so drop it.
|
||||||
if (i == 0 && !objects[i])
|
if (i == 0 && !objects[i])
|
||||||
|
@ -341,9 +299,6 @@ struct graph_t
|
||||||
vertex_t* v = vertices_.push ();
|
vertex_t* v = vertices_.push ();
|
||||||
if (check_success (!vertices_.in_error ()))
|
if (check_success (!vertices_.in_error ()))
|
||||||
v->obj = *objects[i];
|
v->obj = *objects[i];
|
||||||
|
|
||||||
check_success (v->link_positions_valid (objects.length, removed_nil));
|
|
||||||
|
|
||||||
if (!removed_nil) continue;
|
if (!removed_nil) continue;
|
||||||
// Fix indices to account for removed nil object.
|
// Fix indices to account for removed nil object.
|
||||||
for (auto& l : v->obj.all_links_writer ()) {
|
for (auto& l : v->obj.all_links_writer ()) {
|
||||||
|
@ -463,13 +418,6 @@ struct graph_t
|
||||||
hb_swap (sorted_graph[new_id], vertices_[next_id]);
|
hb_swap (sorted_graph[new_id], vertices_[next_id]);
|
||||||
const vertex_t& next = sorted_graph[new_id];
|
const vertex_t& next = sorted_graph[new_id];
|
||||||
|
|
||||||
if (unlikely (!check_success(new_id >= 0))) {
|
|
||||||
// We are out of ids. Which means we've visited a node more than once.
|
|
||||||
// This graph contains a cycle which is not allowed.
|
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Invalid graph. Contains cycle.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
id_map[next_id] = new_id--;
|
id_map[next_id] = new_id--;
|
||||||
|
|
||||||
for (const auto& link : next.obj.all_links ()) {
|
for (const auto& link : next.obj.all_links ()) {
|
||||||
|
@ -547,12 +495,6 @@ struct graph_t
|
||||||
return as_table_from_index<T> (index_for_offset (parent, offset), std::forward<Ts>(ds)...);
|
return as_table_from_index<T> (index_for_offset (parent, offset), std::forward<Ts>(ds)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename ...Ts>
|
|
||||||
vertex_and_table_t<T> as_mutable_table (unsigned parent, const void* offset, Ts... ds)
|
|
||||||
{
|
|
||||||
return as_table_from_index<T> (mutable_index_for_offset (parent, offset), std::forward<Ts>(ds)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename ...Ts>
|
template <typename T, typename ...Ts>
|
||||||
vertex_and_table_t<T> as_table_from_index (unsigned index, Ts... ds)
|
vertex_and_table_t<T> as_table_from_index (unsigned index, Ts... ds)
|
||||||
{
|
{
|
||||||
|
@ -632,7 +574,7 @@ struct graph_t
|
||||||
|
|
||||||
while (roots)
|
while (roots)
|
||||||
{
|
{
|
||||||
uint32_t next = HB_SET_VALUE_INVALID;
|
unsigned next = HB_SET_VALUE_INVALID;
|
||||||
if (unlikely (!check_success (!roots.in_error ()))) break;
|
if (unlikely (!check_success (!roots.in_error ()))) break;
|
||||||
if (!roots.next (&next)) break;
|
if (!roots.next (&next)) break;
|
||||||
|
|
||||||
|
@ -700,9 +642,6 @@ struct graph_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_error ())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!made_changes)
|
if (!made_changes)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -716,8 +655,8 @@ struct graph_t
|
||||||
|
|
||||||
auto new_subgraph =
|
auto new_subgraph =
|
||||||
+ subgraph.keys ()
|
+ subgraph.keys ()
|
||||||
| hb_map([&] (uint32_t node_idx) {
|
| hb_map([&] (unsigned node_idx) {
|
||||||
const uint32_t *v;
|
const unsigned *v;
|
||||||
if (index_map.has (node_idx, &v)) return *v;
|
if (index_map.has (node_idx, &v)) return *v;
|
||||||
return node_idx;
|
return node_idx;
|
||||||
})
|
})
|
||||||
|
@ -727,10 +666,10 @@ struct graph_t
|
||||||
remap_obj_indices (index_map, parents.iter (), true);
|
remap_obj_indices (index_map, parents.iter (), true);
|
||||||
|
|
||||||
// Update roots set with new indices as needed.
|
// Update roots set with new indices as needed.
|
||||||
uint32_t next = HB_SET_VALUE_INVALID;
|
unsigned next = HB_SET_VALUE_INVALID;
|
||||||
while (roots.next (&next))
|
while (roots.next (&next))
|
||||||
{
|
{
|
||||||
const uint32_t *v;
|
const unsigned *v;
|
||||||
if (index_map.has (next, &v))
|
if (index_map.has (next, &v))
|
||||||
{
|
{
|
||||||
roots.del (next);
|
roots.del (next);
|
||||||
|
@ -745,7 +684,7 @@ struct graph_t
|
||||||
{
|
{
|
||||||
for (const auto& link : vertices_[node_idx].obj.all_links ())
|
for (const auto& link : vertices_[node_idx].obj.all_links ())
|
||||||
{
|
{
|
||||||
const uint32_t *v;
|
const unsigned *v;
|
||||||
if (subgraph.has (link.objidx, &v))
|
if (subgraph.has (link.objidx, &v))
|
||||||
{
|
{
|
||||||
subgraph.set (link.objidx, *v + 1);
|
subgraph.set (link.objidx, *v + 1);
|
||||||
|
@ -836,11 +775,7 @@ struct graph_t
|
||||||
if (index_map.has (node_idx))
|
if (index_map.has (node_idx))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned clone_idx = duplicate (node_idx);
|
index_map.set (node_idx, duplicate (node_idx));
|
||||||
if (!check_success (clone_idx != (unsigned) -1))
|
|
||||||
return;
|
|
||||||
|
|
||||||
index_map.set (node_idx, clone_idx);
|
|
||||||
for (const auto& l : object (node_idx).all_links ()) {
|
for (const auto& l : object (node_idx).all_links ()) {
|
||||||
duplicate_subgraph (l.objidx, index_map);
|
duplicate_subgraph (l.objidx, index_map);
|
||||||
}
|
}
|
||||||
|
@ -898,20 +833,7 @@ struct graph_t
|
||||||
* parent to the clone. The copy is a shallow copy, objects
|
* parent to the clone. The copy is a shallow copy, objects
|
||||||
* linked from child are not duplicated.
|
* linked from child are not duplicated.
|
||||||
*/
|
*/
|
||||||
unsigned duplicate_if_shared (unsigned parent_idx, unsigned child_idx)
|
bool duplicate (unsigned parent_idx, unsigned child_idx)
|
||||||
{
|
|
||||||
unsigned new_idx = duplicate (parent_idx, child_idx);
|
|
||||||
if (new_idx == (unsigned) -1) return child_idx;
|
|
||||||
return new_idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Creates a copy of child and re-assigns the link from
|
|
||||||
* parent to the clone. The copy is a shallow copy, objects
|
|
||||||
* linked from child are not duplicated.
|
|
||||||
*/
|
|
||||||
unsigned duplicate (unsigned parent_idx, unsigned child_idx)
|
|
||||||
{
|
{
|
||||||
update_parents ();
|
update_parents ();
|
||||||
|
|
||||||
|
@ -925,12 +847,12 @@ struct graph_t
|
||||||
{
|
{
|
||||||
// Can't duplicate this node, doing so would orphan the original one as all remaining links
|
// Can't duplicate this node, doing so would orphan the original one as all remaining links
|
||||||
// to child are from parent.
|
// to child are from parent.
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %u => %u",
|
DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d",
|
||||||
parent_idx, child_idx);
|
parent_idx, child_idx);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %u => %u",
|
DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
|
||||||
parent_idx, child_idx);
|
parent_idx, child_idx);
|
||||||
|
|
||||||
unsigned clone_idx = duplicate (child_idx);
|
unsigned clone_idx = duplicate (child_idx);
|
||||||
|
@ -947,7 +869,7 @@ struct graph_t
|
||||||
reassign_link (l, parent_idx, clone_idx);
|
reassign_link (l, parent_idx, clone_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return clone_idx;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -988,7 +910,7 @@ struct graph_t
|
||||||
*/
|
*/
|
||||||
bool raise_childrens_priority (unsigned parent_idx)
|
bool raise_childrens_priority (unsigned parent_idx)
|
||||||
{
|
{
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %u",
|
DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %d",
|
||||||
parent_idx);
|
parent_idx);
|
||||||
// This operation doesn't change ordering until a sort is run, so no need
|
// This operation doesn't change ordering until a sort is run, so no need
|
||||||
// to invalidate positions. It does not change graph structure so no need
|
// to invalidate positions. It does not change graph structure so no need
|
||||||
|
@ -1000,72 +922,6 @@ struct graph_t
|
||||||
return made_change;
|
return made_change;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_fully_connected ()
|
|
||||||
{
|
|
||||||
update_parents();
|
|
||||||
|
|
||||||
if (root().parents)
|
|
||||||
// Root cannot have parents.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < root_idx (); i++)
|
|
||||||
{
|
|
||||||
if (!vertices_[i].parents)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* Saves the current graph to a packed binary format which the repacker fuzzer takes
|
|
||||||
* as a seed.
|
|
||||||
*/
|
|
||||||
void save_fuzzer_seed (hb_tag_t tag) const
|
|
||||||
{
|
|
||||||
FILE* f = fopen ("./repacker_fuzzer_seed", "w");
|
|
||||||
fwrite ((void*) &tag, sizeof (tag), 1, f);
|
|
||||||
|
|
||||||
uint16_t num_objects = vertices_.length;
|
|
||||||
fwrite ((void*) &num_objects, sizeof (num_objects), 1, f);
|
|
||||||
|
|
||||||
for (const auto& v : vertices_)
|
|
||||||
{
|
|
||||||
uint16_t blob_size = v.table_size ();
|
|
||||||
fwrite ((void*) &blob_size, sizeof (blob_size), 1, f);
|
|
||||||
fwrite ((const void*) v.obj.head, blob_size, 1, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t link_count = 0;
|
|
||||||
for (const auto& v : vertices_)
|
|
||||||
link_count += v.obj.real_links.length;
|
|
||||||
|
|
||||||
fwrite ((void*) &link_count, sizeof (link_count), 1, f);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint16_t parent;
|
|
||||||
uint16_t child;
|
|
||||||
uint16_t position;
|
|
||||||
uint8_t width;
|
|
||||||
} link_t;
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < vertices_.length; i++)
|
|
||||||
{
|
|
||||||
for (const auto& l : vertices_[i].obj.real_links)
|
|
||||||
{
|
|
||||||
link_t link {
|
|
||||||
(uint16_t) i, (uint16_t) l.objidx,
|
|
||||||
(uint16_t) l.position, (uint8_t) l.width
|
|
||||||
};
|
|
||||||
fwrite ((void*) &link, sizeof (link), 1, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose (f);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void print_orphaned_nodes ()
|
void print_orphaned_nodes ()
|
||||||
{
|
{
|
||||||
if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
|
if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
|
||||||
|
@ -1074,10 +930,6 @@ struct graph_t
|
||||||
parents_invalid = true;
|
parents_invalid = true;
|
||||||
update_parents();
|
update_parents();
|
||||||
|
|
||||||
if (root().parents) {
|
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Root node has incoming edges.");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < root_idx (); i++)
|
for (unsigned i = 0; i < root_idx (); i++)
|
||||||
{
|
{
|
||||||
const auto& v = vertices_[i];
|
const auto& v = vertices_[i];
|
||||||
|
@ -1194,11 +1046,6 @@ struct graph_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < vertices_.length; i++)
|
|
||||||
// parents arrays must be accurate or downstream operations like cycle detection
|
|
||||||
// and sorting won't work correctly.
|
|
||||||
check_success (!vertices_[i].parents.in_error ());
|
|
||||||
|
|
||||||
parents_invalid = false;
|
parents_invalid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1317,7 +1164,7 @@ struct graph_t
|
||||||
{
|
{
|
||||||
for (auto& link : vertices_[i].obj.all_links_writer ())
|
for (auto& link : vertices_[i].obj.all_links_writer ())
|
||||||
{
|
{
|
||||||
const uint32_t *v;
|
const unsigned *v;
|
||||||
if (!id_map.has (link.objidx, &v)) continue;
|
if (!id_map.has (link.objidx, &v)) continue;
|
||||||
if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
|
if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
|
||||||
|
|
||||||
|
|
|
@ -131,10 +131,8 @@ struct Lookup : public OT::Lookup
|
||||||
for (unsigned i = 0; i < subTable.len; i++)
|
for (unsigned i = 0; i < subTable.len; i++)
|
||||||
{
|
{
|
||||||
unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
|
unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
|
||||||
unsigned parent_index = this_index;
|
|
||||||
if (is_ext) {
|
if (is_ext) {
|
||||||
unsigned ext_subtable_index = subtable_index;
|
unsigned ext_subtable_index = subtable_index;
|
||||||
parent_index = ext_subtable_index;
|
|
||||||
ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
|
ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
|
||||||
(ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*)
|
(ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*)
|
||||||
c.graph.object (ext_subtable_index).head;
|
c.graph.object (ext_subtable_index).head;
|
||||||
|
@ -152,9 +150,9 @@ struct Lookup : public OT::Lookup
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
new_sub_tables = split_subtable<PairPos> (c, parent_index, subtable_index); break;
|
new_sub_tables = split_subtable<PairPos> (c, subtable_index); break;
|
||||||
case 4:
|
case 4:
|
||||||
new_sub_tables = split_subtable<MarkBasePos> (c, parent_index, subtable_index); break;
|
new_sub_tables = split_subtable<MarkBasePos> (c, subtable_index); break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -174,14 +172,13 @@ struct Lookup : public OT::Lookup
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
hb_vector_t<unsigned> split_subtable (gsubgpos_graph_context_t& c,
|
hb_vector_t<unsigned> split_subtable (gsubgpos_graph_context_t& c,
|
||||||
unsigned parent_idx,
|
|
||||||
unsigned objidx)
|
unsigned objidx)
|
||||||
{
|
{
|
||||||
T* sub_table = (T*) c.graph.object (objidx).head;
|
T* sub_table = (T*) c.graph.object (objidx).head;
|
||||||
if (!sub_table || !sub_table->sanitize (c.graph.vertices_[objidx]))
|
if (!sub_table || !sub_table->sanitize (c.graph.vertices_[objidx]))
|
||||||
return hb_vector_t<unsigned> ();
|
return hb_vector_t<unsigned> ();
|
||||||
|
|
||||||
return sub_table->split_subtables (c, parent_idx, objidx);
|
return sub_table->split_subtables (c, objidx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_sub_tables (gsubgpos_graph_context_t& c,
|
void add_sub_tables (gsubgpos_graph_context_t& c,
|
||||||
|
@ -201,7 +198,7 @@ struct Lookup : public OT::Lookup
|
||||||
+ new_subtable_count * OT::Offset16::static_size;
|
+ new_subtable_count * OT::Offset16::static_size;
|
||||||
char* buffer = (char*) hb_calloc (1, new_size);
|
char* buffer = (char*) hb_calloc (1, new_size);
|
||||||
c.add_buffer (buffer);
|
c.add_buffer (buffer);
|
||||||
hb_memcpy (buffer, v.obj.head, v.table_size());
|
memcpy (buffer, v.obj.head, v.table_size());
|
||||||
|
|
||||||
v.obj.head = buffer;
|
v.obj.head = buffer;
|
||||||
v.obj.tail = buffer + new_size;
|
v.obj.tail = buffer + new_size;
|
||||||
|
@ -355,7 +352,7 @@ struct GSTAR : public OT::GSUBGPOS
|
||||||
{
|
{
|
||||||
switch (u.version.major) {
|
switch (u.version.major) {
|
||||||
case 1: return u.version1.get_lookup_list_offset ();
|
case 1: return u.version1.get_lookup_list_offset ();
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 2: return u.version2.get_lookup_list_offset ();
|
case 2: return u.version2.get_lookup_list_offset ();
|
||||||
#endif
|
#endif
|
||||||
default: return 0;
|
default: return 0;
|
||||||
|
@ -374,7 +371,7 @@ struct GSTAR : public OT::GSUBGPOS
|
||||||
{
|
{
|
||||||
switch (u.version.major) {
|
switch (u.version.major) {
|
||||||
case 1: find_lookups<SmallTypes> (graph, lookups); break;
|
case 1: find_lookups<SmallTypes> (graph, lookups); break;
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 2: find_lookups<MediumTypes> (graph, lookups); break;
|
case 2: find_lookups<MediumTypes> (graph, lookups); break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ struct AnchorMatrix : public OT::Layout::GPOS_impl::AnchorMatrix
|
||||||
auto& child = c.graph.vertices_[child_idx];
|
auto& child = c.graph.vertices_[child_idx];
|
||||||
child.remove_parent (this_index);
|
child.remove_parent (this_index);
|
||||||
|
|
||||||
o.real_links.remove_unordered (i);
|
o.real_links.remove (i);
|
||||||
num_links--;
|
num_links--;
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
|
@ -209,9 +209,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
||||||
return vertex_len >= MarkBasePosFormat1::static_size;
|
return vertex_len >= MarkBasePosFormat1::static_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||||
unsigned parent_index,
|
|
||||||
unsigned this_index)
|
|
||||||
{
|
{
|
||||||
hb_set_t visited;
|
hb_set_t visited;
|
||||||
|
|
||||||
|
@ -263,7 +261,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
||||||
split_context_t split_context {
|
split_context_t split_context {
|
||||||
c,
|
c,
|
||||||
this,
|
this,
|
||||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
this_index,
|
||||||
std::move (class_to_info),
|
std::move (class_to_info),
|
||||||
c.graph.vertices_[mark_array_id].position_to_index_map (),
|
c.graph.vertices_[mark_array_id].position_to_index_map (),
|
||||||
};
|
};
|
||||||
|
@ -367,12 +365,12 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
||||||
|
|
||||||
classCount = count;
|
classCount = count;
|
||||||
|
|
||||||
auto mark_coverage = sc.c.graph.as_mutable_table<Coverage> (this_index,
|
auto mark_coverage = sc.c.graph.as_table<Coverage> (this_index,
|
||||||
&markCoverage);
|
&markCoverage);
|
||||||
if (!mark_coverage) return false;
|
if (!mark_coverage) return false;
|
||||||
hb_set_t marks = sc.marks_for (0, count);
|
hb_set_t marks = sc.marks_for (0, count);
|
||||||
auto new_coverage =
|
auto new_coverage =
|
||||||
+ hb_enumerate (mark_coverage.table->iter ())
|
+ hb_zip (hb_range (), mark_coverage.table->iter ())
|
||||||
| hb_filter (marks, hb_first)
|
| hb_filter (marks, hb_first)
|
||||||
| hb_map_retains_sorting (hb_second)
|
| hb_map_retains_sorting (hb_second)
|
||||||
;
|
;
|
||||||
|
@ -382,17 +380,17 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
auto base_array = sc.c.graph.as_mutable_table<AnchorMatrix> (this_index,
|
auto base_array = sc.c.graph.as_table<AnchorMatrix> (this_index,
|
||||||
&baseArray,
|
&baseArray,
|
||||||
old_count);
|
old_count);
|
||||||
if (!base_array || !base_array.table->shrink (sc.c,
|
if (!base_array || !base_array.table->shrink (sc.c,
|
||||||
base_array.index,
|
base_array.index,
|
||||||
old_count,
|
old_count,
|
||||||
count))
|
count))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto mark_array = sc.c.graph.as_mutable_table<MarkArray> (this_index,
|
auto mark_array = sc.c.graph.as_table<MarkArray> (this_index,
|
||||||
&markArray);
|
&markArray);
|
||||||
if (!mark_array || !mark_array.table->shrink (sc.c,
|
if (!mark_array || !mark_array.table->shrink (sc.c,
|
||||||
sc.mark_array_links,
|
sc.mark_array_links,
|
||||||
mark_array.index,
|
mark_array.index,
|
||||||
|
@ -431,7 +429,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
||||||
if (!mark_coverage) return false;
|
if (!mark_coverage) return false;
|
||||||
hb_set_t marks = sc.marks_for (start, end);
|
hb_set_t marks = sc.marks_for (start, end);
|
||||||
auto new_coverage =
|
auto new_coverage =
|
||||||
+ hb_enumerate (mark_coverage.table->iter ())
|
+ hb_zip (hb_range (), mark_coverage.table->iter ())
|
||||||
| hb_filter (marks, hb_first)
|
| hb_filter (marks, hb_first)
|
||||||
| hb_map_retains_sorting (hb_second)
|
| hb_map_retains_sorting (hb_second)
|
||||||
;
|
;
|
||||||
|
@ -471,13 +469,12 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
||||||
struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
|
struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
|
||||||
{
|
{
|
||||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||||
unsigned parent_index,
|
|
||||||
unsigned this_index)
|
unsigned this_index)
|
||||||
{
|
{
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1:
|
case 1:
|
||||||
return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, this_index);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 2: HB_FALLTHROUGH;
|
case 2: HB_FALLTHROUGH;
|
||||||
// Don't split 24bit PairPos's.
|
// Don't split 24bit PairPos's.
|
||||||
#endif
|
#endif
|
||||||
|
@ -494,7 +491,7 @@ struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1:
|
case 1:
|
||||||
return ((MarkBasePosFormat1*)(&u.format1))->sanitize (vertex);
|
return ((MarkBasePosFormat1*)(&u.format1))->sanitize (vertex);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 2: HB_FALLTHROUGH;
|
case 2: HB_FALLTHROUGH;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -47,9 +47,7 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
||||||
min_size + pairSet.get_size () - pairSet.len.get_size();
|
min_size + pairSet.get_size () - pairSet.len.get_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||||
unsigned parent_index,
|
|
||||||
unsigned this_index)
|
|
||||||
{
|
{
|
||||||
hb_set_t visited;
|
hb_set_t visited;
|
||||||
|
|
||||||
|
@ -83,7 +81,7 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
||||||
split_context_t split_context {
|
split_context_t split_context {
|
||||||
c,
|
c,
|
||||||
this,
|
this,
|
||||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
this_index,
|
||||||
};
|
};
|
||||||
|
|
||||||
return actuate_subtable_split<split_context_t> (split_context, split_points);
|
return actuate_subtable_split<split_context_t> (split_context, split_points);
|
||||||
|
@ -127,19 +125,23 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
||||||
pairSet.len = count;
|
pairSet.len = count;
|
||||||
c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size;
|
c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size;
|
||||||
|
|
||||||
auto coverage = c.graph.as_mutable_table<Coverage> (this_index, &this->coverage);
|
unsigned coverage_id = c.graph.mutable_index_for_offset (this_index, &coverage);
|
||||||
if (!coverage) return false;
|
unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
|
||||||
|
auto& coverage_v = c.graph.vertices_[coverage_id];
|
||||||
|
|
||||||
|
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
|
||||||
|
if (!coverage_table || !coverage_table->sanitize (coverage_v))
|
||||||
|
return false;
|
||||||
|
|
||||||
unsigned coverage_size = coverage.vertex->table_size ();
|
|
||||||
auto new_coverage =
|
auto new_coverage =
|
||||||
+ hb_zip (coverage.table->iter (), hb_range ())
|
+ hb_zip (coverage_table->iter (), hb_range ())
|
||||||
| hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
|
| hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
|
||||||
return p.second < count;
|
return p.second < count;
|
||||||
})
|
})
|
||||||
| hb_map_retains_sorting (hb_first)
|
| hb_map_retains_sorting (hb_first)
|
||||||
;
|
;
|
||||||
|
|
||||||
return Coverage::make_coverage (c, new_coverage, coverage.index, coverage_size);
|
return Coverage::make_coverage (c, new_coverage, coverage_id, coverage_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new PairPos including PairSet's from start (inclusive) to end (exclusive).
|
// Create a new PairPos including PairSet's from start (inclusive) to end (exclusive).
|
||||||
|
@ -204,9 +206,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
||||||
min_size + class1_count * get_class1_record_size ();
|
min_size + class1_count * get_class1_record_size ();
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||||
unsigned parent_index,
|
|
||||||
unsigned this_index)
|
|
||||||
{
|
{
|
||||||
const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>::min_size;
|
const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>::min_size;
|
||||||
const unsigned class_def_2_size = size_of (c, this_index, &classDef2);
|
const unsigned class_def_2_size = size_of (c, this_index, &classDef2);
|
||||||
|
@ -287,7 +287,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
||||||
split_context_t split_context {
|
split_context_t split_context {
|
||||||
c,
|
c,
|
||||||
this,
|
this,
|
||||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
this_index,
|
||||||
class1_record_size,
|
class1_record_size,
|
||||||
total_value_len,
|
total_value_len,
|
||||||
value_1_len,
|
value_1_len,
|
||||||
|
@ -434,7 +434,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
||||||
|
|
||||||
char* start_addr = ((char*)&values[0]) + start * split_context.class1_record_size;
|
char* start_addr = ((char*)&values[0]) + start * split_context.class1_record_size;
|
||||||
unsigned num_records = end - start;
|
unsigned num_records = end - start;
|
||||||
hb_memcpy (&pair_pos_prime->values[0],
|
memcpy (&pair_pos_prime->values[0],
|
||||||
start_addr,
|
start_addr,
|
||||||
num_records * split_context.class1_record_size);
|
num_records * split_context.class1_record_size);
|
||||||
|
|
||||||
|
@ -508,37 +508,40 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
||||||
graph.vertices_[split_context.this_index].obj.tail -=
|
graph.vertices_[split_context.this_index].obj.tail -=
|
||||||
(old_count - count) * split_context.class1_record_size;
|
(old_count - count) * split_context.class1_record_size;
|
||||||
|
|
||||||
auto coverage =
|
unsigned coverage_id =
|
||||||
graph.as_mutable_table<Coverage> (split_context.this_index, &this->coverage);
|
graph.mutable_index_for_offset (split_context.this_index, &coverage);
|
||||||
if (!coverage) return false;
|
unsigned class_def_1_id =
|
||||||
|
graph.mutable_index_for_offset (split_context.this_index, &classDef1);
|
||||||
auto class_def_1 =
|
auto& coverage_v = graph.vertices_[coverage_id];
|
||||||
graph.as_mutable_table<ClassDef> (split_context.this_index, &classDef1);
|
auto& class_def_1_v = graph.vertices_[class_def_1_id];
|
||||||
if (!class_def_1) return false;
|
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
|
||||||
|
ClassDef* class_def_1_table = (ClassDef*) class_def_1_v.obj.head;
|
||||||
|
if (!coverage_table
|
||||||
|
|| !coverage_table->sanitize (coverage_v)
|
||||||
|
|| !class_def_1_table
|
||||||
|
|| !class_def_1_table->sanitize (class_def_1_v))
|
||||||
|
return false;
|
||||||
|
|
||||||
auto klass_map =
|
auto klass_map =
|
||||||
+ coverage.table->iter ()
|
+ coverage_table->iter ()
|
||||||
| hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
|
| hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
|
||||||
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1.table->get_class (gid));
|
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1_table->get_class (gid));
|
||||||
})
|
})
|
||||||
| hb_filter ([&] (hb_codepoint_t klass) {
|
| hb_filter ([&] (hb_codepoint_t klass) {
|
||||||
return klass < count;
|
return klass < count;
|
||||||
}, hb_second)
|
}, hb_second)
|
||||||
;
|
;
|
||||||
|
|
||||||
auto new_coverage = + klass_map | hb_map_retains_sorting (hb_first);
|
|
||||||
if (!Coverage::make_coverage (split_context.c,
|
if (!Coverage::make_coverage (split_context.c,
|
||||||
+ new_coverage,
|
+ klass_map | hb_map_retains_sorting (hb_first),
|
||||||
coverage.index,
|
coverage_id,
|
||||||
// existing ranges my not be kept, worst case size is a format 1
|
coverage_v.table_size ()))
|
||||||
// coverage table.
|
|
||||||
4 + new_coverage.len() * 2))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return ClassDef::make_class_def (split_context.c,
|
return ClassDef::make_class_def (split_context.c,
|
||||||
+ klass_map,
|
+ klass_map,
|
||||||
class_def_1.index,
|
class_def_1_id,
|
||||||
class_def_1.vertex->table_size ());
|
class_def_1_v.table_size ());
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_hashmap_t<unsigned, unsigned>
|
hb_hashmap_t<unsigned, unsigned>
|
||||||
|
@ -602,16 +605,14 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
||||||
|
|
||||||
struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
||||||
{
|
{
|
||||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||||
unsigned parent_index,
|
|
||||||
unsigned this_index)
|
|
||||||
{
|
{
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1:
|
case 1:
|
||||||
return ((PairPosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
return ((PairPosFormat1*)(&u.format1))->split_subtables (c, this_index);
|
||||||
case 2:
|
case 2:
|
||||||
return ((PairPosFormat2*)(&u.format2))->split_subtables (c, parent_index, this_index);
|
return ((PairPosFormat2*)(&u.format2))->split_subtables (c, this_index);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: HB_FALLTHROUGH;
|
case 3: HB_FALLTHROUGH;
|
||||||
case 4: HB_FALLTHROUGH;
|
case 4: HB_FALLTHROUGH;
|
||||||
// Don't split 24bit PairPos's.
|
// Don't split 24bit PairPos's.
|
||||||
|
@ -631,7 +632,7 @@ struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
||||||
return ((PairPosFormat1*)(&u.format1))->sanitize (vertex);
|
return ((PairPosFormat1*)(&u.format1))->sanitize (vertex);
|
||||||
case 2:
|
case 2:
|
||||||
return ((PairPosFormat2*)(&u.format2))->sanitize (vertex);
|
return ((PairPosFormat2*)(&u.format2))->sanitize (vertex);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BORING_EXPANSION
|
||||||
case 3: HB_FALLTHROUGH;
|
case 3: HB_FALLTHROUGH;
|
||||||
case 4: HB_FALLTHROUGH;
|
case 4: HB_FALLTHROUGH;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,23 +33,6 @@ struct overflow_record_t
|
||||||
{
|
{
|
||||||
unsigned parent;
|
unsigned parent;
|
||||||
unsigned child;
|
unsigned child;
|
||||||
|
|
||||||
bool operator != (const overflow_record_t o) const
|
|
||||||
{ return !(*this == o); }
|
|
||||||
|
|
||||||
inline bool operator == (const overflow_record_t& o) const
|
|
||||||
{
|
|
||||||
return parent == o.parent &&
|
|
||||||
child == o.child;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32_t hash () const
|
|
||||||
{
|
|
||||||
uint32_t current = 0;
|
|
||||||
current = current * 31 + hb_hash (parent);
|
|
||||||
current = current * 31 + hb_hash (child);
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
@ -111,7 +94,6 @@ will_overflow (graph_t& graph,
|
||||||
if (overflows) overflows->resize (0);
|
if (overflows) overflows->resize (0);
|
||||||
graph.update_positions ();
|
graph.update_positions ();
|
||||||
|
|
||||||
hb_hashmap_t<overflow_record_t*, bool> record_set;
|
|
||||||
const auto& vertices = graph.vertices_;
|
const auto& vertices = graph.vertices_;
|
||||||
for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--)
|
for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--)
|
||||||
{
|
{
|
||||||
|
@ -127,10 +109,7 @@ will_overflow (graph_t& graph,
|
||||||
overflow_record_t r;
|
overflow_record_t r;
|
||||||
r.parent = parent_idx;
|
r.parent = parent_idx;
|
||||||
r.child = link.objidx;
|
r.child = link.objidx;
|
||||||
if (record_set.has(&r)) continue; // don't keep duplicate overflows.
|
|
||||||
|
|
||||||
overflows->push (r);
|
overflows->push (r);
|
||||||
record_set.set(&r, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,8 +132,8 @@ void print_overflows (graph_t& graph,
|
||||||
const auto& child = graph.vertices_[o.child];
|
const auto& child = graph.vertices_[o.child];
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||||
" overflow from "
|
" overflow from "
|
||||||
"%4u (%4u in, %4u out, space %2u) => "
|
"%4d (%4d in, %4d out, space %2d) => "
|
||||||
"%4u (%4u in, %4u out, space %2u)",
|
"%4d (%4d in, %4d out, space %2d)",
|
||||||
o.parent,
|
o.parent,
|
||||||
parent.incoming_edges (),
|
parent.incoming_edges (),
|
||||||
parent.obj.real_links.length + parent.obj.virtual_links.length,
|
parent.obj.real_links.length + parent.obj.virtual_links.length,
|
||||||
|
@ -165,7 +144,7 @@ void print_overflows (graph_t& graph,
|
||||||
graph.space_for (o.child));
|
graph.space_for (o.child));
|
||||||
}
|
}
|
||||||
if (overflows.length > 10) {
|
if (overflows.length > 10) {
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %u more overflows.", overflows.length - 10);
|
DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %d more overflows.", overflows.length - 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +223,7 @@ inline hb_blob_t* serialize (const graph_t& graph)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_memcpy (start, vertices[i].obj.head, size);
|
memcpy (start, vertices[i].obj.head, size);
|
||||||
|
|
||||||
// Only real links needs to be serialized.
|
// Only real links needs to be serialized.
|
||||||
for (const auto& link : vertices[i].obj.real_links)
|
for (const auto& link : vertices[i].obj.real_links)
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
prefix=%prefix%
|
|
||||||
exec_prefix=%exec_prefix%
|
|
||||||
libdir=%libdir%
|
|
||||||
includedir=%includedir%
|
|
||||||
|
|
||||||
Name: harfbuzz cairo integration
|
|
||||||
Description: HarfBuzz cairo integration
|
|
||||||
Version: %VERSION%
|
|
||||||
|
|
||||||
Requires: harfbuzz = %VERSION%
|
|
||||||
Libs: -L${libdir} -lharfbuzz-cairo
|
|
||||||
Cflags: -I${includedir}/harfbuzz
|
|
|
@ -1,5 +1,29 @@
|
||||||
|
# Set these variables so that the `${prefix}/lib` expands to something we can
|
||||||
|
# remove.
|
||||||
|
set(_harfbuzz_remove_string "REMOVE_ME")
|
||||||
|
set(exec_prefix "${_harfbuzz_remove_string}")
|
||||||
|
set(prefix "${_harfbuzz_remove_string}")
|
||||||
|
|
||||||
|
# Compute the installation prefix by stripping components from our current
|
||||||
|
# location.
|
||||||
|
get_filename_component(_harfbuzz_prefix "${CMAKE_CURRENT_LIST_DIR}" DIRECTORY)
|
||||||
|
get_filename_component(_harfbuzz_prefix "${_harfbuzz_prefix}" DIRECTORY)
|
||||||
set(_harfbuzz_libdir "@libdir@")
|
set(_harfbuzz_libdir "@libdir@")
|
||||||
|
string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_libdir "${_harfbuzz_libdir}")
|
||||||
|
set(_harfbuzz_libdir_iter "${_harfbuzz_libdir}")
|
||||||
|
while (_harfbuzz_libdir_iter)
|
||||||
|
set(_harfbuzz_libdir_prev_iter "${_harfbuzz_libdir_iter}")
|
||||||
|
get_filename_component(_harfbuzz_libdir_iter "${_harfbuzz_libdir_iter}" DIRECTORY)
|
||||||
|
if (_harfbuzz_libdir_prev_iter STREQUAL _harfbuzz_libdir_iter)
|
||||||
|
break()
|
||||||
|
endif ()
|
||||||
|
get_filename_component(_harfbuzz_prefix "${_harfbuzz_prefix}" DIRECTORY)
|
||||||
|
endwhile ()
|
||||||
|
unset(_harfbuzz_libdir_iter)
|
||||||
|
|
||||||
|
# Get the include subdir.
|
||||||
set(_harfbuzz_includedir "@includedir@")
|
set(_harfbuzz_includedir "@includedir@")
|
||||||
|
string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_includedir "${_harfbuzz_includedir}")
|
||||||
|
|
||||||
# Extract version information from libtool.
|
# Extract version information from libtool.
|
||||||
set(_harfbuzz_version_info "@HB_LIBTOOL_VERSION_INFO@")
|
set(_harfbuzz_version_info "@HB_LIBTOOL_VERSION_INFO@")
|
||||||
|
@ -12,45 +36,41 @@ list(GET _harfbuzz_version_info 2
|
||||||
_harfbuzz_age)
|
_harfbuzz_age)
|
||||||
unset(_harfbuzz_version_info)
|
unset(_harfbuzz_version_info)
|
||||||
|
|
||||||
if ("@default_library@" MATCHES "static")
|
if (APPLE)
|
||||||
set(_harfbuzz_lib_suffix ".a")
|
set(_harfbuzz_lib_suffix ".0${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||||
|
elseif (UNIX)
|
||||||
|
set(_harfbuzz_lib_suffix "${CMAKE_SHARED_LIBRARY_SUFFIX}.0.${_harfbuzz_current}.${_harfbuzz_revision}")
|
||||||
else ()
|
else ()
|
||||||
if (APPLE)
|
# Unsupported.
|
||||||
set(_harfbuzz_lib_suffix ".0${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
set(harfbuzz_FOUND 0)
|
||||||
elseif (UNIX)
|
|
||||||
set(_harfbuzz_lib_suffix "${CMAKE_SHARED_LIBRARY_SUFFIX}.0.${_harfbuzz_current}.${_harfbuzz_revision}")
|
|
||||||
else ()
|
|
||||||
# Unsupported.
|
|
||||||
set(harfbuzz_FOUND 0)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Add the libraries.
|
# Add the libraries.
|
||||||
add_library(harfbuzz::harfbuzz SHARED IMPORTED)
|
add_library(harfbuzz::harfbuzz SHARED IMPORTED)
|
||||||
set_target_properties(harfbuzz::harfbuzz PROPERTIES
|
set_target_properties(harfbuzz::harfbuzz PROPERTIES
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
|
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||||
IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}")
|
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}")
|
||||||
|
|
||||||
add_library(harfbuzz::icu SHARED IMPORTED)
|
add_library(harfbuzz::icu SHARED IMPORTED)
|
||||||
set_target_properties(harfbuzz::icu PROPERTIES
|
set_target_properties(harfbuzz::icu PROPERTIES
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
|
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||||
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
||||||
IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-icu${_harfbuzz_lib_suffix}")
|
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-icu${_harfbuzz_lib_suffix}")
|
||||||
|
|
||||||
add_library(harfbuzz::subset SHARED IMPORTED)
|
add_library(harfbuzz::subset SHARED IMPORTED)
|
||||||
set_target_properties(harfbuzz::subset PROPERTIES
|
set_target_properties(harfbuzz::subset PROPERTIES
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
|
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||||
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
||||||
IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-subset${_harfbuzz_lib_suffix}")
|
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-subset${_harfbuzz_lib_suffix}")
|
||||||
|
|
||||||
# Only add the gobject library if it was built.
|
# Only add the gobject library if it was built.
|
||||||
set(_harfbuzz_have_gobject "@have_gobject@")
|
set(_harfbuzz_have_gobject "@have_gobject@")
|
||||||
if (_harfbuzz_have_gobject)
|
if (_harfbuzz_have_gobject)
|
||||||
add_library(harfbuzz::gobject SHARED IMPORTED)
|
add_library(harfbuzz::gobject SHARED IMPORTED)
|
||||||
set_target_properties(harfbuzz::gobject PROPERTIES
|
set_target_properties(harfbuzz::gobject PROPERTIES
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
|
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||||
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
||||||
IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-gobject${_harfbuzz_lib_suffix}")
|
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-gobject${_harfbuzz_lib_suffix}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Clean out variables we used in our scope.
|
# Clean out variables we used in our scope.
|
||||||
|
@ -60,3 +80,7 @@ unset(_harfbuzz_revision)
|
||||||
unset(_harfbuzz_age)
|
unset(_harfbuzz_age)
|
||||||
unset(_harfbuzz_includedir)
|
unset(_harfbuzz_includedir)
|
||||||
unset(_harfbuzz_libdir)
|
unset(_harfbuzz_libdir)
|
||||||
|
unset(_harfbuzz_prefix)
|
||||||
|
unset(exec_prefix)
|
||||||
|
unset(prefix)
|
||||||
|
unset(_harfbuzz_remove_string)
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "hb-buffer.cc"
|
#include "hb-buffer.cc"
|
||||||
#include "hb-common.cc"
|
#include "hb-common.cc"
|
||||||
#include "hb-draw.cc"
|
#include "hb-draw.cc"
|
||||||
#include "hb-face-builder.cc"
|
|
||||||
#include "hb-face.cc"
|
#include "hb-face.cc"
|
||||||
#include "hb-fallback-shape.cc"
|
#include "hb-fallback-shape.cc"
|
||||||
#include "hb-font.cc"
|
#include "hb-font.cc"
|
||||||
|
@ -41,9 +40,6 @@
|
||||||
#include "hb-ot-shaper-vowel-constraints.cc"
|
#include "hb-ot-shaper-vowel-constraints.cc"
|
||||||
#include "hb-ot-tag.cc"
|
#include "hb-ot-tag.cc"
|
||||||
#include "hb-ot-var.cc"
|
#include "hb-ot-var.cc"
|
||||||
#include "hb-outline.cc"
|
|
||||||
#include "hb-paint-extents.cc"
|
|
||||||
#include "hb-paint.cc"
|
|
||||||
#include "hb-set.cc"
|
#include "hb-set.cc"
|
||||||
#include "hb-shape-plan.cc"
|
#include "hb-shape-plan.cc"
|
||||||
#include "hb-shape.cc"
|
#include "hb-shape.cc"
|
||||||
|
@ -54,7 +50,6 @@
|
||||||
#include "hb-subset-cff1.cc"
|
#include "hb-subset-cff1.cc"
|
||||||
#include "hb-subset-cff2.cc"
|
#include "hb-subset-cff2.cc"
|
||||||
#include "hb-subset-input.cc"
|
#include "hb-subset-input.cc"
|
||||||
#include "hb-subset-instancer-solver.cc"
|
|
||||||
#include "hb-subset-plan.cc"
|
#include "hb-subset-plan.cc"
|
||||||
#include "hb-subset-repacker.cc"
|
#include "hb-subset-repacker.cc"
|
||||||
#include "hb-subset.cc"
|
#include "hb-subset.cc"
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue