pango: vendor as full-fork recipe (path=source, patches baked)

This commit is contained in:
2026-08-01 04:45:54 +03:00
parent 16c88c177c
commit 1baeac5b18
579 changed files with 151795 additions and 3 deletions
+8 -3
View File
@@ -3,9 +3,14 @@ name = "pango"
version = "1.56"
[source]
tar = "https://download.gnome.org/sources/pango/1.56/pango-1.56.4.tar.xz"
blake3 = "8042a82f08101c1dabcb337a96035167e3a300de395c57678ce1a133b2dba346"
patches = ["redox.patch"]
# Vendored local fork (full-fork model): builds from the committed source/
# tree (offline, reproducible). source/ = pristine upstream + the patches below
# BAKED IN. .patch files kept tracked so a version bump can re-apply them via
# sync-recipe-source.sh.
# upstream: https://download.gnome.org/sources/pango/1.56/pango-1.56.4.tar.xz
# blake3: 8042a82f08101c1dabcb337a96035167e3a300de395c57678ce1a133b2dba346
# patch (baked): redox.patch
path = "source"
[build]
dependencies = [
Binary file not shown.
@@ -0,0 +1 @@
/subprojects/*/
@@ -0,0 +1,199 @@
include:
- component: gitlab.gnome.org/GNOME/citemplates/release-service@master
inputs:
dist-job-name: "linux-fedora"
tarball-artifact-path: "_build/meson-dist/$CI_PROJECT_NAME-$CI_COMMIT_TAG.tar.xz"
stages:
- build
- analysis
- docs
- deploy
- release
# Common variables
variables:
COMMON_MESON_FLAGS: ""
MESON_TEST_TIMEOUT_MULTIPLIER: 2
FEDORA_IMAGE: registry.gitlab.gnome.org/gnome/pango/fedora:v13
.only-default:
only:
- branches
except:
- tags
linux-fedora:
image: $FEDORA_IMAGE
stage: build
needs: []
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both"
script:
- git config --global --add safe.directory $CI_PROJECT_DIR
- meson setup ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} _build
- meson compile -C _build
- .gitlab-ci/run-tests.sh _build
- meson dist -C _build --include-subprojects --no-tests
artifacts:
name: "${env:CI_JOB_NAME}-${env:CI_COMMIT_REF_NAME}"
when: always
reports:
junit:
- "${CI_PROJECT_DIR}/_build/meson-logs/testlog.junit.xml"
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
- "${CI_PROJECT_DIR}/_build/meson-dist/*.tar.xz"
- "${CI_PROJECT_DIR}/_build/hello.png"
- "${CI_PROJECT_DIR}/_build/fontlist.txt"
asan-build:
extends: .only-default
image: $FEDORA_IMAGE
tags: [ asan ]
stage: analysis
needs: []
script:
- CC=clang meson setup --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=disabled _build
- meson compile -C _build
- .gitlab-ci/run-tests.sh _build
artifacts:
name: "${env:CI_JOB_NAME}-${env:CI_COMMIT_REF_NAME}"
when: always
reports:
junit:
- "${CI_PROJECT_DIR}/_build/meson-logs/testlog.junit.xml"
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
- "${CI_PROJECT_DIR}/_build/hello.png"
- "${CI_PROJECT_DIR}/_build/fontlist.txt"
msys2-mingw64:
extends: .only-default
stage: build
needs: []
tags:
- win32-ps
variables:
MSYSTEM: "MINGW64"
CHERE_INVOKING: "yes"
script:
- C:\msys64\usr\bin\pacman --noconfirm -Syyuu
- C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab-ci/test-msys2.sh"
- C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab-ci/render-msys2.sh"
- C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab-ci/list-msys2.sh"
artifacts:
name: "${env:CI_JOB_NAME}-${env:CI_COMMIT_REF_NAME}"
when: always
reports:
junit:
- "${CI_PROJECT_DIR}/_build/meson-logs/testlog.junit.xml"
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
- "${CI_PROJECT_DIR}/_build/hello.png"
- "${CI_PROJECT_DIR}/_build/fontlist.txt"
vs2019-x64:
# TODO: Uncomment this when ready to merge.
# rules:
# - if: $CI_PROJECT_NAMESPACE == "GNOME"
stage: build
tags:
- win32-ps
needs: []
script:
- .gitlab-ci/test-msvc.bat
artifacts:
name: "${env:CI_JOB_NAME}-${env:CI_COMMIT_REF_NAME}"
when: always
reports:
junit:
- "${CI_PROJECT_DIR}/_build/meson-logs/testlog.junit.xml"
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
macos:
extends: .only-default
only:
- branches@GNOME/pango
- branches@dehesselle/pango
stage: build
tags:
- macos
- arm64
needs: []
variables:
# ragel -Wno-unused-const-variable, -Wno-overloaded-virtual
# pcre2 -Wno-overlength-strings
# glib -Wno-deprecated-declarations, -Wno-literal-conversion
# fribidi -Wno-deprecated-non-prototype, -Wno-enum-conversion
# libpng -Wno-unused-but-set-variable
# pixman -Wno-unknown-attributes
# cairo -Wno-switch-enum, -Wno-deprecated-declarations, -Wno-unused-const-variable
CFLAGS: "-Wno-overlength-strings -Wno-deprecated-non-prototype -Wno-enum-conversion -Wno-unused-but-set-variable -Wno-unknown-attributes -Wno-switch-enum -Wno-deprecated-declarations -Wno-unused-const-variable -Wno-literal-conversion"
CXXFLAGS: "-Wno-overloaded-virtual -Wno-unused-const-variable"
OBJCFLAGS: -Wno-deprecated-declarations
CCACHE_DIR: /Users/Shared/work/ccache
CCACHE_VER: "4.9.1"
CCACHE_URL: https://github.com/ccache/ccache/releases/download/v$CCACHE_VER/ccache-$CCACHE_VER-darwin.tar.gz
EXTRA_MESON_FLAGS: "-Dintrospection=disabled -Dpixman:tests=disabled -Dharfbuzz:ragel_subproject=true"
PIP_CACHE_DIR: /Users/Shared/work/cache
PIPENV_CACHE_DIR: $PIP_CACHE_DIR
PYTHONPYCACHEPREFIX: $PIP_CACHE_DIR
SDKROOT: /opt/sdks/MacOSX11.3.sdk
before_script:
- python3 -m venv .venv
- curl -L $CCACHE_URL | tar -C .venv/bin -xz --strip-components=1 ccache-$CCACHE_VER-darwin/ccache
- source .venv/bin/activate
- pip3 install meson==1.4.2 ninja==1.11.1.1 packaging==23.2
# Disable font-scale test as it SIGTRAPs. (The test code is skipped over by
# inserting "return;" as first statement into the relevant function.)
- |
LINE_NO=$(grep -n "test_font_scale (void)" tests/test-font.c | awk -F ':' '{ print $1 }')
sed -i '' ''$((LINE_NO+2))'i\
return;' tests/test-font.c
script:
- meson setup ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} _build
- meson compile -C _build
- .gitlab-ci/run-tests.sh _build
artifacts:
name: "${env:CI_JOB_NAME}-${env:CI_COMMIT_REF_NAME}"
when: always
reports:
junit:
- "${CI_PROJECT_DIR}/_build/meson-logs/testlog.junit.xml"
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
- "${CI_PROJECT_DIR}/_build/hello.png"
- "${CI_PROJECT_DIR}/_build/fontlist.txt"
reference:
image: $FEDORA_IMAGE
stage: docs
needs: []
variables:
EXTRA_MESON_FLAGS: ""
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} -Ddocumentation=true _build
- ninja -C _build
- mkdir -p _reference/
- mv _build/docs/Pango/ _reference/
- mv _build/docs/PangoCairo/ _reference/
- mv _build/docs/PangoFc/ _reference/
- mv _build/docs/PangoFT2/ _reference/
- mv _build/docs/PangoOT/ _reference/
- mv _build/docs/PangoXft/ _reference/
artifacts:
paths:
- _reference
pages:
stage: deploy
needs: ['reference']
script:
- mv _reference/ public/
artifacts:
paths:
- public
only:
- main
@@ -0,0 +1,38 @@
## Pango CI infrastructure
Pango uses different CI images depending on platform and jobs.
The CI images are Docker containers, generated either using `docker` or
`podman`, and pushed to the GitLab [container registry][registry].
Each Docker image has a tag composed of two parts:
- `${image}`: the base image for a given platform, like "fedora" or
"debian-stable"
- `${number}`: an incremental version number, or `latest`
See the [container registry][registry] for the available images for each
branch, as well as their available versions.
### Checklist for Updating a CI image
- [ ] Update the `${image}.Dockerfile` file with the dependencies
- [ ] Run `./run-docker.sh build --base ${image} --base-version ${number}`
- [ ] Run `./run-docker.sh push --base ${image} --base-version ${number}`
once the Docker image is built; you may need to log in by using
`docker login` or `podman login`
- [ ] Update the `image` keys in the `.gitlab-ci.yml` file with the new
image tag
- [ ] Open a merge request with your changes and let it run
### Checklist for Adding a new CI image
- [ ] Write a new `${image}.Dockerfile` with the instructions to set up
a build environment
- [ ] Add the `pip3 install meson` incantation
- [ ] Run `./run-docker.sh build --base ${image} --base-version ${number}`
- [ ] Run `./run-docker.sh push --base ${image} --base-version ${number}`
- [ ] Add the new job to `.gitlab-ci.yml` referencing the image
- [ ] Open a merge request with your changes and let it run
[registry]: https://gitlab.gnome.org/GNOME/pango/container_registry
@@ -0,0 +1,59 @@
FROM fedora:42
RUN dnf -y install \
abattis-cantarell-fonts \
cairo-devel \
cairo-gobject-devel \
ccache \
clang \
clang-analyzer \
desktop-file-utils \
diffutils \
fontconfig-devel \
fribidi-devel \
gcc \
gcc-c++ \
gettext \
git \
glib2-devel \
glib2-static \
glibc-devel \
glibc-headers \
glibc-langpack-en \
gobject-introspection-devel \
google-droid-sans-fonts \
gtk-doc \
harfbuzz-devel \
hicolor-icon-theme \
itstool \
json-glib-devel \
libasan \
lcov \
libthai-devel \
libubsan \
libXft-devel \
llvm \
meson \
ninja-build \
python3 \
python3-docutils \
python3-jinja2 \
python3-markdown \
python3-packaging \
python3-pip \
python3-pygments \
python3-toml \
python3-typogrify \
python3-wheel \
redhat-rpm-config \
thai-scalable-waree-fonts \
&& dnf clean all
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -ms /bin/bash user
USER user
WORKDIR /home/user
ENV LANG C.UTF-8
@@ -0,0 +1,5 @@
#!/bin/bash
set -e
PATH=_build/pango:$PATH _build/utils/pango-list --verbose --metrics > _build/fontlist.txt || true
@@ -0,0 +1,5 @@
#!/bin/bash
set -e
PATH=_build/pango:$PATH _build/utils/pango-view --no-display --output _build/hello.png utils/HELLO.txt || true
+135
View File
@@ -0,0 +1,135 @@
#!/bin/bash
read_arg() {
# $1 = arg name
# $2 = arg value
# $3 = arg parameter
local rematch='^[^=]*=(.*)$'
if [[ $2 =~ $rematch ]]; then
read "$1" <<< "${BASH_REMATCH[1]}"
else
read "$1" <<< "$3"
# There is no way to shift our callers args, so
# return 1 to indicate they should do it instead.
return 1
fi
}
set -e
build=0
run=0
push=0
list=0
print_help=0
no_login=0
while (($# > 0)); do
case "${1%%=*}" in
build) build=1;;
run) run=1;;
push) push=1;;
list) list=1;;
help) print_help=1;;
--base|-b) read_arg base "$@" || shift;;
--base-version) read_arg base_version "$@" || shift;;
--no-login) no_login=1;;
*) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;;
esac
shift
done
if [ $print_help == 1 ]; then
echo "$0 - Build and run Docker images"
echo ""
echo "Usage: $0 <command> [options] [basename]"
echo ""
echo "Available commands"
echo ""
echo " build --base=<BASENAME> - Build Docker image <BASENAME>.Dockerfile"
echo " run --base=<BASENAME> - Run Docker image <BASENAME>"
echo " push --base=<BASENAME> - Push Docker image <BASENAME> to the registry"
echo " list - List available images"
echo " help - This help message"
echo ""
exit 0
fi
cd "$(dirname "$0")"
if [ $list == 1 ]; then
echo "Available Docker images:"
for f in *.Dockerfile; do
filename=$( basename -- "$f" )
basename="${filename%.*}"
echo -e " \e[1;39m$basename\e[0m"
done
exit 0
fi
# All commands after this require --base to be set
if [ -z $base ]; then
echo "Usage: $0 <command>"
exit 1
fi
if [ ! -f "$base.Dockerfile" ]; then
echo -e "\e[1;31mERROR\e[0m: Dockerfile for '$base' not found"
exit 1
fi
if [ -z $base_version ]; then
base_version="latest"
else
base_version="v$base_version"
fi
if [ ! -x "$(command -v docker)" ] || [ docker --help |& grep -q podman ]; then
# Docker is actually implemented by podman, and its OCI output
# is incompatible with some of the dockerd instances on GitLab
# CI runners.
echo "Using: Podman"
format="--format docker"
CMD="podman"
else
echo "Using: Docker"
format=""
CMD="sudo socker"
fi
REGISTRY="registry.gitlab.gnome.org"
TAG="${REGISTRY}/gnome/pango/${base}:${base_version}"
if [ $build == 1 ]; then
echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}"
${CMD} build \
${format} \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
exit $?
fi
if [ $push == 1 ]; then
echo -e "\e[1;32mPUSHING\e[0m: ${base} as ${TAG}"
if [ $no_login == 0 ]; then
${CMD} login ${REGISTRY}
fi
${CMD} push ${TAG}
exit $?
fi
if [ $run == 1 ]; then
echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}"
${CMD} run \
--rm \
--volume "$(pwd)/..:/home/user/app" \
--workdir "/home/user/app" \
--tty \
--interactive "${TAG}" \
bash
exit $?
fi
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
set +x
set +e
srcdir=$( pwd )
builddir=$1
# Ignore memory leaks lower in dependencies
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:symbolize=1
export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--suite=pango
# Store the exit code for the CI run, but always
# generate the reports
exit_code=$?
cd ${builddir}
./utils/pango-list --verbose > fontlist.txt
./tests/test-font -p /pango/font/metrics --verbose
./utils/pango-view --no-display --output hello.png ${srcdir}/utils/HELLO.txt
exit $exit_code
@@ -0,0 +1,18 @@
@echo on
:: vcvarsall.bat sets various env vars like PATH, INCLUDE, LIB, LIBPATH for the
:: specified build architecture
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
@echo on
:: Tests use the diff utility
set PATH=%PATH%;C:\Program Files\Git\usr\bin
pip3 install --upgrade --user meson~=1.2 || goto :error
meson setup -Dbackend_max_links=1 -Ddebug=false _build || goto :error
meson compile -C _build || goto :error
meson test -C _build -t "%MESON_TEST_TIMEOUT_MULTIPLIER%" --print-errorlogs --suite pango || goto :error
exit /b 0
:error
exit /b 1
@@ -0,0 +1,27 @@
#!/bin/bash
set -e
if [[ "$MSYSTEM" == "MINGW32" ]]; then
export MSYS2_ARCH="i686"
else
export MSYS2_ARCH="x86_64"
fi
pacman --noconfirm -Suy
pacman --noconfirm -S --needed \
base-devel \
mingw-w64-$MSYS2_ARCH-gobject-introspection \
mingw-w64-$MSYS2_ARCH-harfbuzz \
mingw-w64-$MSYS2_ARCH-fontconfig \
mingw-w64-$MSYS2_ARCH-fribidi \
mingw-w64-$MSYS2_ARCH-libthai \
mingw-w64-$MSYS2_ARCH-cairo \
mingw-w64-$MSYS2_ARCH-meson \
mingw-w64-$MSYS2_ARCH-toolchain \
mingw-w64-$MSYS2_ARCH-cantarell-fonts
meson setup --buildtype debug _build
meson compile -C _build
meson test -C _build -t "$MESON_TEST_TIMEOUT_MULTIPLIER" --print-errorlogs --suite pango
@@ -0,0 +1 @@
pango-1.56.4.tar.xz
@@ -0,0 +1,127 @@
Formatting
==========
The Pango formatting style is basically the GNU style of formatting
(see http://www.gnu.org/prep/standards.html), with a few additions.
In brief overview:
- Two character indents are used; braces go on a separate line, and
get a separate indentation level, so the total indent for an
enclosed block is 4 characters.
```c
if (x < foo (y, z))
haha = bar[4] + 5;
else
{
while (z)
{
haha += foo (z, z);
z--;
}
return abc (haha);
}
```
- Spaces should be present between function name and argument block,
and after commas.
foo (z, z)
- In pointer types, the '*' is grouped with the variable name,
not with the base type.
int *a;
Not:
int* a;
In cases where there is no variable name, for instance, return
values, there should be a single space between the base type
and the '*'.
- function and variable names are lower_case_with_underscores
type names are StudlyCaps, macro names are UPPER_CASE_WITH_UNDERSCORES
Documentation comments
======================
All public API functions should have inline documentation headers
in the gtk-doc / gnome-doc style. For instance:
```c
/**
* pango_layout_get_line:
* @layout: a `PangoLayout`
* @line: the index of a line, which must be between 0 and
* `pango_layout_get_line_count(layout) - 1`, inclusive.
*
* Retrieves a particular line from a `PangoLayout` (or @layout.)
*
* Return value: the requested `PangoLayoutLine`, or %NULL
* if the index is out of range. This layout line can
* be ref'ed and retained, but will become invalid
* if changes are made to the `PangoLayout`.
*
* Since: 1.6
*/
PangoLayoutLine *
pango_layout_get_line (PangoLayout *layout,
int line)
[...]
```
Choosing Function Names
=======================
- Don't abbreviate in unexpected ways:
```c
pango_layout_get_line_count ();
```
Not:
```c
pango_layout_ln_cnt ();
```
- function that retrieve a value in a side-effect free fashion, should
include "get" in the name.
```c
int pango_layout_get_line_count (PangoLayout *layout);
```
Not:
```c
pango_layout_line_count ();
```
- functions that set a single parameter in a side-effect free fashion
should include "set" in the name, for instance:
```c
void pango_layout_set_width (PangoLayout *layout,
int width);
```
Other comments
==============
- Avoid unsigned values for all but flags fields. This is because
the way C handles unsigned values generates bugs like crazy:
If width is unsigned and 10, then:
```c
int new_width = MAX (width - 15, 1);
```
produces 4294967291, not 1.
+482
View File
@@ -0,0 +1,482 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307 USA.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
File diff suppressed because it is too large Load Diff
+76
View File
@@ -0,0 +1,76 @@
Pango
=====
Pango is a library for layout and rendering of text, with an emphasis
on internationalization. Pango can be used anywhere that text layout
is needed; however, most of the work on Pango so far has been done using
the GTK widget toolkit as a test platform. Pango forms the core of text
and font handling for GTK.
Pango is designed to be modular; the core Pango layout can be used
with different font backends. There are three basic backends, with
multiple options for rendering with each.
- Client-side fonts using the FreeType and FontConfig libraries.
Rendering can be with with Cairo or Xft libraries, or directly
to an in-memory buffer with no additional libraries.
- Native fonts on Microsoft Windows. Rendering can be done via Cairo
or directly using the native Win32 API.
- Native fonts on MacOS X with the CoreText framework, rendering via
Cairo.
The integration of Pango with [Cairo](https://cairographics.org)
provides a complete solution with high quality text handling and
graphics rendering.
As well as the low level layout rendering routines, Pango includes
PangoLayout, a high level driver for laying out entire blocks of text,
and routines to assist in editing internationalized text.
For more information about Pango, see:
https://www.pango.org/
Dependencies
------------
Pango depends on the GLib library; more information about GLib can
be found at https://www.gtk.org/.
To use the Free Software stack backend, Pango depends on the following
libraries:
- [FontConfig](https://www.fontconfig.org) for font discovery,
- [FreeType](https://www.freetype.org) for font access,
- [HarfBuzz](http://www.harfbuzz.org) for complex text shaping
- [fribidi](http://fribidi.org) for bidirectional text handling
Cairo support depends on the [Cairo](https://cairographics.org) library.
The Cairo backend is the preferred backend to use Pango with and is
subject of most of the development in the future. It has the
advantage that the same code can be used for display and printing.
We suggest using Pango with Cairo as described above, but you can also
do X-specific rendering using the Xft library. The Xft backend uses
version 2 of the Xft library to manage client side fonts. Version 2 of
Xft is available from https://xlibs.freedesktop.org/release/. You'll
need the libXft package, and possibly the libXrender and renderext
packages as well. You'll also need FontConfig.
Installation of Pango on Win32 is possible, see README.win32.
License
-------
Most of the code of Pango is licensed under the terms of the
GNU Lesser Public License (LGPL) - see the file COPYING for details.
Versioning
----------
Historically, Pango was following the traditionally even/odd library
versioning scheme where stable releases are marked by even minor
and development releases by an odd minor.
In recent years, Pango development has slowed down so much that it
no longer makes sense to have unstable cycles, or even unstable releases.
Going forward, pango versions will simply be increasing triples, with
no particular significance to the parity of the minor version.
@@ -0,0 +1,112 @@
## Preface
The Pango backend written for Win32 is PangoWin32. PangoWin32 uses
the Win32 GDI font API. GTK+ 2.8 and later on Win32 however actually
uses the PangoCairo backend (which then uses only small parts of
PangoWin32). Much of the GDI/DirectWrite font API calls are in Cairo.
The PangoFt2 backend was originally written with Win32 in mind, but
its main use nowadays is on other platforms than Win32.
## ToolChain Requirement for Building Pango for Win32
You need to have gcc (mingw-w64) or Visual Studio 2015 or later (Visual
Studio 2019 or later is recommended if introspection files are being built),
along with Python 3.7.x+ and Meson 0.60.0 at the time of writing. If building
the introspection files, you will also need to ensure that the Python
release series and build architecture (i.e. Win32 (x86)/ x64 (amd64/x86-64)/ARM64
(aarch64)) matches the Python release series and build architecture that was used
to build GObject-Introspection is installed onthe system.
Cross-compiling Pango for ARM64/aarch64 with Visual Studio 2017 or later is
also supported, provided if a cross compilation file for Meson is properly
setup for such builds (please refer to the Meson documentation for further
instructions). Support for introspection for cross-compiled ARM64 builds is
currently not supported, as introspection builds are currently not supported
for any cross-builds where the compiled code cannot run on the build system.
The Ninja build utility must also be in your PATH, unless using the
Visual Studio IDE as noted [below](#building-pango).
## Dependencies
You will also need the following libraries installed with their headers
and import libraries, and their DLLs, if applicable, needs to be found in
%PATH%. All of their required dependencies are required as well. Their
pkg-config files are needed on all builds unless otherwise noted, where
only their headers/import libraries are needed on Visual Studio (please also read
[this section](#additional-notes-on-building-pangoft2) for more info for enabling
PangoFt2):
* GLib
* Fribidi
* Cairo (also via headers and libs; with Win32 support built in, and FreeType and
FontConfig support built in if building PangoFT2; Cairo 1.18.0 or later is highly
recommended)
* HarfBuzz (GLib support required, and FreeType2 support if building PangoFT2;
for Visual Studio builds, this needs to be built with Visual Studio 2017 15.9.x or
later--if building introspection files, Visual Studio 2019 or later is highly
recommended)
* FreeType (needed if building PangoFT2)
* FontConfig (needed if building PangoFT2)
Please see `meson.build` to see what versions are needed for these dependencies.
## Building Pango
1. Invoke the Meson configuration as follows, in a directory separate from the
sources:
1.1. MinGW (please adjust the paths accordingly, in a MSYS/MSYS2 bash prompt):
```
PATH=/devel/dist/glib-2.8.0/bin:$PATH ACLOCAL_FLAGS="-I /devel/dist/glib-2.8.0/share/aclocal" CC='gcc -mtune=pentium3' CPPFLAGS='-I/opt/gnu/include' LDFLAGS='-L/opt/gnu/lib' CFLAGS=-O meson setup $(pango_root_srcdir) --buildtype=$(buildtype) --prefix=$(PREFIX) [--pkg-config-path=...]
```
1.2 Visual Studio (set the `%INCLUDE%`, `%LIB%`, `%PATH%` envvars as needed
before running the following in a Visual Studio command prompt)
```
meson $(pango_root_srcdir) --buildtype=$(buildtype) --prefix=$(PREFIX) [--pkg-config-path=...]
```
For Visual Studio builds, support for building using Visual Studio Project
Files is also supported to some extent. Append `--backend=vs` to the Meson
configuration command above to use this support. Note that this support
may not work as well as the builds that are carried out by `ninja`, and
issues in regards to building with Meson using Visual Studio Project files
(i.e. `msbuild`) should be reported to the Meson project.
2. Build Pango by running Ninja (or with the generated Visual Studio project
files).
3. Run tests and/or install the build using the `test` and `install` targets. To
run the tests, you may need to have GNU `diff` in your `%PATH%`, that can be
obtained via installing MSYS2 for Visual Studio users (the path where GNU `diff`
is located should be towards the end of your `%PATH%`).
## Additional notes on building PangoFt2
Please take note of the following items when attempting to build with PangoFt2 on
Windows, in addition to the things mentioned [here](#dependencies), when invoking
Meson to configure the build (builds of Cairo, HarfBuzz and FreeType as subprojects
will be built consistent with the descriptions below):
* Pango: You need to pass in `-Dfontconfig=enabled -Dfreetype=enabled` when
building Pango itself, as FontConfig/FreeType support needs to be explicitly
enabled for Windows builds, that is used to build PangoFt2.
* Cairo: Cairo needs to be built with FreeType *and* FontConfig support, which
must be explicitly enabled as they are disabled by default, in particular when
building Cairo 1.17.x or later, which is also done by Meson. Pass in
`-Dfontconfig=enabled -Dfreetype=enabled` when building Cairo.
* HarfBuzz: HarfBuzz needs to be built with FreeType support enabled, so ensure
that is true by using `-Dfreetype=enabled`.
* FreeType: If Pango is being built without FreeType *and* HarfBuzz
found, FreeType will be built without HarfBuzz support. In this case, if building
FreeType with HarfBuzz is desired, first build and install PangoFt2 along with
FreeType and HarfBuzz, and then do a separate standalone build of FreeType against
that PangoFt2 build, and you will have your FreeType build with HarfBuzz enabled.
This is consistent with the official instructions for building FreeType that has
HarfBuzz enabled, from scratch.
See the following GNOME Live! page for a more detailed description of building
Pango's dependencies with Visual Studio:
https://wiki.gnome.org/Projects/GTK/Win32/MSVCCompilationOfGTKStack
+13
View File
@@ -0,0 +1,13 @@
Abigail Brady (Indic shapers)
Hans Breuer (Windows backend)
Matthias Clasen (Documentation)
Sivaraj Doddannan (Tamil shaper)
Behdad Esfahbod
Dov Grobgeld (Hebrew shaper)
Karl Koehler (Arabic shaper)
Alex Larsson (FreeType and Windows backends)
Tor Lillqvist (FreeType and Windows backends)
Changwoo Ryu (Hangul shaper)
Havoc Pennington
Roozbeh Pournader (Arabic shaper)
Chookij Vanatham (Hebrew shaper)
@@ -0,0 +1,23 @@
#!/usr/bin/env python3
import os
import shutil
references = [
'docs/Pango',
'docs/PangoCairo',
'docs/PangoFc',
'docs/PangoFT2',
'docs/PangoOT',
'docs/PangoXft',
]
sourceroot = os.environ.get('MESON_SOURCE_ROOT')
buildroot = os.environ.get('MESON_BUILD_ROOT')
distroot = os.environ.get('MESON_DIST_ROOT')
for reference in references:
src_path = os.path.join(buildroot, reference)
if os.path.isdir(src_path):
dst_path = os.path.join(distroot, reference)
shutil.copytree(src_path, dst_path)
Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

@@ -0,0 +1,740 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="180.01096"
height="144.02473"
viewBox="0 0 47.627897 38.106544"
version="1.1"
id="svg5"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
sodipodi:docname="baseline-shift.svg"
inkscape:export-filename="/var/home/mclasen/caret-metrics-light.png"
inkscape:export-xdpi="225.31"
inkscape:export-ydpi="225.31"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="3.9105941"
inkscape:cx="101.39124"
inkscape:cy="96.149074"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
inkscape:object-paths="true"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
inkscape:snap-grids="false"
inkscape:snap-to-guides="false"
fit-margin-top="20"
fit-margin-left="20"
fit-margin-right="20"
fit-margin-bottom="20"
units="px" />
<defs
id="defs2">
<marker
style="overflow:visible"
id="marker24390"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:isstock="true">
<path
transform="matrix(-0.4,0,0,-0.4,-4,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path21033" />
</marker>
<marker
style="overflow:visible"
id="TriangleOutM"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutM"
inkscape:isstock="true">
<path
transform="scale(0.4)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path21169" />
</marker>
<marker
style="overflow:visible"
id="marker21412"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mend"
inkscape:isstock="true">
<path
transform="scale(-0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path21410" />
</marker>
<marker
style="overflow:visible"
id="marker21402"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Send"
inkscape:isstock="true">
<path
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path21400" />
</marker>
<marker
style="overflow:visible"
id="marker21392"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mend"
inkscape:isstock="true">
<path
transform="scale(-0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path21390" />
</marker>
<marker
style="overflow:visible"
id="marker21382"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mend"
inkscape:isstock="true">
<path
transform="scale(-0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path21380" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Send"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Send"
inkscape:isstock="true">
<path
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path21039" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Mend"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mend"
inkscape:isstock="true">
<path
transform="scale(-0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path21051" />
</marker>
<inkscape:path-effect
effect="spiro"
id="path-effect21022"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect1403"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect1399"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect1395"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect1391"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect1387"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect30886"
is_visible="true"
lpeversion="1" />
<marker
style="overflow:visible"
id="Arrow1Mend"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:isstock="true">
<path
transform="matrix(-0.4,0,0,-0.4,-4,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path2044" />
</marker>
<inkscape:path-effect
effect="spiro"
id="path-effect4021"
is_visible="true"
lpeversion="1" />
<marker
style="overflow:visible"
id="marker2401"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.3,0,0,0.3,-0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path2065" />
</marker>
<marker
style="overflow:visible"
id="marker2296"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mstart"
inkscape:isstock="true">
<path
transform="scale(0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path2059" />
</marker>
<rect
x="139.09132"
y="517.55841"
width="202.35896"
height="141.97411"
id="rect107047" />
<inkscape:path-effect
effect="spiro"
id="path-effect103696"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect103692"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect103484"
is_visible="true"
lpeversion="1" />
<rect
x="150.41676"
y="496.0325"
width="172.54581"
height="27.762665"
id="rect90731" />
<rect
x="204.81763"
y="459.16251"
width="163.89055"
height="21.140196"
id="rect77941" />
<rect
x="271.01688"
y="341.36365"
width="148.94479"
height="44.471401"
id="rect60708" />
<inkscape:path-effect
effect="spiro"
id="path-effect57120"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect56375"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect55858"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect55696"
is_visible="true"
lpeversion="1" />
<marker
style="overflow:visible"
id="marker55148"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.3,0,0,0.3,-0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path55146" />
</marker>
<marker
style="overflow:visible"
id="marker55138"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.2,0,0,0.2,1.2,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path55136" />
</marker>
<marker
style="overflow:visible"
id="TriangleInM"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleInM"
inkscape:isstock="true">
<path
transform="scale(-0.4)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path53260" />
</marker>
<marker
style="overflow:visible"
id="marker54831"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.3,0,0,0.3,-0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path54829" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Sstart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.3,0,0,0.3,-0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53154" />
</marker>
<marker
style="overflow:visible"
id="marker54813"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mstart"
inkscape:isstock="true">
<path
transform="scale(0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path54811" />
</marker>
<marker
style="overflow:visible"
id="marker54803"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.2,0,0,0.2,1.2,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path54801" />
</marker>
<inkscape:path-effect
effect="spiro"
id="path-effect54776"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect54369"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect54152"
is_visible="true"
lpeversion="1" />
<marker
style="overflow:visible"
id="Arrow2Send"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Send"
inkscape:isstock="true">
<path
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53157" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Sstart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.2,0,0,0.2,1.2,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path53136" />
</marker>
<marker
style="overflow:visible"
id="marker53402"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mstart"
inkscape:isstock="true">
<path
transform="scale(0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53400" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Mstart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mstart"
inkscape:isstock="true">
<path
transform="scale(0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53148" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Mstart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mstart"
inkscape:isstock="true">
<path
transform="matrix(0.4,0,0,0.4,4,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path53130" />
</marker>
<inkscape:path-effect
effect="spiro"
id="path-effect53122"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect20193"
is_visible="true"
lpeversion="1" />
<rect
x="123.0892"
y="373.96039"
width="320.96652"
height="243.09319"
id="rect2256" />
<marker
style="overflow:visible"
id="Arrow1Sstart-0"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.2,0,0,0.2,1.2,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path53136-9" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Send-1"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Send"
inkscape:isstock="true">
<path
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53157-7" />
</marker>
<marker
style="overflow:visible"
id="marker55148-9"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.3,0,0,0.3,-0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path55146-7" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Send-7"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Send"
inkscape:isstock="true">
<path
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53157-6" />
</marker>
<marker
style="overflow:visible"
id="marker2401-7"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.3,0,0,0.3,-0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path2065-6" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Send-7-5"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Send"
inkscape:isstock="true">
<path
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53157-6-6" />
</marker>
<rect
x="150.41676"
y="496.0325"
width="172.54581"
height="27.762665"
id="rect90731-9" />
<marker
style="overflow:visible"
id="marker54803-3"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.2,0,0,0.2,1.2,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path54801-7" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Send-1-4"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Send"
inkscape:isstock="true">
<path
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53157-7-5" />
</marker>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-35.213392,-125.60093)">
<text
xml:space="preserve"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.5778px;line-height:1.25;font-family:'Source Serif 4 Display';-inkscape-font-specification:'Source Serif 4 Display, Italic';font-variant-ligatures:normal;font-variant-position:super;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0px;word-spacing:0px;white-space:pre;stroke-width:0.264583"
x="38.598801"
y="153.3134"
id="text4660-2"><tspan
sodipodi:role="line"
id="tspan24369"
x="38.598801"
y="153.3134">V3</tspan></text>
<text
xml:space="preserve"
transform="scale(0.26458333)"
id="text2254"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:85.3333px;line-height:1.25;font-family:'Source Serif 4 Display';-inkscape-font-specification:'Source Serif 4 Display, Italic';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect2256)" />
<text
xml:space="preserve"
style="font-size:4.23333px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';letter-spacing:0px;word-spacing:0px;white-space:pre;inline-size:24.5413;stroke-width:0.264583"
x="86.092941"
y="107.69234"
id="text14426"
transform="translate(-28.538334,44.819313)"><tspan
x="86.092941"
y="107.69234"
id="tspan33547"><tspan
style="text-align:center;text-anchor:middle"
id="tspan33545">Baseline
</tspan></tspan><tspan
x="86.092941"
y="112.984"
id="tspan33551"><tspan
style="text-align:center;text-anchor:middle"
id="tspan33549">shift</tspan></tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="49.235531"
y="118.93787"
id="text19042"><tspan
sodipodi:role="line"
id="tspan19040"
style="stroke-width:0.264583"
x="49.235531"
y="118.93787" /></text>
<path
style="vector-effect:non-scaling-stroke;fill:none;stroke:#000000;stroke-width:0.00070004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;-inkscape-stroke:hairline"
d="m 52.928213,149.72038 c 0.960916,-0.36512 2.080231,-0.2873 2.98138,0.20727 0.507629,0.2786 0.939845,0.67633 1.431893,0.98161 0.492152,0.30534 1.039531,0.51482 1.600499,0.65891 0.661475,0.1699 1.345777,0.2507 2.028632,0.23953"
id="path30884"
sodipodi:nodetypes="csssc"
inkscape:original-d="m 52.928213,149.72038 c 0.719616,-0.76028 2.257271,0.96807 2.98138,0.20727 0.724109,-0.76081 0.225896,1.37606 1.431893,0.98161 1.205995,-0.39445 0.627475,1.38743 1.600499,0.65891 0.973026,-0.72851 1.351259,0.31674 2.028632,0.23953"
inkscape:path-effect="#path-effect30886" />
<rect
style="vector-effect:non-scaling-stroke;fill:none;fill-opacity:0.374651;stroke:#000000;stroke-width:0.000703217;stroke-linejoin:round;-inkscape-stroke:hairline"
id="rect26849-7"
width="11.669242"
height="25.364506"
x="40.505409"
y="133.0513"
ry="0" />
<rect
style="vector-effect:non-scaling-stroke;fill:none;fill-opacity:0.374651;stroke:#000000;stroke-width:0.000699238;stroke-linejoin:round;-inkscape-stroke:hairline"
id="rect47446-4"
width="11.669"
height="4.9391327"
x="40.505058"
y="153.46092" />
<text
xml:space="preserve"
style="font-size:22.5778px;line-height:1.25;font-family:'Source Serif 4 Display';-inkscape-font-specification:'Source Serif 4 Display, Normal';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="74.198402"
y="145.47556"
id="text4743"><tspan
sodipodi:role="line"
id="tspan4741"
style="stroke-width:0.264583"
x="74.198402"
y="145.47556" /></text>
<rect
style="vector-effect:non-scaling-stroke;fill:none;fill-opacity:0.28;stroke:#000000;stroke-width:0.000700042;stroke-linejoin:round;-inkscape-stroke:hairline"
id="rect20307"
width="6.9471126"
height="16.905811"
x="54.158123"
y="130.89259"
ry="0" />
<rect
style="vector-effect:non-scaling-stroke;fill:none;fill-opacity:0.28;stroke:#000000;stroke-width:0.000699027;stroke-linejoin:round;-inkscape-stroke:hairline"
id="rect20806"
width="6.947"
height="4.1181569"
x="54.158058"
y="143.70164" />
<path
style="fill:none;stroke:#000000;stroke-width:0.18;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker21402)"
d="m 52.147677,153.46938 1.858616,-9.23348"
id="path21020"
inkscape:path-effect="#path-effect21022"
inkscape:original-d="m 52.147677,153.46938 c 0.664644,-3.24552 1.194501,-5.98743 1.858616,-9.23348"
sodipodi:nodetypes="cc" />
<ellipse
style="fill:none;fill-opacity:0.28;stroke:#000000;stroke-width:0.18;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path24420"
cx="52.133064"
cy="153.49341"
rx="0.1028779"
ry="0.10498031" />
<ellipse
style="fill:none;fill-opacity:0.28;stroke:#000000;stroke-width:0.18;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path24420-6"
cx="54.107121"
cy="143.74577"
rx="0.1028779"
ry="0.10498031" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -0,0 +1,535 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="213.04005"
height="126.27227"
viewBox="0 0 56.366846 33.409538"
version="1.1"
id="svg5"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
sodipodi:docname="caret-metrics.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="3.9105941"
inkscape:cx="123.38279"
inkscape:cy="92.057624"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
inkscape:object-paths="true"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
inkscape:snap-grids="false"
inkscape:snap-to-guides="false"
fit-margin-top="20"
fit-margin-left="20"
fit-margin-right="20"
fit-margin-bottom="20"
units="px" />
<defs
id="defs2">
<inkscape:path-effect
effect="spiro"
id="path-effect30886"
is_visible="true"
lpeversion="1" />
<marker
style="overflow:visible"
id="Arrow1Mend"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:isstock="true">
<path
transform="matrix(-0.4,0,0,-0.4,-4,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path2044" />
</marker>
<inkscape:path-effect
effect="spiro"
id="path-effect4021"
is_visible="true"
lpeversion="1" />
<marker
style="overflow:visible"
id="marker2401"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.3,0,0,0.3,-0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path2065" />
</marker>
<marker
style="overflow:visible"
id="marker2296"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mstart"
inkscape:isstock="true">
<path
transform="scale(0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path2059" />
</marker>
<rect
x="139.09132"
y="517.55841"
width="202.35896"
height="141.97411"
id="rect107047" />
<inkscape:path-effect
effect="spiro"
id="path-effect103696"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect103692"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect103484"
is_visible="true"
lpeversion="1" />
<rect
x="150.41676"
y="496.0325"
width="172.54581"
height="27.762665"
id="rect90731" />
<rect
x="204.81763"
y="459.16251"
width="163.89055"
height="21.140196"
id="rect77941" />
<rect
x="271.01688"
y="341.36365"
width="148.94479"
height="44.471401"
id="rect60708" />
<inkscape:path-effect
effect="spiro"
id="path-effect57120"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect56375"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect55858"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect55696"
is_visible="true"
lpeversion="1" />
<marker
style="overflow:visible"
id="marker55148"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.3,0,0,0.3,-0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path55146" />
</marker>
<marker
style="overflow:visible"
id="marker55138"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.2,0,0,0.2,1.2,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path55136" />
</marker>
<marker
style="overflow:visible"
id="TriangleInM"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleInM"
inkscape:isstock="true">
<path
transform="scale(-0.4)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path53260" />
</marker>
<marker
style="overflow:visible"
id="marker54831"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.3,0,0,0.3,-0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path54829" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Sstart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.3,0,0,0.3,-0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53154" />
</marker>
<marker
style="overflow:visible"
id="marker54813"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mstart"
inkscape:isstock="true">
<path
transform="scale(0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path54811" />
</marker>
<marker
style="overflow:visible"
id="marker54803"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.2,0,0,0.2,1.2,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path54801" />
</marker>
<inkscape:path-effect
effect="spiro"
id="path-effect54776"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect54369"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect54152"
is_visible="true"
lpeversion="1" />
<marker
style="overflow:visible"
id="Arrow2Send"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Send"
inkscape:isstock="true">
<path
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53157" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Sstart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.2,0,0,0.2,1.2,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path53136" />
</marker>
<marker
style="overflow:visible"
id="marker53402"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mstart"
inkscape:isstock="true">
<path
transform="scale(0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53400" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Mstart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mstart"
inkscape:isstock="true">
<path
transform="scale(0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53148" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Mstart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mstart"
inkscape:isstock="true">
<path
transform="matrix(0.4,0,0,0.4,4,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path53130" />
</marker>
<inkscape:path-effect
effect="spiro"
id="path-effect53122"
is_visible="true"
lpeversion="1" />
<inkscape:path-effect
effect="spiro"
id="path-effect20193"
is_visible="true"
lpeversion="1" />
<rect
x="123.0892"
y="373.96039"
width="320.96652"
height="243.09319"
id="rect2256" />
<marker
style="overflow:visible"
id="Arrow1Sstart-0"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.2,0,0,0.2,1.2,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path53136-9" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Send-1"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Send"
inkscape:isstock="true">
<path
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53157-7" />
</marker>
<marker
style="overflow:visible"
id="marker55148-9"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Sstart"
inkscape:isstock="true">
<path
transform="matrix(0.3,0,0,0.3,-0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path55146-7" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Send-7"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Send"
inkscape:isstock="true">
<path
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:context-stroke;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path53157-6" />
</marker>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-31.56006,-85.001638)">
<text
xml:space="preserve"
transform="scale(0.26458333)"
id="text2254"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:85.3333px;line-height:1.25;font-family:'Source Serif 4 Display';-inkscape-font-specification:'Source Serif 4 Display, Italic';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect2256)" />
<text
xml:space="preserve"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.5778px;line-height:1.25;font-family:'Source Serif 4 Display';-inkscape-font-specification:'Source Serif 4 Display, Italic';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0px;word-spacing:0px;white-space:pre;stroke-width:0.264583"
x="34.999043"
y="107.79361"
id="text4660"><tspan
sodipodi:role="line"
id="tspan14164"
x="34.999043"
y="107.79361">V</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 52.003705,90.321005 47.188159,112.8095"
id="path20191"
inkscape:path-effect="#path-effect20193"
inkscape:original-d="M 52.003705,90.321005 C 50.375864,96.847521 48.816529,106.28351 47.188159,112.8095"
sodipodi:nodetypes="cc" />
<rect
style="vector-effect:non-scaling-stroke;fill:none;fill-opacity:0.374651;stroke:#000000;stroke-width:0.000703217;stroke-linejoin:round;-inkscape-stroke:hairline"
id="rect26849"
width="13.32"
height="15.373064"
x="36.852001"
y="92.568069" />
<rect
style="vector-effect:non-scaling-stroke;fill:none;fill-opacity:0.374651;stroke:#000000;stroke-width:0.000698065;stroke-linejoin:round;-inkscape-stroke:hairline"
id="rect47446"
width="13.32"
height="4.9391289"
x="36.852001"
y="107.94113" />
<rect
style="vector-effect:non-scaling-stroke;fill:none;fill-opacity:0.374651;stroke:#000000;stroke-width:0.000700042;stroke-linejoin:round;-inkscape-stroke:hairline"
id="rect47448"
width="13.320173"
height="2.1710472"
x="36.851727"
y="90.397018" />
<path
style="fill:none;stroke:#000000;stroke-width:0.18;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#marker2401);marker-end:url(#Arrow2Send-7)"
d="m 48.6,107.94113 1.343724,-1.3e-4"
id="path53120-7-7"
inkscape:path-effect="#path-effect55858"
inkscape:original-d="m 48.6,107.94113 c 0.105657,-3.48672 1.207527,7.58718 1.343724,-1.3e-4"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,20.743954,-37.081682)"
id="text90729"
style="font-size:16px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect90731)"><tspan
x="150.41602"
y="510.4014"
id="tspan31459">Caret offset</tspan></text>
<path
style="vector-effect:non-scaling-stroke;fill:none;stroke:#000000;stroke-width:0.00070004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;-inkscape-stroke:hairline"
d="m 49.227839,107.96224 c 0.226502,-1.30291 0.991077,-2.50383 2.075741,-3.26038 0.589803,-0.41139 1.260378,-0.69131 1.874822,-1.0649 0.307222,-0.18679 0.601638,-0.39816 0.854742,-0.65353 0.253105,-0.25537 0.4645,-0.55649 0.589158,-0.89374 0.207454,-0.56124 0.164013,-1.1798 0.117586,-1.77636 -0.04643,-0.596547 -0.0902,-1.215021 0.116666,-1.776479 0.165326,-0.44871 0.483779,-0.831003 0.863402,-1.121796 0.379622,-0.290792 0.819152,-0.494983 1.270146,-0.653973 0.863783,-0.304512 1.783339,-0.450018 2.698938,-0.427067"
id="path103694"
inkscape:path-effect="#path-effect103696"
inkscape:original-d="m 49.227839,107.96224 c 0.494964,0.52279 1.502441,-3.68765 2.075741,-3.26038 1.969315,1.46769 2.34869,-0.91307 3.318722,-2.61217 0.793545,-1.38997 -0.102491,-1.94963 0.234252,-3.552839 0.336743,-1.6032 1.758494,-1.355839 2.133548,-1.775769 0.375055,-0.41994 2.262835,-0.267827 2.698938,-0.427067"
sodipodi:nodetypes="cssssc" />
<rect
style="vector-effect:non-scaling-stroke;fill:#000000;fill-opacity:0.278821;stroke:#000000;stroke-width:0.00047625;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;-inkscape-stroke:hairline"
id="rect3709"
width="4.8884287"
height="22.486149"
x="47.13298"
y="90.397003" />
<path
style="fill:none;stroke:#000000;stroke-width:0.18;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#marker54803);marker-end:url(#Arrow2Send-1)"
d="m 48.070703,111.07067 c 0.25639,0.1329 0.482591,0.32364 0.656888,0.5539 0.212398,0.2806 0.346674,0.6197 0.383947,0.96964"
id="path4019"
inkscape:path-effect="#path-effect4021"
inkscape:original-d="m 48.070703,111.07067 c 0.717077,0.0712 0.389053,0.23991 0.656888,0.5539 0.265044,0.31071 0.08663,-0.0602 0.383947,0.96964"
sodipodi:nodetypes="csc" />
<text
xml:space="preserve"
style="font-size:4.23333px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';letter-spacing:0px;word-spacing:0px;white-space:pre;inline-size:24.5413;stroke-width:0.264583"
x="86.092941"
y="107.69234"
id="text14426"
transform="translate(-27.172048,-0.62225867)"><tspan
x="86.092941"
y="107.69234"
id="tspan31463"><tspan
style="text-align:center;text-anchor:middle"
id="tspan31461">Caret slope
</tspan></tspan><tspan
x="86.092941"
y="112.984"
id="tspan31467"><tspan
style="text-align:center;text-anchor:middle"
id="tspan31465">(rise / run)</tspan></tspan></text>
<text
xml:space="preserve"
style="font-size:4.23333px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="49.235531"
y="118.93787"
id="text19042"><tspan
sodipodi:role="line"
id="tspan19040"
style="stroke-width:0.264583"
x="49.235531"
y="118.93787" /></text>
<path
style="vector-effect:non-scaling-stroke;fill:none;stroke:#000000;stroke-width:0.00070004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;-inkscape-stroke:hairline"
d="m 48.86262,111.80936 c 0.304076,-1.04831 1.140855,-1.92686 2.17312,-2.28161 0.64251,-0.2208 1.332751,-0.24528 2.010063,-0.29841 0.677312,-0.0531 1.37244,-0.14326 1.964718,-0.4761 0.532566,-0.29928 0.942559,-0.77292 1.324313,-1.24985 0.381754,-0.47692 0.753236,-0.97325 1.239557,-1.34296 0.568865,-0.43247 1.282661,-0.67073 1.997236,-0.66666"
id="path30884"
inkscape:path-effect="#path-effect30886"
inkscape:original-d="m 48.86262,111.80936 c 0.719616,-0.76028 1.449011,-1.52081 2.17312,-2.28161 0.724109,-0.76081 2.768784,-0.38006 3.974781,-0.77451 1.205995,-0.39445 1.590846,-1.86429 2.56387,-2.59281 0.973026,-0.72851 1.319863,-0.58945 1.997236,-0.66666"
sodipodi:nodetypes="csssc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="157.43535"
height="126.08757"
viewBox="0 0 41.654768 33.360671"
version="1.1"
id="svg122363"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
sodipodi:docname="cursor-positions2.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview122365"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="2.7652076"
inkscape:cx="2.3506372"
inkscape:cy="113.55386"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
units="px"
fit-margin-top="20"
fit-margin-left="20"
fit-margin-right="20"
fit-margin-bottom="20" />
<defs
id="defs122360" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-35.434213,-118.42405)">
<rect
style="vector-effect:non-scaling-stroke;fill:none;fill-opacity:0.374651;stroke:#000000;stroke-width:0.00070229;stroke-linejoin:round;-inkscape-stroke:hairline"
id="rect26849-7-6-3"
width="19.828447"
height="15.754494"
x="50.619915"
y="126.2482" />
<rect
style="vector-effect:non-scaling-stroke;fill:none;fill-opacity:0.374651;stroke:#000000;stroke-width:0.000704165;stroke-linejoin:round;-inkscape-stroke:hairline"
id="rect26849-7-6-0-2"
width="9.6999998"
height="15.754"
x="40.920364"
y="126.24852" />
<g
aria-label="w"
transform="matrix(0.26458333,0,0,0.26458333,53.283913,76.543917)"
id="text4642-7-1"
style="font-size:85.3333px;line-height:1.25;font-family:'Source Serif 4 Display';-inkscape-font-specification:'Source Serif 4 Display, Normal';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect4644)">
<path
d="m 1.2424688,246.68612 0.3413332,0.34133 2.1333324,-0.34133 c 7.3386636,-8.448 14.0799946,-20.90666 17.2373266,-28.92799 0.341333,8.10666 0.767999,18.43199 1.194666,28.92799 l 0.341333,0.34133 2.047999,-0.34133 c 8.191997,-8.448 15.01866,-18.00533 18.090659,-25.25866 1.024,-2.38933 3.754665,-7.08266 3.754665,-11.09333 0,-0.85333 -0.170666,-1.536 -0.341333,-2.21866 -0.597333,-0.59734 -1.450666,-1.024 -2.645332,-1.024 -1.791999,0 -3.327999,1.024 -3.327999,4.43733 0,1.28 0.08533,3.072 1.024,6.99733 l 0.256,1.10933 c -0.170667,0.42667 -0.341333,0.768 -0.512,1.19467 -3.071999,7.168 -8.27733,14.07999 -13.567994,20.39466 -0.426667,-11.008 -0.853333,-22.01599 -1.365333,-33.10932 H 22.74646 c -4.437332,12.11733 -10.410662,23.80799 -16.5546599,32.85332 -0.085333,-9.472 -0.6826664,-20.13866 -1.706666,-27.30666 -0.6826664,-4.608 -2.0479991,-6.57066 -5.37599775,-6.57066 -3.92533165,0 -6.31466405,3.41333 -9.04532955,9.89866 l 1.0239996,0.768 c 3.0719987,-4.94933 4.4373314,-6.31466 5.8879975,-6.31466 1.1093329,0 1.8773326,0.85333 2.38933235,4.52266 1.10933287,8.61866 1.62133265,17.83466 1.87733255,30.71999 z"
id="path32016-5-5" />
</g>
<g
aria-label="i"
id="text23394-6-9"
style="font-size:22.5778px;line-height:1.25;font-family:'Source Serif 4 Display';-inkscape-font-specification:'Source Serif 4 Display, Normal';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
transform="translate(21.723853,-8.999446)">
<path
d="m 44.502481,150.0899 c 0,0.67734 0.587023,0.99343 1.12889,0.99343 1.399824,0 3.360056,-0.89409 4.059967,-2.04556 l 0.382126,-0.45413 c -0.790223,0.90312 -3.268047,1.34822 -3.697025,1.34822 -0.2032,0 -0.406401,-0.15805 -0.406401,-0.42898 0,-0.22578 0.09031,-0.63218 0.180623,-1.10631 l 1.648179,-7.87965 -0.2032,-0.18063 -4.247235,1.53975 0.504014,0.24314 2.275639,-0.20244 -1.444979,6.79592 c -0.158045,0.79022 -0.180623,1.10631 -0.180623,1.37724 z m 3.138315,-12.21459 c 0.677334,0 1.309512,-0.58702 1.309512,-1.39982 0,-0.58702 -0.383823,-0.99342 -0.970845,-0.99342 -0.677334,0 -1.286935,0.63217 -1.286935,1.44498 0,0.56444 0.4064,0.94826 0.948268,0.94826 z"
id="path32019-9-9"
sodipodi:nodetypes="ssccsscccccccsssssss" />
</g>
<circle
style="vector-effect:non-scaling-stroke;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.000763294;stroke-linejoin:round;-inkscape-stroke:hairline"
id="path35788-2-1"
cx="50.619915"
cy="141.94321"
r="0.25" />
<circle
style="vector-effect:non-scaling-stroke;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.000763296;stroke-linejoin:round;-inkscape-stroke:hairline"
id="path35788-4-82-4"
cx="65.832771"
cy="141.94321"
r="0.25" />
<circle
style="vector-effect:non-scaling-stroke;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.000763296;stroke-linejoin:round;-inkscape-stroke:hairline"
id="path35788-4-8-9-9"
cx="70.508347"
cy="141.94321"
r="0.25" />
<circle
style="vector-effect:non-scaling-stroke;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.000763296;stroke-linejoin:round;-inkscape-stroke:hairline"
id="path35788-4-8-1-9-1"
cx="40.97588"
cy="141.94321"
r="0.25" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.5778px;line-height:1.25;font-family:'Source Serif 4 Display';-inkscape-font-specification:'Source Serif 4 Display, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="40.889793"
y="141.745"
id="text84375-0"><tspan
sodipodi:role="line"
id="tspan86335-7"
x="40.889793"
y="141.745">o</tspan></text>
<rect
style="vector-effect:non-scaling-stroke;fill:#000000;fill-opacity:0.28;stroke:#000000;stroke-width:0.000677452;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;-inkscape-stroke:hairline"
id="rect121833-0-4"
width="0.60000002"
height="22.777336"
x="65.532852"
y="123.71571" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="157.43535"
height="126.08757"
viewBox="0 0 41.654768 33.360671"
version="1.1"
id="svg122363"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
sodipodi:docname="glyphstring-positions.svg"
inkscape:export-filename="/var/home/mclasen/cursor-positions2-light.png"
inkscape:export-xdpi="225.31"
inkscape:export-ydpi="225.31"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview122365"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="2.7652076"
inkscape:cx="2.3506372"
inkscape:cy="113.55386"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
units="px"
fit-margin-top="20"
fit-margin-left="20"
fit-margin-right="20"
fit-margin-bottom="20" />
<defs
id="defs122360" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-35.434213,-118.42405)">
<rect
style="vector-effect:non-scaling-stroke;fill:none;fill-opacity:0.374651;stroke:#000000;stroke-width:0.00070229;stroke-linejoin:round;-inkscape-stroke:hairline"
id="rect26849-7-6-3"
width="19.828447"
height="15.754494"
x="50.619915"
y="126.2482" />
<rect
style="vector-effect:non-scaling-stroke;fill:none;fill-opacity:0.374651;stroke:#000000;stroke-width:0.000704165;stroke-linejoin:round;-inkscape-stroke:hairline"
id="rect26849-7-6-0-2"
width="9.6999998"
height="15.754"
x="40.920364"
y="126.24852" />
<g
aria-label="w"
transform="matrix(0.26458333,0,0,0.26458333,53.283913,76.543917)"
id="text4642-7-1"
style="font-size:85.3333px;line-height:1.25;font-family:'Source Serif 4 Display';-inkscape-font-specification:'Source Serif 4 Display, Normal';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect4644)">
<path
d="m 1.2424688,246.68612 0.3413332,0.34133 2.1333324,-0.34133 c 7.3386636,-8.448 14.0799946,-20.90666 17.2373266,-28.92799 0.341333,8.10666 0.767999,18.43199 1.194666,28.92799 l 0.341333,0.34133 2.047999,-0.34133 c 8.191997,-8.448 15.01866,-18.00533 18.090659,-25.25866 1.024,-2.38933 3.754665,-7.08266 3.754665,-11.09333 0,-0.85333 -0.170666,-1.536 -0.341333,-2.21866 -0.597333,-0.59734 -1.450666,-1.024 -2.645332,-1.024 -1.791999,0 -3.327999,1.024 -3.327999,4.43733 0,1.28 0.08533,3.072 1.024,6.99733 l 0.256,1.10933 c -0.170667,0.42667 -0.341333,0.768 -0.512,1.19467 -3.071999,7.168 -8.27733,14.07999 -13.567994,20.39466 -0.426667,-11.008 -0.853333,-22.01599 -1.365333,-33.10932 H 22.74646 c -4.437332,12.11733 -10.410662,23.80799 -16.5546599,32.85332 -0.085333,-9.472 -0.6826664,-20.13866 -1.706666,-27.30666 -0.6826664,-4.608 -2.0479991,-6.57066 -5.37599775,-6.57066 -3.92533165,0 -6.31466405,3.41333 -9.04532955,9.89866 l 1.0239996,0.768 c 3.0719987,-4.94933 4.4373314,-6.31466 5.8879975,-6.31466 1.1093329,0 1.8773326,0.85333 2.38933235,4.52266 1.10933287,8.61866 1.62133265,17.83466 1.87733255,30.71999 z"
id="path32016-5-5" />
</g>
<g
aria-label="i"
id="text23394-6-9"
style="font-size:22.5778px;line-height:1.25;font-family:'Source Serif 4 Display';-inkscape-font-specification:'Source Serif 4 Display, Normal';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
transform="translate(21.723853,-8.999446)">
<path
d="m 44.502481,150.0899 c 0,0.67734 0.587023,0.99343 1.12889,0.99343 1.399824,0 3.360056,-0.89409 4.059967,-2.04556 l 0.382126,-0.45413 c -0.790223,0.90312 -3.268047,1.34822 -3.697025,1.34822 -0.2032,0 -0.406401,-0.15805 -0.406401,-0.42898 0,-0.22578 0.09031,-0.63218 0.180623,-1.10631 l 1.648179,-7.87965 -0.2032,-0.18063 -4.247235,1.53975 0.504014,0.24314 2.275639,-0.20244 -1.444979,6.79592 c -0.158045,0.79022 -0.180623,1.10631 -0.180623,1.37724 z m 3.138315,-12.21459 c 0.677334,0 1.309512,-0.58702 1.309512,-1.39982 0,-0.58702 -0.383823,-0.99342 -0.970845,-0.99342 -0.677334,0 -1.286935,0.63217 -1.286935,1.44498 0,0.56444 0.4064,0.94826 0.948268,0.94826 z"
id="path32019-9-9"
sodipodi:nodetypes="ssccsscccccccsssssss" />
</g>
<circle
style="vector-effect:non-scaling-stroke;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.000763294;stroke-linejoin:round;-inkscape-stroke:hairline"
id="path35788-2-1"
cx="50.619915"
cy="141.94321"
r="0.25" />
<circle
style="vector-effect:non-scaling-stroke;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.000763296;stroke-linejoin:round;-inkscape-stroke:hairline"
id="path35788-4-82-4"
cx="65.832771"
cy="141.94321"
r="0.25" />
<circle
style="vector-effect:non-scaling-stroke;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.000763296;stroke-linejoin:round;-inkscape-stroke:hairline"
id="path35788-4-8-9-9"
cx="70.508347"
cy="141.94321"
r="0.25" />
<circle
style="vector-effect:non-scaling-stroke;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.000763296;stroke-linejoin:round;-inkscape-stroke:hairline"
id="path35788-4-8-1-9-1"
cx="40.97588"
cy="141.94321"
r="0.25" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.5778px;line-height:1.25;font-family:'Source Serif 4 Display';-inkscape-font-specification:'Source Serif 4 Display, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="40.889793"
y="141.745"
id="text84375-0"><tspan
sodipodi:role="line"
id="tspan86335-7"
x="40.889793"
y="141.745">o</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

@@ -0,0 +1,231 @@
%!PS-Adobe-2.0 EPSF-2.0
%%Title: layout.eps
%%Creator: fig2dev Version 3.2 Patchlevel 1
%%CreationDate: Thu Mar 9 16:51:04 2000
%%For: otaylor@fresnel.labs.redhat.com (Owen Taylor,,547-0012 x249)
%%Orientation: Portrait
%%BoundingBox: 0 0 629 233
%%Pages: 0
%%BeginSetup
%%EndSetup
%%Magnification: 1.0000
%%EndComments
/$F2psDict 200 dict def
$F2psDict begin
$F2psDict /mtrx matrix put
/col-1 {0 setgray} bind def
/col0 {0.000 0.000 0.000 srgb} bind def
/col1 {0.000 0.000 1.000 srgb} bind def
/col2 {0.000 1.000 0.000 srgb} bind def
/col3 {0.000 1.000 1.000 srgb} bind def
/col4 {1.000 0.000 0.000 srgb} bind def
/col5 {1.000 0.000 1.000 srgb} bind def
/col6 {1.000 1.000 0.000 srgb} bind def
/col7 {1.000 1.000 1.000 srgb} bind def
/col8 {0.000 0.000 0.560 srgb} bind def
/col9 {0.000 0.000 0.690 srgb} bind def
/col10 {0.000 0.000 0.820 srgb} bind def
/col11 {0.530 0.810 1.000 srgb} bind def
/col12 {0.000 0.560 0.000 srgb} bind def
/col13 {0.000 0.690 0.000 srgb} bind def
/col14 {0.000 0.820 0.000 srgb} bind def
/col15 {0.000 0.560 0.560 srgb} bind def
/col16 {0.000 0.690 0.690 srgb} bind def
/col17 {0.000 0.820 0.820 srgb} bind def
/col18 {0.560 0.000 0.000 srgb} bind def
/col19 {0.690 0.000 0.000 srgb} bind def
/col20 {0.820 0.000 0.000 srgb} bind def
/col21 {0.560 0.000 0.560 srgb} bind def
/col22 {0.690 0.000 0.690 srgb} bind def
/col23 {0.820 0.000 0.820 srgb} bind def
/col24 {0.500 0.190 0.000 srgb} bind def
/col25 {0.630 0.250 0.000 srgb} bind def
/col26 {0.750 0.380 0.000 srgb} bind def
/col27 {1.000 0.500 0.500 srgb} bind def
/col28 {1.000 0.630 0.630 srgb} bind def
/col29 {1.000 0.750 0.750 srgb} bind def
/col30 {1.000 0.880 0.880 srgb} bind def
/col31 {1.000 0.840 0.000 srgb} bind def
/col32 {0.443 0.459 0.443 srgb} bind def
end
save
-5.0 253.0 translate
1 -1 scale
/cp {closepath} bind def
/ef {eofill} bind def
/gr {grestore} bind def
/gs {gsave} bind def
/sa {save} bind def
/rs {restore} bind def
/l {lineto} bind def
/m {moveto} bind def
/rm {rmoveto} bind def
/n {newpath} bind def
/s {stroke} bind def
/sh {show} bind def
/slc {setlinecap} bind def
/slj {setlinejoin} bind def
/slw {setlinewidth} bind def
/srgb {setrgbcolor} bind def
/rot {rotate} bind def
/sc {scale} bind def
/sd {setdash} bind def
/ff {findfont} bind def
/sf {setfont} bind def
/scf {scalefont} bind def
/sw {stringwidth} bind def
/tr {translate} bind def
/tnt {dup dup currentrgbcolor
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
bind def
/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
4 -2 roll mul srgb} bind def
/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
/$F2psEnd {$F2psEnteredState restore end} def
%%EndProlog
$F2psBegin
10 setmiterlimit
n -1000 5215 m -1000 -1000 l 11561 -1000 l 11561 5215 l cp clip
0.06000 0.06000 sc
% Polyline
15.000 slw
gs clippath
10200 3405 m 10350 3450 l 10200 3495 l 10380 3495 l 10380 3405 l cp
6300 3495 m 6150 3450 l 6300 3405 l 6120 3405 l 6120 3495 l cp
clip
n 6150 3450 m 10350 3450 l gs col-1 s gr gr
% arrowhead
7.500 slw
n 6300 3495 m 6150 3450 l 6300 3405 l 6300 3450 l 6300 3495 l cp gs 0.00 setgray ef gr col-1 s
% arrowhead
n 10200 3405 m 10350 3450 l 10200 3495 l 10200 3450 l 10200 3405 l cp gs 0.00 setgray ef gr col-1 s
% Polyline
n 1200 675 m 1200 3600 l gs col-1 s gr
% Polyline
15.000 slw
gs clippath
5250 3405 m 5400 3450 l 5250 3495 l 5430 3495 l 5430 3405 l cp
1350 3495 m 1200 3450 l 1350 3405 l 1170 3405 l 1170 3495 l cp
clip
n 1200 3450 m 5400 3450 l gs col-1 s gr gr
% arrowhead
7.500 slw
n 1350 3495 m 1200 3450 l 1350 3405 l 1350 3450 l 1350 3495 l cp gs 0.00 setgray ef gr col-1 s
% arrowhead
n 5250 3405 m 5400 3450 l 5250 3495 l 5250 3450 l 5250 3405 l cp gs 0.00 setgray ef gr col-1 s
% Polyline
n 1050 2175 m 1200 2175 l gs col-1 s gr
% Polyline
15.000 slw
n 1125 2025 m 1125 2175 l gs col-1 s gr
% Polyline
7.500 slw
n 6150 975 m 6150 3600 l gs col-1 s gr
% Polyline
n 5400 975 m 5400 3600 l gs col-1 s gr
% Polyline
n 1800 975 m 1800 675 l gs col-1 s gr
% Polyline
15.000 slw
gs clippath
1650 780 m 1800 825 l 1650 870 l 1830 870 l 1830 780 l cp
1350 870 m 1200 825 l 1350 780 l 1170 780 l 1170 870 l cp
clip
n 1200 825 m 1800 825 l gs col-1 s gr gr
% arrowhead
7.500 slw
n 1350 870 m 1200 825 l 1350 780 l 1350 825 l 1350 870 l cp gs 0.00 setgray ef gr col-1 s
% arrowhead
n 1650 780 m 1800 825 l 1650 870 l 1650 825 l 1650 780 l cp gs 0.00 setgray ef gr col-1 s
% Polyline
n 9750 975 m 9750 675 l gs col-1 s gr
% Polyline
15.000 slw
gs clippath
10200 780 m 10350 825 l 10200 870 l 10380 870 l 10380 780 l cp
9900 870 m 9750 825 l 9900 780 l 9720 780 l 9720 870 l cp
clip
n 9750 825 m 10350 825 l gs col-1 s gr gr
% arrowhead
7.500 slw
n 9900 870 m 9750 825 l 9900 780 l 9900 825 l 9900 870 l cp gs 0.00 setgray ef gr col-1 s
% arrowhead
n 10200 780 m 10350 825 l 10200 870 l 10200 825 l 10200 780 l cp gs 0.00 setgray ef gr col-1 s
% Polyline
n 10350 675 m 10350 3600 l gs col-1 s gr
% Polyline
15.000 slw
n 4950 1425 m 1800 1425 l 1800 975 l 4950 975 l cp gs col32 s gr
% Polyline
n 4575 2025 m 1200 2025 l 1200 1575 l 4575 1575 l cp gs col32 s gr
% Polyline
n 5250 2625 m 1200 2625 l 1200 2175 l 5250 2175 l cp gs col32 s gr
% Polyline
n 2400 3225 m 1200 3225 l 1200 2775 l 2400 2775 l cp gs col32 s gr
% Polyline
n 9750 1425 m 6600 1425 l 6600 975 l 9750 975 l cp gs col32 s gr
% Polyline
n 10350 2025 m 6975 2025 l 6975 1575 l 10350 1575 l cp gs col32 s gr
% Polyline
n 10350 2625 m 6300 2625 l 6300 2175 l 10350 2175 l cp gs col32 s gr
% Polyline
n 10350 3225 m 9150 3225 l 9150 2775 l 10350 2775 l cp gs col32 s gr
% Polyline
7.500 slw
n 1200 2025 m 1050 2025 l gs col-1 s gr
/Times-Roman ff 360.00 scf sf
1200 2475 m
gs 1 -1 sc (demonstrate PangoLayout's) col0 sh gr
/Times-Roman ff 360.00 scf sf
1200 3075 m
gs 1 -1 sc (features.) col0 sh gr
/Times-Roman ff 360.00 scf sf
1200 1875 m
gs 1 -1 sc (should wrap suitably to) col0 sh gr
/Helvetica ff 240.00 scf sf
525 2175 m
gs 1 -1 sc (spacing) dup sw pop 2 div neg 0 rm col-1 sh gr
/Times-Roman ff 360.00 scf sf
1800 1275 m
gs 1 -1 sc (Here is some text that) col0 sh gr
/Times-Roman ff 360.00 scf sf
9150 3075 m
gs 1 -1 sc (features.) col0 sh gr
/Times-Roman ff 360.00 scf sf
6600 1275 m
gs 1 -1 sc (Here is some text that) col0 sh gr
/Helvetica ff 240.00 scf sf
1875 3825 m
gs 1 -1 sc (width) dup sw pop 2 div neg 0 rm col-1 sh gr
/Helvetica ff 240.00 scf sf
6825 3825 m
gs 1 -1 sc (width) dup sw pop 2 div neg 0 rm col-1 sh gr
/Helvetica ff 240.00 scf sf
10050 525 m
gs 1 -1 sc (indent) dup sw pop 2 div neg 0 rm col-1 sh gr
/Helvetica ff 240.00 scf sf
1575 525 m
gs 1 -1 sc (indent) dup sw pop 2 div neg 0 rm col-1 sh gr
/Helvetica ff 300.00 scf sf
9225 4125 m
gs 1 -1 sc (Right Aligned) dup sw pop 2 div neg 0 rm col-1 sh gr
/Helvetica ff 300.00 scf sf
4350 4125 m
gs 1 -1 sc (Left Aligned) dup sw pop 2 div neg 0 rm col-1 sh gr
/Times-Roman ff 360.00 scf sf
6975 1875 m
gs 1 -1 sc (should wrap suitably to) col0 sh gr
/Times-Roman ff 360.00 scf sf
6300 2475 m
gs 1 -1 sc (demonstrate PangoLayout's) col0 sh gr
$F2psEnd
rs
@@ -0,0 +1,75 @@
#FIG 3.2
Landscape
Center
Inches
Letter
100.00
Single
-2
1200 2
0 32 #717571
2 1 0 2 -1 7 100 0 -1 0.000 0 0 -1 1 1 2
1 1 1.00 90.00 150.00
1 1 1.00 90.00 150.00
6150 3450 10350 3450
2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
1200 675 1200 3600
2 1 0 2 -1 7 100 0 -1 0.000 0 0 -1 1 1 2
1 1 1.00 90.00 150.00
1 1 1.00 90.00 150.00
1200 3450 5400 3450
2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
1050 2175 1200 2175
2 1 0 2 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
1125 2025 1125 2175
2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
6150 975 6150 3600
2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
5400 975 5400 3600
2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
1800 975 1800 675
2 1 0 2 -1 7 100 0 -1 0.000 0 0 -1 1 1 2
1 1 1.00 90.00 150.00
1 1 1.00 90.00 150.00
1200 825 1800 825
2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
9750 975 9750 675
2 1 0 2 -1 7 100 0 -1 0.000 0 0 -1 1 1 2
1 1 1.00 90.00 150.00
1 1 1.00 90.00 150.00
9750 825 10350 825
2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
10350 675 10350 3600
2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
4950 1425 1800 1425 1800 975 4950 975 4950 1425
2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
4575 2025 1200 2025 1200 1575 4575 1575 4575 2025
2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
5250 2625 1200 2625 1200 2175 5250 2175 5250 2625
2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
2400 3225 1200 3225 1200 2775 2400 2775 2400 3225
2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
9750 1425 6600 1425 6600 975 9750 975 9750 1425
2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
10350 2025 6975 2025 6975 1575 10350 1575 10350 2025
2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
10350 2625 6300 2625 6300 2175 10350 2175 10350 2625
2 2 0 2 32 7 100 0 -1 0.000 0 0 -1 0 0 5
10350 3225 9150 3225 9150 2775 10350 2775 10350 3225
2 1 0 1 -1 7 100 0 -1 0.000 0 0 -1 0 0 2
1200 2025 1050 2025
4 0 0 100 0 0 24 0.0000 4 330 4155 1200 2475 demonstrate PangoLayout's\001
4 0 0 100 0 0 24 0.0000 4 255 1260 1200 3075 features.\001
4 0 0 100 0 0 24 0.0000 4 330 3405 1200 1875 should wrap suitably to\001
4 1 -1 100 0 16 16 0.0000 4 240 855 525 2175 spacing\001
4 0 0 100 0 0 24 0.0000 4 255 3270 1800 1275 Here is some text that\001
4 0 0 100 0 0 24 0.0000 4 255 1260 9150 3075 features.\001
4 0 0 100 0 0 24 0.0000 4 255 3270 6600 1275 Here is some text that\001
4 1 -1 100 0 16 16 0.0000 4 180 540 1875 3825 width\001
4 1 -1 100 0 16 16 0.0000 4 180 540 6825 3825 width\001
4 1 -1 100 0 16 16 0.0000 4 180 645 10050 525 indent\001
4 1 -1 100 0 16 16 0.0000 4 180 645 1575 525 indent\001
4 1 -1 100 0 16 20 0.0000 4 300 1770 9225 4125 Right Aligned\001
4 1 -1 100 0 16 20 0.0000 4 300 1590 4350 4125 Left Aligned\001
4 0 0 100 0 0 24 0.0000 4 330 3405 6975 1875 should wrap suitably to\001
4 0 0 100 0 0 24 0.0000 4 330 4155 6300 2475 demonstrate PangoLayout's\001
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

@@ -0,0 +1,497 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg8"
sodipodi:docname="layout.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14">
<defs
id="defs2">
<marker
inkscape:stockid="TriangleInM"
orient="auto"
refY="0.0"
refX="0.0"
id="marker14051"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path14049"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(-0.4)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker7942"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="TriangleOutM">
<path
transform="scale(0.4)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
id="path7940" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker7139"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="TriangleOutM">
<path
transform="scale(0.4)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
id="path7137" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker7071"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="TriangleOutM">
<path
transform="scale(0.4)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
id="path7069" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker6673"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="TriangleInM"
inkscape:collect="always">
<path
transform="scale(-0.4)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
id="path6671" />
</marker>
<marker
inkscape:stockid="TriangleOutM"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleOutM"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path1067"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4)" />
</marker>
<marker
inkscape:stockid="TriangleInM"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleInM"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path1058"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(-0.4)" />
</marker>
<marker
inkscape:stockid="Arrow1Sstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Sstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path934"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.2) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path925"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.8) rotate(180) translate(12.5,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path922"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.8) translate(12.5,0)" />
</marker>
<marker
inkscape:stockid="TriangleInM"
orient="auto"
refY="0"
refX="0"
id="TriangleInM-0"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path1058-6"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="scale(-0.4)" />
</marker>
<marker
inkscape:stockid="TriangleOutM"
orient="auto"
refY="0"
refX="0"
id="TriangleOutM-4"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path1067-6"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="scale(0.4)" />
</marker>
<marker
inkscape:stockid="TriangleInM"
orient="auto"
refY="0"
refX="0"
id="TriangleInM-5"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path1058-8"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="scale(-0.4)" />
</marker>
<marker
inkscape:stockid="TriangleOutM"
orient="auto"
refY="0"
refX="0"
id="TriangleOutM-6"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path1067-2"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="scale(0.4)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker6673-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleInM">
<path
inkscape:connector-curvature="0"
transform="scale(-0.4)"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path6671-2" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker7139-9"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutM">
<path
inkscape:connector-curvature="0"
transform="scale(0.4)"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path7137-9" />
</marker>
<marker
inkscape:stockid="TriangleInM"
orient="auto"
refY="0"
refX="0"
id="marker14051-8"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path14049-1"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="scale(-0.4)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker7942-3"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutM">
<path
inkscape:connector-curvature="0"
transform="scale(0.4)"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path7940-1" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8284271"
inkscape:cx="62.552344"
inkscape:cy="945.78705"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
showguides="true"
inkscape:snap-global="false"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<flowRoot
xml:space="preserve"
id="flowRoot815"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:85.33333588px;line-height:1.25;font-family:'DejaVu Serif';-inkscape-font-specification:'DejaVu Serif';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
transform="scale(0.26458333)"><flowRegion
id="flowRegion817"
style="font-size:85.33333588px"><rect
id="rect819"
width="351.42859"
height="708.57141"
x="211.42857"
y="182.51968"
style="font-size:85.33333588px" /></flowRegion><flowPara
id="flowPara821"
style="font-size:96.00000121px">Mg</flowPara></flowRoot> <rect
style="fill:none;fill-opacity:1;stroke-width:0.26458333;stroke-miterlimit:4;stroke-dasharray:none;"
id="rect823"
width="47.624996"
height="24.209377"
x="52.255207"
y="52.260418" />
<rect
style="fill:none;fill-opacity:1;stroke-width:0.26458333;stroke-miterlimit:4;stroke-dasharray:none"
id="rect845"
width="47.624996"
height="24.209377"
x="52.255207"
y="52.260418" />
<path
style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 104.9316,52.260417 c -56.885887,0 -56.885887,0 -56.885887,0 v 0"
id="path849"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 104.72835,71.043661 c -56.605254,0 -56.605254,0 -56.605254,0 v 0"
id="path849-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 104.68306,76.469795 c -56.605249,0 -56.605249,0 -56.605249,0 v 0"
id="path849-8-0"
inkscape:connector-curvature="0" />
<flowRoot
transform="matrix(0.26458333,0,0,0.26458333,-0.49993439,29.92432)"
xml:space="preserve"
id="flowRoot815-2"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:85.33333588px;line-height:1.25;font-family:'DejaVu Serif';-inkscape-font-specification:'DejaVu Serif';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"><flowRegion
id="flowRegion817-1"
style="font-size:85.33333588px"><rect
id="rect819-0"
width="351.42859"
height="708.57141"
x="211.42857"
y="182.51968"
style="font-size:85.33333588px" /></flowRegion><flowPara
id="flowPara821-5"
style="font-size:96px">Mg</flowPara></flowRoot> <rect
style="fill:none;fill-opacity:1;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none"
id="rect823-1"
width="47.624996"
height="24.209377"
x="51.75528"
y="82.184738" />
<rect
style="fill:none;fill-opacity:1;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none"
id="rect845-1"
width="47.624996"
height="24.209377"
x="51.75528"
y="82.184738" />
<path
style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 104.80585,82.184738 c -57.07298,0 -57.07298,0 -57.07298,0 v 0"
id="path849-0"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 104.88322,100.82767 c -56.885878,0 -56.885878,0 -56.885878,0 v 0"
id="path849-8-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 104.83794,106.39412 c -56.979428,0 -56.979428,0 -56.979428,0 v 0"
id="path849-8-0-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.25984162px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#TriangleInM);marker-end:url(#TriangleOutM)"
d="m 102.52459,70.326803 c -0.0936,-17.322528 -0.0936,-17.322528 -0.0936,-17.322528"
id="path920"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26465496px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker6673);marker-end:url(#marker7139)"
d="m 102.45365,72.131518 c -0.13882,3.407593 -0.13882,3.407593 -0.13882,3.407593"
id="path10620"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:Cantarell;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="107.29259"
y="62.917221"
id="text13750"><tspan
sodipodi:role="line"
id="tspan13748"
x="107.29259"
y="62.917221"
style="stroke-width:0.26458332">Ascent</tspan><tspan
sodipodi:role="line"
x="107.29259"
y="68.208885"
style="stroke-width:0.26458332"
id="tspan13752" /></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:Cantarell;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="107.10825"
y="74.800102"
id="text13756"><tspan
sodipodi:role="line"
id="tspan13754"
x="107.10825"
y="74.800102"
style="stroke-width:0.26458332">Descent</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.26465496px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker6673-6);marker-end:url(#marker7139-9)"
d="m 49.428752,77.64513 c -0.13882,3.407594 -0.13882,3.407594 -0.13882,3.407594"
id="path10620-0"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:Cantarell;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="28.730095"
y="80.757591"
id="text14031"><tspan
sodipodi:role="line"
id="tspan14029"
x="28.730095"
y="80.757591"
style="stroke-width:0.26458332">Spacing</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.26399428px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker14051);marker-end:url(#marker7942)"
d="M 102.41047,105.39271 C 102.21678,77.415754 102.21678,77.415754 102.21678,77.415754"
id="path14041"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.26399428px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker14051-8);marker-end:url(#marker7942-3)"
d="M 53.385014,99.776343 C 53.19133,71.79943 53.19133,71.79943 53.19133,71.79943"
id="path14041-1"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:Cantarell;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="107.14215"
y="92.602859"
id="text16168"><tspan
sodipodi:role="line"
id="tspan16166"
x="107.14215"
y="92.602859"
style="stroke-width:0.26458332">Height</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333333px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;"
x="12.434073"
y="62.795258"
id="text16172"><tspan
sodipodi:role="line"
id="tspan16188">Baseline-to-baseline</tspan><tspan
sodipodi:role="line"
id="tspan16190">distance</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.12913886;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 53.1315,74.164103 c 0,0 -4.818074,0.125651 -7.969503,-0.151187 -2.845534,-0.249967 -5.290399,-0.985067 -7.513672,-1.679659 -4.72719,-1.476863 -7.250826,-3.884947 -7.250826,-3.884947"
id="path16192"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

@@ -0,0 +1,275 @@
gidocgen = find_program('gi-docgen', required: get_option('documentation'), native: true)
gidocgen_common_args = [
'--quiet',
'--no-namespace-dir',
]
if get_option('werror')
gidocgen_common_args += ['--fatal-warnings']
endif
docs_dir = pango_datadir / 'doc'
if get_option('documentation') and not build_gir
error('API reference requires introspection.')
endif
pango_content_files = [
'pango_rendering.md',
'pango_markup.md',
'pango_fonts.md',
'pango_bidi.md',
'pango-name.png',
'layout-light.png',
'layout-dark.png',
'pipeline-light.png',
'pipeline-dark.png',
'rects1.png',
'rects2.png',
'rects3.png',
'arabic-markup.png',
'blue-text.png',
'align-left.png',
'align-center.png',
'align-right.png',
'align-left-justify.png',
'align-center-justify.png',
'align-right-justify.png',
'vertical-light.png',
'vertical-dark.png',
'm-south.png',
'm-west.png',
'm-north.png',
'm-east.png',
'bidi-input-light.png',
'bidi-input-dark.png',
'bidi-annotate-light.png',
'bidi-annotate-dark.png',
'split-cursor.png',
'split-cursor-light.png',
'split-cursor-dark.png',
'fontmetrics-light.png',
'fontmetrics-dark.png',
'caret-metrics-light.png',
'caret-metrics-dark.png',
'cursor-positions-light.png',
'cursor-positions-dark.png',
'glyphstring-positions-light.png',
'glyphstring-positions-dark.png',
'baseline-shift-light.png',
'baseline-shift-dark.png',
]
doc_conf = configuration_data()
doc_conf.set('PANGO_VERSION', meson.project_version())
if get_option('documentation')
pango_toml = configure_file(input: 'pango.toml.in',
output: 'pango.toml',
configuration: doc_conf)
custom_target('pango-doc',
input: pango_gir[0],
output: 'Pango',
command: [
gidocgen,
'generate',
gidocgen_common_args,
'--add-include-path=@0@'.format(meson.current_build_dir() / '../pango'),
'--config', pango_toml,
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_source_dir()),
'@INPUT@',
],
depend_files: [ pango_toml, pango_content_files],
build_by_default: true,
install: true,
install_dir: docs_dir,
)
if build_pangoft2
pangoft2_toml = configure_file(input: 'pangoft2.toml.in',
output: 'pangoft2.toml',
configuration: doc_conf)
custom_target('pangoft-doc',
input: pangoft2_gir[0],
output: 'PangoFT2',
command: [
gidocgen,
'generate',
gidocgen_common_args,
'--add-include-path=@0@'.format(meson.current_build_dir() / '../pango'),
'--config', pangoft2_toml,
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_source_dir()),
'@INPUT@',
],
depend_files: [ pangoft2_toml, 'pango-name.png' ],
build_by_default: true,
install: true,
install_dir: docs_dir,
)
endif
if xft_dep.found() and fontconfig_dep.found()
pangoxft_toml = configure_file(input: 'pangoxft.toml.in',
output: 'pangoxft.toml',
configuration: doc_conf)
custom_target('pangoxft-doc',
input: pangoxft_gir[0],
output: 'PangoXft',
command: [
gidocgen,
'generate',
gidocgen_common_args,
'--add-include-path=@0@'.format(meson.current_build_dir() / '../pango'),
'--config', pangoxft_toml,
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_source_dir()),
'@INPUT@',
],
depend_files: [ pangoxft_toml, 'pango-name.png' ],
build_by_default: true,
install: true,
install_dir: docs_dir,
)
endif
if cairo_dep.found()
pangocairo_content_files = [
'pango_cairo.md',
'pango-name.png',
'rotated-text.png',
]
pangocairo_toml = configure_file(input: 'pangocairo.toml.in',
output: 'pangocairo.toml',
configuration: doc_conf)
custom_target('pangocairo-doc',
input: pangocairo_gir[0],
output: 'PangoCairo',
command: [
gidocgen,
'generate',
gidocgen_common_args,
'--add-include-path=@0@'.format(meson.current_build_dir() / '../pango'),
'--config', pangocairo_toml,
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_source_dir()),
'@INPUT@',
],
depend_files: [ pangocairo_toml, pangocairo_content_files ],
build_by_default: true,
install: true,
install_dir: docs_dir,
)
endif
if fontconfig_dep.found()
pangoot_toml = configure_file(input: 'pangoot.toml.in',
output: 'pangoot.toml',
configuration: doc_conf)
custom_target('pangoot-doc',
input: pangoot_gir[0],
output: 'PangoOT',
command: [
gidocgen,
'generate',
gidocgen_common_args,
'--add-include-path=@0@'.format(meson.current_build_dir() / '../pango'),
'--config', pangoot_toml,
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_source_dir()),
'@INPUT@',
],
depend_files: [ pangoot_toml, 'pango-name.png' ],
build_by_default: true,
install: true,
install_dir: docs_dir,
)
pangofc_toml = configure_file(input: 'pangofc.toml.in',
output: 'pangofc.toml',
configuration: doc_conf)
custom_target('pangofc-doc',
input: pangofc_gir[0],
output: 'PangoFc',
command: [
gidocgen,
'generate',
gidocgen_common_args,
'--add-include-path=@0@'.format(meson.current_build_dir() / '../pango'),
'--config', pangofc_toml,
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_source_dir()),
'@INPUT@',
],
depend_files: [ pangofc_toml, 'pango-name.png' ],
build_by_default: true,
install: true,
install_dir: docs_dir,
)
endif
endif
rst2man = find_program('rst2man', 'rst2man.py', required: get_option('man-pages'))
rst2html5 = find_program('rst2html5', 'rst2html5.py', required: get_option('documentation'))
rst_files = [
[ 'pango-view', '1' ],
[ 'pango-list', '1' ],
[ 'pango-segmentation', '1' ],
]
rst2x_flags = [
'--syntax-highlight=none',
]
if get_option('man-pages')
foreach rst: rst_files
man_name = rst[0]
man_section = rst.get(1, '1')
custom_target('man-@0@'.format(man_name),
input: '@0@.rst'.format(man_name),
output: '@0@.@1@'.format(man_name, man_section),
command: [
rst2man,
rst2x_flags,
'@INPUT@',
],
capture: true,
install: true,
install_dir: get_option('mandir') / 'man@0@'.format(man_section),
install_tag: 'doc',
)
endforeach
endif
if get_option('documentation')
foreach rst: rst_files
man_name = rst[0]
custom_target(
input: '@0@.rst'.format(man_name),
output: '@0@.html'.format(man_name),
command: [
rst2html5,
rst2x_flags,
'@INPUT@',
],
capture: true,
install: true,
install_dir: docs_dir / 'Pango',
install_tag: 'doc',
)
endforeach
endif
@@ -0,0 +1,49 @@
.. _pango-list(1):
==========
pango-list
==========
----------------------
Pango font enumeration
----------------------
:Version: Pango
:Manual section: 1
:Manual group: Pango commands
SYNOPSIS
--------
| **pango-list** [OPTIONS...]
DESCRIPTION
-----------
``pango-list`` enumerates fonts using Pangos font map apis.
HELP OPTIONS
------------
``-h, --help``
Show help options.
``--version``
Print the command's version and exit.
APPLICATION OPTIONS
-------------------
``--verbose``
Print verbose information.
``--metrics``
Print font metrics.
``--variations``
Print font variations.
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1,50 @@
.. _pango-segmentation(1):
==================
pango-segmentation
==================
-----------------------
Pango text segmentation
-----------------------
:Version: Pango
:Manual section: 1
:Manual group: Pango commands
SYNOPSIS
--------
| **pango-segmentation** [OPTIONS...] [FILE]
DESCRIPTION
-----------
``pango-segmentation`` shows text boundaries determined by Pango.
These can be graphemes (cursor positions), words boundaries, word
starts and ends, line break possibilities, sentence boundaries, or
sentence starts and ends.
HELP OPTIONS
------------
``-h, --help``
Show help options.
``--version``
Print the command's version and exit.
APPLICATION OPTIONS
-------------------
``--text=STRING``
Text to display (instead of ``FILE``).
``--kind=KIND``
The boundary to show. ``KIND`` can be one of grapheme, word, words, line, sentence,
sentences. (default: grapheme).
@@ -0,0 +1,211 @@
.. _pango-view(1):
==========
pango-view
==========
-----------------
Pango text viewer
-----------------
:Version: Pango
:Manual section: 1
:Manual group: Pango commands
SYNOPSIS
--------
| **pango-view** [OPTIONS...] FILE
DESCRIPTION
-----------
``pango-view`` formats a text using Pango, with options to exercise
most of Pango's layout features.
HELP OPTIONS
------------
``-h, --help``
Show help options.
``--help-all``
Show all help options.
``--help-cairo``
Show help for options understood by the cairo backend.
``--version``
Print the command's version and exit.
CAIRO BACKEND OPTIONS
---------------------
``--annotate=FLAGS``
Annotate the output. Comma-separated list of gravity, progression, baselines,
layout, line, run, cluster, char, glyph, caret, slope
APPLICATION OPTIONS
-------------------
``--no-auto-dir``
No layout direction according to contents.
``--backend=cairo/xft/ft2``
Pango backend to use for rendering (default: cairo).
``--background=red/#rrggbb/#rrggbbaa/transparent``
Set the background color.
``-q, --no-display``
Do not display (just write to file or whatever).
``--dpi=number``
Set the resolution.
``--align=left/center/right``
Set text alignment.
``--ellipsize=start/middle/end``
Set ellipsization mode.
``--font=description``
Set the font description.
``--foreground=red/#rrggbb/#rrggbbaa``
Set the text color.
``--gravity=south/east/north/west/auto``
Set base gravity: glyph rotation.
``--gravity-hint=natural/strong/line``
Set gravity hint.
``--header``
Display the options in the output.
``--height=+points/-numlines``
Set height in points (positive) or number of lines (negative) for ellipsizing.
``--hinting=none/auto/slight/medium/full``
Set hinting style.
``--antialias=none/gray/subpixel``
Set antialiasing.
``--hint-metrics=on/off``
Set hint metrics.
``--subpixel-positions``
Set subpixel positioning.
``--subpixel-order=rgb/bgr/vrgb/vbgr``
Set subpixel order.
``--indent=points``
Set paragraph indentation (in points).
``--spacing=points``
Set line spacing (in points).
``--line-spacing=factor``
Set spread factor for line height.
``--justify``
Stretch paragraph lines to be justified.
``--justify-last-line``
Justify the last line of the paragraph.
``--language=en_US/etc``
Set language to use for font selection.
``--margin=CSS-style numbers in pixels``
Set the margin on the output in pixels.
``--markup``
Interpret text as Pango markup.
``-o, --output=file``
Save rendered image to output file.
``--pixels``
Use pixel units instead of points (sets dpi to 72).
``--pango-units``
Use Pango units instead of points.
``--rtl``
Set base direction to right-to-left.
``--rotate=degrees``
Set angle at which to rotate results,
``-n, --runs=integer``
Run Pango layout engine this many times.
``--single-par``
Enable single-paragraph mode.
``-t, --text=string``
Text to display (instead of a file).
``--waterfall``
Create a waterfall display.
``-w, --width=points``
Width in points to which to wrap lines or ellipsize.
``--wrap=word/char/word-char``
Text wrapping mode (needs a width to be set).
``--serialized=FILE``
Create layout from a serialized file,
``--serialize-to=FILE``
Serialize result to a file.
@@ -0,0 +1,112 @@
[library]
namespace = "Pango"
version = "@PANGO_VERSION@"
browse_url = "https://gitlab.gnome.org/GNOME/pango/"
repository_url = "https://gitlab.gnome.org/GNOME/pango.git"
docs_url = "https://docs.gtk.org/Pango"
website_url = "https://www.pango.org"
authors = "Owen Taylor, Behdad Esfahbod"
logo_url = "pango-name.png"
license = "LGPL-2.1-or-later"
description = "Internationalized text layout and rendering"
dependencies = [ "GObject-2.0", "HarfBuzz-0.0", "PangoCairo-1.0",
"PangoFc-1.0", "PangoFT2-1.0", "PangoOT-1.0",
"PangoXft-1.0" ]
related = [ "PangoCairo-1.0", "PangoFc-1.0", "PangoFT2-1.0", "PangoOT-1.0",
"PangoXft-1.0" ]
devhelp = true
search_index = true
[dependencies."GObject-2.0"]
name = "GObject"
description = "The base type system library"
docs_url = "https://docs.gtk.org/gobject/"
[dependencies."HarfBuzz-0.0"]
name = "HarfBuzz"
description = "A text shaping library"
docs_url = "https://harfbuzz.github.io/"
[related."PangoCairo-1.0"]
name = "PangoCairo"
description = "Cairo support for Pango"
docs_url = "../PangoCairo/"
[related."PangoFc-1.0"]
name = "PangoFc"
description = "Fontconfig support for Pango"
docs_url = "../PangoFc/"
[related."PangoFT2-1.0"]
name = "PangoFT2"
description = "FreeType support for Pango"
docs_url = "../PangoFT2/"
[related."PangoOT-1.0"]
name = "PangoOT"
description = "OpenType support for Pango"
docs_url = "../PangoOT/"
[related."PangoXft-1.0"]
name = "PangoXft"
description = "Xft support for Pango"
docs_url = "../PangoXft/"
[theme]
name = "basic"
show_index_summary = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/pango/-/blob/main/"
[extra]
content_files = [
"pango_rendering.md",
"pango_markup.md",
"pango_fonts.md",
"pango_bidi.md",
"tools.md",
]
content_images = [
"pango-name.png",
"layout-light.png",
"layout-dark.png",
"pipeline-light.png",
"pipeline-dark.png",
"rects1.png",
"rects2.png",
"rects3.png",
"arabic-markup.png",
"blue-text.png",
"align-left.png",
"align-center.png",
"align-right.png",
"align-left-justify.png",
"align-center-justify.png",
"align-right-justify.png",
"vertical-light.png",
"vertical-dark.png",
"m-south.png",
"m-west.png",
"m-north.png",
"m-east.png",
"bidi-input-light.png",
"bidi-input-dark.png",
"bidi-annotate-light.png",
"bidi-annotate-dark.png",
"split-cursor-light.png",
"split-cursor-dark.png",
"fontmetrics-light.png",
"fontmetrics-dark.png",
"caret-metrics-light.png",
"caret-metrics-dark.png",
"cursor-positions-light.png",
"cursor-positions-dark.png",
"glyphstring-positions-light.png",
"glyphstring-positions-dark.png",
"baseline-shift-light.png",
"baseline-shift-dark.png",
]
urlmap_file = "urlmap.js"
@@ -0,0 +1,65 @@
pango_alignment_get_type
pango_attr_iterator_get_type
pango_attr_list_get_type
pango_attr_type_get_type
pango_attribute_get_type
pango_bidi_type_get_type
pango_cairo_fc_font_get_type
pango_cairo_fc_font_map_get_type
pango_cairo_font_get_type
pango_cairo_font_map_get_type
pango_cairo_renderer_get_type
pango_color_get_type
pango_context_get_type
pango_coverage_get_type
pango_coverage_level_get_type
pango_direction_get_type
pango_ellipsize_mode_get_type
pango_engine_get_type
pango_engine_lang_get_type
pango_engine_shape_get_type
pango_fc_decoder_get_type
pango_fc_font_get_type
pango_fc_font_map_get_type
pango_font_description_get_type
pango_font_face_get_type
pango_font_family_get_type
pango_font_get_type
pango_font_map_get_type
pango_font_mask_get_type
pango_font_metrics_get_type
pango_fontset_get_type
pango_fontset_simple_get_type
pango_ft2_font_get_type
pango_ft2_font_map_get_type
pango_ft2_renderer_get_type
pango_glyph_item_get_type
pango_glyph_item_iter_get_type
pango_glyph_string_get_type
pango_gravity_get_type
pango_gravity_hint_get_type
pango_item_get_type
pango_language_get_type
pango_layout_get_type
pango_layout_iter_get_type
pango_layout_line_get_type
pango_matrix_get_type
pango_ot_info_get_type
pango_ot_ruleset_get_type
pango_render_part_get_type
pango_renderer_get_type
pango_script_get_type
pango_script_iter_get_type
pango_shape_flags_get_type
pango_show_flags_get_type
pango_stretch_get_type
pango_style_get_type
pango_tab_align_get_type
pango_tab_array_get_type
pango_underline_get_type
pango_variant_get_type
pango_weight_get_type
pango_wrap_mode_get_type
pango_xft_font_get_type
pango_xft_font_map_get_type
pango_xft_renderer_get_type
@@ -0,0 +1,79 @@
---
Title: Bidirectional and Vertical Text
---
# Bidirectional Text
Pango supports bidirectional text (like Arabic and Hebrew) automatically.
Some applications however, need some help to correctly handle bidirectional text.
The [enum@Pango.Direction] type can be used with [method@Pango.Context.set_base_dir]
to instruct Pango about direction of text, though in most cases Pango detects
that correctly and automatically. For application that need more direct
control over bidirectional setting of text, Pango provides APIs such as
[func@unichar_direction], [func@find_base_dir], [func@get_mirror_char]
or [func@Pango.BidiType.for_unichar].
Here is an example for mixed-direction text (shown in logical order):
<picture>
<source srcset="bidi-input-dark.png" media="(prefers-color-scheme: dark)">
<img alt="mixed-direction text, logical order" src="bidi-input-light.png">
</picture>
(the text to copy is: abאב12αβ )
Pango reorders the text according to the direction of the runs:
<picture>
<source srcset="bidi-annotate-dark.png" media="(prefers-color-scheme: dark)">
<img alt="mixed-direction text, visual order" src="bidi-annotate-light.png">
</picture>
# Vertical Text
Pango is not only capable of vertical text layout, it can handle mixed vertical
and non-vertical text correctly. This section describes the types used for setting
vertical text parameters.
<picture>
<source srcset="vertical-dark.png" media="(prefers-color-scheme: dark)">
<img alt="gravity west, rotated 90 degrees" align="right" valign="top" src="vertical-light.png">
</picture>
The way this is implemented is through the concept of *gravity*. Gravity tells glyphs which way is down, so the gravity of normal Latin text is south. A gravity value of east means that glyphs will be rotated ninety degrees
counterclockwise. So, to render vertical text one needs
to set the gravity and rotate the layout using the matrix machinery already
in place. This has the huge advantage that most algorithms working on a
[class@Pango.Layout] do not need any change as the assumption that lines run
in the X direction and stack in the Y direction holds even for vertical text
layouts.
Here is an example for some English text rendered with gravity west, rotated 90 degrees:
Applications should only need to set base gravity on [class@Pango.Context] in use,
and let Pango decide the gravity assigned to each run of text. This automatically
handles text with mixed scripts. A very common use is to set the context base
gravity to auto using [method@Pango.Context.set_base_gravity] and rotate the layout
normally. Pango will make sure that Asian languages take the right form, while
other scripts are rotated normally.
The correct way to set gravity on a layout is to set it on the context associated
with it using [method@Pango.Context.set_base_gravity]. The context of a layout can
be accessed using [method@Pango.Layout.get_context]. The currently set base gravity
of the context can be accessed using [method@Pango.Context.get_base_gravity] and the
*resolved* gravity of it using [method@Pango.Context.get_gravity]. The resolved
gravity is the same as the base gravity for the most part, except that if the base
gravity is set to `PANGO_GRAVITY_AUTO`, the resolved gravity will depend on the
current matrix set on context, and is derived using [func@Pango.Gravity.get_for_matrix].
The next thing an application may want to set on the context is the *gravity hint*.
A [enum@Pango.GravityHint] instructs how different scripts should react to the set
base gravity.
Font descriptions have a gravity property too, that can be set using
[method@Pango.FontDescription.set_gravity] and accessed using
[method@Pango.FontDescription.get_gravity]. However, those are rarely useful
from application code and are mainly used by `PangoLayout` internally.
Last but not least, one can create `PangoAttributes` for gravity and gravity
hint using [func@attr_gravity_new] and [func@attr_gravity_hint_new].
@@ -0,0 +1,129 @@
---
Title: Rendering with Cairo
---
# Rendering with Cairo
The Cairo library is a vector graphics library with a powerful rendering model.
It has such features as anti-aliased primitives, alpha-compositing, and gradients.
Multiple backends for Cairo are available, to allow rendering to images, to PDF
files, and to the screen on X and on other windowing systems. The functions in
this section allow using Pango to render to Cairo surfaces.
Using Pango with Cairo is straightforward. A `PangoContext` created with
pango_cairo_font_map_create_context() can be used on any Cairo context (`cairo_t`),
but needs to be updated to match the current transformation matrix and target
surface of the Cairo context using pango_cairo_update_context(). The convenience
functions pango_cairo_create_layout() and pango_cairo_update_layout() handle
the common case where the program doesn't need to manipulate the properties of
the `PangoContext`.
When you get the metrics of a layout or of a piece of a layout using functions
such as pango_layout_get_extents(), the reported metrics are in user-space
coordinates. If a piece of text is 10 units long, and you call
`cairo_scale (cr, 2.0)`, it still is more-or-less 10 units long. However, the
results will be affected by hinting (that is, the process of adjusting the text
to look good on the pixel grid), so you shouldn't assume they are completely
independent of the current transformation matrix. Note that the basic metrics
functions in Pango report results in integer Pango units. To get to the floating
point units used in Cairo divide by `PANGO_SCALE`.
## Using Pango with Cairo
```
#include <math.h>
#include <pango/pangocairo.h>
#define RADIUS 150
#define N_WORDS 10
#define FONT "Sans Bold 27"
static void
draw_text (cairo_t *cr)
{
PangoLayout *layout;
PangoFontDescription *desc;
int i;
/* Center coordinates on the middle of the region we are drawing */
cairo_translate (cr, RADIUS, RADIUS);
/* Create a PangoLayout, set the font and text */
layout = pango_cairo_create_layout (cr);
pango_layout_set_text (layout, "Text", -1);
desc = pango_font_description_from_string (FONT);
pango_layout_set_font_description (layout, desc);
pango_font_description_free (desc);
/* Draw the layout N_WORDS times in a circle */
for (i = 0; i < N_WORDS; i++)
{
int width, height;
double angle = (360. * i) / N_WORDS;
double red;
cairo_save (cr);
/* Gradient from red at angle == 60 to blue at angle == 240 */
red = (1 + cos ((angle - 60) * G_PI / 180.)) / 2;
cairo_set_source_rgb (cr, red, 0, 1.0 - red);
cairo_rotate (cr, angle * G_PI / 180.);
/* Inform Pango to re-layout the text with the new transformation */
pango_cairo_update_layout (cr, layout);
pango_layout_get_size (layout, &width, &height);
cairo_move_to (cr, - ((double)width / PANGO_SCALE) / 2, - RADIUS);
pango_cairo_show_layout (cr, layout);
cairo_restore (cr);
}
/* free the layout object */
g_object_unref (layout);
}
int
main (int argc, char **argv)
{
cairo_t *cr;
char *filename;
cairo_status_t status;
cairo_surface_t *surface;
if (argc != 2)
{
g_printerr ("Usage: cairosimple OUTPUT_FILENAME\n");
return 1;
}
filename = argv[1];
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
2 * RADIUS, 2 * RADIUS);
cr = cairo_create (surface);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_paint (cr);
draw_text (cr);
cairo_destroy (cr);
status = cairo_surface_write_to_png (surface, filename);
cairo_surface_destroy (surface);
if (status != CAIRO_STATUS_SUCCESS)
{
g_printerr ("Could not save png to '%s'\n", filename);
return 1;
}
return 0;
}
```
Once you build and run the example code above, you should see the
following result:
![Output of rotated-example](rotated-text.png)
@@ -0,0 +1,65 @@
---
Title: Fonts and Glyphs
---
# Fonts
Pango supports a flexible architecture where a particular rendering architecture
can supply an implementation of fonts. The `PangoFont` structure represents an
abstract rendering-system-independent font. Pango provides routines to list
available fonts, and to load a font matching a given description.
Conceptually, Pango groups fonts into faces and families which are identified
by a name. A *font face* provides the different sizes of a single font style.
A *font family* provides the available styles of a font.
As an example, "Helvetica" is a family, "Helvetica Bold" is a face of this
family, and "Helvetica Bold 12pt" is a concrete font of this face.
# Font Enumeration
The central object for dealing with the available fonts on a system and caching
loaded fonts is a [class@Pango.FontMap]. An application typically uses a single
font map.
Since the font map depends on the rendering architecture in use, you'll need to
use the backend function pango_cairo_font_map_get_default() to obtain the default
fontmap. Depending on the platform, it will return a `PangoCairoFcFontMap`, a
`PangoCairoWin32FontMap` or a `PangoCairoCoreTextFontMap`.
Once you have a fontmap, you can enumerate the available font families with
[method@Pango.FontMap.list_families]. To enumerate the faces of a font family,
use [method@Pango.FontFamily.list_faces].
# Font Descriptions
Since loading fonts uses system resources, Pango provides a way to describe
a font without loading it. A [struct@Pango.FontDescription] is a struct that
contains enough information to load a concrete font with
[method@Pango.FontMap.load_font] or [method@Pango.Context.load_font]. You can
obtain a font description from a font face using [method@Pango.FontFace.describe],
or by parsing a string such as
Helvetica Bold 12pt
with [func@Pango.FontDescription.from_string].
# Glyphs
A font provides information about glyphs and how to position and render them.
The Pango rendering pipeline uses this information to create a
[struct@Pango.GlyphString], which contains the glyphs corresponding to the
characters in the text and related information such as glyph positions and sizes,
and clustering information (i.e. which glyphs correspond to which characters).
![A glyph string](rects3.png)
A glyph is identified by a [alias@Pango.Glyph], which is a numeric ID. Note that
glyph IDs are font-specific: the same character can be represented by diffferent
glyph IDs in different fonts.
The mapping between characters and glyphs is in general neither 1-1 nor a map:
a single glyph may represent multiple characters (as is the case with ligatures),
a single character may be represented by multiple glyphs (for example, when
combining accents and base character), and in complex scripts, multiple characters
may form clusters that get rearranged and represented by multiple glyphs.
@@ -0,0 +1,249 @@
---
Title: Text Attributes and Markup
---
# Text Attributes
Attributed text is used in a number of places in Pango. It is used as the
input to the itemization process and also when creating a [class@Pango.Layout].
Attributes can influence the various stages of the rendering pipeline. For example,
font or size attributes will influence the font selection that is happening during
itemization, font features and letterspacing attributes will influence shaping, and
color or underline attributes will be used for rendering.
Pango uses a simple structs for individual attributes, such as
[struct@Pango.AttrColor] or [struct@Pango.AttrFontDesc]. Each attribute has a type,
and a start and end index that determine the range of characters that the attribute
applies to. See the [enum@Pango.AttrType] enumeration for all the possible
attribute types.
Attributes rarely come alone. Pango uses the [struct@Pango.AttrList] structure
to hold all attributes that apply to a piece of text.
# Pango Markup
Frequently, you want to display some text to the user with attributes applied to
part of the text (for example, you might want bold or italicized words). With the
base Pango interfaces, you could create a [struct@Pango.AttrList] and apply it to
the text; the problem is that you'd need to apply attributes to some numeric range
of characters, for example "characters 12-17." This is broken from an
internationalization standpoint; once the text is translated, the word you wanted
to italicize could be in a different position.
The solution is to include the text attributes in the string to be translated.
Pango provides this feature with a small markup language. You can parse a marked-up
string into the string text plus a [struct@Pango.AttrList] using either of
[func@parse_markup] or [func@markup_parser_new].
A simple example of a marked-up string might be:
```
<span foreground="blue" size="x-large">Blue text</span> is <i>cool</i>!
```
![Markup example](blue-text.png)
A more elaborate example of using markup to color combining marks in
Arabic text:
```
<span foreground="purple">ا</span><span foreground="red">َ</span>ل<span foreground="blue">ْ</span>ع<span foreground="red">َ</span>ر<span foreground="red">َ</span>ب<span foreground="red">ِ</span>ي<span foreground="green">ّ</span><span foreground="red">َ</span>ة<span foreground="blue">ُ</span>
```
![Markup example](arabic-markup.png)
Pango uses GMarkup to parse this language, which means that XML features
such as numeric character entities such as `&#169;` for © can be used too.
The root tag of a marked-up document is `<markup>`, but [func@Pango.parse_markup]
allows you to omit this tag, so you will most likely never need to use it.
The most general markup tag is `<span>`, then there are some convenience
tags.
## The `<span>` Attributes
font
font_desc
: A font description string, such as "Sans Italic 12". See
[func@Pango.FontDescription.from_string] for a description of the format of
the string representation. Note that any other span attributes will override
this description. So if you have "Sans Italic" and also a style="normal"
attribute, you will get Sans normal, not italic.
font_family
face
: A font family name.
font_size
size
: Font size in 1024ths of a point, or in points (e.g. '12.5pt'), or one of the
absolute sizes 'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large',
'xx-large', or a percentage (e.g. '200%'), or one of the relative sizes 'smaller'
or 'larger'.
If you want to specify a absolute size, it's usually easier to take advantage
of the ability to specify a partial font description using 'font'; you can use
font='12.5' rather than size='12800' or size='12.5pt'.
Support for specifying font sizes in points or as percentages was added in
Pango 1.50.
font_style
style
: One of 'normal', 'oblique', 'italic'.
font_weight
weight
: One of 'ultralight', 'light', 'normal', 'bold', 'ultrabold', 'heavy', or a
numeric weight.
font_variant
variant
: One of 'normal', 'small-caps', 'all-small-caps', 'petite-caps', 'all-petite-caps',
'unicase', 'title-caps'. Values other than 'normal' and 'small-caps' are available
since 1.50.
font_stretch
stretch
: One of 'ultracondensed', 'extracondensed',
'condensed', 'semicondensed', 'normal', 'semiexpanded', 'expanded',
'extraexpanded', 'ultraexpanded'.
font_features
: A comma-separated list of OpenType font feature settings, in the same syntax as
accepted by CSS. E.g: `font_features='dlig=1, -kern, afrc on'`.
foreground
fgcolor
color
: An RGB color specification such as '#00FF00' or a color name such as 'red'.
Since 1.38, an RGBA color specification such as '#00FF007F' will be interpreted
as specifying both a foreground color and foreground alpha.
background
bgcolor
: An RGB color specification such as '#00FF00' or a color name such as 'red'.
Since 1.38, an RGBA color specification such as '#00FF007F' will be interpreted
as specifying both a background color and background alpha.
alpha
fgalpha
: An alpha value for the foreground color, either a plain integer between 1 and
65536 or a percentage value like '50%'.
background_alpha
bgalpha
: An alpha value for the background color, either a plain integer between 1 and
65536 or a percentage value like '50%'.
underline
: One of 'none', 'single', 'double', 'low', 'error'.
underline_color
: The color of underlines; an RGB color specification such as '#00FF00' or a color
name such as 'red'.
overline
: One of 'none' or 'single'. Overline support was added in Pango 1.46.
overline_color
: The color of overlines; an RGB color specification such as '#00FF00' or a color
name such as 'red'. Overline support was added in Pango 1.46.
rise
: Vertical displacement, in Pango units or in points (e.g. '5pt'). Can be
negative for subscript, positive for superscript.
Support for specifying rise in points was added in Pango 1.50.
baseline_shift
: Vertical displacement. In contrast to rise, baseline_shift attributes are cumulative.
The value can be a length in Pango units or in points (e.g. '5pt'), or 'superscript'
or 'subscript'. Available since 1.50.
font_scale:
: Font size change. The possible values are 'superscript', 'subscript' or 'small-caps'.
This is similar to the font_size values 'smaller' or 'larger', but uses font metrics
to find the new size. Available since 1.50.
strikethrough
: 'true' or 'false' whether to strike through the text.
strikethrough_color
: The color of strikethrough lines; an RGB color specification such as '#00FF00'
or a color name such as 'red'.
fallback
: 'true' or 'false' whether to enable fallback. If disabled, then characters will
only be used from the closest matching font on the system. No fallback will be
done to other fonts on the system that might contain the characters in the text.
Fallback is enabled by default. Most applications should not disable fallback.
lang
: A language code, indicating the text language.
letter_spacing
: Inter-letter spacing in 1024ths of a point.
gravity
: One of 'south', 'east', 'north', 'west', 'auto'.
gravity_hint
: One of 'natural', 'strong', 'line'.
show
: Specifies what special characters to show visibly. The value can be 'none'
or a combination of 'spaces', 'line-breaks' and 'ignorables', combined with '|'.
Support for showing special characters was added in Pango 1.44.
insert_hyphens
: 'true' or 'false' to indicate whether hyphens should be inserted when breaking
lines in the middle of words. Available since Pango 1.44.
allow_breaks
: 'true' or 'false' to indicate whether breaking lines is allowed. Available
since Pango 1.44.
line_height
: Overrides the line height. The value can be either a factor (< 1024) that is
used to scale up the logical extents of runs or an absolute value (in 1024th
of a point).
Available since Pango 1.50.
text_transform
: Specifies how characters are transformed during shaping. The values can be
'none', 'lowercase', 'uppercase' or 'capitalize'. Support for text transformation
was added in Pango 1.50.
segment
: Overrides word or sentence boundaries. The value can be 'word' or 'sentence',
to indicate that the span should be treated as a single word or sentence.
Overlapping segments will be split to allow this, and line breaks will be
adjusted accordingly. Available since Pango 1.50.
## Convenience Tags
`<b>`
: Bold
`<big>`
: Makes font relatively larger, equivalent to `<span size="larger">`
`<i>`
: Italic
`<s>`
: Strikethrough
`<sub>`
: Subscript
`<sup>`
: Superscript
`<small>`
: Makes font relatively smaller, equivalent to `<span size="smaller">`
`<tt>`
: Monospace font
`<u>`
: Underline
@@ -0,0 +1,40 @@
---
Title: The Rendering Pipeline
---
# The Rendering Pipeline
The Pango rendering pipeline takes a string of Unicode characters, converts them
it into glyphs, and renders them on some output medium. This section describes the
various stages of this pipeline and the APIs that implement them.
<picture>
<source srcset="pipeline-dark.png" media="(prefers-color-scheme: dark)">
<img alt="Pango Rendering Pipeline" src="pipeline-light.png">
</picture>
Itemization
: breaks a piece of text into segments with consistent direction and shaping
properties. Among other things, this determines which font to use for each
character. Use [func@Pango.itemize] or [func@Pango.itemize_with_base_dir]
to itemize text.
Shaping
: converts characters into glyphs. Use [func@Pango.shape],
[func@Pango.shape_full] or [func@Pango.shape_item] to shape text.
Line Breaking
: determines where line breaks should be inserted into a sequence of glyphs.
The functions [func@Pango.default_break], [func@Pango.tailor_break] and
[func@Pango.attr_break] determine possible line breaks. The actual line
breaking is done by [class@Pango.Layout].
Justification
: adjusts inter-word spacing to form lines of even length. This is done by
[class@Pango.Layout].
Rendering
: takes a string of positioned glyphs, and renders them onto a surface.
This is accomplished by a [class@Pango.Renderer] object. The functions
pango_cairo_show_glyph_string() and pango_cairo_show_layout() use a
[class@Pango.Renderer] to draw text onto a cairo surface.
@@ -0,0 +1,26 @@
Title: Xft Fonts and Rendering
The Xft library is a library for displaying fonts on the X window
system; internally it uses the fontconfig library to locate font
files, and the FreeType library to load and render fonts. The
Xft backend is the recommended Pango font backend for screen
display with X. (The Cairo back end is another possibility.)
Using the Xft backend is generally straightforward;
[func@PangoXft.get_context] creates a context for a specified display
and screen. You can then create a [class@Pango.Layout] with that context
and render it with [func@PangoXft.render_layout]. At a more advanced
level, the low-level fontconfig options used for rendering fonts
can be affected using [func@PangoXft.set_default_substitute], and
[func@PangoXft.substitute_changed].
A range of functions for drawing pieces of a layout, such as individual
layout lines and glyphs strings are provided. You can also directly
create a [class@PangoXft.Renderer]. Finally, in some advanced cases,
it is useful to derive from [class@PangoXft.Renderer]. Deriving from
[class@PangoXft.Renderer] is useful for two reasons. One reason is be
to support custom attributes by overriding `PangoRendererClass` virtual
functions like 'prepare_run' or 'draw_shape'. The other reason is to
customize exactly how the final bits are drawn to the destination by
overriding the `PangoXftRendererClass` virtual functions
'composite_glyphs' and 'composite_trapezoids'.
@@ -0,0 +1,43 @@
[library]
namespace = "PangoCairo"
version = "@PANGO_VERSION@"
browse_url = "https://gitlab.gnome.org/GNOME/pango/"
repository_url = "https://gitlab.gnome.org/GNOME/pango.git"
docs_url = "https://docs.gtk.org/PangoCairo"
website_url = "https://www.pango.org"
authors = "Owen Taylor, Behdad Esfahbod"
logo_url = "pango-name.png"
license = "LGPL-2.1-or-later"
description = "Cairo support for Pango"
dependencies = [ "Pango-1.0", "cairo-1.0" ]
devhelp = true
search_index = true
[dependencies."Pango-1.0"]
name = "Pango"
description = "A library for layout out and rendering of text"
docs_url = "../Pango/"
[dependencies."cairo-1.0"]
name = "cairo"
description = "A vector graphics library"
docs_url = "https://www.cairographics.org/manual/"
[theme]
name = "basic"
show_index_summary = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/pango/-/blob/main/"
[extra]
content_files = [
"pango_cairo.md",
]
content_images = [
"pango-name.png",
"rotated-text.png"
]
urlmap_file = "urlmap.js"
@@ -0,0 +1,40 @@
[library]
namespace = "PangoFc"
version = "@PANGO_VERSION@"
browse_url = "https://gitlab.gnome.org/GNOME/pango/"
repository_url = "https://gitlab.gnome.org/GNOME/pango.git"
docs_url = "https://docs.gtk.org/PangoFc"
website_url = "https://www.pango.org"
authors = "Owen Taylor, Behdad Esfahbod"
logo_url = "pango-name.png"
license = "LGPL-2.1-or-later"
description = "Fontconfig support for Pango"
dependencies = [ "Pango-1.0", "fontconfig-2.0" ]
devhelp = true
search_index = true
[dependencies."Pango-1.0"]
name = "Pango"
description = "A library for layout out and rendering of text"
docs_url = "../Pango/"
[dependencies."fontconfig-2.0"]
name = "fontconfig"
description = "A font configuration and enumeration library"
docs_url = "https://www.fontconfig.org"
[theme]
name = "basic"
show_index_summary = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/pango/-/blob/main/"
[extra]
content_images = [
"pango-name.png"
]
urlmap_file = "urlmap.js"
@@ -0,0 +1,40 @@
[library]
namespace = "PangoFT2"
version = "@PANGO_VERSION@"
browse_url = "https://gitlab.gnome.org/GNOME/pango/"
repository_url = "https://gitlab.gnome.org/GNOME/pango.git"
docs_url = "https://docs.gtk.org/PangoFT2"
website_url = "https://www.pango.org"
authors = "Owen Taylor, Behdad Esfahbod"
logo_url = "pango-name.png"
license = "LGPL-2.1-or-later"
description = "FreeType support for Pango"
dependencies = [ "Pango-1.0", "freetype2-2.0" ]
devhelp = true
search_index = true
[dependencies."Pango-1.0"]
name = "Pango"
description = "A library for layout out and rendering of text"
docs_url = "../Pango/"
[dependencies."freetype2-2.0"]
name = "freetype2"
description = "A font loading and rendering library"
docs_url = "https://www.freetype.org"
[theme]
name = "basic"
show_index_summary = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/pango/-/blob/main/"
[extra]
content_images = [
"pango-name.png"
]
urlmap_file = "urlmap.js"
@@ -0,0 +1,34 @@
[library]
namespace = "PangoOT"
version = "@PANGO_VERSION@"
browse_url = "https://gitlab.gnome.org/GNOME/pango/"
repository_url = "https://gitlab.gnome.org/GNOME/pango.git"
docs_url = "https://docs.gtk.org/PangoOT"
website_url = "https://www.pango.org"
authors = "Owen Taylor, Behdad Esfahbod"
logo_url = "pango-name.png"
license = "LGPL-2.1-or-later"
description = "OpenType support for Pango"
dependencies = [ "Pango-1.0" ]
devhelp = true
search_index = true
[dependencies."Pango-1.0"]
name = "Pango"
description = "A library for layout out and rendering of text"
docs_url = "../Pango/"
[theme]
name = "basic"
show_index_summary = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/pango/-/blob/main/"
[extra]
content_images = [
"pango-name.png"
]
urlmap_file = "urlmap.js"
@@ -0,0 +1,42 @@
[library]
namespace = "PangoXft"
version = "@PANGO_VERSION@"
browse_url = "https://gitlab.gnome.org/GNOME/pango/"
repository_url = "https://gitlab.gnome.org/GNOME/pango.git"
docs_url = "https://docs.gtk.org/PangoXft"
website_url = "https://www.pango.org"
authors = "Owen Taylor, Behdad Esfahbod"
logo_url = "pango-name.png"
license = "LGPL-2.1-or-later"
description = "Xft support for Pango"
dependencies = [ "Pango-1.0", "xft-2.0" ]
devhelp = true
search_index = true
[dependencies."Pango-1.0"]
name = "Pango"
description = "A library for layout out and rendering of text"
docs_url = "../Pango/"
[dependencies."xft-2.0"]
name = "xft"
description = "X11 client-side font rendering library"
docs_url = "https://x.org"
[theme]
name = "basic"
show_index_summary = true
[source-location]
base_url = "https://gitlab.gnome.org/GNOME/pango/-/blob/main/"
[extra]
content_files = [
"pango_xft.md"
]
content_images = [
"pango-name.png"
]
urlmap_file = "urlmap.js"
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

@@ -0,0 +1,251 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
viewBox="0 0 913.1756 82.351768"
stroke-miterlimit="10"
id="svg959"
sodipodi:docname="pipeline.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
width="913.1756"
height="82.351768"
style="fill:none;stroke:none;stroke-linecap:square;stroke-miterlimit:10">
<metadata
id="metadata965">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs963">
<marker
inkscape:stockid="Arrow2Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Mend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1042"
style="fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(-0.6)"
inkscape:connector-curvature="0" />
</marker>
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview961"
showgrid="false"
inkscape:zoom="1.0742188"
inkscape:cx="456.59634"
inkscape:cy="-178.24927"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="g957"
fit-margin-top="20"
fit-margin-left="20"
fit-margin-right="20"
fit-margin-bottom="20" />
<clipPath
id="p.0">
<path
d="M 0,0 H 1024 V 768 H 0 Z"
id="path910"
inkscape:connector-curvature="0"
style="clip-rule:nonzero" />
</clipPath>
<g
clip-path="url(#p.0)"
id="g957"
transform="translate(-59.1273,-123.39896)">
<path
d="M 0,0 H 1024 V 768 H 0 Z"
id="path913"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
<path
d="m 79.6273,143.89896 h 114.55119 v 40.56692 H 79.6273 Z"
id="path915"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
<path
d="m 79.6273,143.89896 h 114.55119 v 40.56692 H 79.6273 Z"
id="path917"
inkscape:connector-curvature="0"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round" />
<path
d="m 265.01312,143.89896 h 89.92127 v 40.56692 h -89.92127 z"
id="path921"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
<path
d="m 265.01312,143.89896 h 89.92127 v 40.56692 h -89.92127 z"
id="path923"
inkscape:connector-curvature="0"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round" />
<path
d="m 428.00525,143.89896 h 140.15747 v 40.56692 H 428.00525 Z"
id="path927"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
<path
d="m 428.00525,143.89896 h 140.15747 v 40.56692 H 428.00525 Z"
id="path929"
inkscape:connector-curvature="0"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round" />
<path
d="m 647.06036,143.89896 h 114.55121 v 40.56692 H 647.06036 Z"
id="path933"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
<path
d="m 647.06036,143.89896 h 114.55121 v 40.56692 H 647.06036 Z"
id="path935"
inkscape:connector-curvature="0"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round" />
<path
d="m 194.17848,164.18242 h 70.83464"
id="path939"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
<path
d="m 194.17848,164.18242 h 64.83464"
id="path941"
inkscape:connector-curvature="0"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round" />
<path
d="m 259.01312,165.83415 4.53809,-1.65173 -4.53809,-1.65174 z"
id="path943"
inkscape:connector-curvature="0"
style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt" />
<path
d="m 354.9344,164.18242 h 73.07086"
id="path945"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
<path
d="m 354.9344,164.18242 h 67.07086"
id="path947"
inkscape:connector-curvature="0"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round" />
<path
d="m 422.00525,165.83415 4.53809,-1.65173 -4.53809,-1.65174 z"
id="path949"
inkscape:connector-curvature="0"
style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt" />
<path
d="m 568.1627,164.18242 h 78.89764"
id="path951"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:0;fill-rule:evenodd" />
<path
d="m 568.1627,164.18242 h 72.89764"
id="path953"
inkscape:connector-curvature="0"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round" />
<path
d="m 641.06036,165.83415 4.53809,-1.65173 -4.53809,-1.65174 z"
id="path955"
inkscape:connector-curvature="0"
style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:0;fill-rule:evenodd"
d="M 837.25167,144.68381 H 951.8029 v 40.56692 H 837.25167 Z"
id="path933-9" />
<path
inkscape:connector-curvature="0"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round"
d="M 837.25167,144.68381 H 951.8029 v 40.56692 H 837.25167 Z"
id="path935-1" />
<path
d="m 762.91845,164.77091 h 72.89764"
id="path953-9"
inkscape:connector-curvature="0"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00157475;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;marker-end:url(#Arrow2Mend)" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.66666603px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="702.94543"
y="169.18546"
id="text1281"><tspan
sodipodi:role="line"
id="tspan1279"
x="702.94543"
y="169.18546">Justification</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:Cantarell;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="95.883636"
y="158.25455"
id="text1285"><tspan
sodipodi:role="line"
id="tspan1283"
x="95.883636"
y="172.62274" /></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.66666603px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="136.84364"
y="169.70181"
id="text1289"><tspan
sodipodi:role="line"
id="tspan1291"
x="136.84364"
y="169.70181">Itemization</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.66666603px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="311.20001"
y="169.70181"
id="text1295"><tspan
sodipodi:role="line"
id="tspan1293"
x="311.20001"
y="169.70181">Shaping</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.66666603px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="496.31274"
y="169.70181"
id="text1299"><tspan
sodipodi:role="line"
id="tspan1297"
x="496.31274"
y="169.70181">Line Breaking</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.66666603px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="893.9491"
y="169.56364"
id="text1303"><tspan
sodipodi:role="line"
id="tspan1301"
x="893.9491"
y="169.56364">Rendering</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@@ -0,0 +1,9 @@
Title: Tools and Demos
Pango ships with a number of tools and demos that come with their own
documentation in the form of man pages.
- [pango-view](pango-view.html)
- [pango-list](pango-list.html)
- [pango-segmentation](pango-segmentation.html)
@@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: 2021 GNOME Foundation
// SPDX-License-Identifier: LGPL-2.1-or-later
// A map between namespaces and base URLs for their online documentation
baseURLs = [
[ 'GLib', 'https://docs.gtk.org/glib/' ],
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
[ 'Gio', 'https://docs.gtk.org/gio/' ],
[ 'Pango', 'https://docs.gtk.org/Pango/' ],
[ 'PangoCairo', 'https://docs.gtk.org/PangoCairo/' ],
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

@@ -0,0 +1,236 @@
/* Example code to show how to use pangocairo to render arbitrary shapes
* inside a text layout, positioned by Pango. This has become possibly
* using the following API added in Pango 1.18:
*
* pango_cairo_context_set_shape_renderer ()
*
* This examples uses a small parser to convert shapes in the format of
* SVG paths to cairo instructions. You can typically extract these from
* the SVG file's <path> elements directly.
*
* The code then searches for the Unicode bullet character in the layout
* text and automatically adds PangoAttribtues to the layout to replace
* each of the with a rendering of the GNOME Foot logo.
*
*
* Written by Behdad Esfahbod, 2007
*
* Permission to use, copy, modify, distribute, and sell this example
* for any purpose is hereby granted without fee.
* It is provided "as is" without express or implied warranty.
*/
#include <stdio.h>
#include <string.h>
#include <pango/pangocairo.h>
#define BULLET "•"
const char text[] =
"The GNOME project provides two things:\n"
"\n"
" • The GNOME desktop environment\n"
" • The GNOME development platform\n"
" • Planet GNOME";
typedef struct {
double width, height;
const char *path;
} MiniSvg;
static MiniSvg GnomeFootLogo = {
96.2152, 118.26,
"M 86.068,1 C 61.466,0 56.851,35.041 70.691,35.041 C 84.529,35.041 110.671,0 86.068,0 z "
"M 45.217,30.699 C 52.586,31.149 60.671,2.577 46.821,4.374 C 32.976,6.171 37.845,30.249 45.217,30.699 z "
"M 11.445,48.453 C 16.686,46.146 12.12,23.581 3.208,29.735 C -5.7,35.89 6.204,50.759 11.445,48.453 z "
"M 26.212,36.642 C 32.451,35.37 32.793,9.778 21.667,14.369 C 10.539,18.961 19.978,37.916 26.212,36.642 L 26.212,36.642 z "
"M 58.791,93.913 C 59.898,102.367 52.589,106.542 45.431,101.092 C 22.644,83.743 83.16,75.088 79.171,51.386 C 75.86,31.712 15.495,37.769 8.621,68.553 C 3.968,89.374 27.774,118.26 52.614,118.26 C 64.834,118.26 78.929,107.226 81.566,93.248 C 83.58,82.589 57.867,86.86 58.791,93.913 L 58.791,93.913 z "
"\0"
};
static void
mini_svg_render (MiniSvg *shape,
cairo_t *cr,
gboolean do_path)
{
double x, y;
const char *p;
char op[2];
int len;
cairo_get_current_point (cr, &x, &y);
cairo_translate (cr, x, y);
for (p = shape->path; sscanf (p, "%1s %n", op, &len), p += len, *p;)
switch (*op)
{
case 'M':
{
sscanf (p, "%lf,%lf %n", &x, &y, &len); p += len;
cairo_move_to (cr, x, y);
break;
}
case 'L':
{
sscanf (p, "%lf,%lf %n", &x, &y, &len); p += len;
cairo_line_to (cr, x, y);
break;
}
case 'C':
{
double x1, y1, x2, y2, x3, y3;
sscanf (p, "%lf,%lf %lf,%lf %lf,%lf %n", &x1, &y1, &x2, &y2, &x3, &y3, &len); p += len;
cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
break;
}
case 'z':
{
cairo_close_path (cr);
break;
}
default:
{
g_warning ("Invalid MiniSvg operation '%c'", *op);
break;
}
}
if (!do_path)
cairo_fill (cr);
}
static void
mini_svg_shape_renderer (cairo_t *cr,
PangoAttrShape *attr,
gboolean do_path,
gpointer data G_GNUC_UNUSED)
{
MiniSvg *shape = (MiniSvg *) attr->data;
double scale_x, scale_y;
scale_x = (double) attr->ink_rect.width / (PANGO_SCALE * shape->width );
scale_y = (double) attr->ink_rect.height / (PANGO_SCALE * shape->height);
cairo_rel_move_to (cr,
(double) attr->ink_rect.x / PANGO_SCALE,
(double) attr->ink_rect.y / PANGO_SCALE);
cairo_scale (cr, scale_x, scale_y);
mini_svg_render (shape, cr, do_path);
}
static PangoLayout *
get_layout (cairo_t *cr)
{
PangoLayout *layout;
PangoAttrList *attrs;
PangoRectangle ink_rect = {1 * PANGO_SCALE, -11 * PANGO_SCALE, 8 * PANGO_SCALE, 10 * PANGO_SCALE};
PangoRectangle logical_rect = {0 * PANGO_SCALE, -12 * PANGO_SCALE, 10 * PANGO_SCALE, 12 * PANGO_SCALE};
const char *p;
/* Create a PangoLayout, set the font and text */
layout = pango_cairo_create_layout (cr);
pango_cairo_context_set_shape_renderer (pango_layout_get_context (layout),
mini_svg_shape_renderer, NULL, NULL);
pango_layout_set_text (layout, text, -1);
attrs = pango_attr_list_new ();
/* Set gnome shape attributes for all bullets */
for (p = text; (p = strstr (p, BULLET)); p += strlen (BULLET))
{
PangoAttribute *attr;
attr = pango_attr_shape_new_with_data (&ink_rect,
&logical_rect,
&GnomeFootLogo,
NULL, NULL);
attr->start_index = p - text;
attr->end_index = attr->start_index + strlen (BULLET);
pango_attr_list_insert (attrs, attr);
}
pango_layout_set_attributes (layout, attrs);
pango_attr_list_unref (attrs);
return layout;
}
static void
draw_text (cairo_t *cr, int *width, int *height)
{
PangoLayout *layout = get_layout (cr);
/* Adds a fixed 10-pixel margin on the sides. */
if (width || height)
{
pango_layout_get_pixel_size (layout, width, height);
if (width)
*width += 20;
if (height)
*height += 20;
}
cairo_move_to (cr, 10, 10);
pango_cairo_show_layout (cr, layout);
g_object_unref (layout);
}
int main (int argc, char **argv)
{
cairo_t *cr;
char *filename;
cairo_status_t status;
cairo_surface_t *surface;
int width, height;
if (argc != 2)
{
g_printerr ("Usage: cairoshape OUTPUT_FILENAME\n");
return 1;
}
filename = argv[1];
/* First create and use a 0x0 surface, to measure how large
* the final surface needs to be */
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
0, 0);
cr = cairo_create (surface);
draw_text (cr, &width, &height);
cairo_destroy (cr);
cairo_surface_destroy (surface);
/* Now create the final surface and draw to it. */
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
width, height);
cr = cairo_create (surface);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_paint (cr);
cairo_set_source_rgb (cr, 0.0, 0.0, 0.5);
draw_text (cr, NULL, NULL);
cairo_destroy (cr);
/* Write out the surface as PNG */
status = cairo_surface_write_to_png (surface, filename);
cairo_surface_destroy (surface);
if (status != CAIRO_STATUS_SUCCESS)
{
g_printerr ("Could not save png to '%s'\n", filename);
return 1;
}
return 0;
}
@@ -0,0 +1,106 @@
/* Simple example to use pangocairo to render rotated text */
#include <math.h>
#include <pango/pangocairo.h>
static void
draw_text (cairo_t *cr)
{
#define RADIUS 200
#define N_WORDS 8
#define FONT_WITH_MANUAL_SIZE "Times new roman,Sans"
#define FONT_SIZE 36
#define DEVICE_DPI 72
/* The following number applies a cairo CTM. Tests for
* https://bugzilla.gnome.org/show_bug.cgi?id=700592
*/
#define TWEAKABLE_SCALE ((double) 0.1)
PangoLayout *layout;
PangoFontDescription *desc;
int i;
/* Center coordinates on the middle of the region we are drawing
*/
cairo_translate (cr, RADIUS / TWEAKABLE_SCALE, RADIUS / TWEAKABLE_SCALE);
/* Create a PangoLayout, set the font and text */
layout = pango_cairo_create_layout (cr);
pango_layout_set_text (layout, "Test\nسَلام", -1);
desc = pango_font_description_from_string (FONT_WITH_MANUAL_SIZE);
pango_font_description_set_absolute_size(desc, FONT_SIZE * DEVICE_DPI * PANGO_SCALE / (72.0 * TWEAKABLE_SCALE));
//pango_font_description_set_size(desc, 27 * PANGO_SCALE / TWEAKABLE_SCALE);
printf("PANGO_SCALE = %d\n", PANGO_SCALE);
pango_layout_set_font_description (layout, desc);
pango_font_description_free (desc);
/* Draw the layout N_WORDS times in a circle */
for (i = 0; i < N_WORDS; i++)
{
int width, height;
double angle = (360. * i) / N_WORDS;
double red;
cairo_save (cr);
/* Gradient from red at angle == 60 to blue at angle == 240 */
red = (1 + cos ((angle - 60) * G_PI / 180.)) / 2;
cairo_set_source_rgb (cr, red, 0, 1.0 - red);
cairo_rotate (cr, angle * G_PI / 180.);
/* Inform Pango to re-layout the text with the new transformation */
pango_cairo_update_layout (cr, layout);
pango_layout_get_size (layout, &width, &height);
cairo_move_to (cr,( - (((double)width) / PANGO_SCALE) / 2.0) , (- RADIUS) / TWEAKABLE_SCALE);
pango_cairo_show_layout (cr, layout);
cairo_restore (cr);
}
/* free the layout object */
g_object_unref (layout);
}
int main (int argc, char **argv)
{
cairo_t *cr;
char *filename;
cairo_status_t status;
cairo_surface_t *surface;
if (argc != 2)
{
g_printerr ("Usage: cairosimple OUTPUT_FILENAME\n");
return 1;
}
filename = argv[1];
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
2 * RADIUS, 2 * RADIUS);
cr = cairo_create (surface);
cairo_scale(cr, 1 * TWEAKABLE_SCALE, 1 * TWEAKABLE_SCALE);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_paint (cr);
draw_text (cr);
cairo_destroy (cr);
status = cairo_surface_write_to_png (surface, filename);
cairo_surface_destroy (surface);
if (status != CAIRO_STATUS_SUCCESS)
{
g_printerr ("Could not save png to '%s'\n", filename);
return 1;
}
return 0;
}
@@ -0,0 +1,625 @@
/* Example code to show how to use pangocairo to render text
* projected on a path.
*
*
* Written by Behdad Esfahbod, 2006..2007
*
* Permission to use, copy, modify, distribute, and sell this example
* for any purpose is hereby granted without fee.
* It is provided "as is" without express or implied warranty.
*/
#include <math.h>
#include <stdlib.h>
#include <pango/pangocairo.h>
void fancy_cairo_stroke (cairo_t *cr);
void fancy_cairo_stroke_preserve (cairo_t *cr);
/* A fancy cairo_stroke[_preserve]() that draws points and control
* points, and connects them together.
*/
static void
_fancy_cairo_stroke (cairo_t *cr, cairo_bool_t preserve)
{
int i;
double line_width;
cairo_path_t *path;
cairo_path_data_t *data;
const double dash[] = {10, 10};
cairo_save (cr);
cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
line_width = cairo_get_line_width (cr);
path = cairo_copy_path (cr);
cairo_new_path (cr);
cairo_save (cr);
cairo_set_line_width (cr, line_width / 3);
cairo_set_dash (cr, dash, G_N_ELEMENTS (dash), 0);
for (i=0; i < path->num_data; i += path->data[i].header.length) {
data = &path->data[i];
switch (data->header.type) {
case CAIRO_PATH_MOVE_TO:
case CAIRO_PATH_LINE_TO:
cairo_move_to (cr, data[1].point.x, data[1].point.y);
break;
case CAIRO_PATH_CURVE_TO:
cairo_line_to (cr, data[1].point.x, data[1].point.y);
cairo_move_to (cr, data[2].point.x, data[2].point.y);
cairo_line_to (cr, data[3].point.x, data[3].point.y);
break;
case CAIRO_PATH_CLOSE_PATH:
break;
default:
g_assert_not_reached ();
}
}
cairo_stroke (cr);
cairo_restore (cr);
cairo_save (cr);
cairo_set_line_width (cr, line_width * 4);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
for (i=0; i < path->num_data; i += path->data[i].header.length) {
data = &path->data[i];
switch (data->header.type) {
case CAIRO_PATH_MOVE_TO:
cairo_move_to (cr, data[1].point.x, data[1].point.y);
break;
case CAIRO_PATH_LINE_TO:
cairo_rel_line_to (cr, 0, 0);
cairo_move_to (cr, data[1].point.x, data[1].point.y);
break;
case CAIRO_PATH_CURVE_TO:
cairo_rel_line_to (cr, 0, 0);
cairo_move_to (cr, data[1].point.x, data[1].point.y);
cairo_rel_line_to (cr, 0, 0);
cairo_move_to (cr, data[2].point.x, data[2].point.y);
cairo_rel_line_to (cr, 0, 0);
cairo_move_to (cr, data[3].point.x, data[3].point.y);
break;
case CAIRO_PATH_CLOSE_PATH:
cairo_rel_line_to (cr, 0, 0);
break;
default:
g_assert_not_reached ();
}
}
cairo_rel_line_to (cr, 0, 0);
cairo_stroke (cr);
cairo_restore (cr);
for (i=0; i < path->num_data; i += path->data[i].header.length) {
data = &path->data[i];
switch (data->header.type) {
case CAIRO_PATH_MOVE_TO:
cairo_move_to (cr, data[1].point.x, data[1].point.y);
break;
case CAIRO_PATH_LINE_TO:
cairo_line_to (cr, data[1].point.x, data[1].point.y);
break;
case CAIRO_PATH_CURVE_TO:
cairo_curve_to (cr, data[1].point.x, data[1].point.y,
data[2].point.x, data[2].point.y,
data[3].point.x, data[3].point.y);
break;
case CAIRO_PATH_CLOSE_PATH:
cairo_close_path (cr);
break;
default:
g_assert_not_reached ();
}
}
cairo_stroke (cr);
if (preserve)
cairo_append_path (cr, path);
cairo_path_destroy (path);
cairo_restore (cr);
}
/* A fancy cairo_stroke() that draws points and control points, and
* connects them together.
*/
void
fancy_cairo_stroke (cairo_t *cr)
{
_fancy_cairo_stroke (cr, FALSE);
}
/* A fancy cairo_stroke_preserve() that draws points and control
* points, and connects them together.
*/
void
fancy_cairo_stroke_preserve (cairo_t *cr)
{
_fancy_cairo_stroke (cr, TRUE);
}
/* Returns Euclidean distance between two points */
static double
two_points_distance (cairo_path_data_t *a, cairo_path_data_t *b)
{
double dx, dy;
dx = b->point.x - a->point.x;
dy = b->point.y - a->point.y;
return sqrt (dx * dx + dy * dy);
}
/* Returns length of a Bezier curve.
* Seems like computing that analytically is not easy. The
* code just flattens the curve using cairo and adds the length
* of segments.
*/
static double
curve_length (double x0, double y0,
double x1, double y1,
double x2, double y2,
double x3, double y3)
{
cairo_surface_t *surface;
cairo_t *cr;
cairo_path_t *path;
cairo_path_data_t *data, current_point = {{0,},};
int i;
double length;
surface = cairo_image_surface_create (CAIRO_FORMAT_A8, 0, 0);
cr = cairo_create (surface);
cairo_surface_destroy (surface);
cairo_move_to (cr, x0, y0);
cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
length = 0;
path = cairo_copy_path_flat (cr);
for (i=0; i < path->num_data; i += path->data[i].header.length) {
data = &path->data[i];
switch (data->header.type) {
case CAIRO_PATH_MOVE_TO:
current_point = data[1];
break;
case CAIRO_PATH_LINE_TO:
length += two_points_distance (&current_point, &data[1]);
current_point = data[1];
break;
default:
case CAIRO_PATH_CURVE_TO:
case CAIRO_PATH_CLOSE_PATH:
g_assert_not_reached ();
}
}
cairo_path_destroy (path);
cairo_destroy (cr);
return length;
}
typedef double parametrization_t;
/* Compute parametrization info. That is, for each part of the
* cairo path, tags it with its length.
*
* Free returned value with g_free().
*/
static parametrization_t *
parametrize_path (cairo_path_t *path)
{
int i;
cairo_path_data_t *data, last_move_to = {{0,},}, current_point = {{0,},};
parametrization_t *parametrization;
parametrization = g_malloc (path->num_data * sizeof (parametrization[0]));
for (i=0; i < path->num_data; i += path->data[i].header.length) {
data = &path->data[i];
parametrization[i] = 0.0;
switch (data->header.type) {
case CAIRO_PATH_MOVE_TO:
last_move_to = data[1];
current_point = data[1];
break;
case CAIRO_PATH_CLOSE_PATH:
/* Make it look like it's a line_to to last_move_to */
data = (&last_move_to) - 1;
G_GNUC_FALLTHROUGH;
case CAIRO_PATH_LINE_TO:
parametrization[i] = two_points_distance (&current_point, &data[1]);
current_point = data[1];
break;
case CAIRO_PATH_CURVE_TO:
/* naive curve-length, treating bezier as three line segments:
parametrization[i] = two_points_distance (&current_point, &data[1])
+ two_points_distance (&data[1], &data[2])
+ two_points_distance (&data[2], &data[3]);
*/
parametrization[i] = curve_length (current_point.point.x, current_point.point.y,
data[1].point.x, data[1].point.y,
data[2].point.x, data[2].point.y,
data[3].point.x, data[3].point.y);
current_point = data[3];
break;
default:
g_assert_not_reached ();
}
}
return parametrization;
}
typedef void (*transform_point_func_t) (void *closure, double *x, double *y);
/* Project a path using a function. Each point of the path (including
* Bezier control points) is passed to the function for transformation.
*/
static void
transform_path (cairo_path_t *path, transform_point_func_t f, void *closure)
{
int i;
cairo_path_data_t *data;
for (i=0; i < path->num_data; i += path->data[i].header.length) {
data = &path->data[i];
switch (data->header.type) {
case CAIRO_PATH_CURVE_TO:
f (closure, &data[3].point.x, &data[3].point.y);
f (closure, &data[2].point.x, &data[2].point.y);
G_GNUC_FALLTHROUGH;
case CAIRO_PATH_MOVE_TO:
case CAIRO_PATH_LINE_TO:
f (closure, &data[1].point.x, &data[1].point.y);
break;
case CAIRO_PATH_CLOSE_PATH:
break;
default:
g_assert_not_reached ();
}
}
}
/* Simple struct to hold a path and its parametrization */
typedef struct {
cairo_path_t *path;
parametrization_t *parametrization;
} parametrized_path_t;
/* Project a point X,Y onto a parameterized path. The final point is
* where you get if you walk on the path forward from the beginning for X
* units, then stop there and walk another Y units perpendicular to the
* path at that point. In more detail:
*
* There's three pieces of math involved:
*
* - The parametric form of the Line equation
* http://en.wikipedia.org/wiki/Line
*
* - The parametric form of the Cubic Bézier curve equation
* http://en.wikipedia.org/wiki/B%C3%A9zier_curve
*
* - The Gradient (aka multi-dimensional derivative) of the above
* http://en.wikipedia.org/wiki/Gradient
*
* The parametric forms are used to answer the question of "where will I be
* if I walk a distance of X on this path". The Gradient is used to answer
* the question of "where will I be if then I stop, rotate left for 90
* degrees and walk straight for a distance of Y".
*/
static void
point_on_path (parametrized_path_t *param,
double *x, double *y)
{
int i;
double ratio, the_y = *y, the_x = *x, dx, dy;
cairo_path_data_t *data, last_move_to = {{0,},}, current_point = {{0,},};
cairo_path_t *path = param->path;
parametrization_t *parametrization = param->parametrization;
for (i=0; i + path->data[i].header.length < path->num_data &&
(the_x > parametrization[i] ||
path->data[i].header.type == CAIRO_PATH_MOVE_TO);
i += path->data[i].header.length) {
the_x -= parametrization[i];
data = &path->data[i];
switch (data->header.type) {
case CAIRO_PATH_MOVE_TO:
current_point = data[1];
last_move_to = data[1];
break;
case CAIRO_PATH_LINE_TO:
current_point = data[1];
break;
case CAIRO_PATH_CURVE_TO:
current_point = data[3];
break;
case CAIRO_PATH_CLOSE_PATH:
break;
default:
g_assert_not_reached ();
}
}
data = &path->data[i];
switch (data->header.type) {
case CAIRO_PATH_MOVE_TO:
break;
case CAIRO_PATH_CLOSE_PATH:
/* Make it look like it's a line_to to last_move_to */
data = (&last_move_to) - 1;
G_GNUC_FALLTHROUGH;
case CAIRO_PATH_LINE_TO:
{
ratio = the_x / parametrization[i];
/* Line polynomial */
*x = current_point.point.x * (1 - ratio) + data[1].point.x * ratio;
*y = current_point.point.y * (1 - ratio) + data[1].point.y * ratio;
/* Line gradient */
dx = -(current_point.point.x - data[1].point.x);
dy = -(current_point.point.y - data[1].point.y);
/*optimization for: ratio = the_y / sqrt (dx * dx + dy * dy);*/
ratio = the_y / parametrization[i];
*x += -dy * ratio;
*y += dx * ratio;
}
break;
case CAIRO_PATH_CURVE_TO:
{
/* FIXME the formulas here are not exactly what we want, because the
* Bezier parametrization is not uniform. But I don't know how to do
* better. The caller can do slightly better though, by flattening the
* Bezier and avoiding this branch completely. That has its own cost
* though, as large y values magnify the flattening error drastically.
*/
double ratio_1_0, ratio_0_1;
double ratio_2_0, ratio_0_2;
double ratio_3_0, ratio_2_1, ratio_1_2, ratio_0_3;
double _1__4ratio_1_0_3ratio_2_0, _2ratio_1_0_3ratio_2_0;
ratio = the_x / parametrization[i];
ratio_1_0 = ratio;
ratio_0_1 = 1 - ratio;
ratio_2_0 = ratio_1_0 * ratio_1_0; /* ratio * ratio */
ratio_0_2 = ratio_0_1 * ratio_0_1; /* (1 - ratio) * (1 - ratio) */
ratio_3_0 = ratio_2_0 * ratio_1_0; /* ratio * ratio * ratio */
ratio_2_1 = ratio_2_0 * ratio_0_1; /* ratio * ratio * (1 - ratio) */
ratio_1_2 = ratio_1_0 * ratio_0_2; /* ratio * (1 - ratio) * (1 - ratio) */
ratio_0_3 = ratio_0_1 * ratio_0_2; /* (1 - ratio) * (1 - ratio) * (1 - ratio) */
_1__4ratio_1_0_3ratio_2_0 = 1 - 4 * ratio_1_0 + 3 * ratio_2_0;
_2ratio_1_0_3ratio_2_0 = 2 * ratio_1_0 - 3 * ratio_2_0;
/* Bezier polynomial */
*x = current_point.point.x * ratio_0_3
+ 3 * data[1].point.x * ratio_1_2
+ 3 * data[2].point.x * ratio_2_1
+ data[3].point.x * ratio_3_0;
*y = current_point.point.y * ratio_0_3
+ 3 * data[1].point.y * ratio_1_2
+ 3 * data[2].point.y * ratio_2_1
+ data[3].point.y * ratio_3_0;
/* Bezier gradient */
dx =-3 * current_point.point.x * ratio_0_2
+ 3 * data[1].point.x * _1__4ratio_1_0_3ratio_2_0
+ 3 * data[2].point.x * _2ratio_1_0_3ratio_2_0
+ 3 * data[3].point.x * ratio_2_0;
dy =-3 * current_point.point.y * ratio_0_2
+ 3 * data[1].point.y * _1__4ratio_1_0_3ratio_2_0
+ 3 * data[2].point.y * _2ratio_1_0_3ratio_2_0
+ 3 * data[3].point.y * ratio_2_0;
ratio = the_y / sqrt (dx * dx + dy * dy);
*x += -dy * ratio;
*y += dx * ratio;
}
break;
default:
g_assert_not_reached ();
}
}
/* Projects the current path of cr onto the provided path. */
static void
map_path_onto (cairo_t *cr, cairo_path_t *path)
{
cairo_path_t *current_path;
parametrized_path_t param;
param.path = path;
param.parametrization = parametrize_path (path);
current_path = cairo_copy_path (cr);
cairo_new_path (cr);
transform_path (current_path,
(transform_point_func_t) point_on_path, &param);
cairo_append_path (cr, current_path);
cairo_path_destroy (current_path);
g_free (param.parametrization);
}
typedef void (*draw_path_func_t) (cairo_t *cr);
static void
draw_text (cairo_t *cr,
double x,
double y,
const char *font,
const char *text)
{
PangoLayout *layout;
PangoLayoutLine *line;
PangoFontDescription *desc;
cairo_font_options_t *font_options;
font_options = cairo_font_options_create ();
cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
cairo_set_font_options (cr, font_options);
cairo_font_options_destroy (font_options);
layout = pango_cairo_create_layout (cr);
desc = pango_font_description_from_string (font);
pango_layout_set_font_description (layout, desc);
pango_font_description_free (desc);
pango_layout_set_text (layout, text, -1);
/* Use pango_layout_get_line() instead of pango_layout_get_line_readonly()
* for older versions of pango
*/
line = pango_layout_get_line_readonly (layout, 0);
cairo_move_to (cr, x, y);
pango_cairo_layout_line_path (cr, line);
g_object_unref (layout);
}
static void
draw_twisted (cairo_t *cr,
double x,
double y,
const char *font,
const char *text)
{
cairo_path_t *path;
cairo_save (cr);
/* Decrease tolerance a bit, since it's going to be magnified */
cairo_set_tolerance (cr, 0.01);
/* Using cairo_copy_path() here shows our deficiency in handling
* Bezier curves, specially around sharper curves.
*
* Using cairo_copy_path_flat() on the other hand, magnifies the
* flattening error with large off-path values. We decreased
* tolerance for that reason. Increase tolerance to see that
* artifact.
*/
path = cairo_copy_path_flat (cr);
/*path = cairo_copy_path (cr);*/
cairo_new_path (cr);
draw_text (cr, x, y, font, text);
map_path_onto (cr, path);
cairo_path_destroy (path);
cairo_fill_preserve (cr);
cairo_save (cr);
cairo_set_source_rgb (cr, 0.1, 0.1, 0.1);
cairo_stroke (cr);
cairo_restore (cr);
cairo_restore (cr);
}
static void
draw_dream (cairo_t *cr)
{
cairo_move_to (cr, 50, 650);
cairo_rel_line_to (cr, 250, 50);
cairo_rel_curve_to (cr, 250, 50, 600, -50, 600, -250);
cairo_rel_curve_to (cr, 0, -400, -300, -100, -800, -300);
cairo_set_line_width (cr, 1.5);
cairo_set_source_rgba (cr, 0.3, 0.3, 1.0, 0.3);
fancy_cairo_stroke_preserve (cr);
draw_twisted (cr,
0, 0,
"Serif 72",
"It was a dream... Oh Just a dream...");
}
static void
draw_wow (cairo_t *cr)
{
cairo_move_to (cr, 400, 780);
cairo_rel_curve_to (cr, 50, -50, 150, -50, 200, 0);
cairo_scale (cr, 1.0, 2.0);
cairo_set_line_width (cr, 2.0);
cairo_set_source_rgba (cr, 0.3, 1.0, 0.3, 1.0);
fancy_cairo_stroke_preserve (cr);
draw_twisted (cr,
-20, -150,
"Serif 60",
"WOW!");
}
int main (int argc, char **argv)
{
cairo_t *cr;
char *filename;
cairo_status_t status;
cairo_surface_t *surface;
if (argc != 2)
{
g_printerr ("Usage: cairotwisted OUTPUT_FILENAME\n");
return 1;
}
filename = argv[1];
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
1000, 800);
cr = cairo_create (surface);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_paint (cr);
draw_dream (cr);
draw_wow (cr);
cairo_destroy (cr);
status = cairo_surface_write_to_png (surface, filename);
cairo_surface_destroy (surface);
if (status != CAIRO_STATUS_SUCCESS)
{
g_printerr ("Could not save png to '%s'\n", filename);
return 1;
}
return 0;
}
@@ -0,0 +1,30 @@
examples = []
if pango_cairo_backends.contains('png')
examples += [
'cairoshape',
'cairosimple',
'cairotwisted',
]
endif
examples_deps = [ libpango_dep, libpangocairo_dep, ]
if pango_font_backends.contains('freetype')
examples_deps += libpangoft2_dep
endif
# somebody will have to fix this
# if host_system == 'windows'
# # This hasn't been built in years, most likely, but try now
# examples += [ 'pangowin32tobmp' ]
# examples_deps += [ libpangowin32_dep ]
# endif
foreach e: examples
executable(e, '@0@.c'.format(e),
dependencies: examples_deps + pango_deps,
c_args: common_cflags,
include_directories: root_inc,
install: false)
endforeach

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