Compare commits
No commits in common. "main" and "patch_mode" have entirely different histories.
main
...
patch_mode
|
@ -2,17 +2,15 @@
|
|||
set -e
|
||||
|
||||
meson --cross-file=.ci/win32-cross-file.txt \
|
||||
--wrap-mode=default \
|
||||
--wrap-mode=forcefallback \
|
||||
-Dtests=disabled \
|
||||
-Dcairo=enabled \
|
||||
-Dcairo:fontconfig=disabled \
|
||||
-Dcairo:freetype=disabled \
|
||||
-Dcairo:dwrite=disabled \
|
||||
-Dcairo:tests=disabled \
|
||||
-Dglib=enabled \
|
||||
-Dfreetype=disabled \
|
||||
-Dfreetype=enabled \
|
||||
-Dgdi=enabled \
|
||||
-Ddirectwrite=enabled \
|
||||
-Dcairo=enabled \
|
||||
win32build \
|
||||
$@
|
||||
|
||||
|
|
|
@ -2,17 +2,15 @@
|
|||
set -e
|
||||
|
||||
meson --cross-file=.ci/win64-cross-file.txt \
|
||||
--wrap-mode=default \
|
||||
--wrap-mode=forcefallback \
|
||||
-Dtests=disabled \
|
||||
-Dcairo=enabled \
|
||||
-Dcairo:fontconfig=disabled \
|
||||
-Dcairo:freetype=disabled \
|
||||
-Dcairo:dwrite=disabled \
|
||||
-Dcairo:tests=disabled \
|
||||
-Dglib=enabled \
|
||||
-Dfreetype=disabled \
|
||||
-Dfreetype=enabled \
|
||||
-Dgdi=enabled \
|
||||
-Ddirectwrite=enabled \
|
||||
-Dcairo=enabled \
|
||||
win64build \
|
||||
$@
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@ jobs:
|
|||
xcode: "12.5.1"
|
||||
steps:
|
||||
- checkout
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config ragel freetype glib cairo python3 icu4c graphite2 gobject-introspection ninja
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config ragel freetype glib cairo python3 icu4c graphite2 gobject-introspection gtk-doc ninja
|
||||
- run: pip3 install meson --upgrade
|
||||
- run: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson 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 test -Cbuild --print-errorlogs
|
||||
- store_artifacts:
|
||||
|
@ -57,8 +57,8 @@ jobs:
|
|||
steps:
|
||||
- checkout
|
||||
- run: dnf install -y pkg-config ragel valgrind gcc gcc-c++ meson git glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python python-pip || true
|
||||
- run: meson setup build --buildtype=debugoptimized
|
||||
- run: meson compile -Cbuild -j9
|
||||
- run: meson build --buildtype=debugoptimized
|
||||
- run: ninja -Cbuild -j9
|
||||
# TOOD: increase timeouts and remove --no-suite=slow
|
||||
- run: RUN_VALGRIND=1 meson test -Cbuild --no-suite=slow --wrap='valgrind --leak-check=full --error-exitcode=1' --print-errorlogs --num-processes=$(($(nproc)/2 + 1))
|
||||
|
||||
|
@ -69,9 +69,24 @@ jobs:
|
|||
- checkout
|
||||
- run: apk update && apk add ragel gcc g++ glib-dev freetype-dev cairo-dev git py3-pip ninja
|
||||
- run: pip3 install meson==0.56.0
|
||||
- run: meson setup build --buildtype=minsize
|
||||
- run: meson 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 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:
|
||||
docker:
|
||||
|
@ -81,9 +96,8 @@ jobs:
|
|||
- run: apt update || true
|
||||
- run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
|
||||
- run: pip3 install meson==0.56.0
|
||||
- run: CC=clang CXX=clang++ meson setup build --default-library=static -Db_sanitize=address,undefined --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
|
||||
- run: meson compile -Cbuild -j9
|
||||
- run: meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||
- run: CC=clang CXX=clang++ meson build --default-library=static -Db_sanitize=address,undefined --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
|
||||
- run: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||
|
||||
tsan:
|
||||
docker:
|
||||
|
@ -93,9 +107,8 @@ jobs:
|
|||
- run: apt update || true
|
||||
- run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
|
||||
- run: pip3 install meson==0.56.0
|
||||
- run: CC=clang CXX=clang++ meson setup build --default-library=static -Db_sanitize=thread --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
|
||||
- run: meson compile -Cbuild -j9
|
||||
- run: meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||
- run: CC=clang CXX=clang++ meson build --default-library=static -Db_sanitize=thread --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
|
||||
- run: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||
|
||||
msan:
|
||||
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: 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
|
||||
- run: CC=clang CXX=clang++ meson setup build --default-library=static -Db_sanitize=memory --buildtype=debugoptimized --wrap-mode=nodownload -Dauto_features=disabled -Dtests=enabled -Dexperimental_api=true
|
||||
- run: meson compile -Cbuild -j9
|
||||
- run: meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||
- 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: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||
|
||||
clang-cxx2a:
|
||||
docker:
|
||||
|
@ -123,8 +135,8 @@ jobs:
|
|||
executor: win32-executor
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build python3 python3-pip git g++-mingw-w64-i686 zip
|
||||
- run: pip3 install meson==0.60.0
|
||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build gtk-doc-tools python3 python3-pip git g++-mingw-w64-i686 zip
|
||||
- run: pip3 install meson==0.56.0 --upgrade
|
||||
- run: .ci/build-win32.sh
|
||||
- store_artifacts:
|
||||
path: harfbuzz-win32.zip
|
||||
|
@ -146,8 +158,8 @@ jobs:
|
|||
executor: win64-executor
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build python3 python3-pip git g++-mingw-w64-x86-64 zip
|
||||
- run: pip3 install meson==0.60.0
|
||||
- run: 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.56.0 --upgrade
|
||||
- run: bash .ci/build-win64.sh
|
||||
- store_artifacts:
|
||||
path: harfbuzz-win64.zip
|
||||
|
@ -186,6 +198,7 @@ workflows:
|
|||
ignore: /.*/
|
||||
- fedora-valgrind
|
||||
- alpine
|
||||
#- archlinux
|
||||
- asan-ubsan
|
||||
- tsan
|
||||
- msan
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
comment: false
|
||||
comment: off
|
||||
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
informational: true
|
||||
patch:
|
||||
default:
|
||||
informational: true
|
||||
threshold: 1%
|
||||
patch: off
|
||||
|
|
|
@ -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
|
||||
on: [pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
@ -11,7 +11,7 @@ permissions:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-18.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
|
|
@ -12,60 +12,46 @@ permissions:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-18.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ runner.arch }}
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install \
|
||||
gcc \
|
||||
gobject-introspection \
|
||||
gtk-doc-tools \
|
||||
libcairo2-dev \
|
||||
libfreetype6-dev \
|
||||
libgirepository1.0-dev \
|
||||
libglib2.0-dev \
|
||||
libgraphite2-dev \
|
||||
libicu-dev \
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
python3 \
|
||||
python3-setuptools
|
||||
- name: Install Python Dependencies
|
||||
run: sudo pip3 install fonttools meson==0.56.0 gcovr==5.0
|
||||
- name: Setup Meson
|
||||
run: |
|
||||
ccache --version
|
||||
meson setup build \
|
||||
-Dauto_features=enabled \
|
||||
-Dchafa=disabled \
|
||||
-Dgraphite=enabled \
|
||||
-Doptimization=2 \
|
||||
-Db_coverage=true \
|
||||
-Ddoc_tests=true \
|
||||
-Dragel_subproject=true
|
||||
- name: Build
|
||||
run: meson compile -Cbuild
|
||||
- name: Test
|
||||
- uses: actions/checkout@v3
|
||||
- name: install dependencies
|
||||
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
|
||||
- run: sudo pip3 install fonttools meson==0.56.0 gcovr==5.0
|
||||
- name: run
|
||||
run: meson build -Db_coverage=true --auto-features=enabled -Dgraphite=enabled -Dchafa=disabled -Dragel_subproject=true -Doptimization=2
|
||||
- name: ci
|
||||
run: meson test --print-errorlogs -Cbuild
|
||||
- name: Generate Documentations
|
||||
|
||||
- name: generate documentations
|
||||
run: ninja -Cbuild harfbuzz-doc
|
||||
- name: Deploy Documentations
|
||||
- name: deploy documentations
|
||||
if: github.ref_type == 'tag'
|
||||
run: .ci/deploy-docs.sh
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
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
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
- uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: build/meson-logs/coverage.xml
|
||||
|
|
|
@ -14,47 +14,17 @@ jobs:
|
|||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ runner.arch }}
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
export HOMEBREW_NO_AUTO_UPDATE=1
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
brew install \
|
||||
cairo \
|
||||
freetype \
|
||||
glib \
|
||||
gobject-introspection \
|
||||
graphite2 \
|
||||
icu4c \
|
||||
meson \
|
||||
ninja \
|
||||
pkg-config
|
||||
- name: Install Python Dependencies
|
||||
run: pip3 install fonttools gcovr==5.0
|
||||
- name: Setup Meson
|
||||
run: |
|
||||
export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig"
|
||||
ccache --version
|
||||
meson setup build \
|
||||
-Dauto_features=enabled \
|
||||
-Ddocs=disabled \
|
||||
-Dchafa=disabled \
|
||||
-Dcoretext=enabled \
|
||||
-Dgraphite=enabled \
|
||||
-Doptimization=2 \
|
||||
-Db_coverage=true \
|
||||
- name: Build
|
||||
run: meson compile -Cbuild
|
||||
- name: Test
|
||||
- uses: actions/checkout@v3
|
||||
- name: install dependencies
|
||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config freetype glib glib-utils cairo icu4c graphite2 gobject-introspection gtk-doc ninja
|
||||
- run: pip3 install fonttools meson==0.56.0 gcovr==5.0
|
||||
- name: run
|
||||
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: ci
|
||||
run: meson test --print-errorlogs -Cbuild
|
||||
- name: Generate Coverage
|
||||
|
||||
- name: cov
|
||||
run: ninja -Cbuild coverage-xml
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
- uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: build/meson-logs/coverage.xml
|
||||
|
|
|
@ -14,7 +14,6 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-2019, windows-latest]
|
||||
include:
|
||||
|
@ -27,35 +26,33 @@ jobs:
|
|||
name: ${{ matrix.name }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
variant: sccache
|
||||
key: ${{ github.job }}-${{ matrix.os }}-${{ matrix.ARCH }}
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Setup MSVC
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch : ${{ matrix.ARCH }}
|
||||
- name: Install Python Dependencies
|
||||
run: |
|
||||
pip install --upgrade meson ninja fonttools
|
||||
- name: Setup Meson
|
||||
run: |
|
||||
sccache --version
|
||||
meson setup build `
|
||||
--wrap-mode=forcefallback `
|
||||
--buildtype=release `
|
||||
-Dglib=enabled `
|
||||
-Dfreetype=enabled `
|
||||
-Dgdi=enabled `
|
||||
-Ddirectwrite=enabled
|
||||
- name: Build
|
||||
run: meson compile -Cbuild
|
||||
- name: Test
|
||||
run: meson test --print-errorlogs --suite=harfbuzz -Cbuild
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch : ${{ matrix.ARCH }}
|
||||
- name: Upgrade pip
|
||||
run: |
|
||||
python -m pip install -U pip
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
pip install --upgrade meson ninja fonttools
|
||||
- name: Build
|
||||
run: |
|
||||
# This dir contains a pkg-config which meson will happily use and later fail, so remove it
|
||||
$env:path = ($env:path.Split(';') | Where-Object { $_ -ne 'C:\Strawberry\perl\bin' }) -join ';'
|
||||
|
||||
meson setup build `
|
||||
--wrap-mode=default `
|
||||
--buildtype=release `
|
||||
-Dglib=enabled `
|
||||
-Dfreetype=enabled `
|
||||
-Dgdi=enabled `
|
||||
-Ddirectwrite=enabled
|
||||
|
||||
meson compile -C build
|
||||
- name: Test
|
||||
run: |
|
||||
meson test --print-errorlogs --suite=harfbuzz -C build
|
||||
|
|
|
@ -14,7 +14,6 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- MSYSTEM: MINGW32
|
||||
|
@ -23,51 +22,47 @@ jobs:
|
|||
MSYS2_ARCH: x86_64
|
||||
name: ${{ matrix.MSYSTEM }}
|
||||
|
||||
env:
|
||||
# XXX: For some reason enabling jit debugging "fixes" random python crashes
|
||||
# see https://github.com/msys2/MINGW-packages/issues/11864
|
||||
MSYS: "winjitdebug"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.MSYSTEM }}
|
||||
update: true
|
||||
install: >-
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-cairo
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-freetype
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc-libs
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gettext
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-glib2
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gobject-introspection
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-graphite2
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-icu
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-meson
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-ninja
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-pkg-config
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-python
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-python-pip
|
||||
- name: Install Python Dependencies
|
||||
run: |
|
||||
pip install --upgrade fonttools
|
||||
- name: Setup Meson
|
||||
run: |
|
||||
meson setup build \
|
||||
--wrap-mode=nodownload \
|
||||
--auto-features=enabled \
|
||||
-Ddocs=disabled \
|
||||
-Ddirectwrite=enabled \
|
||||
-Dgdi=enabled \
|
||||
-Dgraphite=enabled \
|
||||
-Dchafa=disabled
|
||||
- name: Build
|
||||
run: meson compile -Cbuild
|
||||
- name: Test
|
||||
run: meson test --print-errorlogs --suite=harfbuzz -Cbuild
|
||||
- uses: actions/checkout@v3
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.MSYSTEM }}
|
||||
update: true
|
||||
install: >-
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-cairo
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-freetype
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc-libs
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gettext
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-glib2
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gobject-introspection
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-graphite2
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-icu
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-meson
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-ninja
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-pkg-config
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-python
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-python-pip
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-ragel
|
||||
- name: Install Python Dependencies
|
||||
run: |
|
||||
pip install --upgrade fonttools
|
||||
- name: Build
|
||||
run: |
|
||||
meson build \
|
||||
--wrap-mode=nodownload \
|
||||
--auto-features=enabled \
|
||||
-Ddirectwrite=enabled \
|
||||
-Dgdi=enabled \
|
||||
-Dgraphite=enabled \
|
||||
-Dchafa=disabled
|
||||
ninja -C build
|
||||
- name: Test
|
||||
run: |
|
||||
meson test \
|
||||
--print-errorlogs \
|
||||
--suite=harfbuzz \
|
||||
-C build
|
||||
|
|
|
@ -566,7 +566,7 @@ if (HB_HAVE_INTROSPECTION)
|
|||
# We need to account for the varying output directories
|
||||
# when we build using Visual Studio projects
|
||||
if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
|
||||
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
|
||||
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
|
||||
else ()
|
||||
set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
|
||||
endif ()
|
||||
|
@ -816,7 +816,7 @@ if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
|
|||
make_pkgconfig_pc_file("harfbuzz-gobject")
|
||||
if (HB_HAVE_INTROSPECTION)
|
||||
if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
|
||||
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
|
||||
set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
|
||||
else ()
|
||||
set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
|
||||
endif ()
|
||||
|
|
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
|
||||
files names COPYING in subdirectories where applicable.
|
||||
|
||||
Copyright © 2010-2022 Google, Inc.
|
||||
Copyright © 2015-2020 Ebrahim Byagowi
|
||||
Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 Google, Inc.
|
||||
Copyright © 2018,2019,2020 Ebrahim Byagowi
|
||||
Copyright © 2019,2020 Facebook, Inc.
|
||||
Copyright © 2012,2015 Mozilla Foundation
|
||||
Copyright © 2012 Mozilla Foundation
|
||||
Copyright © 2011 Codethink Limited
|
||||
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
||||
Copyright © 2009 Keith Stribley
|
||||
Copyright © 2011 Martin Hosken and SIL International
|
||||
Copyright © 2009 Martin Hosken and SIL International
|
||||
Copyright © 2007 Chris Wilson
|
||||
Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod
|
||||
Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc.
|
||||
Copyright © 1998-2005 David Turner and Werner Lemberg
|
||||
Copyright © 2016 Igalia S.L.
|
||||
Copyright © 2022 Matthias Clasen
|
||||
Copyright © 2018,2021 Khaled Hosny
|
||||
Copyright © 2018,2019,2020 Adobe, Inc
|
||||
Copyright © 2013-2015 Alexei Podtelezhnikov
|
||||
Copyright © 2005,2006,2020,2021 Behdad Esfahbod
|
||||
Copyright © 2005 David Turner
|
||||
Copyright © 2004,2007,2008,2009,2010 Red Hat, Inc.
|
||||
Copyright © 1998-2004 David Turner and Werner Lemberg
|
||||
|
||||
For full copyright notices consult the individual files in the package.
|
||||
|
||||
|
|
216
NEWS
216
NEWS
|
@ -1,219 +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
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
- [ ] 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.
|
||||
|
||||
|
|
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_INIT([HarfBuzz],
|
||||
[7.1.0],
|
||||
[5.3.0],
|
||||
[https://github.com/harfbuzz/harfbuzz/issues/new],
|
||||
[harfbuzz],
|
||||
[http://harfbuzz.org/])
|
||||
|
@ -45,7 +45,7 @@ AC_SUBST(HB_VERSION)
|
|||
|
||||
# Libtool version
|
||||
m4_define([hb_version_int],
|
||||
m4_eval(60000 + hb_version_major*100 + hb_version_minor*10 + hb_version_micro))
|
||||
m4_eval(hb_version_major*10000 + hb_version_minor*100 + hb_version_micro))
|
||||
HB_LIBTOOL_VERSION_INFO=hb_version_int:0:hb_version_int
|
||||
AC_SUBST(HB_LIBTOOL_VERSION_INFO)
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ SCANGOBJ_OPTIONS=
|
|||
# Extra options to supply to gtkdoc-scan.
|
||||
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
|
||||
SCAN_OPTIONS=--rebuild-types --deprecated-guards="HB_DISABLE_DEPRECATED" \
|
||||
--ignore-decorators='HB_EXTERN|HB_DEPRECATED|HB_DEPRECATED_FOR()'
|
||||
--ignore-decorators='HB_EXTERN|HB_DEPRECATED'
|
||||
|
||||
# Header files or dirs to ignore when scanning. Use base file/dir names
|
||||
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
|
||||
|
|
|
@ -56,9 +56,7 @@
|
|||
<xi:include href="xml/hb-blob.xml"/>
|
||||
<xi:include href="xml/hb-buffer.xml"/>
|
||||
<xi:include href="xml/hb-common.xml"/>
|
||||
<xi:include href="xml/hb-features.xml"/>
|
||||
<xi:include href="xml/hb-draw.xml"/>
|
||||
<xi:include href="xml/hb-paint.xml"/>
|
||||
<xi:include href="xml/hb-deprecated.xml"/>
|
||||
<xi:include href="xml/hb-face.xml"/>
|
||||
<xi:include href="xml/hb-font.xml"/>
|
||||
|
@ -98,7 +96,6 @@
|
|||
<xi:include href="xml/hb-uniscribe.xml"/>
|
||||
<xi:include href="xml/hb-gdi.xml"/>
|
||||
<xi:include href="xml/hb-directwrite.xml"/>
|
||||
<xi:include href="xml/hb-cairo.xml"/>
|
||||
</chapter>
|
||||
|
||||
<chapter id="style-api">
|
||||
|
@ -118,79 +115,76 @@
|
|||
</chapter-->
|
||||
|
||||
<index id="api-index-full"><title>API Index</title><xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="deprecated-api-index"><title>Index of deprecated API</title><xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="deprecated-api-index" role="deprecated"><title>Index of deprecated API</title><xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include></index>
|
||||
|
||||
<index id="api-index-7-1-0"><title>Index of new symbols in 7.1.0</title><xi:include href="xml/api-index-7.1.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-7-0-0"><title>Index of new symbols in 7.0.0</title><xi:include href="xml/api-index-7.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-6-0-0"><title>Index of new symbols in 6.0.0</title><xi:include href="xml/api-index-6.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-5-3-0"><title>Index of new symbols in 5.3.0</title><xi:include href="xml/api-index-5.3.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-5-0-0"><title>Index of new symbols in 5.0.0</title><xi:include href="xml/api-index-5.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-4-4-0"><title>Index of new symbols in 4.4.0</title><xi:include href="xml/api-index-4.4.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-4-3-0"><title>Index of new symbols in 4.3.0</title><xi:include href="xml/api-index-4.3.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-4-2-0"><title>Index of new symbols in 4.2.0</title><xi:include href="xml/api-index-4.2.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-4-1-0"><title>Index of new symbols in 4.1.0</title><xi:include href="xml/api-index-4.1.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-4-0-0"><title>Index of new symbols in 4.0.0</title><xi:include href="xml/api-index-4.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-3-4-0"><title>Index of new symbols in 3.4.0</title><xi:include href="xml/api-index-3.4.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-3-3-0"><title>Index of new symbols in 3.3.0</title><xi:include href="xml/api-index-3.3.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-3-1-0"><title>Index of new symbols in 3.1.0</title><xi:include href="xml/api-index-3.1.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-3-0-0"><title>Index of new symbols in 3.0.0</title><xi:include href="xml/api-index-3.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-9-1"><title>Index of new symbols in 2.9.1</title><xi:include href="xml/api-index-2.9.1.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-9-0"><title>Index of new symbols in 2.9.0</title><xi:include href="xml/api-index-2.9.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-8-2"><title>Index of new symbols in 2.8.2</title><xi:include href="xml/api-index-2.8.2.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-7-3"><title>Index of new symbols in 2.7.3</title><xi:include href="xml/api-index-2.7.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-6-8"><title>Index of new symbols in 2.6.8</title><xi:include href="xml/api-index-2.6.8.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-6-5"><title>Index of new symbols in 2.6.5</title><xi:include href="xml/api-index-2.6.5.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-6-3"><title>Index of new symbols in 2.6.3</title><xi:include href="xml/api-index-2.6.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-6-0"><title>Index of new symbols in 2.6.0</title><xi:include href="xml/api-index-2.6.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-5-0"><title>Index of new symbols in 2.5.0</title><xi:include href="xml/api-index-2.5.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-4-0"><title>Index of new symbols in 2.4.0</title><xi:include href="xml/api-index-2.4.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-3-0"><title>Index of new symbols in 2.3.0</title><xi:include href="xml/api-index-2.3.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-2-0"><title>Index of new symbols in 2.2.0</title><xi:include href="xml/api-index-2.2.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-1-0"><title>Index of new symbols in 2.1.0</title><xi:include href="xml/api-index-2.1.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-0-0"><title>Index of new symbols in 2.0.0</title><xi:include href="xml/api-index-2.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-9-0"><title>Index of new symbols in 1.9.0</title><xi:include href="xml/api-index-1.9.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-8-6"><title>Index of new symbols in 1.8.6</title><xi:include href="xml/api-index-1.8.6.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-8-5"><title>Index of new symbols in 1.8.5</title><xi:include href="xml/api-index-1.8.5.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-8-1"><title>Index of new symbols in 1.8.1</title><xi:include href="xml/api-index-1.8.1.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-8-0"><title>Index of new symbols in 1.8.0</title><xi:include href="xml/api-index-1.8.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-7-7"><title>Index of new symbols in 1.7.7</title><xi:include href="xml/api-index-1.7.7.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-7-2"><title>Index of new symbols in 1.7.2</title><xi:include href="xml/api-index-1.7.2.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-6-0"><title>Index of new symbols in 1.6.0</title><xi:include href="xml/api-index-1.6.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-5-0"><title>Index of new symbols in 1.5.0</title><xi:include href="xml/api-index-1.5.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-4-3"><title>Index of new symbols in 1.4.3</title><xi:include href="xml/api-index-1.4.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-4-2"><title>Index of new symbols in 1.4.2</title><xi:include href="xml/api-index-1.4.2.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-4-0"><title>Index of new symbols in 1.4.0</title><xi:include href="xml/api-index-1.4.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-3-3"><title>Index of new symbols in 1.3.3</title><xi:include href="xml/api-index-1.3.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-2-3"><title>Index of new symbols in 1.2.3</title><xi:include href="xml/api-index-1.2.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-1-3"><title>Index of new symbols in 1.1.3</title><xi:include href="xml/api-index-1.1.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-1-2"><title>Index of new symbols in 1.1.2</title><xi:include href="xml/api-index-1.1.2.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-0-5"><title>Index of new symbols in 1.0.5</title><xi:include href="xml/api-index-1.0.5.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-42"><title>Index of new symbols in 0.9.42</title><xi:include href="xml/api-index-0.9.42.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-41"><title>Index of new symbols in 0.9.41</title><xi:include href="xml/api-index-0.9.41.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-39"><title>Index of new symbols in 0.9.39</title><xi:include href="xml/api-index-0.9.39.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-38"><title>Index of new symbols in 0.9.38</title><xi:include href="xml/api-index-0.9.38.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-33"><title>Index of new symbols in 0.9.33</title><xi:include href="xml/api-index-0.9.33.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-31"><title>Index of new symbols in 0.9.31</title><xi:include href="xml/api-index-0.9.31.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-30"><title>Index of new symbols in 0.9.30</title><xi:include href="xml/api-index-0.9.30.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-28"><title>Index of new symbols in 0.9.28</title><xi:include href="xml/api-index-0.9.28.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-26"><title>Index of new symbols in 0.9.26</title><xi:include href="xml/api-index-0.9.26.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-22"><title>Index of new symbols in 0.9.22</title><xi:include href="xml/api-index-0.9.22.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-21"><title>Index of new symbols in 0.9.21</title><xi:include href="xml/api-index-0.9.21.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-20"><title>Index of new symbols in 0.9.20</title><xi:include href="xml/api-index-0.9.20.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-11"><title>Index of new symbols in 0.9.11</title><xi:include href="xml/api-index-0.9.11.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-10"><title>Index of new symbols in 0.9.10</title><xi:include href="xml/api-index-0.9.10.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-8"><title>Index of new symbols in 0.9.8</title><xi:include href="xml/api-index-0.9.8.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-7"><title>Index of new symbols in 0.9.7</title><xi:include href="xml/api-index-0.9.7.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-5"><title>Index of new symbols in 0.9.5</title><xi:include href="xml/api-index-0.9.5.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-2"><title>Index of new symbols in 0.9.2</title><xi:include href="xml/api-index-0.9.2.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-6-0"><title>Index of new symbols in 0.6.0</title><xi:include href="xml/api-index-0.6.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-5-3-0" role="5.3.0"><title>Index of new symbols in 5.3.0</title><xi:include href="xml/api-index-5.3.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-5-0-0" 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-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-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-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-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-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-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-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-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-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-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-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-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-2-7-3" role="2.7.3"><title>Index of new symbols in 2.7.3</title><xi:include href="xml/api-index-2.7.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-6-8" role="2.6.8"><title>Index of new symbols in 2.6.8</title><xi:include href="xml/api-index-2.6.8.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-6-5" role="2.6.5"><title>Index of new symbols in 2.6.5</title><xi:include href="xml/api-index-2.6.5.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-6-3" role="2.6.3"><title>Index of new symbols in 2.6.3</title><xi:include href="xml/api-index-2.6.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-6-0" role="2.6.0"><title>Index of new symbols in 2.6.0</title><xi:include href="xml/api-index-2.6.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-5-0" role="2.5.0"><title>Index of new symbols in 2.5.0</title><xi:include href="xml/api-index-2.5.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-4-0" role="2.4.0"><title>Index of new symbols in 2.4.0</title><xi:include href="xml/api-index-2.4.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-3-0" role="2.3.0"><title>Index of new symbols in 2.3.0</title><xi:include href="xml/api-index-2.3.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-2-0" role="2.2.0"><title>Index of new symbols in 2.2.0</title><xi:include href="xml/api-index-2.2.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-1-0" role="2.1.0"><title>Index of new symbols in 2.1.0</title><xi:include href="xml/api-index-2.1.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-2-0-0" role="2.0.0"><title>Index of new symbols in 2.0.0</title><xi:include href="xml/api-index-2.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-9-0" role="1.9.0"><title>Index of new symbols in 1.9.0</title><xi:include href="xml/api-index-1.9.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-8-6" role="1.8.6"><title>Index of new symbols in 1.8.6</title><xi:include href="xml/api-index-1.8.6.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-8-5" role="1.8.5"><title>Index of new symbols in 1.8.5</title><xi:include href="xml/api-index-1.8.5.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-8-1" role="1.8.1"><title>Index of new symbols in 1.8.1</title><xi:include href="xml/api-index-1.8.1.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-8-0" role="1.8.0"><title>Index of new symbols in 1.8.0</title><xi:include href="xml/api-index-1.8.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-7-7" role="1.7.7"><title>Index of new symbols in 1.7.7</title><xi:include href="xml/api-index-1.7.7.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-7-2" role="1.7.2"><title>Index of new symbols in 1.7.2</title><xi:include href="xml/api-index-1.7.2.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-6-0" role="1.6.0"><title>Index of new symbols in 1.6.0</title><xi:include href="xml/api-index-1.6.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-5-0" role="1.5.0"><title>Index of new symbols in 1.5.0</title><xi:include href="xml/api-index-1.5.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-4-3" role="1.4.3"><title>Index of new symbols in 1.4.3</title><xi:include href="xml/api-index-1.4.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-4-2" role="1.4.2"><title>Index of new symbols in 1.4.2</title><xi:include href="xml/api-index-1.4.2.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-4-0" role="1.4.0"><title>Index of new symbols in 1.4.0</title><xi:include href="xml/api-index-1.4.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-3-3" role="1.3.3"><title>Index of new symbols in 1.3.3</title><xi:include href="xml/api-index-1.3.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-2-3" role="1.2.3"><title>Index of new symbols in 1.2.3</title><xi:include href="xml/api-index-1.2.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-1-3" role="1.1.3"><title>Index of new symbols in 1.1.3</title><xi:include href="xml/api-index-1.1.3.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-1-2" role="1.1.2"><title>Index of new symbols in 1.1.2</title><xi:include href="xml/api-index-1.1.2.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-1-0-5" role="1.0.5"><title>Index of new symbols in 1.0.5</title><xi:include href="xml/api-index-1.0.5.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-42" role="0.9.42"><title>Index of new symbols in 0.9.42</title><xi:include href="xml/api-index-0.9.42.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-41" role="0.9.41"><title>Index of new symbols in 0.9.41</title><xi:include href="xml/api-index-0.9.41.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-39" role="0.9.39"><title>Index of new symbols in 0.9.39</title><xi:include href="xml/api-index-0.9.39.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-38" role="0.9.38"><title>Index of new symbols in 0.9.38</title><xi:include href="xml/api-index-0.9.38.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-33" role="0.9.33"><title>Index of new symbols in 0.9.33</title><xi:include href="xml/api-index-0.9.33.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-31" role="0.9.31"><title>Index of new symbols in 0.9.31</title><xi:include href="xml/api-index-0.9.31.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-30" role="0.9.30"><title>Index of new symbols in 0.9.30</title><xi:include href="xml/api-index-0.9.30.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-28" role="0.9.28"><title>Index of new symbols in 0.9.28</title><xi:include href="xml/api-index-0.9.28.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-26" role="0.9.26"><title>Index of new symbols in 0.9.26</title><xi:include href="xml/api-index-0.9.26.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-22" role="0.9.22"><title>Index of new symbols in 0.9.22</title><xi:include href="xml/api-index-0.9.22.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-21" role="0.9.21"><title>Index of new symbols in 0.9.21</title><xi:include href="xml/api-index-0.9.21.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-20" role="0.9.20"><title>Index of new symbols in 0.9.20</title><xi:include href="xml/api-index-0.9.20.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-11" role="0.9.11"><title>Index of new symbols in 0.9.11</title><xi:include href="xml/api-index-0.9.11.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-10" role="0.9.10"><title>Index of new symbols in 0.9.10</title><xi:include href="xml/api-index-0.9.10.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-8" role="0.9.8"><title>Index of new symbols in 0.9.8</title><xi:include href="xml/api-index-0.9.8.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-7" role="0.9.7"><title>Index of new symbols in 0.9.7</title><xi:include href="xml/api-index-0.9.7.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-5" role="0.9.5"><title>Index of new symbols in 0.9.5</title><xi:include href="xml/api-index-0.9.5.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-9-2" role="0.9.2"><title>Index of new symbols in 0.9.2</title><xi:include href="xml/api-index-0.9.2.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-0-6-0" role="0.6.0"><title>Index of new symbols in 0.6.0</title><xi:include href="xml/api-index-0.6.0.xml"><xi:fallback /></xi:include></index>
|
||||
|
||||
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
|
||||
</part>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
The current HarfBuzz codebase is stable
|
||||
The current HarfBuzz codebase is versioned 2.x.x and is stable
|
||||
and under active maintenance. This is what is used in latest
|
||||
versions of Firefox, GNOME, ChromeOS, Chrome, LibreOffice,
|
||||
XeTeX, Android, and KDE, among other places.
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
<SECTION>
|
||||
<SUBSECTION Private>
|
||||
HB_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_sub_blob
|
||||
hb_blob_copy_writable_or_fail
|
||||
hb_blob_get_empty
|
||||
hb_blob_reference
|
||||
hb_blob_destroy
|
||||
hb_blob_set_user_data
|
||||
hb_blob_get_user_data
|
||||
hb_blob_make_immutable
|
||||
hb_blob_is_immutable
|
||||
hb_blob_get_data
|
||||
hb_blob_get_data_writable
|
||||
hb_blob_get_empty
|
||||
hb_blob_get_length
|
||||
hb_blob_get_user_data
|
||||
hb_blob_is_immutable
|
||||
hb_blob_make_immutable
|
||||
hb_blob_reference
|
||||
hb_blob_set_user_data
|
||||
hb_blob_t
|
||||
hb_memory_mode_t
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-buffer</FILE>
|
||||
HB_SEGMENT_PROPERTIES_DEFAULT
|
||||
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT
|
||||
hb_buffer_create
|
||||
hb_buffer_allocation_successful
|
||||
hb_buffer_create_similar
|
||||
hb_buffer_get_empty
|
||||
hb_buffer_reference
|
||||
hb_buffer_get_empty
|
||||
hb_buffer_destroy
|
||||
hb_buffer_set_user_data
|
||||
hb_buffer_get_user_data
|
||||
hb_buffer_reset
|
||||
hb_buffer_clear_contents
|
||||
hb_buffer_pre_allocate
|
||||
hb_buffer_allocation_successful
|
||||
hb_buffer_add
|
||||
hb_buffer_add_codepoints
|
||||
hb_buffer_add_utf32
|
||||
|
@ -80,14 +79,15 @@ hb_buffer_get_segment_properties
|
|||
hb_buffer_guess_segment_properties
|
||||
hb_buffer_set_unicode_funcs
|
||||
hb_buffer_get_unicode_funcs
|
||||
hb_buffer_set_user_data
|
||||
hb_buffer_get_user_data
|
||||
hb_buffer_get_glyph_infos
|
||||
hb_glyph_info_get_glyph_flags
|
||||
hb_buffer_get_glyph_positions
|
||||
hb_buffer_has_positions
|
||||
hb_buffer_set_invisible_glyph
|
||||
hb_buffer_get_invisible_glyph
|
||||
hb_buffer_set_not_found_glyph
|
||||
hb_buffer_set_invisible_glyph
|
||||
hb_buffer_get_not_found_glyph
|
||||
hb_buffer_set_not_found_glyph
|
||||
hb_buffer_set_replacement_codepoint
|
||||
hb_buffer_get_replacement_codepoint
|
||||
hb_buffer_normalize_glyphs
|
||||
|
@ -106,11 +106,9 @@ hb_segment_properties_equal
|
|||
hb_segment_properties_hash
|
||||
hb_segment_properties_overlay
|
||||
hb_buffer_diff
|
||||
hb_buffer_message_func_t
|
||||
hb_buffer_set_message_func
|
||||
HB_SEGMENT_PROPERTIES_DEFAULT
|
||||
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT
|
||||
hb_buffer_t
|
||||
hb_glyph_info_get_glyph_flags
|
||||
hb_glyph_info_t
|
||||
hb_glyph_flags_t
|
||||
hb_glyph_position_t
|
||||
|
@ -121,25 +119,18 @@ hb_segment_properties_t
|
|||
hb_buffer_serialize_format_t
|
||||
hb_buffer_serialize_flags_t
|
||||
hb_buffer_diff_flags_t
|
||||
hb_buffer_message_func_t
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-common</FILE>
|
||||
HB_TAG
|
||||
HB_UNTAG
|
||||
hb_tag_from_string
|
||||
hb_tag_to_string
|
||||
hb_direction_from_string
|
||||
hb_direction_to_string
|
||||
HB_DIRECTION_REVERSE
|
||||
HB_DIRECTION_IS_BACKWARD
|
||||
HB_DIRECTION_IS_FORWARD
|
||||
HB_DIRECTION_IS_HORIZONTAL
|
||||
HB_DIRECTION_IS_VALID
|
||||
HB_DIRECTION_IS_VERTICAL
|
||||
hb_script_from_iso15924_tag
|
||||
hb_script_to_iso15924_tag
|
||||
hb_script_from_string
|
||||
hb_script_to_iso15924_tag
|
||||
hb_script_get_horizontal_direction
|
||||
hb_language_from_string
|
||||
hb_language_to_string
|
||||
|
@ -161,9 +152,17 @@ hb_position_t
|
|||
hb_tag_t
|
||||
hb_script_t
|
||||
hb_user_data_key_t
|
||||
HB_TAG
|
||||
HB_TAG_NONE
|
||||
HB_TAG_MAX
|
||||
HB_TAG_MAX_SIGNED
|
||||
HB_UNTAG
|
||||
HB_DIRECTION_REVERSE
|
||||
HB_DIRECTION_IS_BACKWARD
|
||||
HB_DIRECTION_IS_FORWARD
|
||||
HB_DIRECTION_IS_HORIZONTAL
|
||||
HB_DIRECTION_IS_VALID
|
||||
HB_DIRECTION_IS_VERTICAL
|
||||
HB_LANGUAGE_INVALID
|
||||
HB_FEATURE_GLOBAL_END
|
||||
HB_FEATURE_GLOBAL_START
|
||||
|
@ -180,35 +179,20 @@ uint16_t
|
|||
uint32_t
|
||||
uint64_t
|
||||
uint8_t
|
||||
<SUBSECTION Private>
|
||||
HB_EXTERN
|
||||
HB_DEPRECATED
|
||||
HB_DEPRECATED_FOR
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-features</FILE>
|
||||
HB_HAS_CAIRO
|
||||
HB_HAS_CORETEXT
|
||||
HB_HAS_DIRECTWRITE
|
||||
HB_HAS_FREETYPE
|
||||
HB_HAS_GDI
|
||||
HB_HAS_GLIB
|
||||
HB_HAS_GOBJECT
|
||||
HB_HAS_GRAPHITE
|
||||
HB_HAS_ICU
|
||||
HB_HAS_UNISCRIBE
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-draw</FILE>
|
||||
hb_draw_funcs_t
|
||||
hb_draw_funcs_create
|
||||
hb_draw_funcs_get_empty
|
||||
hb_draw_funcs_reference
|
||||
hb_draw_funcs_destroy
|
||||
hb_draw_funcs_set_user_data
|
||||
hb_draw_funcs_get_user_data
|
||||
hb_draw_funcs_make_immutable
|
||||
hb_draw_funcs_reference
|
||||
hb_draw_funcs_is_immutable
|
||||
hb_draw_funcs_make_immutable
|
||||
hb_draw_move_to_func_t
|
||||
hb_draw_funcs_set_move_to_func
|
||||
hb_draw_line_to_func_t
|
||||
|
@ -219,79 +203,13 @@ hb_draw_cubic_to_func_t
|
|||
hb_draw_funcs_set_cubic_to_func
|
||||
hb_draw_close_path_func_t
|
||||
hb_draw_funcs_set_close_path_func
|
||||
hb_draw_state_t
|
||||
HB_DRAW_STATE_DEFAULT
|
||||
hb_draw_move_to
|
||||
hb_draw_line_to
|
||||
hb_draw_quadratic_to
|
||||
hb_draw_cubic_to
|
||||
hb_draw_close_path
|
||||
HB_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>
|
||||
|
@ -346,24 +264,23 @@ hb_face_count
|
|||
hb_face_t
|
||||
hb_face_create
|
||||
hb_face_create_for_tables
|
||||
hb_face_get_empty
|
||||
hb_face_reference
|
||||
hb_face_destroy
|
||||
hb_face_set_user_data
|
||||
hb_face_get_user_data
|
||||
hb_face_make_immutable
|
||||
hb_face_is_immutable
|
||||
hb_face_get_empty
|
||||
hb_face_get_table_tags
|
||||
hb_face_set_glyph_count
|
||||
hb_face_get_glyph_count
|
||||
hb_face_set_index
|
||||
hb_face_get_index
|
||||
hb_face_set_upem
|
||||
hb_face_get_upem
|
||||
hb_face_get_user_data
|
||||
hb_face_is_immutable
|
||||
hb_face_make_immutable
|
||||
hb_face_reference
|
||||
hb_face_reference_blob
|
||||
hb_face_reference_table
|
||||
hb_face_set_glyph_count
|
||||
hb_face_set_index
|
||||
hb_face_set_upem
|
||||
hb_face_set_user_data
|
||||
hb_face_collect_unicodes
|
||||
hb_face_collect_nominal_glyph_mapping
|
||||
hb_face_collect_variation_selectors
|
||||
hb_face_collect_variation_unicodes
|
||||
hb_face_builder_create
|
||||
|
@ -376,124 +293,113 @@ hb_face_builder_sort_tables
|
|||
hb_font_add_glyph_origin_for_direction
|
||||
hb_font_create
|
||||
hb_font_create_sub_font
|
||||
hb_font_get_empty
|
||||
hb_font_reference
|
||||
hb_font_destroy
|
||||
hb_font_set_user_data
|
||||
hb_font_get_user_data
|
||||
hb_font_make_immutable
|
||||
hb_font_is_immutable
|
||||
hb_font_set_face
|
||||
hb_font_funcs_create
|
||||
hb_font_funcs_destroy
|
||||
hb_font_funcs_get_empty
|
||||
hb_font_funcs_get_user_data
|
||||
hb_font_funcs_is_immutable
|
||||
hb_font_funcs_make_immutable
|
||||
hb_font_funcs_reference
|
||||
hb_font_funcs_set_glyph_contour_point_func
|
||||
hb_font_funcs_set_glyph_extents_func
|
||||
hb_font_funcs_set_glyph_from_name_func
|
||||
hb_font_funcs_set_glyph_h_advance_func
|
||||
hb_font_funcs_set_glyph_h_advances_func
|
||||
hb_font_funcs_set_glyph_h_kerning_func
|
||||
hb_font_funcs_set_glyph_h_origin_func
|
||||
hb_font_funcs_set_glyph_name_func
|
||||
hb_font_funcs_set_glyph_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_glyph
|
||||
hb_font_get_glyph_advance_for_direction
|
||||
hb_font_get_glyph_advance_func_t
|
||||
hb_font_get_glyph_advances_for_direction
|
||||
hb_font_get_glyph_advances_func_t
|
||||
hb_font_get_glyph_contour_point
|
||||
hb_font_get_glyph_contour_point_for_origin
|
||||
hb_font_get_glyph_contour_point_func_t
|
||||
hb_font_get_glyph_extents
|
||||
hb_font_get_glyph_extents_for_origin
|
||||
hb_font_get_glyph_extents_func_t
|
||||
hb_font_get_glyph_from_name
|
||||
hb_font_get_glyph_from_name_func_t
|
||||
hb_font_get_glyph_h_advance
|
||||
hb_font_get_glyph_v_advance
|
||||
hb_font_get_glyph_h_advance_func_t
|
||||
hb_font_get_glyph_h_advances
|
||||
hb_font_get_glyph_v_advances
|
||||
hb_font_get_glyph_h_advances_func_t
|
||||
hb_font_get_glyph_h_kerning
|
||||
hb_font_get_glyph_kerning_for_direction
|
||||
hb_font_get_glyph_h_kerning_func_t
|
||||
hb_font_get_glyph_h_origin
|
||||
hb_font_get_glyph_v_origin
|
||||
hb_font_get_glyph_origin_for_direction
|
||||
hb_font_get_glyph_h_origin_func_t
|
||||
hb_font_get_glyph_kerning_for_direction
|
||||
hb_font_get_glyph_kerning_func_t
|
||||
hb_font_get_glyph_name
|
||||
hb_font_get_glyph_name_func_t
|
||||
hb_font_get_glyph_origin_for_direction
|
||||
hb_font_get_glyph_origin_func_t
|
||||
hb_font_get_glyph_shape
|
||||
hb_font_draw_glyph
|
||||
hb_font_paint_glyph
|
||||
hb_font_get_glyph_shape_func_t
|
||||
hb_font_get_glyph_v_advance
|
||||
hb_font_get_glyph_v_advance_func_t
|
||||
hb_font_get_glyph_v_advances
|
||||
hb_font_get_glyph_v_advances_func_t
|
||||
hb_font_get_glyph_v_origin
|
||||
hb_font_get_glyph_v_origin_func_t
|
||||
hb_font_get_nominal_glyph
|
||||
hb_font_get_nominal_glyph_func_t
|
||||
hb_font_get_nominal_glyphs
|
||||
hb_font_get_variation_glyph
|
||||
hb_font_set_parent
|
||||
hb_font_get_nominal_glyphs_func_t
|
||||
hb_font_get_parent
|
||||
hb_font_set_ppem
|
||||
hb_font_get_ppem
|
||||
hb_font_set_ptem
|
||||
hb_font_get_ptem
|
||||
hb_font_set_scale
|
||||
hb_font_get_scale
|
||||
hb_font_get_synthetic_bold
|
||||
hb_font_set_synthetic_bold
|
||||
hb_font_set_synthetic_slant
|
||||
hb_font_get_synthetic_slant
|
||||
hb_font_set_variations
|
||||
hb_font_set_variation
|
||||
HB_FONT_NO_VAR_NAMED_INSTANCE
|
||||
hb_font_set_var_named_instance
|
||||
hb_font_get_var_named_instance
|
||||
hb_font_set_var_coords_design
|
||||
hb_font_get_user_data
|
||||
hb_font_get_variation_glyph
|
||||
hb_font_get_variation_glyph_func_t
|
||||
hb_font_get_var_coords_design
|
||||
hb_font_set_var_coords_normalized
|
||||
hb_font_get_var_coords_normalized
|
||||
hb_font_glyph_from_string
|
||||
hb_font_glyph_to_string
|
||||
hb_font_is_immutable
|
||||
hb_font_make_immutable
|
||||
hb_font_get_serial
|
||||
hb_font_changed
|
||||
hb_font_reference
|
||||
hb_font_set_face
|
||||
hb_font_set_funcs
|
||||
hb_font_set_funcs_data
|
||||
hb_font_set_parent
|
||||
hb_font_set_ppem
|
||||
hb_font_set_ptem
|
||||
hb_font_set_scale
|
||||
hb_font_set_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_funcs_create
|
||||
hb_font_funcs_get_empty
|
||||
hb_font_funcs_reference
|
||||
hb_font_funcs_destroy
|
||||
hb_font_funcs_set_user_data
|
||||
hb_font_funcs_get_user_data
|
||||
hb_font_funcs_make_immutable
|
||||
hb_font_funcs_is_immutable
|
||||
hb_font_get_glyph_contour_point_func_t
|
||||
hb_font_funcs_set_glyph_contour_point_func
|
||||
hb_font_get_glyph_extents_func_t
|
||||
hb_font_funcs_set_glyph_extents_func
|
||||
hb_font_get_glyph_from_name_func_t
|
||||
hb_font_funcs_set_glyph_from_name_func
|
||||
hb_font_get_glyph_advance_func_t
|
||||
hb_font_get_glyph_h_advance_func_t
|
||||
hb_font_funcs_set_glyph_h_advance_func
|
||||
hb_font_get_glyph_v_advance_func_t
|
||||
hb_font_funcs_set_glyph_v_advance_func
|
||||
hb_font_get_glyph_advances_func_t
|
||||
hb_font_get_glyph_h_advances_func_t
|
||||
hb_font_funcs_set_glyph_h_advances_func
|
||||
hb_font_get_glyph_v_advances_func_t
|
||||
hb_font_funcs_set_glyph_v_advances_func
|
||||
hb_font_get_glyph_kerning_func_t
|
||||
hb_font_get_glyph_h_kerning_func_t
|
||||
hb_font_funcs_set_glyph_h_kerning_func
|
||||
hb_font_get_glyph_origin_func_t
|
||||
hb_font_get_glyph_h_origin_func_t
|
||||
hb_font_funcs_set_glyph_h_origin_func
|
||||
hb_font_get_glyph_v_origin_func_t
|
||||
hb_font_funcs_set_glyph_v_origin_func
|
||||
hb_font_get_glyph_name_func_t
|
||||
hb_font_funcs_set_glyph_name_func
|
||||
hb_font_get_glyph_shape_func_t
|
||||
hb_font_funcs_set_glyph_shape_func
|
||||
hb_font_draw_glyph_func_t
|
||||
hb_font_funcs_set_draw_glyph_func
|
||||
hb_font_paint_glyph_func_t
|
||||
hb_font_funcs_set_paint_glyph_func
|
||||
hb_font_get_nominal_glyph_func_t
|
||||
hb_font_funcs_set_nominal_glyph_func
|
||||
hb_font_get_nominal_glyphs_func_t
|
||||
hb_font_funcs_set_nominal_glyphs_func
|
||||
hb_font_get_variation_glyph_func_t
|
||||
hb_font_funcs_set_variation_glyph_func
|
||||
hb_font_funcs_t
|
||||
hb_font_t
|
||||
hb_reference_table_func_t
|
||||
hb_font_funcs_set_font_h_extents_func
|
||||
hb_font_funcs_set_font_v_extents_func
|
||||
hb_font_get_extents_for_direction
|
||||
hb_font_get_font_extents_func_t
|
||||
hb_font_get_font_h_extents_func_t
|
||||
hb_font_funcs_set_font_h_extents_func
|
||||
hb_font_get_font_v_extents_func_t
|
||||
hb_font_funcs_set_font_v_extents_func
|
||||
hb_font_get_h_extents
|
||||
hb_font_get_v_extents
|
||||
hb_font_get_extents_for_direction
|
||||
hb_font_extents_t
|
||||
hb_glyph_extents_t
|
||||
</SECTION>
|
||||
|
@ -544,33 +450,30 @@ hb_icu_script_to_script
|
|||
|
||||
<SECTION>
|
||||
<FILE>hb-map</FILE>
|
||||
hb_map_create
|
||||
hb_map_allocation_successful
|
||||
hb_map_copy
|
||||
hb_map_clear
|
||||
hb_map_get_empty
|
||||
hb_map_reference
|
||||
hb_map_destroy
|
||||
hb_map_set_user_data
|
||||
hb_map_get_user_data
|
||||
hb_map_set
|
||||
hb_map_get
|
||||
hb_map_del
|
||||
hb_map_has
|
||||
hb_map_get_population
|
||||
hb_map_is_empty
|
||||
hb_map_is_equal
|
||||
hb_map_hash
|
||||
hb_map_update
|
||||
hb_map_next
|
||||
hb_map_keys
|
||||
hb_map_values
|
||||
HB_MAP_VALUE_INVALID
|
||||
hb_map_allocation_successful
|
||||
hb_map_clear
|
||||
hb_map_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
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-ot-color</FILE>
|
||||
hb_color_t
|
||||
HB_COLOR
|
||||
hb_color_get_alpha
|
||||
hb_color_get_blue
|
||||
|
@ -580,19 +483,16 @@ hb_ot_color_glyph_get_layers
|
|||
hb_ot_color_glyph_reference_png
|
||||
hb_ot_color_glyph_reference_svg
|
||||
hb_ot_color_has_layers
|
||||
hb_ot_color_has_paint
|
||||
hb_ot_color_glyph_has_paint
|
||||
hb_ot_color_has_palettes
|
||||
hb_ot_color_has_png
|
||||
hb_ot_color_has_svg
|
||||
hb_ot_color_layer_t
|
||||
hb_ot_color_palette_color_get_name_id
|
||||
hb_ot_color_palette_flags_t
|
||||
hb_ot_color_palette_get_colors
|
||||
hb_ot_color_palette_get_count
|
||||
hb_ot_color_palette_get_flags
|
||||
hb_ot_color_palette_get_name_id
|
||||
hb_color_t
|
||||
hb_ot_color_layer_t
|
||||
hb_ot_color_palette_flags_t
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -602,21 +502,35 @@ hb_ot_font_set_funcs
|
|||
|
||||
<SECTION>
|
||||
<FILE>hb-ot-name</FILE>
|
||||
hb_ot_name_id_t
|
||||
HB_OT_NAME_ID_INVALID
|
||||
hb_ot_name_entry_t
|
||||
hb_ot_name_list_names
|
||||
hb_ot_name_get_utf16
|
||||
hb_ot_name_get_utf32
|
||||
hb_ot_name_get_utf8
|
||||
hb_ot_name_id_t
|
||||
hb_ot_name_id_predefined_t
|
||||
hb_ot_name_entry_t
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-ot-layout</FILE>
|
||||
HB_OT_MAX_TAGS_PER_LANGUAGE
|
||||
HB_OT_MAX_TAGS_PER_SCRIPT
|
||||
HB_OT_TAG_DEFAULT_LANGUAGE
|
||||
HB_OT_TAG_DEFAULT_SCRIPT
|
||||
hb_ot_tag_to_language
|
||||
hb_ot_tag_to_script
|
||||
hb_ot_tags_from_script_and_language
|
||||
hb_ot_tags_to_script_and_language
|
||||
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX
|
||||
HB_OT_LAYOUT_NO_FEATURE_INDEX
|
||||
HB_OT_LAYOUT_NO_SCRIPT_INDEX
|
||||
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_features
|
||||
hb_ot_layout_feature_get_characters
|
||||
|
@ -631,6 +545,7 @@ hb_ot_layout_get_glyph_class
|
|||
hb_ot_layout_get_glyphs_in_class
|
||||
hb_ot_layout_get_ligature_carets
|
||||
hb_ot_layout_get_size_params
|
||||
hb_ot_layout_glyph_class_t
|
||||
hb_ot_layout_has_glyph_classes
|
||||
hb_ot_layout_has_positioning
|
||||
hb_ot_layout_has_substitution
|
||||
|
@ -647,7 +562,6 @@ hb_ot_layout_lookup_would_substitute
|
|||
hb_ot_layout_script_find_language
|
||||
hb_ot_layout_script_get_language_tags
|
||||
hb_ot_layout_script_select_language
|
||||
hb_ot_layout_script_select_language2
|
||||
hb_ot_layout_table_find_feature_variations
|
||||
hb_ot_layout_table_get_feature_tags
|
||||
hb_ot_layout_table_get_script_tags
|
||||
|
@ -655,25 +569,18 @@ hb_ot_layout_table_get_lookup_count
|
|||
hb_ot_layout_table_select_script
|
||||
hb_ot_shape_plan_collect_lookups
|
||||
hb_ot_layout_language_get_required_feature_index
|
||||
HB_OT_MAX_TAGS_PER_LANGUAGE
|
||||
HB_OT_MAX_TAGS_PER_SCRIPT
|
||||
HB_OT_TAG_DEFAULT_LANGUAGE
|
||||
HB_OT_TAG_DEFAULT_SCRIPT
|
||||
HB_OT_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>
|
||||
<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_get_constant
|
||||
hb_ot_math_get_glyph_italics_correction
|
||||
|
@ -684,31 +591,23 @@ hb_ot_math_is_glyph_extended_shape
|
|||
hb_ot_math_get_glyph_variants
|
||||
hb_ot_math_get_min_connector_overlap
|
||||
hb_ot_math_get_glyph_assembly
|
||||
HB_OT_TAG_MATH
|
||||
HB_OT_TAG_MATH_SCRIPT
|
||||
hb_ot_math_constant_t
|
||||
hb_ot_math_kern_t
|
||||
hb_ot_math_kern_entry_t
|
||||
hb_ot_math_glyph_variant_t
|
||||
hb_ot_math_glyph_part_flags_t
|
||||
hb_ot_math_glyph_part_t
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-ot-meta</FILE>
|
||||
hb_ot_meta_tag_t
|
||||
hb_ot_meta_get_entry_tags
|
||||
hb_ot_meta_reference_entry
|
||||
hb_ot_meta_tag_t
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-ot-metrics</FILE>
|
||||
hb_ot_metrics_tag_t
|
||||
hb_ot_metrics_get_position
|
||||
hb_ot_metrics_get_position_with_fallback
|
||||
hb_ot_metrics_get_variation
|
||||
hb_ot_metrics_get_x_variation
|
||||
hb_ot_metrics_get_y_variation
|
||||
hb_ot_metrics_tag_t
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -718,7 +617,14 @@ hb_ot_shape_glyphs_closure
|
|||
|
||||
<SECTION>
|
||||
<FILE>hb-ot-var</FILE>
|
||||
HB_OT_TAG_VAR_AXIS_ITALIC
|
||||
HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
|
||||
HB_OT_TAG_VAR_AXIS_SLANT
|
||||
HB_OT_TAG_VAR_AXIS_WEIGHT
|
||||
HB_OT_TAG_VAR_AXIS_WIDTH
|
||||
hb_ot_var_has_data
|
||||
hb_ot_var_axis_flags_t
|
||||
hb_ot_var_axis_info_t
|
||||
hb_ot_var_find_axis_info
|
||||
hb_ot_var_get_axis_count
|
||||
hb_ot_var_get_axis_infos
|
||||
|
@ -728,44 +634,31 @@ hb_ot_var_named_instance_get_postscript_name_id
|
|||
hb_ot_var_named_instance_get_design_coords
|
||||
hb_ot_var_normalize_variations
|
||||
hb_ot_var_normalize_coords
|
||||
HB_OT_TAG_VAR_AXIS_ITALIC
|
||||
HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
|
||||
HB_OT_TAG_VAR_AXIS_SLANT
|
||||
HB_OT_TAG_VAR_AXIS_WEIGHT
|
||||
HB_OT_TAG_VAR_AXIS_WIDTH
|
||||
hb_ot_var_axis_flags_t
|
||||
hb_ot_var_axis_info_t
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-set</FILE>
|
||||
hb_set_create
|
||||
hb_set_allocation_successful
|
||||
hb_set_copy
|
||||
hb_set_get_empty
|
||||
hb_set_reference
|
||||
hb_set_destroy
|
||||
hb_set_set_user_data
|
||||
hb_set_get_user_data
|
||||
hb_set_clear
|
||||
hb_set_set
|
||||
hb_set_has
|
||||
HB_SET_VALUE_INVALID
|
||||
hb_set_add
|
||||
hb_set_add_range
|
||||
hb_set_add_sorted_array
|
||||
hb_set_allocation_successful
|
||||
hb_set_copy
|
||||
hb_set_clear
|
||||
hb_set_create
|
||||
hb_set_del
|
||||
hb_set_del_range
|
||||
hb_set_destroy
|
||||
hb_set_get_empty
|
||||
hb_set_get_max
|
||||
hb_set_get_min
|
||||
hb_set_get_population
|
||||
hb_set_is_empty
|
||||
hb_set_get_user_data
|
||||
hb_set_has
|
||||
hb_set_hash
|
||||
hb_set_subtract
|
||||
hb_set_intersect
|
||||
hb_set_union
|
||||
hb_set_symmetric_difference
|
||||
hb_set_invert
|
||||
hb_set_is_inverted
|
||||
hb_set_is_empty
|
||||
hb_set_is_equal
|
||||
hb_set_is_subset
|
||||
hb_set_next
|
||||
|
@ -773,15 +666,19 @@ hb_set_next_range
|
|||
hb_set_next_many
|
||||
hb_set_previous
|
||||
hb_set_previous_range
|
||||
HB_SET_VALUE_INVALID
|
||||
hb_set_reference
|
||||
hb_set_set
|
||||
hb_set_set_user_data
|
||||
hb_set_subtract
|
||||
hb_set_symmetric_difference
|
||||
hb_set_t
|
||||
hb_set_union
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-shape</FILE>
|
||||
hb_shape
|
||||
hb_shape_full
|
||||
hb_shape_justify
|
||||
hb_shape_list_shapers
|
||||
</SECTION>
|
||||
|
||||
|
@ -791,50 +688,50 @@ hb_shape_plan_create
|
|||
hb_shape_plan_create_cached
|
||||
hb_shape_plan_create2
|
||||
hb_shape_plan_create_cached2
|
||||
hb_shape_plan_get_empty
|
||||
hb_shape_plan_reference
|
||||
hb_shape_plan_destroy
|
||||
hb_shape_plan_set_user_data
|
||||
hb_shape_plan_get_user_data
|
||||
hb_shape_plan_execute
|
||||
hb_shape_plan_get_empty
|
||||
hb_shape_plan_get_shaper
|
||||
hb_shape_plan_get_user_data
|
||||
hb_shape_plan_reference
|
||||
hb_shape_plan_set_user_data
|
||||
hb_shape_plan_t
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-unicode</FILE>
|
||||
hb_unicode_general_category
|
||||
hb_unicode_combining_class
|
||||
hb_unicode_mirroring
|
||||
hb_unicode_script
|
||||
hb_unicode_compose
|
||||
hb_unicode_decompose
|
||||
hb_unicode_funcs_create
|
||||
hb_unicode_funcs_get_empty
|
||||
hb_unicode_funcs_reference
|
||||
hb_unicode_funcs_destroy
|
||||
hb_unicode_funcs_set_user_data
|
||||
hb_unicode_funcs_get_user_data
|
||||
hb_unicode_funcs_make_immutable
|
||||
hb_unicode_funcs_is_immutable
|
||||
hb_unicode_funcs_get_default
|
||||
hb_unicode_funcs_get_parent
|
||||
hb_unicode_general_category_func_t
|
||||
hb_unicode_funcs_set_general_category_func
|
||||
hb_unicode_combining_class_func_t
|
||||
hb_unicode_funcs_set_combining_class_func
|
||||
hb_unicode_mirroring_func_t
|
||||
hb_unicode_funcs_set_mirroring_func
|
||||
hb_unicode_script_func_t
|
||||
hb_unicode_funcs_set_script_func
|
||||
hb_unicode_compose_func_t
|
||||
hb_unicode_funcs_set_compose_func
|
||||
hb_unicode_decompose_func_t
|
||||
hb_unicode_funcs_set_decompose_func
|
||||
HB_UNICODE_MAX
|
||||
hb_unicode_combining_class
|
||||
hb_unicode_combining_class_func_t
|
||||
hb_unicode_combining_class_t
|
||||
hb_unicode_general_category_t
|
||||
hb_unicode_compose
|
||||
hb_unicode_compose_func_t
|
||||
hb_unicode_decompose
|
||||
hb_unicode_decompose_func_t
|
||||
hb_unicode_funcs_create
|
||||
hb_unicode_funcs_destroy
|
||||
hb_unicode_funcs_get_default
|
||||
hb_unicode_funcs_get_empty
|
||||
hb_unicode_funcs_get_parent
|
||||
hb_unicode_funcs_get_user_data
|
||||
hb_unicode_funcs_is_immutable
|
||||
hb_unicode_funcs_make_immutable
|
||||
hb_unicode_funcs_reference
|
||||
hb_unicode_funcs_set_combining_class_func
|
||||
hb_unicode_funcs_set_compose_func
|
||||
hb_unicode_funcs_set_decompose_func
|
||||
hb_unicode_funcs_set_general_category_func
|
||||
hb_unicode_funcs_set_mirroring_func
|
||||
hb_unicode_funcs_set_script_func
|
||||
hb_unicode_funcs_set_user_data
|
||||
hb_unicode_funcs_t
|
||||
hb_unicode_general_category
|
||||
hb_unicode_general_category_func_t
|
||||
hb_unicode_general_category_t
|
||||
hb_unicode_mirroring
|
||||
hb_unicode_mirroring_func_t
|
||||
hb_unicode_script
|
||||
hb_unicode_script_func_t
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -846,13 +743,13 @@ hb_uniscribe_font_get_logfontw
|
|||
<SECTION>
|
||||
<FILE>hb-version</FILE>
|
||||
HB_VERSION_ATLEAST
|
||||
hb_version
|
||||
hb_version_atleast
|
||||
hb_version_string
|
||||
HB_VERSION_MAJOR
|
||||
HB_VERSION_MICRO
|
||||
HB_VERSION_MINOR
|
||||
HB_VERSION_STRING
|
||||
hb_version
|
||||
hb_version_atleast
|
||||
hb_version_string
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -863,19 +760,20 @@ hb_style_get_value
|
|||
|
||||
<SECTION>
|
||||
<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_reference
|
||||
hb_subset_input_destroy
|
||||
hb_subset_input_set_user_data
|
||||
hb_subset_input_get_user_data
|
||||
hb_subset_input_keep_everything
|
||||
hb_subset_input_set_flags
|
||||
hb_subset_input_get_flags
|
||||
hb_subset_input_set_flags
|
||||
hb_subset_input_unicode_set
|
||||
hb_subset_input_glyph_set
|
||||
hb_subset_input_set
|
||||
hb_subset_input_pin_axis_location
|
||||
hb_subset_input_pin_axis_to_default
|
||||
hb_subset_or_fail
|
||||
hb_subset_plan_create_or_fail
|
||||
hb_subset_plan_reference
|
||||
|
@ -886,28 +784,10 @@ hb_subset_plan_execute_or_fail
|
|||
hb_subset_plan_unicode_to_old_glyph_mapping
|
||||
hb_subset_plan_new_to_old_glyph_mapping
|
||||
hb_subset_plan_old_to_new_glyph_mapping
|
||||
hb_subset_preprocess
|
||||
hb_subset_flags_t
|
||||
hb_subset_input_t
|
||||
hb_subset_sets_t
|
||||
hb_subset_plan_t
|
||||
<SUBSECTION Private>
|
||||
hb_link_t
|
||||
hb_object_t
|
||||
hb_subset_repack_or_fail
|
||||
hb_subset_input_override_name_table
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-cairo</FILE>
|
||||
hb_cairo_font_face_create_for_font
|
||||
hb_cairo_font_face_get_font
|
||||
hb_cairo_font_face_create_for_face
|
||||
hb_cairo_font_face_get_face
|
||||
hb_cairo_font_init_func_t
|
||||
hb_cairo_font_face_set_font_init_func
|
||||
hb_cairo_scaled_font_get_font
|
||||
hb_cairo_font_face_set_scale_factor
|
||||
hb_cairo_font_face_get_scale_factor
|
||||
hb_cairo_glyphs_from_buffer
|
||||
hb_subset_input_pin_axis_location
|
||||
hb_subset_input_pin_axis_to_default
|
||||
</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()
|
||||
message('Not building documentation as gtk-doc was not found')
|
||||
subdir_done()
|
||||
|
@ -36,7 +41,6 @@ html_images = [
|
|||
]
|
||||
|
||||
ignore_headers = [
|
||||
'hb-features.h',
|
||||
'hb-gobject.h',
|
||||
'hb-gobject-enums.h',
|
||||
'hb-gobject-enums-tmp.h',
|
||||
|
@ -49,7 +53,7 @@ gnome.gtkdoc('harfbuzz',
|
|||
meson.current_build_dir() / '..' / 'src',
|
||||
],
|
||||
scan_args: ['--deprecated-guards=HB_DISABLE_DEPRECATED',
|
||||
'--ignore-decorators=HB_EXTERN|HB_DEPRECATED|HB_DEPRECATED_FOR()',
|
||||
'--ignore-decorators=HB_EXTERN|HB_DEPRECATED',
|
||||
],
|
||||
mkdb_args: ['--source-suffixes=h,cc',
|
||||
'--xml-mode',
|
||||
|
@ -59,6 +63,4 @@ gnome.gtkdoc('harfbuzz',
|
|||
html_assets: html_images,
|
||||
ignore_headers: ignore_headers,
|
||||
dependencies: [libharfbuzz_dep],
|
||||
install: true,
|
||||
check: get_option('doc_tests'),
|
||||
)
|
||||
install: true)
|
||||
|
|
|
@ -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>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><emphasis>Level 0</emphasis> is the default.
|
||||
<para><emphasis>Level 0</emphasis> is the default and
|
||||
reproduces the behavior of the old HarfBuzz library.
|
||||
</para>
|
||||
<para>
|
||||
The distinguishing feature of level 0 behavior is that, at
|
||||
|
@ -193,7 +194,7 @@
|
|||
as well as the <emphasis>Zero Width Joiner</emphasis> and
|
||||
<emphasis>Zero Width Non-Joiner</emphasis> code points, are
|
||||
assigned the cluster value of the closest preceding code
|
||||
point from <emphasis>different</emphasis> category.
|
||||
point from <emphasis>different</emphasis> category.
|
||||
</para>
|
||||
<para>
|
||||
In essence, whenever a base character is followed by a mark
|
||||
|
@ -205,11 +206,6 @@
|
|||
url="https://www.unicode.org/reports/tr29/#Regex_Definitions">Unicode
|
||||
Technical Report 29</ulink>.
|
||||
</para>
|
||||
<para>
|
||||
This cluster level is suitable for code that likes to use
|
||||
HarfBuzz cluster values as an approximation of the Unicode
|
||||
Grapheme Cluster Boundaries as well.
|
||||
</para>
|
||||
<para>
|
||||
Client programs can specify level 0 behavior for a buffer by
|
||||
setting its <literal>cluster_level</literal> to
|
||||
|
@ -224,13 +220,13 @@
|
|||
implement backward compatibility with the old HarfBuzz.
|
||||
</para>
|
||||
<para>
|
||||
<emphasis>Level 1</emphasis> differs from level 0 by not merging the
|
||||
Level 1 differs from level 0 by not merging the
|
||||
clusters of marks and other modifier code points with the
|
||||
preceding "base" code point's cluster. By preserving the
|
||||
separate cluster values of these marks and modifier code
|
||||
points, script shapers can perform additional operations
|
||||
that might lead to improved results (for example, coloring
|
||||
mark glyphs differently than their base).
|
||||
that might lead to improved results (for example, reordering
|
||||
a sequence of marks).
|
||||
</para>
|
||||
<para>
|
||||
Client programs can specify level 1 behavior for a buffer by
|
||||
|
@ -246,7 +242,7 @@
|
|||
</para>
|
||||
<para>
|
||||
This difference can be seen most clearly when HarfBuzz processes
|
||||
ligature substitutions and glyph decompositions. In level 0
|
||||
ligature substitutions and glyph decompositions. In level 0
|
||||
and level 1, ligatures and glyph decomposition both involve
|
||||
merging clusters; in level 2, neither of these operations
|
||||
triggers a merge.
|
||||
|
@ -263,7 +259,7 @@
|
|||
assign initial cluster values in a buffer by reusing the indices
|
||||
of the code points in the input text. This gives a sequence of
|
||||
cluster values that is monotonically increasing (for example,
|
||||
0,1,2,3,4).
|
||||
0,1,2,3,4).
|
||||
</para>
|
||||
<para>
|
||||
It is not <emphasis>required</emphasis> that the cluster values
|
||||
|
@ -318,7 +314,7 @@
|
|||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="a-clustering-example-for-levels-0-and-1">
|
||||
<title>A clustering example for levels 0 and 1</title>
|
||||
<para>
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
shaping. The typeface must be set to a specific point size in
|
||||
order for some details (such as hinting) to work. In addition,
|
||||
if the font file in question is an OpenType Variable Font, then
|
||||
you may need to specify one or more variation-axis settings (or a
|
||||
you may need to specify one or variation-axis settings (or a
|
||||
named instance) in order to get the output you need.
|
||||
</para>
|
||||
<para>
|
||||
|
@ -256,18 +256,6 @@
|
|||
<para>
|
||||
<function>hb_font_get_glyph_from_name_func_t</function>: returns
|
||||
the glyph index that corresponds to a given glyph name.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_draw_glyph_func_t</function>: gets the outlines
|
||||
of a glyph (by calling #hb_draw_funcs_t callbacks).
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<function>hb_font_paint_glyph_func_t</function>: paints a glyph
|
||||
(by calling #hb_paint_funcs_t callbacks).
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
@ -387,6 +375,20 @@
|
|||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
<!-- Commenting out FreeType integration section-holder for now. May move
|
||||
to the full-blown Integration Chapter. -->
|
||||
|
||||
<!-- <section id="fonts-and-faces-freetype">
|
||||
<title>Using FreeType</title>
|
||||
<para>
|
||||
|
||||
</para>
|
||||
<para>
|
||||
|
||||
</para>
|
||||
</section> -->
|
||||
|
||||
<section id="fonts-and-faces-variable">
|
||||
<title>Working with OpenType Variable Fonts</title>
|
||||
<para>
|
||||
|
@ -453,66 +455,13 @@
|
|||
range actually implemented in the font's variation axis. After
|
||||
all, a font might only provide lighter-than-regular weights, and
|
||||
setting a heavier value on the <literal>wght</literal> axis will
|
||||
not change that.
|
||||
not change that.
|
||||
</para>
|
||||
<para>
|
||||
Once your variation settings are specified on your font object,
|
||||
however, shaping with a variable font is just like shaping a
|
||||
static font.
|
||||
</para>
|
||||
<para>
|
||||
In addition to providing the variation axes themselves, fonts may also
|
||||
pre-define certain variation coordinates as named instances. HarfBuzz
|
||||
makes these coordinates (and their associated names) available via
|
||||
<function>hb_ot_var_named_instance_get_design_coords()</function> and
|
||||
<function>hb_ot_var_named_instance_get_subfamily_name_id()</function>.
|
||||
</para>
|
||||
<para>
|
||||
Applications should treat named instances like multiple independent,
|
||||
static fonts.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="glyphs-and-rendering">
|
||||
<title>Glyphs and rendering</title>
|
||||
|
||||
<para>
|
||||
The main purpose of HarfBuzz is shaping, which creates a list of positioned
|
||||
glyphs as output. The remaining task for text layout is to convert this list
|
||||
into rendered output. While HarfBuzz does not handle rasterization of glyphs
|
||||
per se, it does have APIs that provide access to the font data that is needed
|
||||
to perform this task.
|
||||
</para>
|
||||
<para>
|
||||
Traditionally, the shapes of glyphs in scalable fonts are provided as quadratic
|
||||
or cubic Beziér curves defining outlines to be filled. To obtain the outlines
|
||||
for a glyph, call <function>hb_font_draw_glyph()</function> and pass a
|
||||
<type>hb_draw_funcs_t</type> struct. The callbacks in that struct will be called
|
||||
for each segment of the outline. Note that this API provides access to outlines
|
||||
as they are defined in the font, without applying hinting to fit the curves
|
||||
to the pixel grid.
|
||||
</para>
|
||||
<para>
|
||||
Fonts may provide pre-rendered images for glyphs instead of or in addition to
|
||||
outlines. This is most common for fonts that contain colored glyphs, such as
|
||||
Emoji. To access these images, use <function>hb_ot_color_reference_png()</function>
|
||||
or <function>hb_ot_color_reference_svg()</function>.
|
||||
</para>
|
||||
<para>
|
||||
Another way in which fonts provide colored glyphs is via paint graphs that
|
||||
combine glyph outlines with gradients and allow for transformations and
|
||||
compositing. In its simplest form, this can be presented as a series of
|
||||
layers that are rendered on top of each other, each with its own color.
|
||||
HarfBuzz has the <function>hb_ot_color_glyph_get_layers()</function> to
|
||||
access glyph data in this form.
|
||||
</para>
|
||||
<para>
|
||||
In the general case, you have to use <function>hb_font_paint_glyph()</function>
|
||||
and pass a <type>hb_paint_funcs_t</type> struct with callbacks to obtain paint
|
||||
graphs for glyphs that have them. The <function>hb_font_paint_glyph()</function>
|
||||
API can handle outline and image glyphs as well, so it provides a unified API for
|
||||
access to glyph rendering information.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
|
|
|
@ -174,9 +174,7 @@
|
|||
<para>
|
||||
HarfBuzz provides integration points with FreeType at the
|
||||
face-object and font-object level and for the font-functions
|
||||
virtual-method structure of a font object. These functions
|
||||
make it easy for clients that use FreeType for rasterization
|
||||
or font-loading, to use HarfBuzz for shaping. To use the
|
||||
virtual-method structure of a font object. To use the
|
||||
FreeType-integration API, include the
|
||||
<filename>hb-ft.h</filename> header.
|
||||
</para>
|
||||
|
@ -310,49 +308,7 @@
|
|||
it when it is unneeded.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="integration-cairo">
|
||||
<title>Cairo integration</title>
|
||||
|
||||
<para>
|
||||
Cairo is a 2D graphics library that is frequently used together
|
||||
with GTK and Pango. Cairo supports rendering text using FreeType, or
|
||||
by using callback-based 'user fonts'.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz provides integration points with cairo for fonts as well as
|
||||
for buffers. To use the Cairo-integration API, link against libharfbuzz-cairo,
|
||||
and include the <filename>hb-cairo.h</filename> header. For easy buildsystem
|
||||
integration, HarfBuzz comes with a <filename>harfbuzz-cairo.pc</filename>
|
||||
pkg-config file.
|
||||
</para>
|
||||
<para>
|
||||
To create a <type>cairo_scaled_font_t</type> font from a HarfBuzz
|
||||
<type>hb_font_t</type>, you can use <function>hb_cairo_font_face_create_for_font()</function>
|
||||
or <function>hb_cairo_font_face_create_for_face()</function>. The former API
|
||||
applies variations and synthetic slant from the <type>hb_font_t</type> when
|
||||
rendering, the latter takes them from the <type>cairo_font_options_t</type>
|
||||
that were passed when creating the <type>cairo_scaled_font_t</type>.
|
||||
</para>
|
||||
<para>
|
||||
The Cairo fonts created in this way make use of Cairo's user-font facilities.
|
||||
They can be used to render on any Cairo context, and provide full support for
|
||||
font rendering features, including color. One current limitation of the
|
||||
implementation is that it does not support hinting for glyph outlines.
|
||||
</para>
|
||||
<para>
|
||||
When using color fonts with this API, the color palette index is taken from
|
||||
the <type>cairo_font_options_t</type> (with new enough Cairo), and the foreground
|
||||
color is extracted from the source of the Cairo context.
|
||||
</para>
|
||||
<para>
|
||||
To render the results of shaping a piece of text, use
|
||||
<function>hb_cairo_glyphs_from_buffer()</function> to obtain the glyphs in
|
||||
a form that can be passed to <function>cairo_show_text_glyphs()</function> or
|
||||
<function>cairo_show_glyphs()</function>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="integration-uniscribe">
|
||||
<title>Uniscribe integration</title>
|
||||
<para>
|
||||
|
|
119
meson.build
119
meson.build
|
@ -1,9 +1,8 @@
|
|||
project('harfbuzz', 'c', 'cpp',
|
||||
meson_version: '>= 0.55.0',
|
||||
version: '7.1.0',
|
||||
version: '5.3.0',
|
||||
default_options: [
|
||||
'cpp_eh=none', # Just to support msvc, we are passing -fno-exceptions also anyway
|
||||
'cpp_rtti=false', # Just to support msvc, we are passing -fno-rtti also anyway
|
||||
'cpp_rtti=false', # Just to support msvc, we are passing -fno-exceptions also anyway
|
||||
'cpp_std=c++11',
|
||||
'wrap_mode=nofallback', # Use --wrap-mode=default to revert, https://github.com/harfbuzz/harfbuzz/pull/2548
|
||||
],
|
||||
|
@ -15,7 +14,7 @@ hb_version_minor = hb_version_arr[1].to_int()
|
|||
hb_version_micro = hb_version_arr[2].to_int()
|
||||
|
||||
# libtool versioning
|
||||
hb_version_int = 60000 + hb_version_major*100 + hb_version_minor*10 + hb_version_micro
|
||||
hb_version_int = hb_version_major*10000 + hb_version_minor*100 + hb_version_micro
|
||||
hb_libtool_version_info = '@0@:0:@0@'.format(hb_version_int)
|
||||
|
||||
pkgmod = import('pkgconfig')
|
||||
|
@ -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
|
||||
# NOTE: Only add warnings here if you are sure they're spurious
|
||||
msvc_args = [
|
||||
'/wd4018', # implicit signed/unsigned conversion
|
||||
'/wd4146', # unary minus on unsigned (beware INT_MIN)
|
||||
'/wd4244', # lossy type conversion (e.g. double -> int)
|
||||
'/wd4305', # truncating type conversion (e.g. double -> float)
|
||||
cpp.get_supported_arguments(['/utf-8']), # set the input encoding to utf-8
|
||||
]
|
||||
add_project_arguments(msvc_args, language: ['c', 'cpp'])
|
||||
# Disable SAFESEH with MSVC for libs that use external deps that are built with MinGW
|
||||
# noseh_link_args = ['/SAFESEH:NO']
|
||||
# disable exception handling
|
||||
add_project_arguments(['/EHs-', '/EHc-'], language: 'cpp')
|
||||
endif
|
||||
|
||||
add_project_link_arguments(cpp.get_supported_link_arguments([
|
||||
|
@ -79,35 +83,20 @@ check_funcs = [
|
|||
|
||||
m_dep = cpp.find_library('m', required: false)
|
||||
|
||||
if meson.version().version_compare('>=0.60.0')
|
||||
# pkg-config: freetype2, cmake: Freetype
|
||||
freetype_dep = dependency('freetype2', 'Freetype',
|
||||
|
||||
# Try pkgconfig name
|
||||
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'),
|
||||
default_options: ['harfbuzz=disabled'],
|
||||
allow_fallback: true)
|
||||
else
|
||||
# painful hack to handle multiple dependencies but also respect options
|
||||
freetype_opt = get_option('freetype')
|
||||
# we want to handle enabled manually after fallbacks, but also handle disabled normally
|
||||
if freetype_opt.enabled()
|
||||
freetype_opt = false
|
||||
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
|
||||
|
||||
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'))
|
||||
graphite_dep = dependency('graphite2', required: get_option('graphite'))
|
||||
|
||||
if meson.version().version_compare('>=0.60.0')
|
||||
# pkg-config: icu-uc, cmake: ICU but with components
|
||||
icu_dep = dependency('icu-uc', 'ICU',
|
||||
components: 'uc',
|
||||
required: get_option('icu'),
|
||||
default_options: ['harfbuzz=disabled'],
|
||||
allow_fallback: true)
|
||||
else
|
||||
# painful hack to handle multiple dependencies but also respect options
|
||||
icu_opt = get_option('icu')
|
||||
# we want to handle enabled manually after fallbacks, but also handle disabled normally
|
||||
if icu_opt.enabled()
|
||||
icu_opt = false
|
||||
endif
|
||||
# try pkg-config name
|
||||
icu_dep = dependency('icu-uc', method: 'pkg-config', required: icu_opt)
|
||||
# when disabled, leave it not-found
|
||||
if not icu_dep.found() and not get_option('icu').disabled()
|
||||
# Try cmake name
|
||||
icu_dep = dependency('ICU', method: 'cmake', components: 'uc', required: false)
|
||||
# Try again with subproject fallback. `allow_fallback: true` means the
|
||||
# fallback will be tried even if the icu option is set to `auto`, but
|
||||
# we cannot pass this option until Meson 0.59.0, because no wrap file
|
||||
# is checked into git.
|
||||
if not icu_dep.found()
|
||||
icu_dep = dependency('icu-uc',
|
||||
method: 'pkg-config',
|
||||
required: get_option('icu'))
|
||||
endif
|
||||
endif
|
||||
# Try pkgconfig name
|
||||
icu_dep = dependency('icu-uc', required: false)
|
||||
if not icu_dep.found()
|
||||
# Try cmake name
|
||||
icu_dep = dependency('ICU',
|
||||
required: false,
|
||||
components: 'uc',
|
||||
method: 'cmake')
|
||||
endif
|
||||
if not icu_dep.found()
|
||||
# Subproject fallback if icu option is enabled
|
||||
icu_dep = dependency('icu-uc', required: get_option('icu'))
|
||||
endif
|
||||
|
||||
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
|
||||
# it will be forced to use that one.
|
||||
cairo_dep = dependency('cairo', required: get_option('cairo'))
|
||||
cairo_ft_required = get_option('cairo').enabled() and get_option('freetype').enabled()
|
||||
cairo_ft_dep = dependency('cairo-ft', required: cairo_ft_required)
|
||||
cairo_ft_dep = dependency('cairo-ft', required: get_option('cairo'))
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -205,19 +175,10 @@ endif
|
|||
|
||||
if cairo_dep.found()
|
||||
conf.set('HAVE_CAIRO', 1)
|
||||
check_cairo_funcs = [
|
||||
['cairo_user_font_face_set_render_color_glyph_func', {'deps': cairo_dep}],
|
||||
['cairo_font_options_get_custom_palette_color', {'deps': cairo_dep}],
|
||||
['cairo_user_scaled_font_get_foreground_source', {'deps': cairo_dep}],
|
||||
]
|
||||
|
||||
if cairo_dep.type_name() == 'internal'
|
||||
foreach func: check_cairo_funcs
|
||||
name = func[0]
|
||||
conf.set('HAVE_@0@'.format(name.to_upper()), 1)
|
||||
endforeach
|
||||
conf.set('HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC', 1)
|
||||
else
|
||||
check_funcs += check_cairo_funcs
|
||||
check_funcs += [['cairo_user_font_face_set_render_color_glyph_func', {'deps': cairo_dep}]]
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -373,10 +334,7 @@ foreach check : check_funcs
|
|||
endforeach
|
||||
|
||||
subdir('src')
|
||||
|
||||
if not get_option('utilities').disabled()
|
||||
subdir('util')
|
||||
endif
|
||||
subdir('util')
|
||||
|
||||
if not get_option('tests').disabled()
|
||||
subdir('test')
|
||||
|
@ -392,9 +350,6 @@ endif
|
|||
|
||||
configure_file(output: 'config.h', configuration: conf)
|
||||
|
||||
alias_target('lib', libharfbuzz)
|
||||
alias_target('libs', libharfbuzz, libharfbuzz_subset)
|
||||
|
||||
build_summary = {
|
||||
'Directories':
|
||||
{'prefix': get_option('prefix'),
|
||||
|
@ -409,8 +364,7 @@ build_summary = {
|
|||
'ICU': conf.get('HAVE_ICU', 0) == 1,
|
||||
},
|
||||
'Font callbacks (the more the merrier)':
|
||||
{'Builtin' : true,
|
||||
'FreeType': conf.get('HAVE_FREETYPE', 0) == 1,
|
||||
{'FreeType': conf.get('HAVE_FREETYPE', 0) == 1,
|
||||
},
|
||||
'Dependencies used for command-line utilities':
|
||||
{'Cairo': conf.get('HAVE_CAIRO', 0) == 1,
|
||||
|
@ -427,7 +381,6 @@ build_summary = {
|
|||
'Other features':
|
||||
{'Documentation': conf.get('HAVE_GTK_DOC', 0) == 1,
|
||||
'GObject bindings': conf.get('HAVE_GOBJECT', 0) == 1,
|
||||
'Cairo integration': conf.get('HAVE_CAIRO', 0) == 1,
|
||||
'Introspection': conf.get('HAVE_INTROSPECTION', 0) == 1,
|
||||
'Experimental APIs': conf.get('HB_EXPERIMENTAL_API', 0) == 1,
|
||||
},
|
||||
|
|
|
@ -29,10 +29,6 @@ option('introspection', type: 'feature', value: 'auto', yield: true,
|
|||
description: 'Generate gobject-introspection bindings (.gir/.typelib files)')
|
||||
option('docs', type: 'feature', value: 'auto', yield: true,
|
||||
description: 'Generate documentation with gtk-doc')
|
||||
option('doc_tests', type: 'boolean', value: false,
|
||||
description: 'Run gtkdoc-check tests')
|
||||
option('utilities', type: 'feature', value: 'enabled', yield: true,
|
||||
description: 'Build harfbuzz utils')
|
||||
|
||||
option('benchmark', type: 'feature', value: 'disabled',
|
||||
description: 'Enable benchmark tests')
|
||||
|
|
|
@ -163,7 +163,7 @@ static void BM_Font (benchmark::State &state,
|
|||
hb_draw_funcs_t *draw_funcs = _draw_funcs_create ();
|
||||
for (auto _ : state)
|
||||
for (unsigned gid = 0; gid < num_glyphs; ++gid)
|
||||
hb_font_draw_glyph (font, gid, draw_funcs, nullptr);
|
||||
hb_font_get_glyph_shape (font, gid, draw_funcs, nullptr);
|
||||
break;
|
||||
hb_draw_funcs_destroy (draw_funcs);
|
||||
}
|
||||
|
|
|
@ -27,18 +27,10 @@ struct test_input_t
|
|||
"perf/texts/fa-thelittleprince.txt",
|
||||
false},
|
||||
|
||||
{"perf/fonts/NotoNastaliqUrdu-Regular.ttf",
|
||||
"perf/texts/fa-words.txt",
|
||||
false},
|
||||
|
||||
{"perf/fonts/Amiri-Regular.ttf",
|
||||
"perf/texts/fa-thelittleprince.txt",
|
||||
false},
|
||||
|
||||
{SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf",
|
||||
"perf/texts/hi-words.txt",
|
||||
false},
|
||||
|
||||
{"perf/fonts/Roboto-Regular.ttf",
|
||||
"perf/texts/en-thelittleprince.txt",
|
||||
false},
|
||||
|
|
|
@ -54,19 +54,18 @@ static inline unsigned int ARRAY_LEN (const Type (&)[n]) { return n; }
|
|||
struct test_input_t
|
||||
{
|
||||
const char *font_path;
|
||||
unsigned max_subset_size;
|
||||
const unsigned max_subset_size;
|
||||
const axis_location_t *instance_opts;
|
||||
unsigned num_instance_opts;
|
||||
} default_tests[] =
|
||||
const unsigned num_instance_opts;
|
||||
} tests[] =
|
||||
{
|
||||
{SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf", 1000, nullptr, 0},
|
||||
{SUBSET_FONT_BASE_PATH "Amiri-Regular.ttf", 4096, nullptr, 0},
|
||||
{SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf", 1400, nullptr, 0},
|
||||
{SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf", 4000, nullptr, 0},
|
||||
{SUBSET_FONT_BASE_PATH "Amiri-Regular.ttf", 4000, 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 "Mplus1p-Regular.ttf", 10000, nullptr, 0},
|
||||
{SUBSET_FONT_BASE_PATH "SourceHanSans-Regular_subset.otf", 10000, nullptr, 0},
|
||||
{SUBSET_FONT_BASE_PATH "SourceSansPro-Regular.otf", 2000, nullptr, 0},
|
||||
{SUBSET_FONT_BASE_PATH "AdobeVFPrototype.otf", 300, nullptr, 0},
|
||||
{SUBSET_FONT_BASE_PATH "MPLUS1-Variable.ttf", 6000, _mplus_instance_opts, ARRAY_LEN (_mplus_instance_opts)},
|
||||
{SUBSET_FONT_BASE_PATH "RobotoFlex-Variable.ttf", 900, _roboto_flex_instance_opts, ARRAY_LEN (_roboto_flex_instance_opts)},
|
||||
#if 0
|
||||
|
@ -74,10 +73,6 @@ struct test_input_t
|
|||
#endif
|
||||
};
|
||||
|
||||
static test_input_t *tests = default_tests;
|
||||
static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
|
||||
|
||||
|
||||
void AddCodepoints(const hb_set_t* codepoints_in_font,
|
||||
unsigned subset_size,
|
||||
hb_subset_input_t* input)
|
||||
|
@ -106,25 +101,23 @@ void AddGlyphs(unsigned num_glyphs_in_font,
|
|||
// the subsetting operations.
|
||||
static hb_face_t* preprocess_face(hb_face_t* face)
|
||||
{
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
hb_face_t* new_face = hb_subset_preprocess(face);
|
||||
hb_face_destroy(face);
|
||||
return new_face;
|
||||
#else
|
||||
return face;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* benchmark for subsetting a font */
|
||||
static void BM_subset (benchmark::State &state,
|
||||
operation_t operation,
|
||||
const test_input_t &test_input,
|
||||
bool hinting)
|
||||
const test_input_t &test_input)
|
||||
{
|
||||
unsigned subset_size = state.range(0);
|
||||
|
||||
hb_face_t *face = nullptr;
|
||||
|
||||
static hb_face_t *cached_face;
|
||||
static const char *cached_font_path;
|
||||
|
||||
if (!cached_font_path || strcmp (cached_font_path, test_input.font_path))
|
||||
hb_face_t *face;
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
|
||||
assert (blob);
|
||||
|
@ -132,22 +125,11 @@ static void BM_subset (benchmark::State &state,
|
|||
hb_blob_destroy (blob);
|
||||
|
||||
face = preprocess_face (face);
|
||||
|
||||
if (cached_face)
|
||||
hb_face_destroy (cached_face);
|
||||
|
||||
cached_face = hb_face_reference (face);
|
||||
cached_font_path = test_input.font_path;
|
||||
}
|
||||
else
|
||||
face = hb_face_reference (cached_face);
|
||||
|
||||
hb_subset_input_t* input = hb_subset_input_create_or_fail ();
|
||||
assert (input);
|
||||
|
||||
if (!hinting)
|
||||
hb_subset_input_set_flags (input, HB_SUBSET_FLAGS_NO_HINTING);
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case subset_codepoints:
|
||||
|
@ -167,6 +149,7 @@ static void BM_subset (benchmark::State &state,
|
|||
break;
|
||||
|
||||
case instance:
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
{
|
||||
hb_set_t* all_codepoints = hb_set_create ();
|
||||
hb_face_collect_unicodes (face, all_codepoints);
|
||||
|
@ -178,6 +161,7 @@ static void BM_subset (benchmark::State &state,
|
|||
test_input.instance_opts[i].axis_tag,
|
||||
test_input.instance_opts[i].axis_value);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -194,7 +178,6 @@ static void BM_subset (benchmark::State &state,
|
|||
|
||||
static void test_subset (operation_t op,
|
||||
const char *op_name,
|
||||
bool hinting,
|
||||
benchmark::TimeUnit time_unit,
|
||||
const test_input_t &test_input)
|
||||
{
|
||||
|
@ -203,57 +186,36 @@ static void test_subset (operation_t op,
|
|||
|
||||
char name[1024] = "BM_subset/";
|
||||
strcat (name, op_name);
|
||||
strcat (name, "/");
|
||||
const char *p = strrchr (test_input.font_path, '/');
|
||||
strcat (name, p ? p + 1 : test_input.font_path);
|
||||
if (!hinting)
|
||||
strcat (name, "/nohinting");
|
||||
strcat (name, strrchr (test_input.font_path, '/'));
|
||||
|
||||
benchmark::RegisterBenchmark (name, BM_subset, op, test_input, hinting)
|
||||
benchmark::RegisterBenchmark (name, BM_subset, op, test_input)
|
||||
->Range(10, test_input.max_subset_size)
|
||||
->Unit(time_unit);
|
||||
}
|
||||
|
||||
static void test_operation (operation_t op,
|
||||
const char *op_name,
|
||||
const test_input_t *tests,
|
||||
unsigned num_tests,
|
||||
benchmark::TimeUnit time_unit)
|
||||
{
|
||||
for (unsigned i = 0; i < num_tests; i++)
|
||||
for (auto& test_input : tests)
|
||||
{
|
||||
auto& test_input = tests[i];
|
||||
test_subset (op, op_name, true, time_unit, test_input);
|
||||
test_subset (op, op_name, false, time_unit, test_input);
|
||||
test_subset (op, op_name, time_unit, test_input);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
benchmark::Initialize(&argc, argv);
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
num_tests = (argc - 1) / 2;
|
||||
tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
|
||||
for (unsigned i = 0; i < num_tests; i++)
|
||||
{
|
||||
tests[i].font_path = argv[1 + i * 2];
|
||||
tests[i].max_subset_size = atoi (argv[2 + i * 2]);
|
||||
}
|
||||
}
|
||||
|
||||
#define TEST_OPERATION(op, time_unit) test_operation (op, #op, tests, num_tests, time_unit)
|
||||
#define TEST_OPERATION(op, time_unit) test_operation (op, #op, time_unit)
|
||||
|
||||
TEST_OPERATION (subset_glyphs, benchmark::kMillisecond);
|
||||
TEST_OPERATION (subset_codepoints, benchmark::kMillisecond);
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
TEST_OPERATION (instance, benchmark::kMillisecond);
|
||||
#endif
|
||||
|
||||
#undef TEST_OPERATION
|
||||
|
||||
benchmark::Initialize(&argc, argv);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
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)
|
||||
HBSOURCES += $(HB_GLIB_sources)
|
||||
HBHEADERS += $(HB_GLIB_headers)
|
||||
HB_HAS_GLIB_DEF = define HB_HAS_GLIB 1
|
||||
else
|
||||
HB_HAS_GLIB_DEF = undef HB_HAS_GLIB
|
||||
endif
|
||||
|
||||
if HAVE_FREETYPE
|
||||
|
@ -58,9 +55,6 @@ HBLIBS += $(FREETYPE_LIBS)
|
|||
HBDEPS += $(FREETYPE_DEPS)
|
||||
HBSOURCES += $(HB_FT_sources)
|
||||
HBHEADERS += $(HB_FT_headers)
|
||||
HB_HAS_FREETYPE_DEF = define HB_HAS_FREETYPE 1
|
||||
else
|
||||
HB_HAS_FREETYPE_DEF = undef HB_HAS_FREETYPE
|
||||
endif
|
||||
|
||||
if HAVE_GRAPHITE2
|
||||
|
@ -69,9 +63,6 @@ HBLIBS += $(GRAPHITE2_LIBS)
|
|||
HBDEPS += $(GRAPHITE2_DEPS)
|
||||
HBSOURCES += $(HB_GRAPHITE2_sources)
|
||||
HBHEADERS += $(HB_GRAPHITE2_headers)
|
||||
HB_HAS_GRAPHITE_DEF = define HB_HAS_GRAPHITE 1
|
||||
else
|
||||
HB_HAS_GRAPHITE_DEF = undef HB_HAS_GRAPHITE
|
||||
endif
|
||||
|
||||
if HAVE_UNISCRIBE
|
||||
|
@ -79,9 +70,6 @@ HBCFLAGS += $(UNISCRIBE_CFLAGS)
|
|||
HBNONPCLIBS += $(UNISCRIBE_LIBS)
|
||||
HBSOURCES += $(HB_UNISCRIBE_sources)
|
||||
HBHEADERS += $(HB_UNISCRIBE_headers)
|
||||
HB_HAS_UNISCRIBE_DEF = define HB_HAS_UNISCRIBE 1
|
||||
else
|
||||
HB_HAS_UNISCRIBE_DEF = undef HB_HAS_UNISCRIBE
|
||||
endif
|
||||
|
||||
if HAVE_DIRECTWRITE
|
||||
|
@ -89,9 +77,6 @@ HBCFLAGS += $(DIRECTWRITE_CXXFLAGS)
|
|||
HBNONPCLIBS += $(DIRECTWRITE_LIBS)
|
||||
HBSOURCES += $(HB_DIRECTWRITE_sources)
|
||||
HBHEADERS += $(HB_DIRECTWRITE_headers)
|
||||
HB_HAS_DIRECTWRITE_DEF = define HB_HAS_DIRECTWRITE 1
|
||||
else
|
||||
HB_HAS_DIRECTWRITE_DEF = undef HB_HAS_DIRECTWRITE
|
||||
endif
|
||||
|
||||
if HAVE_GDI
|
||||
|
@ -99,9 +84,6 @@ HBCFLAGS += $(GDI_CXXFLAGS)
|
|||
HBNONPCLIBS += $(GDI_LIBS)
|
||||
HBSOURCES += $(HB_GDI_sources)
|
||||
HBHEADERS += $(HB_GDI_headers)
|
||||
HB_HAS_GDI_DEF = define HB_HAS_GDI 1
|
||||
else
|
||||
HB_HAS_GDI_DEF = undef HB_HAS_GDI
|
||||
endif
|
||||
|
||||
if HAVE_CORETEXT
|
||||
|
@ -109,9 +91,6 @@ HBCFLAGS += $(CORETEXT_CFLAGS)
|
|||
HBNONPCLIBS += $(CORETEXT_LIBS)
|
||||
HBSOURCES += $(HB_CORETEXT_sources)
|
||||
HBHEADERS += $(HB_CORETEXT_headers)
|
||||
HB_HAS_CORETEXT_DEF = define HB_HAS_CORETEXT 1
|
||||
else
|
||||
HB_HAS_CORETEXT_DEF = undef HB_HAS_CORETEXT
|
||||
endif
|
||||
|
||||
|
||||
|
@ -135,8 +114,6 @@ export_symbols = -export-symbols harfbuzz.def
|
|||
harfbuzz_def_dependency = harfbuzz.def
|
||||
export_symbols_subset = -export-symbols harfbuzz-subset.def
|
||||
harfbuzz_subset_def_dependency = harfbuzz-subset.def
|
||||
export_symbols_cairo = -export-symbols harfbuzz-cairo.def
|
||||
harfbuzz_cairo_def_dependency = harfbuzz-cairo.def
|
||||
export_symbols_icu = -export-symbols harfbuzz-icu.def
|
||||
harfbuzz_icu_def_dependency = harfbuzz-icu.def
|
||||
export_symbols_gobject = -export-symbols harfbuzz-gobject.def
|
||||
|
@ -170,7 +147,7 @@ pkgconfigdir = $(libdir)/pkgconfig
|
|||
pkgconfig_DATA = harfbuzz.pc
|
||||
cmakedir = $(libdir)/cmake/harfbuzz
|
||||
cmake_DATA = harfbuzz-config.cmake
|
||||
EXTRA_DIST += hb-version.h.in hb-features.h.in harfbuzz.pc.in harfbuzz-config.cmake.in
|
||||
EXTRA_DIST += hb-version.h.in harfbuzz.pc.in harfbuzz-config.cmake.in
|
||||
|
||||
lib_LTLIBRARIES += libharfbuzz-subset.la
|
||||
libharfbuzz_subset_la_LINK = $(chosen_linker) $(libharfbuzz_subset_la_LDFLAGS)
|
||||
|
@ -195,24 +172,12 @@ harfbuzz-subset.cc: Makefile.sources
|
|||
|| ($(RM) $(srcdir)/harfbuzz-subset.cc; false)
|
||||
BUILT_SOURCES += harfbuzz-subset.cc
|
||||
|
||||
lib_LTLIBRARIES += libharfbuzz-cairo.la
|
||||
libharfbuzz_cairo_la_LINK = $(chosen_linker) $(libharfbuzz_cairo_la_LDFLAGS)
|
||||
libharfbuzz_cairo_la_SOURCES = $(HB_CAIRO_sources)
|
||||
libharfbuzz_cairo_la_CPPFLAGS = $(HBCFLAGS) $(CAIRO_CFLAGS) $(CODE_COVERAGE_CFLAGS)
|
||||
libharfbuzz_cairo_la_LDFLAGS = $(base_link_flags) $(export_symbols_cairo) $(CODE_COVERAGE_LDFLAGS)
|
||||
libharfbuzz_cairo_la_LIBADD = $(CAIRO_LIBS) libharfbuzz.la
|
||||
EXTRA_libharfbuzz_cairo_la_DEPENDENCIES = $(harfbuzz_cairo_def_dependency)
|
||||
pkginclude_HEADERS += $(HB_CAIRO_headers)
|
||||
pkgconfig_DATA += harfbuzz-cairo.pc
|
||||
EXTRA_DIST += harfbuzz-cairo.pc.in
|
||||
|
||||
if HAVE_ICU
|
||||
if HAVE_ICU_BUILTIN
|
||||
HBCFLAGS += $(ICU_CFLAGS)
|
||||
HBLIBS += $(ICU_LIBS)
|
||||
HBSOURCES += $(HB_ICU_sources)
|
||||
HBHEADERS += $(HB_ICU_headers)
|
||||
HB_HAS_ICU_DEF = define HB_HAS_ICU 1
|
||||
else
|
||||
lib_LTLIBRARIES += libharfbuzz-icu.la
|
||||
libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
|
||||
|
@ -222,7 +187,6 @@ libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la
|
|||
EXTRA_libharfbuzz_icu_la_DEPENDENCIES = $(harfbuzz_icu_def_dependency)
|
||||
pkginclude_HEADERS += $(HB_ICU_headers)
|
||||
pkgconfig_DATA += harfbuzz-icu.pc
|
||||
HB_HAS_ICU_DEF = undef HB_HAS_ICU
|
||||
endif
|
||||
endif
|
||||
EXTRA_DIST += harfbuzz-icu.pc.in
|
||||
|
@ -254,9 +218,6 @@ hb-gobject-enums.%: hb-gobject-enums.%.tmpl $(HBHEADERS)
|
|||
--template $^ | \
|
||||
sed 's/_t_get_type/_get_type/g; s/_T (/ (/g' > "$@" \
|
||||
|| ($(RM) "$@"; false)
|
||||
HB_HAS_GOBJECT_DEF = define HB_HAS_GOBJECT 1
|
||||
else
|
||||
HB_HAS_GOBJECT_DEF = undef HB_HAS_GOBJECT
|
||||
endif
|
||||
EXTRA_DIST += \
|
||||
harfbuzz-gobject.pc.in \
|
||||
|
@ -265,27 +226,6 @@ EXTRA_DIST += \
|
|||
$(NULL)
|
||||
|
||||
|
||||
BUILT_SOURCES += \
|
||||
hb-features.h
|
||||
DISTCLEANFILES += \
|
||||
hb-features.h
|
||||
|
||||
hb-features.h: hb-features.h.in $(top_builddir)/config.status
|
||||
$(AM_V_GEN) $(SED) \
|
||||
-e 's/mesondefine HB_HAS_CAIRO/$(HB_HAS_CAIRO_DEF)/' \
|
||||
-e 's/mesondefine HB_HAS_FREETYPE/$(HB_HAS_FREETYPE_DEF)/' \
|
||||
-e 's/mesondefine HB_HAS_GDI/$(HB_HAS_GDI_DEF)/' \
|
||||
-e 's/mesondefine HB_HAS_GDI/$(HB_HAS_GDI_DEF)/' \
|
||||
-e 's/mesondefine HB_HAS_GRAPHITE/$(HB_HAS_GRAPHITE_DEF)/' \
|
||||
-e 's/mesondefine HB_HAS_GLIB/$(HB_HAS_GLIB_DEF)/' \
|
||||
-e 's/mesondefine HB_HAS_GOBJECT/$(HB_HAS_GOBJECT_DEF)/' \
|
||||
-e 's/mesondefine HB_HAS_UNISCRIBE/$(HB_HAS_UNISCRIBE_DEF)/' \
|
||||
-e 's/mesondefine HB_HAS_DIRECTWRITE/$(HB_HAS_DIRECTWRITE_DEF)/' \
|
||||
-e 's/mesondefine HB_HAS_CORETEXT/$(HB_HAS_CORETEXT_DEF)/' \
|
||||
-e 's/mesondefine HB_HAS_ICU/$(HB_HAS_ICU_DEF)/' \
|
||||
"$<" > "$@" || ($(RM) "$@"; false)
|
||||
|
||||
|
||||
%.pc: %.pc.in $(top_builddir)/config.status
|
||||
$(AM_V_GEN) \
|
||||
$(SED) -e 's@%prefix%@$(prefix)@g' \
|
||||
|
@ -312,8 +252,6 @@ harfbuzz.def: $(HBHEADERS)
|
|||
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
|
||||
harfbuzz-subset.def: $(HB_SUBSET_headers)
|
||||
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
|
||||
harfbuzz-cairo.def: $(HB_CAIRO_headers)
|
||||
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
|
||||
harfbuzz-icu.def: $(HB_ICU_headers)
|
||||
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
|
||||
harfbuzz-gobject.def: $(HB_GOBJECT_headers)
|
||||
|
@ -382,7 +320,6 @@ noinst_PROGRAMS = \
|
|||
test-ot-name \
|
||||
test-ot-glyphname \
|
||||
test-gpos-size-params \
|
||||
test-gsub-get-alternates \
|
||||
test-gsub-would-substitute \
|
||||
test-use-table \
|
||||
$(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_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_gsub_get_alternates_SOURCES = test-gsub-get-alternates.cc
|
||||
test_gsub_get_alternates_CPPFLAGS = $(HBCFLAGS)
|
||||
test_gsub_get_alternates_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc
|
||||
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
|
||||
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
||||
|
@ -435,7 +368,6 @@ COMPILED_TESTS = \
|
|||
test-iter \
|
||||
test-machinery \
|
||||
test-map \
|
||||
test-multimap \
|
||||
test-number \
|
||||
test-ot-tag \
|
||||
test-priority-queue \
|
||||
|
@ -475,10 +407,6 @@ test_map_SOURCES = test-map.cc hb-static.cc
|
|||
test_map_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_map_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
||||
test_multimap_SOURCES = test-multimap.cc hb-static.cc
|
||||
test_multimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_multimap_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
||||
test_number_SOURCES = test-number.cc hb-number.cc
|
||||
test_number_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_number_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
|
|
@ -42,19 +42,16 @@ HB_BASE_sources = \
|
|||
hb-draw.hh \
|
||||
hb-face.cc \
|
||||
hb-face.hh \
|
||||
hb-face-builder.cc \
|
||||
hb-fallback-shape.cc \
|
||||
hb-font.cc \
|
||||
hb-font.hh \
|
||||
hb-iter.hh \
|
||||
hb-kern.hh \
|
||||
hb-limits.hh \
|
||||
hb-machinery.hh \
|
||||
hb-map.cc \
|
||||
hb-map.hh \
|
||||
hb-meta.hh \
|
||||
hb-ms-feature-ranges.hh \
|
||||
hb-multimap.hh \
|
||||
hb-mutex.hh \
|
||||
hb-null.hh \
|
||||
hb-number.cc \
|
||||
|
@ -69,6 +66,11 @@ HB_BASE_sources = \
|
|||
hb-ot-cff2-table.cc \
|
||||
hb-ot-cff2-table.hh \
|
||||
hb-ot-cmap-table.hh \
|
||||
hb-ot-color-cbdt-table.hh \
|
||||
hb-ot-color-colr-table.hh \
|
||||
hb-ot-color-cpal-table.hh \
|
||||
hb-ot-color-sbix-table.hh \
|
||||
hb-ot-color-svg-table.hh \
|
||||
hb-ot-color.cc \
|
||||
hb-ot-face-table-list.hh \
|
||||
hb-ot-face.cc \
|
||||
|
@ -85,18 +87,7 @@ HB_BASE_sources = \
|
|||
hb-ot-layout-common.hh \
|
||||
hb-ot-layout-gdef-table.hh \
|
||||
hb-ot-layout-gpos-table.hh \
|
||||
hb-outline.hh \
|
||||
hb-outline.cc \
|
||||
hb-paint.cc \
|
||||
hb-paint.hh \
|
||||
hb-paint-extents.cc \
|
||||
hb-paint-extents.hh \
|
||||
hb-ot-layout-gsub-table.hh \
|
||||
OT/Color/CBDT/CBDT.hh \
|
||||
OT/Color/COLR/COLR.hh \
|
||||
OT/Color/CPAL/CPAL.hh \
|
||||
OT/Color/sbix/sbix.hh \
|
||||
OT/Color/svg/svg.hh \
|
||||
OT/glyf/glyf.hh \
|
||||
OT/glyf/glyf-helpers.hh \
|
||||
OT/glyf/loca.hh \
|
||||
|
@ -104,17 +95,13 @@ HB_BASE_sources = \
|
|||
OT/glyf/Glyph.hh \
|
||||
OT/glyf/GlyphHeader.hh \
|
||||
OT/glyf/SimpleGlyph.hh \
|
||||
OT/glyf/coord-setter.hh \
|
||||
OT/glyf/composite-iter.hh \
|
||||
OT/glyf/CompositeGlyph.hh \
|
||||
OT/glyf/VarCompositeGlyph.hh \
|
||||
OT/glyf/SubsetGlyph.hh \
|
||||
OT/Layout/types.hh \
|
||||
OT/Layout/Common/Coverage.hh \
|
||||
OT/Layout/Common/CoverageFormat1.hh \
|
||||
OT/Layout/Common/CoverageFormat2.hh \
|
||||
OT/Layout/Common/RangeRecord.hh \
|
||||
OT/Layout/GDEF/GDEF.hh \
|
||||
OT/Layout/GPOS/AnchorFormat1.hh \
|
||||
OT/Layout/GPOS/AnchorFormat2.hh \
|
||||
OT/Layout/GPOS/AnchorFormat3.hh \
|
||||
|
@ -169,7 +156,6 @@ HB_BASE_sources = \
|
|||
OT/Layout/GSUB/SingleSubst.hh \
|
||||
OT/Layout/GSUB/SubstLookup.hh \
|
||||
OT/Layout/GSUB/SubstLookupSubTable.hh \
|
||||
OT/name/name.hh \
|
||||
hb-ot-layout-gsubgpos.hh \
|
||||
hb-ot-layout-jstf-table.hh \
|
||||
hb-ot-layout.cc \
|
||||
|
@ -225,7 +211,6 @@ HB_BASE_sources = \
|
|||
hb-ot-tag.cc \
|
||||
hb-ot-var-avar-table.hh \
|
||||
hb-ot-var-common.hh \
|
||||
hb-ot-var-cvar-table.hh \
|
||||
hb-ot-var-fvar-table.hh \
|
||||
hb-ot-var-gvar-table.hh \
|
||||
hb-ot-var-hvar-table.hh \
|
||||
|
@ -261,8 +246,7 @@ HB_BASE_sources = \
|
|||
|
||||
HB_BASE_RAGEL_GENERATED_sources = \
|
||||
hb-buffer-deserialize-json.hh \
|
||||
hb-buffer-deserialize-text-glyphs.hh \
|
||||
hb-buffer-deserialize-text-unicode.hh \
|
||||
hb-buffer-deserialize-text.hh \
|
||||
hb-number-parser.hh \
|
||||
hb-ot-shaper-indic-machine.hh \
|
||||
hb-ot-shaper-khmer-machine.hh \
|
||||
|
@ -271,8 +255,7 @@ HB_BASE_RAGEL_GENERATED_sources = \
|
|||
$(NULL)
|
||||
HB_BASE_RAGEL_sources = \
|
||||
hb-buffer-deserialize-json.rl \
|
||||
hb-buffer-deserialize-text-glyphs.rl \
|
||||
hb-buffer-deserialize-text-unicode.rl \
|
||||
hb-buffer-deserialize-text.rl \
|
||||
hb-number-parser.rl \
|
||||
hb-ot-shaper-indic-machine.rl \
|
||||
hb-ot-shaper-khmer-machine.rl \
|
||||
|
@ -303,7 +286,6 @@ HB_BASE_headers = \
|
|||
hb-ot-shape.h \
|
||||
hb-ot-var.h \
|
||||
hb-ot.h \
|
||||
hb-paint.h \
|
||||
hb-set.h \
|
||||
hb-shape-plan.h \
|
||||
hb-shape.h \
|
||||
|
@ -315,7 +297,7 @@ HB_BASE_headers = \
|
|||
|
||||
# Optional Sources and Headers with external deps
|
||||
|
||||
HB_FT_sources = hb-ft.cc hb-ft-colr.hh
|
||||
HB_FT_sources = hb-ft.cc
|
||||
HB_FT_headers = hb-ft.h
|
||||
|
||||
HB_GLIB_sources = hb-glib.cc
|
||||
|
@ -348,6 +330,7 @@ HB_SUBSET_sources = \
|
|||
hb-number.hh \
|
||||
hb-ot-cff1-table.cc \
|
||||
hb-ot-cff2-table.cc \
|
||||
hb-ot-color-colrv1-closure.hh \
|
||||
hb-ot-post-table-v2subset.hh \
|
||||
hb-static.cc \
|
||||
hb-subset-cff-common.cc \
|
||||
|
@ -358,7 +341,6 @@ HB_SUBSET_sources = \
|
|||
hb-subset-cff2.hh \
|
||||
hb-subset-input.cc \
|
||||
hb-subset-input.hh \
|
||||
hb-subset-instancer-solver.cc \
|
||||
hb-subset-accelerator.hh \
|
||||
hb-subset-plan.cc \
|
||||
hb-subset-plan.hh \
|
||||
|
@ -376,7 +358,6 @@ HB_SUBSET_sources = \
|
|||
graph/markbasepos-graph.hh \
|
||||
graph/split-helpers.hh \
|
||||
graph/serialize.hh \
|
||||
OT/Color/COLR/colrv1-closure.hh \
|
||||
$(NULL)
|
||||
|
||||
HB_SUBSET_headers = \
|
||||
|
@ -384,16 +365,6 @@ HB_SUBSET_headers = \
|
|||
hb-subset-repacker.h \
|
||||
$(NULL)
|
||||
|
||||
HB_CAIRO_sources = \
|
||||
hb-cairo.cc \
|
||||
hb-cairo-utils.cc \
|
||||
hb-cairo-utils.hh \
|
||||
hb-static.cc \
|
||||
$(NULL)
|
||||
HB_CAIRO_headers = \
|
||||
hb-cairo.h \
|
||||
$(NULL)
|
||||
|
||||
HB_GOBJECT_DIST_sources = hb-gobject-structs.cc
|
||||
HB_GOBJECT_DIST_headers = hb-gobject.h hb-gobject-structs.h
|
||||
HB_GOBJECT_ENUM_sources = hb-gobject-enums.cc
|
||||
|
|
|
@ -49,7 +49,7 @@ struct Coverage
|
|||
HBUINT16 format; /* Format identifier */
|
||||
CoverageFormat1_3<SmallTypes> format1;
|
||||
CoverageFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
CoverageFormat1_3<MediumTypes>format3;
|
||||
CoverageFormat2_4<MediumTypes>format4;
|
||||
#endif
|
||||
|
@ -65,7 +65,7 @@ struct Coverage
|
|||
{
|
||||
case 1: return_trace (u.format1.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 4: return_trace (u.format4.sanitize (c));
|
||||
#endif
|
||||
|
@ -74,8 +74,10 @@ struct Coverage
|
|||
}
|
||||
|
||||
/* Has interface. */
|
||||
unsigned operator [] (hb_codepoint_t k) const { return get (k); }
|
||||
bool has (hb_codepoint_t k) const { return (*this)[k] != NOT_COVERED; }
|
||||
static constexpr unsigned SENTINEL = 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. */
|
||||
bool operator () (hb_codepoint_t k) const { return has (k); }
|
||||
|
||||
|
@ -85,7 +87,7 @@ struct Coverage
|
|||
switch (u.format) {
|
||||
case 1: return u.format1.get_coverage (glyph_id);
|
||||
case 2: return u.format2.get_coverage (glyph_id);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: return u.format3.get_coverage (glyph_id);
|
||||
case 4: return u.format4.get_coverage (glyph_id);
|
||||
#endif
|
||||
|
@ -98,7 +100,7 @@ struct Coverage
|
|||
switch (u.format) {
|
||||
case 1: return u.format1.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 4: return u.format4.get_population ();
|
||||
#endif
|
||||
|
@ -125,7 +127,7 @@ struct Coverage
|
|||
}
|
||||
u.format = count <= num_ranges * 3 ? 1 : 2;
|
||||
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
if (count && last > 0xFFFFu)
|
||||
u.format += 2;
|
||||
#endif
|
||||
|
@ -134,7 +136,7 @@ struct Coverage
|
|||
{
|
||||
case 1: return_trace (u.format1.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 4: return_trace (u.format4.serialize (c, glyphs));
|
||||
#endif
|
||||
|
@ -147,7 +149,6 @@ struct Coverage
|
|||
TRACE_SUBSET (this);
|
||||
auto it =
|
||||
+ iter ()
|
||||
| hb_take (c->plan->source->get_num_glyphs ())
|
||||
| hb_filter (c->plan->glyph_map_gsub)
|
||||
| hb_map_retains_sorting (c->plan->glyph_map_gsub)
|
||||
;
|
||||
|
@ -165,7 +166,7 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.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 4: return u.format4.intersects (glyphs);
|
||||
#endif
|
||||
|
@ -178,7 +179,7 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.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 4: return u.format4.intersects_coverage (glyphs, index);
|
||||
#endif
|
||||
|
@ -195,7 +196,7 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.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 4: return u.format4.collect_coverage (glyphs);
|
||||
#endif
|
||||
|
@ -211,7 +212,7 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
|
||||
case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
|
||||
case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
|
||||
#endif
|
||||
|
@ -224,13 +225,13 @@ struct Coverage
|
|||
static constexpr bool is_sorted_iterator = true;
|
||||
iter_t (const Coverage &c_ = Null (Coverage))
|
||||
{
|
||||
hb_memset (this, 0, sizeof (*this));
|
||||
memset (this, 0, sizeof (*this));
|
||||
format = c_.u.format;
|
||||
switch (format)
|
||||
{
|
||||
case 1: u.format1.init (c_.u.format1); return;
|
||||
case 2: u.format2.init (c_.u.format2); return;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: u.format3.init (c_.u.format3); return;
|
||||
case 4: u.format4.init (c_.u.format4); return;
|
||||
#endif
|
||||
|
@ -243,7 +244,7 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.__more__ ();
|
||||
case 2: return u.format2.__more__ ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: return u.format3.__more__ ();
|
||||
case 4: return u.format4.__more__ ();
|
||||
#endif
|
||||
|
@ -256,7 +257,7 @@ struct Coverage
|
|||
{
|
||||
case 1: u.format1.__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 4: u.format4.__next__ (); break;
|
||||
#endif
|
||||
|
@ -272,7 +273,7 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.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 4: return u.format4.get_glyph ();
|
||||
#endif
|
||||
|
@ -286,7 +287,7 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1 != o.u.format1;
|
||||
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 4: return u.format4 != o.u.format4;
|
||||
#endif
|
||||
|
@ -301,7 +302,7 @@ struct Coverage
|
|||
{
|
||||
case 1: it.u.format1 = u.format1.__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 4: it.u.format4 = u.format4.__end__ (); break;
|
||||
#endif
|
||||
|
@ -313,7 +314,7 @@ struct Coverage
|
|||
private:
|
||||
unsigned int format;
|
||||
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. */
|
||||
CoverageFormat1_3<MediumTypes>::iter_t format3;
|
||||
#endif
|
||||
|
|
|
@ -77,14 +77,7 @@ struct CoverageFormat1_3
|
|||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
|
||||
{
|
||||
for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
|
||||
if (get_coverage (g) != NOT_COVERED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO Speed up, using hb_set_next() and bsearch()? */
|
||||
for (const auto& g : glyphArray.as_array ())
|
||||
if (glyphs->has (g))
|
||||
return true;
|
||||
|
|
|
@ -80,6 +80,8 @@ struct CoverageFormat2_4
|
|||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
|
||||
/* TODO(iter) Write more efficiently? */
|
||||
|
||||
unsigned num_ranges = 0;
|
||||
hb_codepoint_t last = (hb_codepoint_t) -2;
|
||||
for (auto g: glyphs)
|
||||
|
@ -113,22 +115,26 @@ struct CoverageFormat2_4
|
|||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
|
||||
{
|
||||
for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
|
||||
if (get_coverage (g) != NOT_COVERED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return hb_any (+ hb_iter (rangeRecord)
|
||||
| hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
|
||||
}
|
||||
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||
{
|
||||
auto *range = rangeRecord.as_array ().bsearch (index);
|
||||
if (range)
|
||||
return range->intersects (*glyphs);
|
||||
auto cmp = [] (const void *pk, const void *pr) -> int
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -136,14 +142,9 @@ struct CoverageFormat2_4
|
|||
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
|
||||
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
|
||||
{
|
||||
/* Break out of loop for overlapping, broken, tables,
|
||||
* to avoid fuzzer timouts. */
|
||||
hb_codepoint_t last = 0;
|
||||
for (const auto& range : rangeRecord)
|
||||
{
|
||||
if (unlikely (range.first < last))
|
||||
break;
|
||||
last = range.last;
|
||||
hb_codepoint_t last = range.last;
|
||||
for (hb_codepoint_t g = range.first - 1;
|
||||
glyphs.next (&g) && g <= last;)
|
||||
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);
|
||||
|
||||
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 (!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;
|
||||
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 (!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 (yDeviceTable)) return_trace (false);
|
||||
|
||||
out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
|
||||
out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
|
||||
out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map);
|
||||
out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map);
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ struct CursivePos
|
|||
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);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
|
|
|
@ -143,7 +143,7 @@ struct CursivePosFormat1
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -241,7 +241,7 @@ struct CursivePosFormat1
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ struct MarkBasePos
|
|||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
MarkBasePosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
MarkBasePosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
@ -22,11 +22,11 @@ struct MarkBasePos
|
|||
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);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
|
|
|
@ -90,25 +90,6 @@ struct MarkBasePosFormat1_2
|
|||
|
||||
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
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
@ -116,54 +97,48 @@ struct MarkBasePosFormat1_2
|
|||
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
/* Now we search backwards for a non-mark glyph.
|
||||
* We don't use skippy_iter.prev() to avoid O(n^2) behavior. */
|
||||
|
||||
/* Now we search backwards for a non-mark glyph */
|
||||
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);
|
||||
|
||||
if (c->last_base_until > buffer->idx)
|
||||
{
|
||||
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)
|
||||
do {
|
||||
unsigned unsafe_from;
|
||||
if (!skippy_iter.prev (&unsafe_from))
|
||||
{
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/4124
|
||||
if (!accept (buffer, j - 1) &&
|
||||
NOT_COVERED == (this+baseCoverage).get_coverage (buffer->info[j - 1].codepoint))
|
||||
match = skippy_iter.SKIP;
|
||||
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
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 */
|
||||
//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)
|
||||
{
|
||||
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 ((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
|
||||
|
|
|
@ -13,7 +13,7 @@ struct MarkLigPos
|
|||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
MarkLigPosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
MarkLigPosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
@ -22,11 +22,11 @@ struct MarkLigPos
|
|||
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);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
|
|
|
@ -100,41 +100,24 @@ struct MarkLigPosFormat1_2
|
|||
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
/* Now we search backwards for a non-mark glyph */
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned idx = (unsigned) c->last_base;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -145,7 +128,7 @@ struct MarkLigPosFormat1_2
|
|||
unsigned int comp_count = lig_attach.rows;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -154,7 +137,7 @@ struct MarkLigPosFormat1_2
|
|||
* can directly use the component index. If not, we attach the mark
|
||||
* glyph to the last component of the ligature. */
|
||||
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_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
|
||||
if (lig_id && lig_id == mark_id && mark_comp > 0)
|
||||
|
@ -162,7 +145,7 @@ struct MarkLigPosFormat1_2
|
|||
else
|
||||
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
|
||||
|
|
|
@ -13,7 +13,7 @@ struct MarkMarkPos
|
|||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
MarkMarkPosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
MarkMarkPosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
@ -22,11 +22,11 @@ struct MarkMarkPos
|
|||
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);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
|
|
|
@ -15,7 +15,7 @@ struct PairPos
|
|||
HBUINT16 format; /* Format identifier */
|
||||
PairPosFormat1_3<SmallTypes> format1;
|
||||
PairPosFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
PairPosFormat1_3<MediumTypes> format3;
|
||||
PairPosFormat2_4<MediumTypes> format4;
|
||||
#endif
|
||||
|
@ -25,12 +25,12 @@ struct PairPos
|
|||
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);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
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)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,7 @@ struct PairPosFormat1_3
|
|||
{
|
||||
valueFormat,
|
||||
len1,
|
||||
PairSet::get_size (len1, len2)
|
||||
1 + len1 + len2
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
+ hb_zip (cov, pairSet)
|
||||
+ hb_zip (this+coverage, pairSet)
|
||||
| hb_filter (*glyphs, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| 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
|
||||
{
|
||||
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 format2 = 0;
|
||||
for (const auto & _ :
|
||||
+ hb_zip (this+coverage, pairSet)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map (hb_second)
|
||||
)
|
||||
+ hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
|
||||
{
|
||||
const PairSet& set = (this + _);
|
||||
const PairValueRecord *record = &set.firstPairValueRecord;
|
||||
|
||||
unsigned count = set.len;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
for (unsigned i = 0; i < set.len; i++)
|
||||
{
|
||||
if (record->intersects (glyphset))
|
||||
{
|
||||
|
@ -200,9 +185,6 @@ struct PairPosFormat1_3
|
|||
}
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
|
||||
if (format1 == valueFormat[0] && format2 == valueFormat[1])
|
||||
break;
|
||||
}
|
||||
|
||||
return hb_pair (format1, format2);
|
||||
|
|
|
@ -49,7 +49,7 @@ struct PairPosFormat2_4
|
|||
|
||||
unsigned int len1 = valueFormat1.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 count = (unsigned int) class1Count * (unsigned int) class2Count;
|
||||
return_trace (c->check_range ((const void *) values,
|
||||
|
@ -220,25 +220,17 @@ struct PairPosFormat2_4
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"try kerning glyphs at %u,%u",
|
||||
"kerning glyphs at %d,%d",
|
||||
c->buffer->idx, skippy_iter.idx);
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
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 ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"tried kerning glyphs at %u,%u",
|
||||
"kerned glyphs at %d,%d",
|
||||
c->buffer->idx, skippy_iter.idx);
|
||||
}
|
||||
|
||||
|
@ -249,15 +241,10 @@ struct PairPosFormat2_4
|
|||
boring:
|
||||
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;
|
||||
if (len2)
|
||||
buffer->idx++;
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
@ -298,8 +285,8 @@ struct PairPosFormat2_4
|
|||
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
|
||||
{
|
||||
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);
|
||||
valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], &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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,7 +309,6 @@ struct PairPosFormat2_4
|
|||
{
|
||||
unsigned len1 = valueFormat1.get_len ();
|
||||
unsigned len2 = valueFormat2.get_len ();
|
||||
unsigned record_size = len1 + len2;
|
||||
|
||||
unsigned format1 = 0;
|
||||
unsigned format2 = 0;
|
||||
|
@ -331,13 +317,10 @@ struct PairPosFormat2_4
|
|||
{
|
||||
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]);
|
||||
format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
|
||||
}
|
||||
|
||||
if (format1 == valueFormat1 && format2 == valueFormat2)
|
||||
break;
|
||||
}
|
||||
|
||||
return hb_pair (format1, format2);
|
||||
|
|
|
@ -24,22 +24,11 @@ struct PairSet
|
|||
public:
|
||||
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
|
||||
{
|
||||
const ValueFormat *valueFormats;
|
||||
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
|
||||
|
@ -48,6 +37,7 @@ struct PairSet
|
|||
if (!(c->check_struct (this)
|
||||
&& c->check_range (&firstPairValueRecord,
|
||||
len,
|
||||
HBUINT16::static_size,
|
||||
closure->stride))) return_trace (false);
|
||||
|
||||
unsigned int count = len;
|
||||
|
@ -59,7 +49,9 @@ struct PairSet
|
|||
bool intersects (const hb_set_t *glyphs,
|
||||
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;
|
||||
unsigned int count = len;
|
||||
|
@ -75,7 +67,9 @@ struct PairSet
|
|||
void collect_glyphs (hb_collect_glyphs_context_t *c,
|
||||
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;
|
||||
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,
|
||||
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;
|
||||
unsigned count = len;
|
||||
|
@ -105,7 +101,7 @@ struct PairSet
|
|||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int len1 = valueFormats[0].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,
|
||||
&firstPairValueRecord,
|
||||
|
@ -116,38 +112,24 @@ struct PairSet
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"try kerning glyphs at %u,%u",
|
||||
"kerning glyphs at %d,%d",
|
||||
c->buffer->idx, 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]);
|
||||
|
||||
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 ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"tried kerning glyphs at %u,%u",
|
||||
"kerned glyphs at %d,%d",
|
||||
c->buffer->idx, pos);
|
||||
}
|
||||
|
||||
if (applied_first || applied_second)
|
||||
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);
|
||||
}
|
||||
pos++;
|
||||
|
||||
buffer->idx = pos;
|
||||
return_trace (true);
|
||||
|
@ -172,7 +154,7 @@ struct PairSet
|
|||
|
||||
unsigned len1 = valueFormats[0].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 =
|
||||
{
|
||||
|
@ -181,7 +163,7 @@ struct PairSet
|
|||
newFormats,
|
||||
len1,
|
||||
&glyph_map,
|
||||
&c->plan->layout_variation_idx_delta_map
|
||||
c->plan->layout_variation_idx_delta_map
|
||||
};
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
|
|
|
@ -72,8 +72,8 @@ struct SinglePos
|
|||
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);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
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)...));
|
||||
|
|
|
@ -28,15 +28,7 @@ struct SinglePosFormat1
|
|||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (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));
|
||||
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
|
@ -71,7 +63,7 @@ struct SinglePosFormat1
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioning glyph at %u",
|
||||
"positioning glyph at %d",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -80,7 +72,7 @@ struct SinglePosFormat1
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioned glyph at %u",
|
||||
"positioned glyph at %d",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -152,7 +144,7 @@ struct SinglePosFormat1
|
|||
;
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -73,7 +73,7 @@ struct SinglePosFormat2
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioning glyph at %u",
|
||||
"positioning glyph at %d",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ struct SinglePosFormat2
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioned glyph at %u",
|
||||
"positioned glyph at %d",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ struct SinglePosFormat2
|
|||
;
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -371,7 +371,7 @@ struct ValueFormat : HBUINT16
|
|||
for (unsigned int i = 0; i < count; i++) {
|
||||
if (!sanitize_value_devices (c, base, values))
|
||||
return_trace (false);
|
||||
values = &StructAtOffset<const Value> (values, stride);
|
||||
values += stride;
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
|
|
|
@ -61,7 +61,7 @@ struct AlternateSet
|
|||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %u (alternate substitution)",
|
||||
"replacing glyph at %d (alternate substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -70,8 +70,8 @@ struct AlternateSet
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %u (alternate substitution)",
|
||||
c->buffer->idx - 1u);
|
||||
"replaced glyph at %d (alternate substitution)",
|
||||
c->buffer->idx - 1);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
|
@ -84,7 +84,7 @@ struct AlternateSet
|
|||
{
|
||||
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))
|
||||
;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ struct AlternateSubst
|
|||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
AlternateSubstFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
AlternateSubstFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
@ -23,11 +23,11 @@ struct AlternateSubst
|
|||
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);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
|
|
|
@ -29,9 +29,6 @@ struct Ligature
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ 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
|
||||
{
|
||||
if (!intersects (c->glyphs)) return;
|
||||
|
@ -72,7 +69,7 @@ struct Ligature
|
|||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %u (ligature substitution)",
|
||||
"replacing glyph at %d (ligature substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -81,8 +78,8 @@ struct Ligature
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %u (ligature substitution)",
|
||||
c->buffer->idx - 1u);
|
||||
"replaced glyph at %d (ligature substitution)",
|
||||
c->buffer->idx - 1);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
|
@ -121,7 +118,7 @@ struct Ligature
|
|||
match_positions[i] += delta;
|
||||
if (i)
|
||||
*p++ = ',';
|
||||
snprintf (p, sizeof(buf) - (p - buf), "%u", match_positions[i]);
|
||||
snprintf (p, sizeof(buf), "%u", match_positions[i]);
|
||||
p += strlen(p);
|
||||
}
|
||||
|
||||
|
@ -141,7 +138,7 @@ struct Ligature
|
|||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"ligated glyph at %u",
|
||||
"ligated glyph at %d",
|
||||
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
|
||||
{
|
||||
+ hb_iter (ligature)
|
||||
|
|
|
@ -14,7 +14,7 @@ struct LigatureSubst
|
|||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
LigatureSubstFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
LigatureSubstFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
@ -23,11 +23,11 @@ struct LigatureSubst
|
|||
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);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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)...));
|
||||
#endif
|
||||
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_filter (glyphset, hb_first)
|
||||
| hb_filter ([&] (const LigatureSet<Types>& _) {
|
||||
return _.intersects_lig_glyph (&glyphset);
|
||||
return _.intersects (&glyphset);
|
||||
}, hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_sink (new_coverage);
|
||||
|
|
|
@ -14,7 +14,7 @@ struct MultipleSubst
|
|||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
MultipleSubstFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
MultipleSubstFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
@ -24,11 +24,11 @@ struct MultipleSubst
|
|||
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);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
|
|
|
@ -20,8 +20,8 @@ struct ReverseChainSingleSubst
|
|||
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);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
|
|
|
@ -135,7 +135,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %u (reverse chaining substitution)",
|
||||
"replacing glyph at %d (reverse chaining substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %u (reverse chaining substitution)",
|
||||
"replaced glyph at %d (reverse chaining substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ struct Sequence
|
|||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %u (multiple substitution)",
|
||||
"replacing glyph at %d (multiple substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,8 @@ struct Sequence
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %u (multiple subtitution)",
|
||||
c->buffer->idx - 1u);
|
||||
"replaced glyph at %d (multiple subtitution)",
|
||||
c->buffer->idx - 1);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
|
@ -67,7 +67,7 @@ struct Sequence
|
|||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"deleting glyph at %u (multiple substitution)",
|
||||
"deleting glyph at %d (multiple substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ struct Sequence
|
|||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"deleted glyph at %u (multiple substitution)",
|
||||
"deleted glyph at %d (multiple substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ struct Sequence
|
|||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"multiplying glyph at %u",
|
||||
"multiplying glyph at %d",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ struct Sequence
|
|||
{
|
||||
if (buf < p)
|
||||
*p++ = ',';
|
||||
snprintf (p, sizeof(buf) - (p - buf), "%u", i);
|
||||
snprintf (p, sizeof(buf), "%u", i);
|
||||
p += strlen(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ struct SingleSubst
|
|||
HBUINT16 format; /* Format identifier */
|
||||
SingleSubstFormat1_3<SmallTypes> format1;
|
||||
SingleSubstFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
SingleSubstFormat1_3<MediumTypes> format3;
|
||||
SingleSubstFormat2_4<MediumTypes> format4;
|
||||
#endif
|
||||
|
@ -27,12 +27,12 @@ struct SingleSubst
|
|||
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);
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
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)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
|
@ -55,7 +55,7 @@ struct SingleSubst
|
|||
format = 1;
|
||||
hb_codepoint_t mask = 0xFFFFu;
|
||||
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
if (+ glyphs
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
| hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; }))
|
||||
|
@ -78,7 +78,7 @@ struct SingleSubst
|
|||
| hb_map_retains_sorting (hb_first),
|
||||
delta));
|
||||
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
|
||||
| hb_map_retains_sorting (hb_first),
|
||||
|
|
|
@ -25,15 +25,7 @@ struct SingleSubstFormat1_3
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (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));
|
||||
return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
|
||||
}
|
||||
|
||||
hb_codepoint_t get_mask () const
|
||||
|
@ -65,7 +57,7 @@ struct SingleSubstFormat1_3
|
|||
hb_codepoint_t max_before = intersection.get_max ();
|
||||
hb_codepoint_t min_after = (min_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 <= max_after && max_after <= max_before)))
|
||||
return;
|
||||
|
@ -95,34 +87,6 @@ struct SingleSubstFormat1_3
|
|||
bool would_apply (hb_would_apply_context_t *c) const
|
||||
{ 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
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
@ -139,7 +103,7 @@ struct SingleSubstFormat1_3
|
|||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %u (single substitution)",
|
||||
"replacing glyph at %d (single substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -148,8 +112,8 @@ struct SingleSubstFormat1_3
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %u (single substitution)",
|
||||
c->buffer->idx - 1u);
|
||||
"replaced glyph at %d (single substitution)",
|
||||
c->buffer->idx - 1);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
|
|
|
@ -36,24 +36,8 @@ struct SingleSubstFormat2_4
|
|||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
auto &cov = this+coverage;
|
||||
auto &glyph_set = c->parent_active_glyphs ();
|
||||
|
||||
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_zip (this+coverage, substitute)
|
||||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_sink (c->output)
|
||||
;
|
||||
|
@ -75,31 +59,6 @@ struct SingleSubstFormat2_4
|
|||
bool would_apply (hb_would_apply_context_t *c) const
|
||||
{ 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
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
@ -112,7 +71,7 @@ struct SingleSubstFormat2_4
|
|||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %u (single substitution)",
|
||||
"replacing glyph at %d (single substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
|
@ -121,8 +80,8 @@ struct SingleSubstFormat2_4
|
|||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %u (single substitution)",
|
||||
c->buffer->idx - 1u);
|
||||
"replaced glyph at %d (single substitution)",
|
||||
c->buffer->idx - 1);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
|
||||
#include "../../hb-open-type.hh"
|
||||
#include "composite-iter.hh"
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
@ -87,34 +86,27 @@ struct CompositeGlyphRecord
|
|||
}
|
||||
}
|
||||
|
||||
void transform_points (contour_point_vector_t &points,
|
||||
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
|
||||
void transform_points (contour_point_vector_t &points) const
|
||||
{
|
||||
float matrix[4];
|
||||
contour_point_t trans;
|
||||
get_transformation (matrix, trans);
|
||||
if (unlikely (!points.resize (points.length + 1))) return false;
|
||||
points[points.length - 1] = trans;
|
||||
return true;
|
||||
if (get_transformation (matrix, trans))
|
||||
{
|
||||
if (scaled_offsets ())
|
||||
{
|
||||
points.translate (trans);
|
||||
points.transform (matrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
points.transform (matrix);
|
||||
points.translate (trans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned compile_with_point (const contour_point_t &point,
|
||||
char *out) const
|
||||
unsigned compile_with_deltas (const contour_point_t &p_delta,
|
||||
char *out) const
|
||||
{
|
||||
const HBINT8 *p = &StructAfter<const HBINT8> (flags);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
@ -128,29 +120,30 @@ struct CompositeGlyphRecord
|
|||
unsigned len_before_val = (const char *)p - (const char *)this;
|
||||
if (flags & ARG_1_AND_2_ARE_WORDS)
|
||||
{
|
||||
// no overflow, copy value
|
||||
hb_memcpy (out, this, len);
|
||||
// no overflow, copy and update value with deltas
|
||||
memcpy (out, this, len);
|
||||
|
||||
const HBINT16 *px = reinterpret_cast<const HBINT16 *> (p);
|
||||
HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
|
||||
o[0] = roundf (point.x);
|
||||
o[1] = roundf (point.y);
|
||||
o[0] = px[0] + roundf (p_delta.x);
|
||||
o[1] = px[1] + roundf (p_delta.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
int new_x = roundf (point.x);
|
||||
int new_y = roundf (point.y);
|
||||
int new_x = p[0] + roundf (p_delta.x);
|
||||
int new_y = p[1] + roundf (p_delta.y);
|
||||
if (new_x <= 127 && new_x >= -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);
|
||||
o[0] = new_x;
|
||||
o[1] = new_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// new point value has an int8 overflow
|
||||
hb_memcpy (out, this, len_before_val);
|
||||
// int8 overflows after deltas applied
|
||||
memcpy (out, this, len_before_val);
|
||||
|
||||
//update flags
|
||||
CompositeGlyphRecord *o = reinterpret_cast<CompositeGlyphRecord *> (out);
|
||||
|
@ -159,14 +152,14 @@ struct CompositeGlyphRecord
|
|||
|
||||
HBINT16 new_value;
|
||||
new_value = new_x;
|
||||
hb_memcpy (out, &new_value, HBINT16::static_size);
|
||||
memcpy (out, &new_value, HBINT16::static_size);
|
||||
out += HBINT16::static_size;
|
||||
|
||||
new_value = new_y;
|
||||
hb_memcpy (out, &new_value, HBINT16::static_size);
|
||||
memcpy (out, &new_value, 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;
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +170,6 @@ struct CompositeGlyphRecord
|
|||
bool scaled_offsets () const
|
||||
{ return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
|
||||
|
||||
public:
|
||||
bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
|
||||
{
|
||||
matrix[0] = matrix[3] = 1.f;
|
||||
|
@ -232,6 +224,7 @@ struct CompositeGlyphRecord
|
|||
return tx || ty;
|
||||
}
|
||||
|
||||
public:
|
||||
hb_codepoint_t get_gid () const
|
||||
{
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
@ -252,27 +245,6 @@ struct CompositeGlyphRecord
|
|||
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:
|
||||
HBUINT16 flags;
|
||||
HBUINT24 pad;
|
||||
|
@ -280,7 +252,55 @@ struct CompositeGlyphRecord
|
|||
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
|
||||
{
|
||||
|
@ -331,7 +351,7 @@ struct CompositeGlyph
|
|||
}
|
||||
|
||||
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 */)
|
||||
{
|
||||
if (source_bytes.length <= GlyphHeader::static_size ||
|
||||
|
@ -346,7 +366,7 @@ struct CompositeGlyph
|
|||
/* try to allocate more memories than source glyph bytes
|
||||
* in case that there might be an overflow for int8 value
|
||||
* 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;
|
||||
|
||||
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;
|
||||
for (const auto &component : it)
|
||||
{
|
||||
/* last 4 points in points_with_deltas are phantom points and should not be included */
|
||||
if (i >= points_with_deltas.length - 4) {
|
||||
free (o);
|
||||
return false;
|
||||
}
|
||||
/* last 4 points in deltas are phantom points and should not be included */
|
||||
if (i >= deltas.length - 4) return false;
|
||||
|
||||
unsigned comp_len = component.get_size ();
|
||||
if (component.is_anchored ())
|
||||
{
|
||||
hb_memcpy (p, &component, comp_len);
|
||||
memcpy (p, &component, comp_len);
|
||||
p += comp_len;
|
||||
}
|
||||
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;
|
||||
}
|
||||
i++;
|
||||
|
@ -381,7 +398,7 @@ struct CompositeGlyph
|
|||
if (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;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
#include "GlyphHeader.hh"
|
||||
#include "SimpleGlyph.hh"
|
||||
#include "CompositeGlyph.hh"
|
||||
#include "VarCompositeGlyph.hh"
|
||||
#include "coord-setter.hh"
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
@ -29,14 +27,7 @@ enum phantom_point_index_t
|
|||
|
||||
struct Glyph
|
||||
{
|
||||
enum glyph_type_t {
|
||||
EMPTY,
|
||||
SIMPLE,
|
||||
COMPOSITE,
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
VAR_COMPOSITE,
|
||||
#endif
|
||||
};
|
||||
enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
|
||||
|
||||
public:
|
||||
composite_iter_t get_composite_iterator () const
|
||||
|
@ -44,25 +35,12 @@ struct Glyph
|
|||
if (type != COMPOSITE) return composite_iter_t ();
|
||||
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
|
||||
{
|
||||
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 SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
|
||||
case EMPTY: return bytes;
|
||||
default: return bytes;
|
||||
}
|
||||
}
|
||||
|
@ -70,72 +48,53 @@ struct Glyph
|
|||
void drop_hints ()
|
||||
{
|
||||
switch (type) {
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
case VAR_COMPOSITE: return; // No hinting
|
||||
#endif
|
||||
case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
|
||||
case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
|
||||
case EMPTY: return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
void set_overlaps_flag ()
|
||||
{
|
||||
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 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
|
||||
{
|
||||
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 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,
|
||||
int xMin, int xMax,
|
||||
int yMin, int yMax,
|
||||
int xMin, int yMax,
|
||||
const contour_point_vector_t &all_points) const
|
||||
{
|
||||
hb_codepoint_t new_gid = 0;
|
||||
if (!plan->new_gid_for_old_gid (gid, &new_gid))
|
||||
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;
|
||||
float leftSideX = all_points[len - 4].x;
|
||||
float rightSideX = all_points[len - 3].x;
|
||||
float topSideY = all_points[len - 2].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;
|
||||
int lsb = roundf (xMin - leftSideX);
|
||||
plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
|
||||
//flag value should be computed using non-empty glyphs
|
||||
if (type != EMPTY && lsb != xMin)
|
||||
plan->head_maxp_info.allXMinIsLsb = false;
|
||||
plan->hmtx_map->set (new_gid, hb_pair (hori_aw, lsb));
|
||||
|
||||
signed vert_aw = roundf (topSideY - bottomSideY);
|
||||
int vert_aw = roundf (topSideY - bottomSideY);
|
||||
if (vert_aw < 0) vert_aw = 0;
|
||||
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,
|
||||
|
@ -143,57 +102,42 @@ struct Glyph
|
|||
hb_bytes_t &dest_bytes /* OUT */) const
|
||||
{
|
||||
GlyphHeader *glyph_header = nullptr;
|
||||
if (!plan->pinned_at_default && type != EMPTY && all_points.length >= 4)
|
||||
if (type != EMPTY && all_points.length > 4)
|
||||
{
|
||||
glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
|
||||
if (unlikely (!glyph_header)) return false;
|
||||
}
|
||||
|
||||
float xMin = 0, xMax = 0;
|
||||
float yMin = 0, yMax = 0;
|
||||
int xMin = 0, xMax = 0;
|
||||
int yMin = 0, yMax = 0;
|
||||
if (all_points.length > 4)
|
||||
{
|
||||
xMin = xMax = all_points[0].x;
|
||||
yMin = yMax = all_points[0].y;
|
||||
xMin = xMax = roundf (all_points[0].x);
|
||||
yMin = yMax = roundf (all_points[0].y);
|
||||
}
|
||||
|
||||
for (unsigned i = 1; i < all_points.length - 4; i++)
|
||||
{
|
||||
float x = all_points[i].x;
|
||||
float y = all_points[i].y;
|
||||
xMin = hb_min (xMin, x);
|
||||
xMax = hb_max (xMax, x);
|
||||
yMin = hb_min (yMin, y);
|
||||
yMax = hb_max (yMax, y);
|
||||
float rounded_x = roundf (all_points[i].x);
|
||||
float rounded_y = roundf (all_points[i].y);
|
||||
xMin = hb_min (xMin, rounded_x);
|
||||
xMax = hb_max (xMax, rounded_x);
|
||||
yMin = hb_min (yMin, rounded_y);
|
||||
yMax = hb_max (yMax, rounded_y);
|
||||
}
|
||||
|
||||
update_mtx (plan, roundf (xMin), roundf (xMax), roundf (yMin), roundf (yMax), all_points);
|
||||
|
||||
int rounded_xMin = roundf (xMin);
|
||||
int rounded_xMax = roundf (xMax);
|
||||
int rounded_yMin = roundf (yMin);
|
||||
int rounded_yMax = roundf (yMax);
|
||||
update_mtx (plan, xMin, yMax, all_points);
|
||||
|
||||
if (type != EMPTY)
|
||||
{
|
||||
plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, rounded_xMin);
|
||||
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 */
|
||||
/*for empty glyphs: all_points only include phantom points.
|
||||
*just update metrics and then return */
|
||||
if (!glyph_header)
|
||||
return true;
|
||||
|
||||
glyph_header->numberOfContours = header->numberOfContours;
|
||||
|
||||
glyph_header->xMin = rounded_xMin;
|
||||
glyph_header->yMin = rounded_yMin;
|
||||
glyph_header->xMax = rounded_xMax;
|
||||
glyph_header->yMax = rounded_yMax;
|
||||
glyph_header->xMin = xMin;
|
||||
glyph_header->yMin = yMin;
|
||||
glyph_header->xMax = xMax;
|
||||
glyph_header->yMax = yMax;
|
||||
|
||||
dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size);
|
||||
return true;
|
||||
|
@ -205,64 +149,35 @@ struct Glyph
|
|||
hb_bytes_t &dest_start, /* IN/OUT */
|
||||
hb_bytes_t &dest_end /* OUT */)
|
||||
{
|
||||
contour_point_vector_t all_points, points_with_deltas;
|
||||
unsigned composite_contours = 0;
|
||||
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)
|
||||
// also ignore .notdef glyph when --notdef-outline is not enabled
|
||||
if (type == EMPTY ||
|
||||
(gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)))
|
||||
{
|
||||
head_maxp_info_p = nullptr;
|
||||
composite_contours_p = nullptr;
|
||||
}
|
||||
|
||||
if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
|
||||
contour_point_vector_t all_points, deltas;
|
||||
if (!get_points (font, glyf, all_points, &deltas, false, false))
|
||||
return false;
|
||||
|
||||
// .notdef, set type to empty so we only update metrics and don't compile bytes for
|
||||
// it
|
||||
if (gid == 0 &&
|
||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||
{
|
||||
type = EMPTY;
|
||||
|
||||
switch (type) {
|
||||
case COMPOSITE:
|
||||
if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
|
||||
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;
|
||||
default:
|
||||
/* set empty bytes for empty glyph
|
||||
* do not use source glyph's pointers */
|
||||
dest_start = hb_bytes_t ();
|
||||
dest_end = hb_bytes_t ();
|
||||
}
|
||||
|
||||
//dont compile bytes when pinned at default, just recalculate bounds
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!compile_header_bytes (plan, all_points, dest_start))
|
||||
|
@ -280,69 +195,40 @@ struct Glyph
|
|||
template <typename accelerator_t>
|
||||
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
||||
contour_point_vector_t &all_points /* OUT */,
|
||||
contour_point_vector_t *points_with_deltas = nullptr, /* OUT */
|
||||
head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
|
||||
unsigned *composite_contours = nullptr, /* OUT */
|
||||
contour_point_vector_t *deltas = nullptr, /* OUT */
|
||||
bool shift_points_hori = true,
|
||||
bool use_my_metrics = true,
|
||||
bool phantom_only = false,
|
||||
hb_array_t<int> coords = hb_array_t<int> (),
|
||||
unsigned int depth = 0,
|
||||
unsigned *edge_count = nullptr) const
|
||||
unsigned int depth = 0) const
|
||||
{
|
||||
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;
|
||||
bool inplace = type == SIMPLE && all_points.length == 0;
|
||||
/* Load into all_points if it's empty, as an optimization. */
|
||||
contour_point_vector_t &points = inplace ? all_points : stack_points;
|
||||
|
||||
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:
|
||||
{
|
||||
for (auto &item : get_composite_iterator ())
|
||||
if (unlikely (!item.get_points (points))) return false;
|
||||
/* pseudo component points for each component in composite glyph */
|
||||
unsigned num_points = hb_len (CompositeGlyph (*header, bytes).iter ());
|
||||
if (unlikely (!points.resize (num_points))) return false;
|
||||
break;
|
||||
}
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
case VAR_COMPOSITE:
|
||||
{
|
||||
for (auto &item : get_var_composite_iterator ())
|
||||
if (unlikely (!item.get_points (points))) return false;
|
||||
}
|
||||
#endif
|
||||
case EMPTY:
|
||||
case SIMPLE:
|
||||
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Init phantom points */
|
||||
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 h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
|
||||
(int) header->xMin - lsb : 0;
|
||||
HB_UNUSED int tsb = 0;
|
||||
int tsb = 0;
|
||||
int v_orig = (int) header->yMax +
|
||||
#ifndef HB_NO_VERTICAL
|
||||
((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb)
|
||||
|
@ -359,29 +245,34 @@ struct Glyph
|
|||
#endif
|
||||
;
|
||||
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_BOTTOM].y = v_orig - (int) v_adv;
|
||||
}
|
||||
|
||||
if (deltas != nullptr && depth == 0 && type == COMPOSITE)
|
||||
{
|
||||
if (unlikely (!deltas->resize (points.length))) return false;
|
||||
deltas->copy_vector (points);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
glyf_accelerator.gvar->apply_deltas_to_points (gid,
|
||||
coords,
|
||||
points.as_array ());
|
||||
glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
|
||||
#endif
|
||||
|
||||
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
|
||||
// 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;
|
||||
points_with_deltas->copy_vector (points);
|
||||
for (unsigned i = 0 ; i < points.length; i++)
|
||||
{
|
||||
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) {
|
||||
case SIMPLE:
|
||||
if (depth == 0 && head_maxp_info)
|
||||
head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, points.length - 4);
|
||||
if (!inplace)
|
||||
all_points.extend (points.as_array ());
|
||||
break;
|
||||
|
@ -393,31 +284,15 @@ struct Glyph
|
|||
{
|
||||
comp_points.reset ();
|
||||
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
||||
.get_points (font,
|
||||
glyf_accelerator,
|
||||
comp_points,
|
||||
points_with_deltas,
|
||||
head_maxp_info,
|
||||
composite_contours,
|
||||
shift_points_hori,
|
||||
use_my_metrics,
|
||||
phantom_only,
|
||||
coords,
|
||||
depth + 1,
|
||||
edge_count)))
|
||||
.get_points (font, glyf_accelerator, comp_points,
|
||||
deltas, shift_points_hori, use_my_metrics, phantom_only, depth + 1)))
|
||||
return false;
|
||||
|
||||
/* 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];
|
||||
/* Apply component transformation & translation */
|
||||
item.transform_points (comp_points);
|
||||
|
||||
float matrix[4];
|
||||
contour_point_t default_trans;
|
||||
item.get_transformation (matrix, default_trans);
|
||||
|
||||
/* Apply component transformation & translation (with deltas applied) */
|
||||
item.transform_points (comp_points, matrix, points[comp_index]);
|
||||
/* Apply translation from gvar */
|
||||
comp_points.translate (points[comp_index]);
|
||||
|
||||
if (item.is_anchored ())
|
||||
{
|
||||
|
@ -433,77 +308,20 @@ struct Glyph
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
} break;
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
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));
|
||||
all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
|
||||
|
||||
if (all_points.length > HB_GLYF_MAX_POINTS)
|
||||
return false;
|
||||
|
||||
points_left += item.get_num_points ();
|
||||
comp_index++;
|
||||
}
|
||||
|
||||
all_points.extend (phantoms);
|
||||
} break;
|
||||
#endif
|
||||
case EMPTY:
|
||||
default:
|
||||
all_points.extend (phantoms);
|
||||
break;
|
||||
}
|
||||
|
||||
if (depth == 0 && shift_points_hori) /* Apply at top level */
|
||||
|
@ -527,8 +345,6 @@ struct Glyph
|
|||
}
|
||||
|
||||
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 (),
|
||||
header (bytes.as<GlyphHeader> ()),
|
||||
|
@ -544,9 +360,6 @@ struct Glyph
|
|||
int num_contours = header->numberOfContours;
|
||||
if (unlikely (num_contours == 0)) type = EMPTY;
|
||||
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 */
|
||||
}
|
||||
|
||||
|
@ -554,7 +367,7 @@ struct Glyph
|
|||
hb_bytes_t bytes;
|
||||
const GlyphHeader *header;
|
||||
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); */
|
||||
int lsb = hb_min (xMin, xMax);
|
||||
(void) glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb);
|
||||
extents->x_bearing = lsb;
|
||||
extents->y_bearing = hb_max (yMin, yMax);
|
||||
extents->width = hb_max (xMin, xMax) - hb_min (xMin, xMax);
|
||||
extents->height = hb_min (yMin, yMax) - hb_max (yMin, yMax);
|
||||
|
||||
font->scale_glyph_extents (extents);
|
||||
extents->x_bearing = font->em_scale_x (lsb);
|
||||
extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax));
|
||||
extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax));
|
||||
extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ struct SimpleGlyph
|
|||
FLAG_X_SAME = 0x10,
|
||||
FLAG_Y_SAME = 0x20,
|
||||
FLAG_OVERLAP_SIMPLE = 0x40,
|
||||
FLAG_CUBIC = 0x80
|
||||
FLAG_RESERVED2 = 0x80
|
||||
};
|
||||
|
||||
const GlyphHeader &header;
|
||||
|
@ -34,11 +34,6 @@ struct SimpleGlyph
|
|||
unsigned int length (unsigned int instruction_len) const
|
||||
{ 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 instruction_length_offset = instruction_len_offset ();
|
||||
|
@ -99,7 +94,6 @@ struct SimpleGlyph
|
|||
/* zero instruction length */
|
||||
void drop_hints ()
|
||||
{
|
||||
if (!has_instructions_length ()) return;
|
||||
GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
|
||||
(HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
|
||||
}
|
||||
|
@ -138,8 +132,8 @@ struct SimpleGlyph
|
|||
if (unlikely (p + 1 > end)) return false;
|
||||
unsigned int repeat_count = *p++;
|
||||
unsigned stop = hb_min (i + repeat_count, count);
|
||||
for (; i < stop; i++)
|
||||
points_.arrayZ[i].flag = flag;
|
||||
for (; i < stop;)
|
||||
points_.arrayZ[i++].flag = flag;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -190,7 +184,7 @@ struct SimpleGlyph
|
|||
if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours]))) return false;
|
||||
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 (phantom_only) return true;
|
||||
|
||||
|
@ -229,34 +223,33 @@ struct SimpleGlyph
|
|||
if (value > 0) flag |= same_flag;
|
||||
else value = -value;
|
||||
|
||||
coords.arrayZ[coords.length++] = (uint8_t) value;
|
||||
coords.push ((uint8_t)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t val = value;
|
||||
coords.arrayZ[coords.length++] = val >> 8;
|
||||
coords.arrayZ[coords.length++] = val & 0xff;
|
||||
coords.push (val >> 8);
|
||||
coords.push (val & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
static void encode_flag (uint8_t &flag,
|
||||
uint8_t &repeat,
|
||||
uint8_t lastflag,
|
||||
uint8_t &lastflag,
|
||||
hb_vector_t<uint8_t> &flags /* OUT */)
|
||||
{
|
||||
if (flag == lastflag && repeat != 255)
|
||||
{
|
||||
repeat++;
|
||||
repeat = repeat + 1;
|
||||
if (repeat == 1)
|
||||
{
|
||||
/* We know there's room. */
|
||||
flags.arrayZ[flags.length++] = flag;
|
||||
flags.push(flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned len = flags.length;
|
||||
flags.arrayZ[len-2] = flag | FLAG_REPEAT;
|
||||
flags.arrayZ[len-1] = repeat;
|
||||
flags[len-2] = flag | FLAG_REPEAT;
|
||||
flags[len-1] = repeat;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -264,6 +257,7 @@ struct SimpleGlyph
|
|||
repeat = 0;
|
||||
flags.push (flag);
|
||||
}
|
||||
lastflag = flag;
|
||||
}
|
||||
|
||||
bool compile_bytes_with_deltas (const contour_point_vector_t &all_points,
|
||||
|
@ -275,30 +269,31 @@ struct SimpleGlyph
|
|||
dest_bytes = hb_bytes_t ();
|
||||
return true;
|
||||
}
|
||||
//convert absolute values to relative values
|
||||
unsigned num_points = all_points.length - 4;
|
||||
|
||||
hb_vector_t<uint8_t> flags, x_coords, y_coords;
|
||||
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;
|
||||
if (unlikely (!flags.alloc (num_points))) return false;
|
||||
if (unlikely (!x_coords.alloc (2*num_points))) return false;
|
||||
if (unlikely (!y_coords.alloc (2*num_points))) return false;
|
||||
|
||||
uint8_t lastflag = 0, repeat = 0;
|
||||
int prev_x = 0.f, prev_y = 0.f;
|
||||
|
||||
for (unsigned i = 0; i < num_points; i++)
|
||||
{
|
||||
uint8_t flag = all_points.arrayZ[i].flag;
|
||||
uint8_t flag = all_points[i].flag;
|
||||
flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE;
|
||||
|
||||
int cur_x = roundf (all_points.arrayZ[i].x);
|
||||
int cur_y = roundf (all_points.arrayZ[i].y);
|
||||
float cur_x = roundf (all_points[i].x);
|
||||
float cur_y = roundf (all_points[i].y);
|
||||
encode_coord (cur_x - prev_x, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
|
||||
encode_coord (cur_y - prev_y, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
|
||||
if (i == 0) lastflag = flag + 1; //make lastflag != flag for the first point
|
||||
encode_flag (flag, repeat, lastflag, flags);
|
||||
|
||||
prev_x = cur_x;
|
||||
prev_y = cur_y;
|
||||
lastflag = flag;
|
||||
}
|
||||
|
||||
unsigned len_before_instrs = 2 * header.numberOfContours + 2;
|
||||
|
@ -308,29 +303,29 @@ struct SimpleGlyph
|
|||
if (!no_hinting)
|
||||
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;
|
||||
|
||||
const char *src = bytes.arrayZ + GlyphHeader::static_size;
|
||||
char *cur = p;
|
||||
hb_memcpy (p, src, len_before_instrs);
|
||||
memcpy (p, src, len_before_instrs);
|
||||
|
||||
cur += len_before_instrs;
|
||||
src += len_before_instrs;
|
||||
|
||||
if (!no_hinting)
|
||||
{
|
||||
hb_memcpy (cur, src, len_instrs);
|
||||
memcpy (cur, src, len_instrs);
|
||||
cur += len_instrs;
|
||||
}
|
||||
|
||||
hb_memcpy (cur, flags.arrayZ, flags.length);
|
||||
memcpy (cur, flags.arrayZ, 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;
|
||||
|
||||
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);
|
||||
return true;
|
||||
|
|
|
@ -18,23 +18,17 @@ struct SubsetGlyph
|
|||
Glyph source_glyph;
|
||||
hb_bytes_t dest_start; /* region of source_glyph to copy first */
|
||||
hb_bytes_t dest_end; /* region of source_glyph to copy second */
|
||||
bool allocated;
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
bool use_short_loca,
|
||||
const hb_subset_plan_t *plan)
|
||||
const hb_subset_plan_t *plan) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
hb_bytes_t dest_glyph = dest_start.copy (c);
|
||||
hb_bytes_t end_copy = dest_end.copy (c);
|
||||
if (!end_copy.arrayZ || !dest_glyph.arrayZ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + end_copy.length);
|
||||
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
|
||||
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;
|
||||
pad = 0;
|
||||
|
@ -46,68 +40,13 @@ struct SubsetGlyph
|
|||
|
||||
if (unlikely (!dest_glyph.length)) return_trace (true);
|
||||
|
||||
/* update components gids. */
|
||||
/* update components gids */
|
||||
for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
|
||||
{
|
||||
hb_codepoint_t new_gid;
|
||||
if (plan->new_gid_for_old_gid (_.get_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)
|
||||
Glyph (dest_glyph).drop_hints ();
|
||||
|
@ -121,18 +60,12 @@ struct SubsetGlyph
|
|||
bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
const glyf_accelerator_t &glyf)
|
||||
{
|
||||
allocated = source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end);
|
||||
return allocated;
|
||||
}
|
||||
{ return source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end); }
|
||||
|
||||
void free_compiled_bytes ()
|
||||
{
|
||||
if (likely (allocated)) {
|
||||
allocated = false;
|
||||
dest_start.fini ();
|
||||
dest_end.fini ();
|
||||
}
|
||||
dest_start.fini ();
|
||||
dest_end.fini ();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
})
|
||||
| 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_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);
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
if (use_short_loca)
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "../../hb-ot-hmtx-table.hh"
|
||||
#include "../../hb-ot-var-gvar-table.hh"
|
||||
#include "../../hb-draw.hh"
|
||||
#include "../../hb-paint.hh"
|
||||
|
||||
#include "glyf-helpers.hh"
|
||||
#include "Glyph.hh"
|
||||
|
@ -31,12 +30,6 @@ struct 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
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -52,11 +45,8 @@ struct glyf
|
|||
const hb_subset_plan_t *plan)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
unsigned init_len = c->length ();
|
||||
for (auto &_ : it)
|
||||
if (unlikely (!_.serialize (c, use_short_loca, plan)))
|
||||
return false;
|
||||
for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
|
||||
|
||||
/* 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
|
||||
|
@ -78,82 +68,56 @@ struct glyf
|
|||
{
|
||||
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> ();
|
||||
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;
|
||||
if (!_populate_subset_glyphs (c->plan, font, glyphs))
|
||||
_populate_subset_glyphs (c->plan, glyphs);
|
||||
|
||||
if (!c->plan->pinned_at_default)
|
||||
{
|
||||
hb_font_destroy (font);
|
||||
return false;
|
||||
if (!_compile_subset_glyphs_with_deltas (c->plan, &glyphs))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
if (font)
|
||||
hb_font_destroy (font);
|
||||
auto padded_offsets =
|
||||
+ hb_iter (glyphs)
|
||||
| hb_map (&glyf_impl::SubsetGlyph::padded_size)
|
||||
;
|
||||
|
||||
unsigned max_offset = 0;
|
||||
for (unsigned i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
padded_offsets[i] = glyphs[i].padded_size ();
|
||||
max_offset += padded_offsets[i];
|
||||
}
|
||||
unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
|
||||
bool use_short_loca = max_offset < 0x1FFFF;
|
||||
|
||||
bool use_short_loca = false;
|
||||
if (likely (!c->plan->force_long_loca))
|
||||
use_short_loca = max_offset < 0x1FFFF;
|
||||
|
||||
glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
|
||||
if (!use_short_loca) {
|
||||
for (unsigned i = 0; i < num_glyphs; i++)
|
||||
padded_offsets[i] = glyphs[i].length ();
|
||||
padded_offsets =
|
||||
+ 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);
|
||||
|
||||
return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan,
|
||||
padded_offsets.iter (),
|
||||
padded_offsets,
|
||||
use_short_loca)));
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const;
|
||||
|
||||
hb_font_t *
|
||||
_create_font_for_instancing (const hb_subset_plan_t *plan) const;
|
||||
bool
|
||||
_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
|
||||
|
||||
void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs) const
|
||||
void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> *glyphs) const
|
||||
{
|
||||
for (unsigned i = 0; i < glyphs.length; i++)
|
||||
glyphs[i].free_compiled_bytes ();
|
||||
for (auto _ : *glyphs)
|
||||
_.free_compiled_bytes ();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -181,7 +145,7 @@ struct glyf_accelerator_t
|
|||
vmtx = nullptr;
|
||||
#endif
|
||||
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. */
|
||||
return;
|
||||
short_offset = 0 == head.indexToLocFormat;
|
||||
|
@ -219,7 +183,7 @@ struct glyf_accelerator_t
|
|||
contour_point_vector_t all_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, true, phantom_only)))
|
||||
return false;
|
||||
|
||||
if (consumer.is_consuming_contour_points ())
|
||||
|
@ -241,8 +205,6 @@ struct glyf_accelerator_t
|
|||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
struct points_aggregator_t
|
||||
{
|
||||
|
@ -275,14 +237,19 @@ struct glyf_accelerator_t
|
|||
extents->y_bearing = 0;
|
||||
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->width = roundf (max_x - extents->x_bearing);
|
||||
extents->y_bearing = roundf (max_y);
|
||||
extents->height = roundf (min_y - extents->y_bearing);
|
||||
|
||||
if (scaled)
|
||||
font->scale_glyph_extents (extents);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,6 +273,7 @@ struct glyf_accelerator_t
|
|||
contour_point_t *get_phantoms_sink () { return phantoms; }
|
||||
};
|
||||
|
||||
public:
|
||||
unsigned
|
||||
get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
|
||||
{
|
||||
|
@ -347,15 +315,6 @@ struct glyf_accelerator_t
|
|||
}
|
||||
#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:
|
||||
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
|
||||
{
|
||||
|
@ -368,15 +327,6 @@ struct glyf_accelerator_t
|
|||
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
|
||||
glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
|
||||
{
|
||||
|
@ -425,14 +375,13 @@ struct glyf_accelerator_t
|
|||
};
|
||||
|
||||
|
||||
inline bool
|
||||
inline void
|
||||
glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const
|
||||
{
|
||||
OT::glyf_accelerator_t glyf (plan->source);
|
||||
unsigned num_glyphs = plan->num_output_glyphs ();
|
||||
if (!glyphs.resize (num_glyphs)) return false;
|
||||
if (!glyphs.resize (num_glyphs)) return;
|
||||
|
||||
for (auto p : plan->glyph_map->iter ())
|
||||
{
|
||||
|
@ -442,48 +391,31 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
|||
|
||||
if (unlikely (new_gid == 0 &&
|
||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) &&
|
||||
!plan->normalized_coords)
|
||||
plan->pinned_at_default)
|
||||
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);
|
||||
}
|
||||
subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
|
||||
|
||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
subset_glyph.drop_hints_bytes ();
|
||||
else
|
||||
subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
|
||||
|
||||
if (font)
|
||||
{
|
||||
if (unlikely (!subset_glyph.compile_bytes_with_deltas (plan, font, glyf)))
|
||||
{
|
||||
// when pinned at default, only bounds are updated, thus no need to free
|
||||
if (!plan->pinned_at_default)
|
||||
_free_compiled_subset_glyphs (glyphs);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline hb_font_t *
|
||||
glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
|
||||
inline bool
|
||||
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);
|
||||
if (unlikely (font == hb_font_get_empty ())) return nullptr;
|
||||
if (unlikely (!font)) return false;
|
||||
|
||||
hb_vector_t<hb_variation_t> vars;
|
||||
if (unlikely (!vars.alloc (plan->user_axes_location.get_population (), true)))
|
||||
{
|
||||
hb_font_destroy (font);
|
||||
return nullptr;
|
||||
}
|
||||
if (unlikely (!vars.alloc (plan->user_axes_location->get_population ())))
|
||||
return false;
|
||||
|
||||
for (auto _ : plan->user_axes_location)
|
||||
for (auto _ : *plan->user_axes_location)
|
||||
{
|
||||
hb_variation_t var;
|
||||
var.tag = _.first;
|
||||
|
@ -491,10 +423,18 @@ glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
|
|||
vars.push (var);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ());
|
||||
#endif
|
||||
return font;
|
||||
hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
|
||||
for (auto& subset_glyph : *glyphs)
|
||||
{
|
||||
if (!const_cast<glyf_impl::SubsetGlyph &> (subset_glyph).compile_bytes_with_deltas (plan, font, glyf))
|
||||
{
|
||||
hb_font_destroy (font);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
hb_font_destroy (font);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,29 +26,22 @@ struct path_builder_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)); }
|
||||
} 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_)
|
||||
{
|
||||
font = font_;
|
||||
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
|
||||
See also:
|
||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
|
||||
* https://stackoverflow.com/a/20772557
|
||||
*
|
||||
* Cubic support added. */
|
||||
* https://stackoverflow.com/a/20772557 */
|
||||
void consume_point (const contour_point_t &point)
|
||||
{
|
||||
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));
|
||||
if (!first_oncurve)
|
||||
{
|
||||
|
@ -59,12 +52,7 @@ struct path_builder_t
|
|||
}
|
||||
else
|
||||
{
|
||||
if (is_cubic && !first_offcurve2)
|
||||
{
|
||||
first_offcurve2 = first_offcurve;
|
||||
first_offcurve = p;
|
||||
}
|
||||
else if (first_offcurve)
|
||||
if (first_offcurve)
|
||||
{
|
||||
optional_point_t mid = first_offcurve.lerp (p, .5f);
|
||||
first_oncurve = mid;
|
||||
|
@ -81,41 +69,16 @@ struct path_builder_t
|
|||
{
|
||||
if (is_on_curve)
|
||||
{
|
||||
if (last_offcurve2)
|
||||
{
|
||||
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);
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
p.x, p.y);
|
||||
last_offcurve = optional_point_t ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_cubic && !last_offcurve2)
|
||||
{
|
||||
last_offcurve2 = last_offcurve;
|
||||
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;
|
||||
}
|
||||
optional_point_t mid = last_offcurve.lerp (p, .5f);
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
last_offcurve = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -131,40 +94,19 @@ struct path_builder_t
|
|||
{
|
||||
if (first_offcurve && last_offcurve)
|
||||
{
|
||||
optional_point_t mid = last_offcurve.lerp (first_offcurve2 ?
|
||||
first_offcurve2 :
|
||||
first_offcurve, .5f);
|
||||
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);
|
||||
optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
last_offcurve = optional_point_t ();
|
||||
/* now check the rest */
|
||||
}
|
||||
/* now check the rest */
|
||||
|
||||
if (first_offcurve && first_oncurve)
|
||||
{
|
||||
if (first_offcurve2)
|
||||
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);
|
||||
}
|
||||
draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
else if (last_offcurve && first_oncurve)
|
||||
{
|
||||
if (last_offcurve2)
|
||||
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);
|
||||
}
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
else if (first_oncurve)
|
||||
draw_session->line_to (first_oncurve.x, first_oncurve.y);
|
||||
else if (first_offcurve)
|
||||
|
@ -175,7 +117,7 @@ struct path_builder_t
|
|||
}
|
||||
|
||||
/* 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 ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
# 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']:
|
||||
so = os.path.join (libs, 'lib%s.%s' % (soname, suffix))
|
||||
if not os.path.exists (so): continue
|
||||
|
|
|
@ -22,7 +22,7 @@ cxxfilt = shutil.which ('c++filt')
|
|||
tested = False
|
||||
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']:
|
||||
so = os.path.join (builddir, libs, 'lib%s.%s' % (soname, suffix))
|
||||
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 ''
|
||||
|
||||
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)]
|
||||
|
||||
# run again c++filt also if is available
|
||||
|
|
|
@ -19,9 +19,10 @@ symbols = sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re
|
|||
if '--experimental-api' not in sys.argv:
|
||||
# Move these to harfbuzz-sections.txt when got stable
|
||||
experimental_symbols = \
|
||||
"""hb_shape_justify
|
||||
hb_subset_repack_or_fail
|
||||
hb_subset_input_override_name_table
|
||||
"""hb_subset_repack_or_fail
|
||||
hb_subset_input_pin_axis_location
|
||||
hb_subset_input_pin_axis_to_default
|
||||
hb_subset_preprocess
|
||||
""".splitlines ()
|
||||
symbols = [x for x in symbols if x not in experimental_symbols]
|
||||
symbols = "\n".join (symbols)
|
||||
|
|
|
@ -95,7 +95,6 @@ categories = {
|
|||
'PLACEHOLDER',
|
||||
'DOTTEDCIRCLE',
|
||||
'RS',
|
||||
'MPst',
|
||||
'Repha',
|
||||
'Ra',
|
||||
'CM',
|
||||
|
@ -169,6 +168,8 @@ category_map = {
|
|||
'Vowel' : 'V',
|
||||
'Vowel_Dependent' : 'M',
|
||||
'Vowel_Independent' : 'V',
|
||||
'Dotted_Circle' : 'DOTTEDCIRCLE', # Ours, not Unicode's
|
||||
'Ra' : 'Ra', # Ours, not Unicode's
|
||||
}
|
||||
position_map = {
|
||||
'Not_Applicable' : 'END',
|
||||
|
@ -239,9 +240,6 @@ category_overrides = {
|
|||
0x0953: '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.
|
||||
0x0A72: '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])
|
||||
|
||||
# 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():
|
||||
if cat not in positioned_categories:
|
||||
pos = 'END'
|
||||
|
@ -452,12 +450,11 @@ for k, (cat, pos, block) in indic_data.items():
|
|||
|
||||
# Keep in sync with CONSONANT_FLAGS in the shaper
|
||||
consonant_categories = ('C', 'CS', 'Ra','CM', 'V', 'PLACEHOLDER', 'DOTTEDCIRCLE')
|
||||
matra_categories = ('M', 'MPst')
|
||||
smvd_categories = ('SM', 'VD', 'A', 'Symbol')
|
||||
for k, (cat, pos, block) in indic_data.items():
|
||||
if cat in consonant_categories:
|
||||
pos = 'BASE_C'
|
||||
elif cat in matra_categories:
|
||||
elif cat == 'M':
|
||||
if block.startswith('Khmer') or block.startswith('Myanmar'):
|
||||
cat = position_to_category(pos)
|
||||
else:
|
||||
|
@ -637,7 +634,7 @@ for u in uu:
|
|||
end = (end-1)//8*8 + 7
|
||||
|
||||
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)
|
||||
else:
|
||||
if last >= 0:
|
||||
|
@ -694,6 +691,6 @@ print ('#endif')
|
|||
print ()
|
||||
print ("/* == End of generated table == */")
|
||||
|
||||
# Maintain at least 50% occupancy in the table */
|
||||
if occupancy < 50:
|
||||
# Maintain at least 30% occupancy in the table */
|
||||
if occupancy < 30:
|
||||
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...')
|
||||
|
||||
|
||||
# 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]
|
||||
ccc = [int(u['ccc']) for u in ucd]
|
||||
bmg = [int(v, 16) - int(u) if v else 0 for u,v in enumerate(u['bmg'] for u in ucd)]
|
||||
#gc_ccc_non0 = set((cat,klass) for cat,klass in zip(gc,ccc) if klass)
|
||||
#gc_bmg_non0 = set((cat,mirr) for cat,mirr in zip(gc, bmg) if mirr)
|
||||
|
||||
sc = [u['sc'] for u in ucd]
|
||||
|
||||
|
||||
# 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)
|
||||
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'}
|
||||
|
@ -77,9 +63,6 @@ dm_order = {None: 0}
|
|||
dm_order.update(dm1_order)
|
||||
dm_order.update(dm2_order)
|
||||
|
||||
|
||||
# Prepare General_Category / Script mapping arrays
|
||||
|
||||
gc_order = dict()
|
||||
for i,v in enumerate(('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu',
|
||||
'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf',
|
||||
|
@ -100,18 +83,10 @@ for line in open(hb_common_h):
|
|||
sc_order[i] = tag
|
||||
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...')
|
||||
print("/* == Start of generated table == */")
|
||||
|
@ -129,9 +104,6 @@ print()
|
|||
print('#include "hb.hh"')
|
||||
print()
|
||||
|
||||
|
||||
# Write mapping data
|
||||
|
||||
code = packTab.Code('_hb_ucd')
|
||||
sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array)
|
||||
dm1_p0_array, _ = code.addArray('uint16_t', 'dm1_p0_map', dm1_p0_array)
|
||||
|
@ -148,24 +120,18 @@ datasets = [
|
|||
('dm', dm, None, dm_order),
|
||||
]
|
||||
|
||||
|
||||
# Write main data
|
||||
|
||||
for step in (DEFAULT, COMPACT, SLOPPY):
|
||||
compression = compression_level[step]
|
||||
for compression in (DEFAULT, COMPACT, SLOPPY):
|
||||
logging.info(' Compression=%d:' % compression)
|
||||
print()
|
||||
if step == DEFAULT:
|
||||
if compression == DEFAULT:
|
||||
print('#ifndef HB_OPTIMIZE_SIZE')
|
||||
elif step == COMPACT:
|
||||
elif compression == COMPACT:
|
||||
print('#elif !defined(HB_NO_UCD_UNASSIGNED)')
|
||||
elif step == SLOPPY:
|
||||
print('#else')
|
||||
else:
|
||||
assert False
|
||||
print('#else')
|
||||
print()
|
||||
|
||||
if step == SLOPPY:
|
||||
if compression == SLOPPY:
|
||||
for i in range(len(gc)):
|
||||
if (i % 128) and gc[i] == 'Cn':
|
||||
gc[i] = gc[i - 1]
|
||||
|
@ -191,7 +157,6 @@ for step in (DEFAULT, COMPACT, SLOPPY):
|
|||
|
||||
print()
|
||||
|
||||
|
||||
print('#endif')
|
||||
print()
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# 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
|
||||
|
||||
Input files:
|
||||
|
@ -468,29 +465,10 @@ print ("")
|
|||
|
||||
import packTab
|
||||
data = {u:v[0] for u,v in use_data.items()}
|
||||
|
||||
DEFAULT = 5
|
||||
COMPACT = 9
|
||||
for compression in (DEFAULT, COMPACT):
|
||||
|
||||
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')
|
||||
code = packTab.Code('hb_use')
|
||||
sol = packTab.pack_table(data, compression=5, default='O')
|
||||
sol.genCode(code, f'get_category')
|
||||
code.print_c(linkage='static inline')
|
||||
|
||||
print ()
|
||||
for k in sorted(use_mapping.keys()):
|
||||
|
|
|
@ -112,7 +112,7 @@ struct ClassDef : public OT::ClassDef
|
|||
{
|
||||
case 1: return ((ClassDefFormat1*)this)->sanitize (vertex);
|
||||
case 2: return ((ClassDefFormat2*)this)->sanitize (vertex);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
// Not currently supported
|
||||
case 3:
|
||||
case 4:
|
||||
|
|
|
@ -136,7 +136,7 @@ struct Coverage : public OT::Layout::Common::Coverage
|
|||
{
|
||||
case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
|
||||
case 2: return ((CoverageFormat2*)this)->sanitize (vertex);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
// Not currently supported
|
||||
case 3:
|
||||
case 4:
|
||||
|
|
|
@ -49,50 +49,6 @@ struct graph_t
|
|||
unsigned end = 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 ()
|
||||
{
|
||||
obj.real_links.qsort ();
|
||||
|
@ -123,7 +79,7 @@ struct graph_t
|
|||
while (a || b)
|
||||
{
|
||||
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++;
|
||||
b++;
|
||||
}
|
||||
|
@ -176,7 +132,7 @@ struct graph_t
|
|||
for (unsigned i = 0; i < parents.length; i++)
|
||||
{
|
||||
if (parents[i] != parent_index) continue;
|
||||
parents.remove_unordered (i);
|
||||
parents.remove (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +148,7 @@ struct graph_t
|
|||
if ((obj.head + link.position) != offset)
|
||||
continue;
|
||||
|
||||
obj.real_links.remove_unordered (i);
|
||||
obj.real_links.remove (i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -330,6 +286,8 @@ struct graph_t
|
|||
vertices_scratch_.alloc (objects.length);
|
||||
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
|
||||
// nil object. We don't need it for our purposes here so drop it.
|
||||
if (i == 0 && !objects[i])
|
||||
|
@ -341,9 +299,6 @@ struct graph_t
|
|||
vertex_t* v = vertices_.push ();
|
||||
if (check_success (!vertices_.in_error ()))
|
||||
v->obj = *objects[i];
|
||||
|
||||
check_success (v->link_positions_valid (objects.length, removed_nil));
|
||||
|
||||
if (!removed_nil) continue;
|
||||
// Fix indices to account for removed nil object.
|
||||
for (auto& l : v->obj.all_links_writer ()) {
|
||||
|
@ -463,13 +418,6 @@ struct graph_t
|
|||
hb_swap (sorted_graph[new_id], vertices_[next_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--;
|
||||
|
||||
for (const auto& link : next.obj.all_links ()) {
|
||||
|
@ -632,7 +580,7 @@ struct graph_t
|
|||
|
||||
while (roots)
|
||||
{
|
||||
uint32_t next = HB_SET_VALUE_INVALID;
|
||||
unsigned next = HB_SET_VALUE_INVALID;
|
||||
if (unlikely (!check_success (!roots.in_error ()))) break;
|
||||
if (!roots.next (&next)) break;
|
||||
|
||||
|
@ -700,9 +648,6 @@ struct graph_t
|
|||
}
|
||||
}
|
||||
|
||||
if (in_error ())
|
||||
return false;
|
||||
|
||||
if (!made_changes)
|
||||
return false;
|
||||
|
||||
|
@ -716,8 +661,8 @@ struct graph_t
|
|||
|
||||
auto new_subgraph =
|
||||
+ subgraph.keys ()
|
||||
| hb_map([&] (uint32_t node_idx) {
|
||||
const uint32_t *v;
|
||||
| hb_map([&] (unsigned node_idx) {
|
||||
const unsigned *v;
|
||||
if (index_map.has (node_idx, &v)) return *v;
|
||||
return node_idx;
|
||||
})
|
||||
|
@ -727,10 +672,10 @@ struct graph_t
|
|||
remap_obj_indices (index_map, parents.iter (), true);
|
||||
|
||||
// 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))
|
||||
{
|
||||
const uint32_t *v;
|
||||
const unsigned *v;
|
||||
if (index_map.has (next, &v))
|
||||
{
|
||||
roots.del (next);
|
||||
|
@ -745,7 +690,7 @@ struct graph_t
|
|||
{
|
||||
for (const auto& link : vertices_[node_idx].obj.all_links ())
|
||||
{
|
||||
const uint32_t *v;
|
||||
const unsigned *v;
|
||||
if (subgraph.has (link.objidx, &v))
|
||||
{
|
||||
subgraph.set (link.objidx, *v + 1);
|
||||
|
@ -836,11 +781,7 @@ struct graph_t
|
|||
if (index_map.has (node_idx))
|
||||
return;
|
||||
|
||||
unsigned clone_idx = duplicate (node_idx);
|
||||
if (!check_success (clone_idx != (unsigned) -1))
|
||||
return;
|
||||
|
||||
index_map.set (node_idx, clone_idx);
|
||||
index_map.set (node_idx, duplicate (node_idx));
|
||||
for (const auto& l : object (node_idx).all_links ()) {
|
||||
duplicate_subgraph (l.objidx, index_map);
|
||||
}
|
||||
|
@ -925,12 +866,12 @@ struct graph_t
|
|||
{
|
||||
// Can't duplicate this node, doing so would orphan the original one as all remaining links
|
||||
// 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);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %u => %u",
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
|
||||
parent_idx, child_idx);
|
||||
|
||||
unsigned clone_idx = duplicate (child_idx);
|
||||
|
@ -988,7 +929,7 @@ struct graph_t
|
|||
*/
|
||||
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);
|
||||
// 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
|
||||
|
@ -1000,72 +941,6 @@ struct graph_t
|
|||
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 ()
|
||||
{
|
||||
if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
|
||||
|
@ -1074,10 +949,6 @@ struct graph_t
|
|||
parents_invalid = true;
|
||||
update_parents();
|
||||
|
||||
if (root().parents) {
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Root node has incoming edges.");
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < root_idx (); i++)
|
||||
{
|
||||
const auto& v = vertices_[i];
|
||||
|
@ -1194,11 +1065,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;
|
||||
}
|
||||
|
||||
|
@ -1317,7 +1183,7 @@ struct graph_t
|
|||
{
|
||||
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 (only_wide && !(link.width == 4 && !link.is_signed)) continue;
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ struct Lookup : public OT::Lookup
|
|||
+ new_subtable_count * OT::Offset16::static_size;
|
||||
char* buffer = (char*) hb_calloc (1, new_size);
|
||||
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.tail = buffer + new_size;
|
||||
|
@ -355,7 +355,7 @@ struct GSTAR : public OT::GSUBGPOS
|
|||
{
|
||||
switch (u.version.major) {
|
||||
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 ();
|
||||
#endif
|
||||
default: return 0;
|
||||
|
@ -374,7 +374,7 @@ struct GSTAR : public OT::GSUBGPOS
|
|||
{
|
||||
switch (u.version.major) {
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ struct AnchorMatrix : public OT::Layout::GPOS_impl::AnchorMatrix
|
|||
auto& child = c.graph.vertices_[child_idx];
|
||||
child.remove_parent (this_index);
|
||||
|
||||
o.real_links.remove_unordered (i);
|
||||
o.real_links.remove (i);
|
||||
num_links--;
|
||||
i--;
|
||||
}
|
||||
|
@ -372,7 +372,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
if (!mark_coverage) return false;
|
||||
hb_set_t marks = sc.marks_for (0, count);
|
||||
auto new_coverage =
|
||||
+ hb_enumerate (mark_coverage.table->iter ())
|
||||
+ hb_zip (hb_range (), mark_coverage.table->iter ())
|
||||
| hb_filter (marks, hb_first)
|
||||
| hb_map_retains_sorting (hb_second)
|
||||
;
|
||||
|
@ -431,7 +431,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
if (!mark_coverage) return false;
|
||||
hb_set_t marks = sc.marks_for (start, end);
|
||||
auto new_coverage =
|
||||
+ hb_enumerate (mark_coverage.table->iter ())
|
||||
+ hb_zip (hb_range (), mark_coverage.table->iter ())
|
||||
| hb_filter (marks, hb_first)
|
||||
| hb_map_retains_sorting (hb_second)
|
||||
;
|
||||
|
@ -477,7 +477,7 @@ struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
|
|||
switch (u.format) {
|
||||
case 1:
|
||||
return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 2: HB_FALLTHROUGH;
|
||||
// Don't split 24bit PairPos's.
|
||||
#endif
|
||||
|
@ -494,7 +494,7 @@ struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
|
|||
switch (u.format) {
|
||||
case 1:
|
||||
return ((MarkBasePosFormat1*)(&u.format1))->sanitize (vertex);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 2: HB_FALLTHROUGH;
|
||||
#endif
|
||||
default:
|
||||
|
|
|
@ -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;
|
||||
unsigned num_records = end - start;
|
||||
hb_memcpy (&pair_pos_prime->values[0],
|
||||
memcpy (&pair_pos_prime->values[0],
|
||||
start_addr,
|
||||
num_records * split_context.class1_record_size);
|
||||
|
||||
|
@ -611,7 +611,7 @@ struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
|||
return ((PairPosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
||||
case 2:
|
||||
return ((PairPosFormat2*)(&u.format2))->split_subtables (c, parent_index, this_index);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: HB_FALLTHROUGH;
|
||||
case 4: HB_FALLTHROUGH;
|
||||
// Don't split 24bit PairPos's.
|
||||
|
@ -631,7 +631,7 @@ struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
|||
return ((PairPosFormat1*)(&u.format1))->sanitize (vertex);
|
||||
case 2:
|
||||
return ((PairPosFormat2*)(&u.format2))->sanitize (vertex);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: HB_FALLTHROUGH;
|
||||
case 4: HB_FALLTHROUGH;
|
||||
#endif
|
||||
|
|
|
@ -33,23 +33,6 @@ struct overflow_record_t
|
|||
{
|
||||
unsigned parent;
|
||||
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
|
||||
|
@ -111,7 +94,6 @@ will_overflow (graph_t& graph,
|
|||
if (overflows) overflows->resize (0);
|
||||
graph.update_positions ();
|
||||
|
||||
hb_hashmap_t<overflow_record_t*, bool> record_set;
|
||||
const auto& vertices = graph.vertices_;
|
||||
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;
|
||||
r.parent = parent_idx;
|
||||
r.child = link.objidx;
|
||||
if (record_set.has(&r)) continue; // don't keep duplicate overflows.
|
||||
|
||||
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];
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||
" overflow from "
|
||||
"%4u (%4u in, %4u out, space %2u) => "
|
||||
"%4u (%4u in, %4u out, space %2u)",
|
||||
"%4d (%4d in, %4d out, space %2d) => "
|
||||
"%4d (%4d in, %4d out, space %2d)",
|
||||
o.parent,
|
||||
parent.incoming_edges (),
|
||||
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));
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
hb_memcpy (start, vertices[i].obj.head, size);
|
||||
memcpy (start, vertices[i].obj.head, size);
|
||||
|
||||
// Only real links needs to be serialized.
|
||||
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@")
|
||||
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@")
|
||||
string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_includedir "${_harfbuzz_includedir}")
|
||||
|
||||
# Extract version information from libtool.
|
||||
set(_harfbuzz_version_info "@HB_LIBTOOL_VERSION_INFO@")
|
||||
|
@ -12,45 +36,41 @@ list(GET _harfbuzz_version_info 2
|
|||
_harfbuzz_age)
|
||||
unset(_harfbuzz_version_info)
|
||||
|
||||
if ("@default_library@" MATCHES "static")
|
||||
set(_harfbuzz_lib_suffix ".a")
|
||||
if (APPLE)
|
||||
set(_harfbuzz_lib_suffix ".0${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
elseif (UNIX)
|
||||
set(_harfbuzz_lib_suffix "${CMAKE_SHARED_LIBRARY_SUFFIX}.0.${_harfbuzz_current}.${_harfbuzz_revision}")
|
||||
else ()
|
||||
if (APPLE)
|
||||
set(_harfbuzz_lib_suffix ".0${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
elseif (UNIX)
|
||||
set(_harfbuzz_lib_suffix "${CMAKE_SHARED_LIBRARY_SUFFIX}.0.${_harfbuzz_current}.${_harfbuzz_revision}")
|
||||
else ()
|
||||
# Unsupported.
|
||||
set(harfbuzz_FOUND 0)
|
||||
endif ()
|
||||
# Unsupported.
|
||||
set(harfbuzz_FOUND 0)
|
||||
endif ()
|
||||
|
||||
# Add the libraries.
|
||||
add_library(harfbuzz::harfbuzz SHARED IMPORTED)
|
||||
set_target_properties(harfbuzz::harfbuzz PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
|
||||
IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}")
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}")
|
||||
|
||||
add_library(harfbuzz::icu SHARED IMPORTED)
|
||||
set_target_properties(harfbuzz::icu PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/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)
|
||||
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"
|
||||
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.
|
||||
set(_harfbuzz_have_gobject "@have_gobject@")
|
||||
if (_harfbuzz_have_gobject)
|
||||
add_library(harfbuzz::gobject SHARED IMPORTED)
|
||||
set_target_properties(harfbuzz::gobject PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/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 ()
|
||||
|
||||
# Clean out variables we used in our scope.
|
||||
|
@ -60,3 +80,7 @@ unset(_harfbuzz_revision)
|
|||
unset(_harfbuzz_age)
|
||||
unset(_harfbuzz_includedir)
|
||||
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-common.cc"
|
||||
#include "hb-draw.cc"
|
||||
#include "hb-face-builder.cc"
|
||||
#include "hb-face.cc"
|
||||
#include "hb-fallback-shape.cc"
|
||||
#include "hb-font.cc"
|
||||
|
@ -41,9 +40,6 @@
|
|||
#include "hb-ot-shaper-vowel-constraints.cc"
|
||||
#include "hb-ot-tag.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-shape-plan.cc"
|
||||
#include "hb-shape.cc"
|
||||
|
@ -54,7 +50,6 @@
|
|||
#include "hb-subset-cff1.cc"
|
||||
#include "hb-subset-cff2.cc"
|
||||
#include "hb-subset-input.cc"
|
||||
#include "hb-subset-instancer-solver.cc"
|
||||
#include "hb-subset-plan.cc"
|
||||
#include "hb-subset-repacker.cc"
|
||||
#include "hb-subset.cc"
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "hb-coretext.cc"
|
||||
#include "hb-directwrite.cc"
|
||||
#include "hb-draw.cc"
|
||||
#include "hb-face-builder.cc"
|
||||
#include "hb-face.cc"
|
||||
#include "hb-fallback-shape.cc"
|
||||
#include "hb-font.cc"
|
||||
|
@ -46,9 +45,6 @@
|
|||
#include "hb-ot-shaper-vowel-constraints.cc"
|
||||
#include "hb-ot-tag.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-shape-plan.cc"
|
||||
#include "hb-shape.cc"
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#define HB_AAT_LAYOUT_COMMON_HH
|
||||
|
||||
#include "hb-aat-layout.hh"
|
||||
#include "hb-aat-map.hh"
|
||||
#include "hb-open-type.hh"
|
||||
|
||||
namespace OT {
|
||||
|
@ -40,43 +39,6 @@ namespace AAT {
|
|||
using namespace OT;
|
||||
|
||||
|
||||
struct ankr;
|
||||
|
||||
struct hb_aat_apply_context_t :
|
||||
hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
|
||||
{
|
||||
const char *get_name () { return "APPLY"; }
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { return obj.apply (this); }
|
||||
static return_t default_return_value () { return false; }
|
||||
bool stop_sublookup_iteration (return_t r) const { return r; }
|
||||
|
||||
const hb_ot_shape_plan_t *plan;
|
||||
hb_font_t *font;
|
||||
hb_face_t *face;
|
||||
hb_buffer_t *buffer;
|
||||
hb_sanitize_context_t sanitizer;
|
||||
const ankr *ankr_table;
|
||||
const OT::GDEF *gdef_table;
|
||||
const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
|
||||
hb_mask_t subtable_flags = 0;
|
||||
|
||||
/* Unused. For debug tracing only. */
|
||||
unsigned int lookup_index;
|
||||
|
||||
HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
|
||||
hb_font_t *font_,
|
||||
hb_buffer_t *buffer_,
|
||||
hb_blob_t *blob = const_cast<hb_blob_t *> (&Null (hb_blob_t)));
|
||||
|
||||
HB_INTERNAL ~hb_aat_apply_context_t ();
|
||||
|
||||
HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
|
||||
|
||||
void set_lookup_index (unsigned int i) { lookup_index = i; }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Lookup Table
|
||||
*/
|
||||
|
@ -464,8 +426,7 @@ enum { DELETED_GLYPH = 0xFFFF };
|
|||
template <typename T>
|
||||
struct Entry
|
||||
{
|
||||
// This does seem like it's ever called.
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
/* Note, we don't recurse-sanitize data because we don't access it.
|
||||
|
@ -493,8 +454,7 @@ struct Entry
|
|||
template <>
|
||||
struct Entry<void>
|
||||
{
|
||||
// This does seem like it's ever called.
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int count /*XXX Unused?*/) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
|
@ -780,44 +740,16 @@ struct StateTableDriver
|
|||
num_glyphs (face_->get_num_glyphs ()) {}
|
||||
|
||||
template <typename context_t>
|
||||
void drive (context_t *c, hb_aat_apply_context_t *ac)
|
||||
void drive (context_t *c)
|
||||
{
|
||||
if (!c->in_place)
|
||||
buffer->clear_output ();
|
||||
|
||||
int state = StateTableT::STATE_START_OF_TEXT;
|
||||
// If there's only one range, we already checked the flag.
|
||||
auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
|
||||
for (buffer->idx = 0; buffer->successful;)
|
||||
{
|
||||
/* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
|
||||
if (last_range)
|
||||
{
|
||||
auto *range = last_range;
|
||||
if (buffer->idx < buffer->len)
|
||||
{
|
||||
unsigned cluster = buffer->cur().cluster;
|
||||
while (cluster < range->cluster_first)
|
||||
range--;
|
||||
while (cluster > range->cluster_last)
|
||||
range++;
|
||||
|
||||
|
||||
last_range = range;
|
||||
}
|
||||
if (!(range->flags & ac->subtable_flags))
|
||||
{
|
||||
if (buffer->idx == buffer->len || unlikely (!buffer->successful))
|
||||
break;
|
||||
|
||||
state = StateTableT::STATE_START_OF_TEXT;
|
||||
(void) buffer->next_glyph ();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int klass = buffer->idx < buffer->len ?
|
||||
machine.get_class (buffer->cur().codepoint, num_glyphs) :
|
||||
machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
|
||||
(unsigned) StateTableT::CLASS_END_OF_TEXT;
|
||||
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
|
||||
const EntryT &entry = machine.get_entry (state, klass);
|
||||
|
@ -913,6 +845,41 @@ struct StateTableDriver
|
|||
};
|
||||
|
||||
|
||||
struct ankr;
|
||||
|
||||
struct hb_aat_apply_context_t :
|
||||
hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
|
||||
{
|
||||
const char *get_name () { return "APPLY"; }
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { return obj.apply (this); }
|
||||
static return_t default_return_value () { return false; }
|
||||
bool stop_sublookup_iteration (return_t r) const { return r; }
|
||||
|
||||
const hb_ot_shape_plan_t *plan;
|
||||
hb_font_t *font;
|
||||
hb_face_t *face;
|
||||
hb_buffer_t *buffer;
|
||||
hb_sanitize_context_t sanitizer;
|
||||
const ankr *ankr_table;
|
||||
const OT::GDEF *gdef_table;
|
||||
|
||||
/* Unused. For debug tracing only. */
|
||||
unsigned int lookup_index;
|
||||
|
||||
HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
|
||||
hb_font_t *font_,
|
||||
hb_buffer_t *buffer_,
|
||||
hb_blob_t *blob = const_cast<hb_blob_t *> (&Null (hb_blob_t)));
|
||||
|
||||
HB_INTERNAL ~hb_aat_apply_context_t ();
|
||||
|
||||
HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
|
||||
|
||||
void set_lookup_index (unsigned int i) { lookup_index = i; }
|
||||
};
|
||||
|
||||
|
||||
} /* namespace AAT */
|
||||
|
||||
|
||||
|
|
|
@ -350,7 +350,7 @@ struct KerxSubTableFormat1
|
|||
driver_context_t dc (this, c);
|
||||
|
||||
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
|
||||
driver.drive (&dc, c);
|
||||
driver.drive (&dc);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
@ -594,7 +594,7 @@ struct KerxSubTableFormat4
|
|||
driver_context_t dc (this, c);
|
||||
|
||||
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
|
||||
driver.drive (&dc, c);
|
||||
driver.drive (&dc);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
@ -869,8 +869,6 @@ struct KerxTable
|
|||
|
||||
bool apply (AAT::hb_aat_apply_context_t *c) const
|
||||
{
|
||||
c->buffer->unsafe_to_concat ();
|
||||
|
||||
typedef typename T::SubTable SubTable;
|
||||
|
||||
bool ret = false;
|
||||
|
@ -891,7 +889,7 @@ struct KerxTable
|
|||
reverse = bool (st->u.header.coverage & st->u.header.Backwards) !=
|
||||
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
|
||||
|
||||
if (!c->buffer->message (c->font, "start subtable %u", c->lookup_index))
|
||||
if (!c->buffer->message (c->font, "start subtable %d", c->lookup_index))
|
||||
goto skip;
|
||||
|
||||
if (!seenCrossStream &&
|
||||
|
@ -923,7 +921,7 @@ struct KerxTable
|
|||
if (reverse)
|
||||
c->buffer->reverse ();
|
||||
|
||||
(void) c->buffer->message (c->font, "end subtable %u", c->lookup_index);
|
||||
(void) c->buffer->message (c->font, "end subtable %d", c->lookup_index);
|
||||
|
||||
skip:
|
||||
st = &StructAfter<SubTable> (*st);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue