Merge branch 'master' into cff-subset
This commit is contained in:
commit
32d291ae89
@ -2,38 +2,55 @@ version: 2
|
||||
|
||||
jobs:
|
||||
|
||||
macos-llvm-gcc-4.2:
|
||||
macos-10.12.6-aat-fonts:
|
||||
macos:
|
||||
xcode: "8.3.3"
|
||||
xcode: "9.2.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run: brew update-reset
|
||||
- run: brew install wget pkg-config libtool ragel freetype glib cairo
|
||||
- run: wget https://packages.macports.org/llvm-gcc42/llvm-gcc42-2336.11_3+universal.darwin_15.i386-x86_64.tbz2 && tar zxvf llvm-gcc42-2336.11_3+universal.darwin_15.i386-x86_64.tbz2
|
||||
- run: CC=$PWD/opt/local/bin/llvm-gcc-4.2 CXX=$PWD/opt/local/bin/llvm-g++-4.2 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo
|
||||
# Ignoring assembler complains, https://stackoverflow.com/a/39867021
|
||||
- run: make 2>&1 | grep -v -e '^/var/folders/*' -e '^[[:space:]]*\.section' -e '^[[:space:]]*\^[[:space:]]*~*'
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel freetype glib cairo
|
||||
- run: ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo
|
||||
- run: make -j4
|
||||
- run: make check || .ci/fail.sh
|
||||
|
||||
macos-notest-apple-gcc-i686-4.2:
|
||||
macos-10.13.6-aat-fonts:
|
||||
macos:
|
||||
xcode: "8.3.3"
|
||||
xcode: "10.1.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run: brew update-reset
|
||||
- run: brew install wget pkg-config libtool ragel
|
||||
- run: wget https://packages.macports.org/apple-gcc42/apple-gcc42-5666.3_15+universal.darwin_15.i386-x86_64.tbz2 && tar zxvf apple-gcc42-5666.3_15+universal.darwin_15.i386-x86_64.tbz2
|
||||
- run: CPP=$PWD/opt/local/bin/i686-apple-darwin15-cpp-apple-4.2.1 CC=$PWD/opt/local/bin/i686-apple-darwin15-gcc-apple-4.2.1 CXX=$PWD/opt/local/bin/i686-apple-darwin15-g++-apple-4.2.1 ./autogen.sh
|
||||
# Ignoring assembler complains, https://stackoverflow.com/a/39867021
|
||||
- run: make 2>&1 | grep -v -e '^/var/folders/*' -e '^[[:space:]]*\.section' -e '^[[:space:]]*\^[[:space:]]*~*'
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel freetype glib cairo
|
||||
- run: ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo
|
||||
- run: make -j4
|
||||
- run: make check || .ci/fail.sh
|
||||
|
||||
# macos-llvm-gcc-4.2:
|
||||
# macos:
|
||||
# xcode: "8.3.3"
|
||||
# steps:
|
||||
# - checkout
|
||||
# - run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel freetype glib cairo
|
||||
# - run: wget https://packages.macports.org/llvm-gcc42/llvm-gcc42-2336.11_3+universal.darwin_15.i386-x86_64.tbz2 && tar zxvf llvm-gcc42-2336.11_3+universal.darwin_15.i386-x86_64.tbz2
|
||||
# - run: CC=$PWD/opt/local/bin/llvm-gcc-4.2 CXX=$PWD/opt/local/bin/llvm-g++-4.2 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo
|
||||
# # Ignoring assembler complains, https://stackoverflow.com/a/39867021
|
||||
# - run: make 2>&1 | grep -v -e '^/var/folders/*' -e '^[[:space:]]*\.section' -e '^[[:space:]]*\^[[:space:]]*~*'
|
||||
# - run: make check || .ci/fail.sh
|
||||
|
||||
# macos-notest-apple-gcc-i686-4.2:
|
||||
# macos:
|
||||
# xcode: "8.3.3"
|
||||
# steps:
|
||||
# - checkout
|
||||
# - run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel
|
||||
# - run: wget https://packages.macports.org/apple-gcc42/apple-gcc42-5666.3_15+universal.darwin_15.i386-x86_64.tbz2 && tar zxvf apple-gcc42-5666.3_15+universal.darwin_15.i386-x86_64.tbz2
|
||||
# - run: CPP=$PWD/opt/local/bin/i686-apple-darwin15-cpp-apple-4.2.1 CC=$PWD/opt/local/bin/i686-apple-darwin15-gcc-apple-4.2.1 CXX=$PWD/opt/local/bin/i686-apple-darwin15-g++-apple-4.2.1 ./autogen.sh
|
||||
# # Ignoring assembler complains, https://stackoverflow.com/a/39867021
|
||||
# - run: make 2>&1 | grep -v -e '^/var/folders/*' -e '^[[:space:]]*\.section' -e '^[[:space:]]*\^[[:space:]]*~*'
|
||||
|
||||
macos-notest-ios:
|
||||
macos:
|
||||
xcode: "10.0.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run: brew update-reset
|
||||
- run: brew install cmake
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake
|
||||
# not needed to be a framework but we like to test that also
|
||||
# TODO: wrong way of targeting iOS as it doesn't point to iOS headers thus building
|
||||
# CoreText support is not possible, after the fix feel free HB_IOS from CMake altogether
|
||||
@ -302,6 +319,8 @@ workflows:
|
||||
build:
|
||||
jobs:
|
||||
# macOS
|
||||
- macos-10.12.6-aat-fonts
|
||||
- macos-10.13.6-aat-fonts
|
||||
#- macos-llvm-gcc-4.2
|
||||
#- macos-notest-apple-gcc-i686-4.2
|
||||
- macos-notest-ios
|
||||
|
7
.codecov.yml
Normal file
7
.codecov.yml
Normal file
@ -0,0 +1,7 @@
|
||||
comment: off
|
||||
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
threshold: 1%
|
@ -508,6 +508,7 @@ test/api/Makefile
|
||||
test/fuzzing/Makefile
|
||||
test/shaping/Makefile
|
||||
test/shaping/data/Makefile
|
||||
test/shaping/data/aots/Makefile
|
||||
test/shaping/data/in-house/Makefile
|
||||
test/shaping/data/text-rendering-tests/Makefile
|
||||
test/subset/Makefile
|
||||
|
@ -112,6 +112,11 @@
|
||||
<xi:include href="xml/hb-ot-var.xml"/>
|
||||
</chapter>
|
||||
|
||||
<chapter>
|
||||
<title>Apple Advanced Typography API</title>
|
||||
<xi:include href="xml/hb-aat-layout.xml"/>
|
||||
</chapter>
|
||||
|
||||
<chapter>
|
||||
<title>Integration API</title>
|
||||
<xi:include href="xml/hb-coretext.xml"/>
|
||||
|
@ -3,6 +3,17 @@ HB_H_IN
|
||||
HB_OT_H_IN
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-aat-layout</FILE>
|
||||
HB_AAT_LAYOUT_NO_SELECTOR_INDEX
|
||||
hb_aat_layout_feature_type_t
|
||||
hb_aat_layout_get_feature_types
|
||||
hb_aat_layout_feature_type_get_name_id
|
||||
hb_aat_layout_feature_selector_t
|
||||
hb_aat_layout_feature_selector_info_t
|
||||
hb_aat_layout_feature_type_get_selector_infos
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-blob</FILE>
|
||||
hb_blob_create
|
||||
@ -161,6 +172,10 @@ hb_ot_layout_table_choose_script
|
||||
hb_ot_layout_table_find_script
|
||||
hb_ot_tag_from_language
|
||||
hb_ot_tags_from_script
|
||||
HB_OT_VAR_NO_AXIS_INDEX
|
||||
hb_ot_var_axis_t
|
||||
hb_ot_var_find_axis
|
||||
hb_ot_var_get_axes
|
||||
hb_set_invert
|
||||
hb_unicode_eastasian_width_func_t
|
||||
hb_unicode_eastasian_width
|
||||
@ -581,14 +596,12 @@ HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
|
||||
HB_OT_TAG_VAR_AXIS_SLANT
|
||||
HB_OT_TAG_VAR_AXIS_WEIGHT
|
||||
HB_OT_TAG_VAR_AXIS_WIDTH
|
||||
HB_OT_VAR_NO_AXIS_INDEX
|
||||
hb_ot_var_axis_t
|
||||
hb_ot_var_has_data
|
||||
hb_ot_var_find_axis
|
||||
hb_ot_var_get_axis_count
|
||||
hb_ot_var_get_axes
|
||||
hb_ot_var_axis_flags_t
|
||||
hb_ot_var_axis_get_flags
|
||||
hb_ot_var_axis_info_t
|
||||
hb_ot_var_find_axis_info
|
||||
hb_ot_var_get_axis_count
|
||||
hb_ot_var_get_axis_infos
|
||||
hb_ot_var_get_named_instance_count
|
||||
hb_ot_var_named_instance_get_subfamily_name_id
|
||||
hb_ot_var_named_instance_get_postscript_name_id
|
||||
|
@ -5,306 +5,538 @@
|
||||
<!ENTITY version SYSTEM "version.xml">
|
||||
]>
|
||||
<chapter id="clusters">
|
||||
<sect1 id="clusters">
|
||||
<title>Clusters</title>
|
||||
<para>
|
||||
In shaping text, a <emphasis>cluster</emphasis> is a sequence of
|
||||
code points that needs to be treated as a single, indivisible unit.
|
||||
</para>
|
||||
<para>
|
||||
When you add text to a HB buffer, each character is associated with
|
||||
a <emphasis>cluster value</emphasis>. This is an arbitrary number as
|
||||
far as HB is concerned.
|
||||
</para>
|
||||
<para>
|
||||
Most clients will use UTF-8, UTF-16, or UTF-32 indices, but the
|
||||
actual number does not matter. Moreover, it is not required for the
|
||||
cluster values to be monotonically increasing, but pretty much all
|
||||
of HB's tests are performed on monotonically increasing cluster
|
||||
numbers. Nevertheless, there is no such assumption in the code
|
||||
itself. With that in mind, let's examine what happens with cluster
|
||||
values during shaping under each cluster-level.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz provides three <emphasis>levels</emphasis> of clustering
|
||||
support. Level 0 is the default behavior and reproduces the behavior
|
||||
of the old HarfBuzz library. Level 1 tweaks this behavior slightly
|
||||
to produce better results, so level 1 clustering is recommended for
|
||||
code that is not required to implement backward compatibility with
|
||||
the old HarfBuzz.
|
||||
</para>
|
||||
<para>
|
||||
Level 2 differs significantly in how it treats cluster values.
|
||||
Levels 0 and 1 both process ligatures and glyph decomposition by
|
||||
merging clusters; level 2 does not.
|
||||
</para>
|
||||
<para>
|
||||
The conceptual model for what the cluster values mean, in levels 0
|
||||
and 1, is this:
|
||||
</para>
|
||||
<itemizedlist spacing="compact">
|
||||
<listitem>
|
||||
<para>
|
||||
the sequence of cluster values will always remain monotone
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
each value represents a single cluster
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
each cluster contains one or more glyphs and one or more
|
||||
characters
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
Assuming that initial cluster numbers were monotonically increasing
|
||||
and distinct, then all adjacent glyphs having the same cluster
|
||||
number belong to the same cluster, and all characters belong to the
|
||||
cluster that has the highest number not larger than their initial
|
||||
cluster number. This will become clearer with an example.
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="a-clustering-example-for-levels-0-and-1">
|
||||
<title>A clustering example for levels 0 and 1</title>
|
||||
<para>
|
||||
Let's say we start with the following character sequence and cluster
|
||||
values:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,B,C,D,E
|
||||
0,1,2,3,4
|
||||
</programlisting>
|
||||
<para>
|
||||
We then map the characters to glyphs. For simplicity, let's assume
|
||||
that each character maps to the corresponding, identical-looking
|
||||
glyph:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,B,C,D,E
|
||||
0,1,2,3,4
|
||||
</programlisting>
|
||||
<para>
|
||||
Now if, for example, <literal>B</literal> and <literal>C</literal>
|
||||
ligate, then the clusters to which they belong "merge".
|
||||
This merged cluster takes for its cluster number the minimum of all
|
||||
the cluster numbers of the clusters that went in. In this case, we
|
||||
get:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,BC,D,E
|
||||
0,1 ,3,4
|
||||
</programlisting>
|
||||
<para>
|
||||
Now let's assume that the <literal>BC</literal> glyph decomposes
|
||||
into three components, and <literal>D</literal> also decomposes into
|
||||
two. The components each inherit the cluster value of their parent:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,BC0,BC1,BC2,D0,D1,E
|
||||
0,1 ,1 ,1 ,3 ,3 ,4
|
||||
</programlisting>
|
||||
<para>
|
||||
Now if <literal>BC2</literal> and <literal>D0</literal> ligate, then
|
||||
their clusters (numbers 1 and 3) merge into
|
||||
<literal>min(1,3) = 1</literal>:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,BC0,BC1,BC2D0,D1,E
|
||||
0,1 ,1 ,1 ,1 ,4
|
||||
</programlisting>
|
||||
<para>
|
||||
At this point, cluster 1 means: the character sequence
|
||||
<literal>BCD</literal> is represented by glyphs
|
||||
<literal>BC0,BC1,BC2D0,D1</literal> and cannot be broken down any
|
||||
further.
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="reordering-in-levels-0-and-1">
|
||||
<title>Reordering in levels 0 and 1</title>
|
||||
<para>
|
||||
Another common operation in the more complex shapers is when things
|
||||
reorder. In those cases, to maintain monotone clusters, HB merges
|
||||
the clusters of everything in the reordering sequence. For example,
|
||||
let's again start with the character sequence:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,B,C,D,E
|
||||
0,1,2,3,4
|
||||
</programlisting>
|
||||
<para>
|
||||
If <literal>D</literal> is reordered before <literal>B</literal>,
|
||||
then the <literal>B</literal>, <literal>C</literal>, and
|
||||
<literal>D</literal> clusters merge, and we get:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,D,B,C,E
|
||||
0,1,1,1,4
|
||||
</programlisting>
|
||||
<para>
|
||||
This is clearly not ideal, but it is the only sensible way to
|
||||
maintain monotone indices and retain the true relationship between
|
||||
glyphs and characters.
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="the-distinction-between-levels-0-and-1">
|
||||
<title>The distinction between levels 0 and 1</title>
|
||||
<para>
|
||||
So, the above is pretty much what cluster levels 0 and 1 do. The
|
||||
only difference between the two is this: in level 0, at the very
|
||||
beginning of the shaping process, we also merge clusters between
|
||||
base characters and all Unicode marks (combining or not) following
|
||||
them. E.g.:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,acute,B
|
||||
0,1 ,2
|
||||
</programlisting>
|
||||
<para>
|
||||
will become:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,acute,B
|
||||
0,0 ,2
|
||||
</programlisting>
|
||||
<para>
|
||||
This is the default behavior. We do it because Windows did it and
|
||||
old HarfBuzz did it, so this remained the default. But this behavior
|
||||
makes it impossible to color diacritic marks differently from their
|
||||
base characters. That's why in level 1 we do not perform this
|
||||
initial merging step.
|
||||
</para>
|
||||
<para>
|
||||
For clients, level 0 is more convenient if they rely on HarfBuzz
|
||||
clusters for cursor positioning. But that's wrong anyway: cursor
|
||||
positions should be determined based on Unicode grapheme boundaries,
|
||||
NOT shaping clusters. As such, level 1 clusters are preferred.
|
||||
</para>
|
||||
<para>
|
||||
One last note about levels 0 and 1. We currently don't allow a
|
||||
<literal>MultipleSubst</literal> lookup to replace a glyph with zero
|
||||
glyphs (i.e., to delete a glyph). But in some other situations,
|
||||
glyphs can be deleted. In those cases, if the glyph being deleted is
|
||||
the last glyph of its cluster, we make sure to merge the cluster
|
||||
with a neighboring cluster.
|
||||
</para>
|
||||
<para>
|
||||
This is, primarily, to make sure that the starting cluster of the
|
||||
text always has the cluster index pointing to the start of the text
|
||||
for the run; more than one client currently relies on this
|
||||
guarantee.
|
||||
</para>
|
||||
<para>
|
||||
Incidentally, Apple's CoreText does something else to maintain the
|
||||
same promise: it inserts a glyph with id 65535 at the beginning of
|
||||
the glyph string if the glyph corresponding to the first character
|
||||
in the run was deleted. HarfBuzz might do something similar in the
|
||||
future.
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="level-2">
|
||||
<title>Level 2</title>
|
||||
<para>
|
||||
Level 2 is a different beast from levels 0 and 1. It is simple to
|
||||
describe, but hard to make sense of. It simply doesn't do any
|
||||
cluster merging whatsoever. When things ligate or otherwise multiple
|
||||
glyphs turn into one, the cluster value of the first glyph is
|
||||
retained.
|
||||
</para>
|
||||
<para>
|
||||
Here are a few examples of why processing cluster values produced at
|
||||
this level might be tricky:
|
||||
</para>
|
||||
<sect2 id="ligatures-with-combining-marks">
|
||||
<title>Ligatures with combining marks</title>
|
||||
<section id="clusters">
|
||||
<title>Clusters</title>
|
||||
<para>
|
||||
Imagine capital letters are bases and lower case letters are
|
||||
combining marks. With an input sequence like this:
|
||||
In text shaping, a <emphasis>cluster</emphasis> is a sequence of
|
||||
characters that needs to be treated as a single, indivisible
|
||||
unit.
|
||||
</para>
|
||||
<para>
|
||||
A cluster is distinct from a <emphasis>grapheme</emphasis>,
|
||||
which is the smallest unit of a writing system or script,
|
||||
because clusters are only relevant for script shaping and the
|
||||
layout of glyphs.
|
||||
</para>
|
||||
<para>
|
||||
For example, a grapheme may be a letter, a number, a logogram,
|
||||
or a symbol. When two letters form a ligature, however, they
|
||||
combine into a single glyph. They are therefore part of the same
|
||||
cluster and are treated as a unit — even though the two
|
||||
original, underlying letters are separate graphemes.
|
||||
</para>
|
||||
<para>
|
||||
During the shaping process, there are several shaping operations
|
||||
that may merge adjacent characters (for example, when two code
|
||||
points form a ligature or a conjunct form and are replaced by a
|
||||
single glyph) or split one character into several (for example,
|
||||
when decomposing a code point through the
|
||||
<literal>ccmp</literal> feature).
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz tracks clusters independently from how these
|
||||
shaping operations affect the individual glyphs that comprise the
|
||||
output HarfBuzz returns in a buffer. Consequently,
|
||||
a client program using HarfBuzz can utilize the cluster
|
||||
information to implement features such as:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Correctly positioning the cursor within a shaped text run,
|
||||
even when characters have formed ligatures, composed or
|
||||
decomposed, reordered, or undergone other shaping operations.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Correctly highlighting a text selection that includes some,
|
||||
but not all, of the characters in a word.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Applying text attributes (such as color or underlining) to
|
||||
part, but not all, of a word.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Generating output document formats (such as PDF) with
|
||||
embedded text that can be fully extracted.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Determining the mapping between input characters and output
|
||||
glyphs, such as which glyphs are ligatures.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Performing line-breaking, justification, and other
|
||||
line-level or paragraph-level operations that must be done
|
||||
after shaping is complete, but which require character-level
|
||||
properties.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
When you add text to a HarfBuzz buffer, each code point must be
|
||||
assigned a <emphasis>cluster value</emphasis>.
|
||||
</para>
|
||||
<para>
|
||||
This cluster value is an arbitrary number; HarfBuzz uses it only
|
||||
to distinguish between clusters. Many client programs will use
|
||||
the index of each code point in the input text stream as the
|
||||
cluster value. This is for the sake of convenience; the actual
|
||||
value does not matter.
|
||||
</para>
|
||||
<para>
|
||||
Client programs can choose how HarfBuzz handles clusters during
|
||||
shaping by setting the
|
||||
<literal>cluster_level</literal> of the
|
||||
buffer. HarfBuzz offers three <emphasis>levels</emphasis> of
|
||||
clustering support for this property:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><emphasis>Level 0</emphasis> is the default and
|
||||
reproduces the behavior of the old HarfBuzz library.
|
||||
</para>
|
||||
<para>
|
||||
The distinguishing feature of level 0 behavior is that, at
|
||||
the beginning of processing the buffer, all code points that
|
||||
are categorized as <emphasis>marks</emphasis>,
|
||||
<emphasis>modifier symbols</emphasis>, or
|
||||
<emphasis>Emoji extended pictographic</emphasis> modifiers,
|
||||
as well as the <emphasis>Zero Width Joiner</emphasis> and
|
||||
<emphasis>Zero Width Non-Joiner</emphasis> code points, are
|
||||
assigned the cluster value of the closest preceding code
|
||||
point from <emphasis>different</emphasis> category.
|
||||
</para>
|
||||
<para>
|
||||
In essence, whenever a base character is followed by a mark
|
||||
character or a sequence of mark characters, those marks are
|
||||
reassigned to the same initial cluster value as the base
|
||||
character. This reassignment is referred to as
|
||||
"merging" the affected clusters. This behavior is based on
|
||||
the Grapheme Cluster Boundary specification in <ulink
|
||||
url="https://www.unicode.org/reports/tr29/#Regex_Definitions">Unicode
|
||||
Technical Report 29</ulink>.
|
||||
</para>
|
||||
<para>
|
||||
Client programs can specify level 0 behavior for a buffer by
|
||||
setting its <literal>cluster_level</literal> to
|
||||
<literal>HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>Level 1</emphasis> tweaks the old behavior
|
||||
slightly to produce better results. Therefore, level 1
|
||||
clustering is recommended for code that is not required to
|
||||
implement backward compatibility with the old HarfBuzz.
|
||||
</para>
|
||||
<para>
|
||||
Level 1 differs from level 0 by not merging the
|
||||
clusters of marks and other modifier code points with the
|
||||
preceding "base" code point's cluster. By preserving the
|
||||
separate cluster values of these marks and modifier code
|
||||
points, script shapers can perform additional operations
|
||||
that might lead to improved results (for example, reordering
|
||||
a sequence of marks).
|
||||
</para>
|
||||
<para>
|
||||
Client programs can specify level 1 behavior for a buffer by
|
||||
setting its <literal>cluster_level</literal> to
|
||||
<literal>HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>Level 2</emphasis> differs significantly in how it
|
||||
treats cluster values. In level 2, HarfBuzz never merges
|
||||
clusters.
|
||||
</para>
|
||||
<para>
|
||||
This difference can be seen most clearly when HarfBuzz processes
|
||||
ligature substitutions and glyph decompositions. In level 0
|
||||
and level 1, ligatures and glyph decomposition both involve
|
||||
merging clusters; in level 2, neither of these operations
|
||||
triggers a merge.
|
||||
</para>
|
||||
<para>
|
||||
Client programs can specify level 2 behavior for a buffer by
|
||||
setting its <literal>cluster_level</literal> to
|
||||
<literal>HB_BUFFER_CLUSTER_LEVEL_CHARACTERS</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
As mentioned earlier, client programs using HarfBuzz often
|
||||
assign initial cluster values in a buffer by reusing the indices
|
||||
of the code points in the input text. This gives a sequence of
|
||||
cluster values that is monotonically increasing (for example,
|
||||
0,1,2,3,4,5).
|
||||
</para>
|
||||
<para>
|
||||
It is not <emphasis>required</emphasis> that the cluster values
|
||||
in a buffer be monotonically increasing. However, if the initial
|
||||
cluster values in a buffer are monotonic and the buffer is
|
||||
configured to use cluster level 0 or 1, then HarfBuzz
|
||||
guarantees that the final cluster values in the shaped buffer
|
||||
will also be monotonic. No such guarantee is made for cluster
|
||||
level 2.
|
||||
</para>
|
||||
<para>
|
||||
In levels 0 and 1, HarfBuzz implements the following conceptual
|
||||
model for cluster values:
|
||||
</para>
|
||||
<itemizedlist spacing="compact">
|
||||
<listitem>
|
||||
<para>
|
||||
If the sequence of input cluster values is monotonic, the
|
||||
sequence of cluster values will remain monotonic.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Each cluster value represents a single cluster.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Each cluster contains one or more glyphs and one or more
|
||||
characters.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
In practice, this model offers several benefits. Assuming that
|
||||
the initial cluster values were monotonically increasing
|
||||
and distinct before shaping began, then, in the final output:
|
||||
</para>
|
||||
<itemizedlist spacing="compact">
|
||||
<listitem>
|
||||
<para>
|
||||
All adjacent glyphs having the same final cluster
|
||||
value belong to the same cluster.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Each character belongs to the cluster that has the highest
|
||||
cluster value <emphasis>not larger than</emphasis> its
|
||||
initial cluster value.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
<section id="a-clustering-example-for-levels-0-and-1">
|
||||
<title>A clustering example for levels 0 and 1</title>
|
||||
<para>
|
||||
The guarantees and benefits of level 0 and level 1 can be seen
|
||||
with some examples. First, let us examine what happens with cluster
|
||||
values when shaping involves cluster merging with ligatures and
|
||||
decomposition.
|
||||
</para>
|
||||
<para>
|
||||
Let's say we start with the following character sequence (top row) and
|
||||
initial cluster values (bottom row):
|
||||
</para>
|
||||
<programlisting>
|
||||
A,a,B,b,C,c
|
||||
0,1,2,3,4,5
|
||||
</programlisting>
|
||||
A,B,C,D,E
|
||||
0,1,2,3,4
|
||||
</programlisting>
|
||||
<para>
|
||||
if <literal>A,B,C</literal> ligate, then here are the cluster
|
||||
values one would get under the various levels:
|
||||
</para>
|
||||
<para>
|
||||
level 0:
|
||||
During shaping, HarfBuzz maps these characters to glyphs from
|
||||
the font. For simplicity, let us assume that each character maps
|
||||
to the corresponding, identical-looking glyph:
|
||||
</para>
|
||||
<programlisting>
|
||||
ABC,a,b,c
|
||||
0 ,0,0,0
|
||||
</programlisting>
|
||||
A,B,C,D,E
|
||||
0,1,2,3,4
|
||||
</programlisting>
|
||||
<para>
|
||||
level 1:
|
||||
Now if, for example, <literal>B</literal> and <literal>C</literal>
|
||||
form a ligature, then the clusters to which they belong
|
||||
"merge". This merged cluster takes for its cluster
|
||||
value the minimum of all the cluster values of the clusters that
|
||||
went in to the ligature. In this case, we get:
|
||||
</para>
|
||||
<programlisting>
|
||||
ABC,a,b,c
|
||||
0 ,0,0,5
|
||||
</programlisting>
|
||||
A,BC,D,E
|
||||
0,1 ,3,4
|
||||
</programlisting>
|
||||
<para>
|
||||
level 2:
|
||||
because 1 is the minimum of the set {1,2}, which were the
|
||||
cluster values of <literal>B</literal> and
|
||||
<literal>C</literal>.
|
||||
</para>
|
||||
<para>
|
||||
Next, let us say that the <literal>BC</literal> ligature glyph
|
||||
decomposes into three components, and <literal>D</literal> also
|
||||
decomposes into two components. These components each inherit the
|
||||
cluster value of their parent:
|
||||
</para>
|
||||
<programlisting>
|
||||
ABC,a,b,c
|
||||
0 ,1,3,5
|
||||
</programlisting>
|
||||
A,BC0,BC1,BC2,D0,D1,E
|
||||
0,1 ,1 ,1 ,3 ,3 ,4
|
||||
</programlisting>
|
||||
<para>
|
||||
Making sense of the last example is the hardest for a client,
|
||||
because there is nothing in the cluster values to suggest that
|
||||
<literal>B</literal> and <literal>C</literal> ligated with
|
||||
<literal>A</literal>.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="reordering">
|
||||
<title>Reordering</title>
|
||||
<para>
|
||||
Another tricky case is when things reorder. Under level 2:
|
||||
Next, if <literal>BC2</literal> and <literal>D0</literal> form a
|
||||
ligature, then their clusters (cluster values 1 and 3) merge into
|
||||
<literal>min(1,3) = 1</literal>:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,B,C,D,E
|
||||
0,1,2,3,4
|
||||
</programlisting>
|
||||
A,BC0,BC1,BC2D0,D1,E
|
||||
0,1 ,1 ,1 ,1 ,4
|
||||
</programlisting>
|
||||
<para>
|
||||
Now imagine <literal>D</literal> moves before
|
||||
<literal>B</literal>:
|
||||
At this point, cluster 1 means: the character sequence
|
||||
<literal>BCD</literal> is represented by glyphs
|
||||
<literal>BC0,BC1,BC2D0,D1</literal> and cannot be broken down any
|
||||
further.
|
||||
</para>
|
||||
</section>
|
||||
<section id="reordering-in-levels-0-and-1">
|
||||
<title>Reordering in levels 0 and 1</title>
|
||||
<para>
|
||||
Another common operation in the more complex shapers is glyph
|
||||
reordering. In order to maintain a monotonic cluster sequence
|
||||
when glyph reordering takes place, HarfBuzz merges the clusters
|
||||
of everything in the reordering sequence.
|
||||
</para>
|
||||
<para>
|
||||
For example, let us again start with the character sequence (top
|
||||
row) and initial cluster values (bottom row):
|
||||
</para>
|
||||
<programlisting>
|
||||
A,D,B,C,E
|
||||
0,3,1,2,4
|
||||
</programlisting>
|
||||
A,B,C,D,E
|
||||
0,1,2,3,4
|
||||
</programlisting>
|
||||
<para>
|
||||
Now, if <literal>D</literal> ligates with <literal>B</literal>, we
|
||||
If <literal>D</literal> is reordered to before <literal>B</literal>,
|
||||
then HarfBuzz merges the <literal>B</literal>,
|
||||
<literal>C</literal>, and <literal>D</literal> clusters, and we
|
||||
get:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,DB,C,E
|
||||
0,3 ,2,4
|
||||
</programlisting>
|
||||
A,D,B,C,E
|
||||
0,1,1,1,4
|
||||
</programlisting>
|
||||
<para>
|
||||
In a different scenario, <literal>A</literal> and
|
||||
<literal>B</literal> could have ligated
|
||||
<emphasis>before</emphasis> <literal>D</literal> reordered; that
|
||||
would have resulted in:
|
||||
This is clearly not ideal, but it is the only sensible way to
|
||||
maintain a monotonic sequence of cluster values and retain the
|
||||
true relationship between glyphs and characters.
|
||||
</para>
|
||||
</section>
|
||||
<section id="the-distinction-between-levels-0-and-1">
|
||||
<title>The distinction between levels 0 and 1</title>
|
||||
<para>
|
||||
The preceding examples demonstrate the main effects of using
|
||||
cluster levels 0 and 1. The only difference between the two
|
||||
levels is this: in level 0, at the very beginning of the shaping
|
||||
process, HarfBuzz also merges clusters between any base character
|
||||
and all Unicode marks (combining or not) that follow it.
|
||||
</para>
|
||||
<para>
|
||||
For example, let us start with the following character sequence
|
||||
(top row) and accompanying initial cluster values (bottom row):
|
||||
</para>
|
||||
<programlisting>
|
||||
AB,D,C,E
|
||||
0 ,3,2,4
|
||||
</programlisting>
|
||||
A,acute,B
|
||||
0,1 ,2
|
||||
</programlisting>
|
||||
<para>
|
||||
There's no way to differentiate between these two scenarios based
|
||||
on the cluster numbers alone.
|
||||
The <literal>acute</literal> is a Unicode mark. If HarfBuzz is
|
||||
using cluster level 0 on this sequence, then the
|
||||
<literal>A</literal> and <literal>acute</literal> clusters will
|
||||
merge, and the result will become:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,acute,B
|
||||
0,0 ,2
|
||||
</programlisting>
|
||||
<para>
|
||||
This initial cluster merging is the default behavior of the
|
||||
Windows shaping engine, and the old HarfBuzz codebase copied
|
||||
that behavior to maintain compatibility. Consequently, it has
|
||||
remained the default behavior in the new HarfBuzz codebase.
|
||||
</para>
|
||||
<para>
|
||||
Another problem happens with ligatures under level 2 if the
|
||||
direction of the text is forced to opposite of its natural
|
||||
direction (e.g. left-to-right Arabic). But that's too much of a
|
||||
corner case to worry about.
|
||||
But this initial cluster-merging behavior makes it impossible to
|
||||
color diacritic marks differently from their base
|
||||
characters. That is why, in level 1, HarfBuzz does not perform
|
||||
the initial merging step.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
<para>
|
||||
For client programs that rely on HarfBuzz cluster values to
|
||||
perform cursor positioning, level 0 is more convenient. But
|
||||
relying on cluster boundaries for cursor positioning is wrong: cursor
|
||||
positions should be determined based on Unicode grapheme
|
||||
boundaries, not on shaping-cluster boundaries. As such, level 1
|
||||
clusters are preferred.
|
||||
</para>
|
||||
<para>
|
||||
One last note about levels 0 and 1. HarfBuzz currently does not allow a
|
||||
<literal>MultipleSubst</literal> lookup to replace a glyph with zero
|
||||
glyphs (in other words, to delete a glyph). But, in some other situations,
|
||||
glyphs can be deleted. In those cases, if the glyph being deleted is
|
||||
the last glyph of its cluster, HarfBuzz makes sure to merge the cluster
|
||||
with a neighboring cluster.
|
||||
</para>
|
||||
<para>
|
||||
This is done primarily to make sure that the starting cluster of the
|
||||
text always has the cluster index pointing to the start of the text
|
||||
for the run; more than one client currently relies on this
|
||||
guarantee.
|
||||
</para>
|
||||
<para>
|
||||
Incidentally, Apple's CoreText does something else to maintain the
|
||||
same promise: it inserts a glyph with id 65535 at the beginning of
|
||||
the glyph string if the glyph corresponding to the first character
|
||||
in the run was deleted. HarfBuzz might do something similar in the
|
||||
future.
|
||||
</para>
|
||||
</section>
|
||||
<section id="level-2">
|
||||
<title>Level 2</title>
|
||||
<para>
|
||||
HarfBuzz's level 2 cluster behavior uses a significantly
|
||||
different model than that of level 0 and level 1.
|
||||
</para>
|
||||
<para>
|
||||
The level 2 behavior is easy to describe, but it may be
|
||||
difficult to understand in practical terms. In brief, level 2
|
||||
performs no merging of clusters whatsoever.
|
||||
</para>
|
||||
<para>
|
||||
When glyphs form a ligature (or when some other feature
|
||||
substitutes multiple glyphs with one glyph), the cluster value
|
||||
of the first glyph is retained as the cluster value for the
|
||||
ligature. However, no subsequent clusters — including
|
||||
marks and modifiers — are affected.
|
||||
</para>
|
||||
<para>
|
||||
Level 2 cluster behavior is less complex than level 0 or level
|
||||
1, but there are a few cases in which processing cluster values
|
||||
produced at level 2 may be tricky.
|
||||
</para>
|
||||
<section id="ligatures-with-combining-marks-in-level-2">
|
||||
<title>Ligatures with combining marks in level 2</title>
|
||||
<para>
|
||||
The first example of how HarfBuzz's level 2 cluster behavior
|
||||
can be tricky is when the text to be shaped includes combining
|
||||
marks attached to ligatures.
|
||||
</para>
|
||||
<para>
|
||||
Let us start with an input sequence with the following
|
||||
characters (top row) and initial cluster values (bottom row):
|
||||
</para>
|
||||
<programlisting>
|
||||
A,acute,B,breve,C,circumflex
|
||||
0,1 ,2,3 ,4,5
|
||||
</programlisting>
|
||||
<para>
|
||||
If the sequence <literal>A,B,C</literal> forms a ligature,
|
||||
then these are the cluster values HarfBuzz will return under
|
||||
the various cluster levels:
|
||||
</para>
|
||||
<para>
|
||||
Level 0:
|
||||
</para>
|
||||
<programlisting>
|
||||
ABC,acute,breve,circumflex
|
||||
0 ,0 ,0 ,0
|
||||
</programlisting>
|
||||
<para>
|
||||
Level 1:
|
||||
</para>
|
||||
<programlisting>
|
||||
ABC,acute,breve,circumflex
|
||||
0 ,0 ,0 ,5
|
||||
</programlisting>
|
||||
<para>
|
||||
Level 2:
|
||||
</para>
|
||||
<programlisting>
|
||||
ABC,acute,breve,circumflex
|
||||
0 ,1 ,3 ,5
|
||||
</programlisting>
|
||||
<para>
|
||||
Making sense of the level 2 result is the hardest for a client
|
||||
program, because there is nothing in the cluster values that
|
||||
indicates that <literal>B</literal> and <literal>C</literal>
|
||||
formed a ligature with <literal>A</literal>.
|
||||
</para>
|
||||
<para>
|
||||
In contrast, the "merged" cluster values of the mark glyphs
|
||||
that are seen in the level 0 and level 1 output are evidence
|
||||
that a ligature substitution took place.
|
||||
</para>
|
||||
</section>
|
||||
<section id="reordering-in-level-2">
|
||||
<title>Reordering in level 2</title>
|
||||
<para>
|
||||
Another example of how HarfBuzz's level 2 cluster behavior
|
||||
can be tricky is when glyphs reorder. Consider an input sequence
|
||||
with the following characters (top row) and initial cluster
|
||||
values (bottom row):
|
||||
</para>
|
||||
<programlisting>
|
||||
A,B,C,D,E
|
||||
0,1,2,3,4
|
||||
</programlisting>
|
||||
<para>
|
||||
Now imagine <literal>D</literal> moves before
|
||||
<literal>B</literal> in a reordering operation. The cluster
|
||||
values will then be:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,D,B,C,E
|
||||
0,3,1,2,4
|
||||
</programlisting>
|
||||
<para>
|
||||
Next, if <literal>D</literal> forms a ligature with
|
||||
<literal>B</literal>, the output is:
|
||||
</para>
|
||||
<programlisting>
|
||||
A,DB,C,E
|
||||
0,3 ,2,4
|
||||
</programlisting>
|
||||
<para>
|
||||
However, in a different scenario, in which the shaping rules
|
||||
of the script instead caused <literal>A</literal> and
|
||||
<literal>B</literal> to form a ligature
|
||||
<emphasis>before</emphasis> the <literal>D</literal> reordered, the
|
||||
result would be:
|
||||
</para>
|
||||
<programlisting>
|
||||
AB,D,C,E
|
||||
0 ,3,2,4
|
||||
</programlisting>
|
||||
<para>
|
||||
There is no way for a client program to differentiate between
|
||||
these two scenarios based on the cluster values
|
||||
alone. Consequently, client programs that use level 2 might
|
||||
need to undertake additional work in order to manage cursor
|
||||
positioning, text attributes, or other desired features.
|
||||
</para>
|
||||
</section>
|
||||
<section id="other-considerations-in-level-2">
|
||||
<title>Other considerations in level 2</title>
|
||||
<para>
|
||||
There may be other problems encountered with ligatures under
|
||||
level 2, such as if the direction of the text is forced to
|
||||
opposite of its natural direction (for example, left-to-right
|
||||
Arabic). But, generally speaking, these other scenarios are
|
||||
minor corner cases that are too obscure for most client
|
||||
programs to need to worry about.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
|
@ -157,7 +157,8 @@
|
||||
</orderedlist>
|
||||
<programlisting language="C">
|
||||
#include <hb-ft.h>
|
||||
FT_New_Face(ft_library, font_path, index, &face)
|
||||
FT_New_Face(ft_library, font_path, index, &face);
|
||||
FT_Set_Char_Size(face, 0, 1000, 0, 0);
|
||||
hb_font_t *font = hb_ft_font_create(face);
|
||||
</programlisting>
|
||||
<orderedlist numeration="arabic">
|
||||
|
@ -424,6 +424,8 @@ HarfBuzz_0_0_gir_CFLAGS = \
|
||||
-DHB_H_IN \
|
||||
-DHB_OT_H \
|
||||
-DHB_OT_H_IN \
|
||||
-DHB_AAT_H \
|
||||
-DHB_AAT_H_IN \
|
||||
-DHB_GOBJECT_H \
|
||||
-DHB_GOBJECT_H_IN \
|
||||
-DHB_EXTERN= \
|
||||
|
@ -192,6 +192,8 @@ HB_OT_RAGEL_sources = \
|
||||
$(NULL)
|
||||
|
||||
HB_OT_headers = \
|
||||
hb-aat.h \
|
||||
hb-aat-layout.h \
|
||||
hb-ot.h \
|
||||
hb-ot-color.h \
|
||||
hb-ot-font.h \
|
||||
|
@ -50,6 +50,8 @@ data[0][0x20F0] = defaults[0]
|
||||
# TODO https://github.com/roozbehp/unicode-data/issues/9
|
||||
data[0][0x11C44] = 'Consonant_Placeholder'
|
||||
data[0][0x11C45] = 'Consonant_Placeholder'
|
||||
# TODO https://github.com/harfbuzz/harfbuzz/pull/1399
|
||||
data[0][0x111C8] = 'Consonant_Placeholder'
|
||||
for u in range (0xFE00, 0xFE0F + 1):
|
||||
data[0][u] = defaults[0]
|
||||
|
||||
@ -168,7 +170,7 @@ def is_BASE(U, UISC, UGC):
|
||||
def is_BASE_IND(U, UISC, UGC):
|
||||
#SPEC-DRAFT return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po)
|
||||
return (UISC in [Consonant_Dead, Modifying_Letter] or
|
||||
(UGC == Po and not U in [0x104B, 0x104E, 0x2022, 0x11A3F, 0x11A45, 0x11C44, 0x11C45]) or
|
||||
(UGC == Po and not U in [0x104B, 0x104E, 0x2022, 0x111C8, 0x11A3F, 0x11A45, 0x11C44, 0x11C45]) or
|
||||
False # SPEC-DRAFT-OUTDATED! U == 0x002D
|
||||
)
|
||||
def is_BASE_NUM(U, UISC, UGC):
|
||||
@ -354,6 +356,9 @@ def map_to_use(data):
|
||||
# TODO: https://github.com/harfbuzz/harfbuzz/issues/1105
|
||||
if U == 0x11134: UISC = Gemination_Mark
|
||||
|
||||
# TODO: https://github.com/harfbuzz/harfbuzz/pull/1399
|
||||
if U == 0x111C9: UISC = Consonant_Final
|
||||
|
||||
values = [k for k,v in items if v(U,UISC,UGC)]
|
||||
assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values)
|
||||
USE = values[0]
|
||||
|
@ -69,13 +69,15 @@ struct LookupFormat0
|
||||
UnsizedArrayOf<T>
|
||||
arrayZ; /* Array of lookup values, indexed by glyph index. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, arrayZ);
|
||||
DEFINE_SIZE_UNBOUNDED (2);
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct LookupSegmentSingle
|
||||
{
|
||||
enum { TerminationWordCount = 2 };
|
||||
|
||||
inline int cmp (hb_codepoint_t g) const {
|
||||
return g < first ? -1 : g <= last ? 0 : +1 ;
|
||||
}
|
||||
@ -134,6 +136,8 @@ struct LookupFormat2
|
||||
template <typename T>
|
||||
struct LookupSegmentArray
|
||||
{
|
||||
enum { TerminationWordCount = 2 };
|
||||
|
||||
inline const T* get_value (hb_codepoint_t glyph_id, const void *base) const
|
||||
{
|
||||
return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
|
||||
@ -204,6 +208,8 @@ struct LookupFormat4
|
||||
template <typename T>
|
||||
struct LookupSingle
|
||||
{
|
||||
enum { TerminationWordCount = 1 };
|
||||
|
||||
inline int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
@ -357,6 +363,14 @@ struct Lookup
|
||||
}
|
||||
}
|
||||
|
||||
inline typename T::type get_class (hb_codepoint_t glyph_id,
|
||||
unsigned int num_glyphs,
|
||||
unsigned int outOfRange) const
|
||||
{
|
||||
const T *v = get_value (glyph_id, num_glyphs);
|
||||
return v ? *v : outOfRange;
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -436,8 +450,10 @@ struct Entry
|
||||
* which ensures that data has a simple sanitize(). To be determined
|
||||
* if I need to remove that as well.
|
||||
*
|
||||
* XXX Because we are a template, our DEFINE_SIZE_STATIC assertion
|
||||
* wouldn't be checked. */
|
||||
* HOWEVER! Because we are a template, our DEFINE_SIZE_STATIC
|
||||
* assertion wouldn't be checked, hence the line below. */
|
||||
static_assert (T::static_size, "");
|
||||
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
@ -472,7 +488,7 @@ struct StateTable
|
||||
{
|
||||
typedef typename Types::HBUINT HBUINT;
|
||||
typedef typename Types::HBUSHORT HBUSHORT;
|
||||
typedef typename Types::ClassType ClassType;
|
||||
typedef typename Types::ClassTypeNarrow ClassType;
|
||||
|
||||
enum State
|
||||
{
|
||||
@ -630,6 +646,7 @@ struct StateTable
|
||||
DEFINE_SIZE_STATIC (4 * sizeof (HBUINT));
|
||||
};
|
||||
|
||||
template <typename HBUCHAR>
|
||||
struct ClassTable
|
||||
{
|
||||
inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int outOfRange) const
|
||||
@ -637,6 +654,12 @@ struct ClassTable
|
||||
unsigned int i = glyph_id - firstGlyph;
|
||||
return i >= classArray.len ? outOfRange : classArray.arrayZ[i];
|
||||
}
|
||||
inline unsigned int get_class (hb_codepoint_t glyph_id,
|
||||
unsigned int num_glyphs HB_UNUSED,
|
||||
unsigned int outOfRange) const
|
||||
{
|
||||
return get_class (glyph_id, outOfRange);
|
||||
}
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -644,7 +667,7 @@ struct ClassTable
|
||||
}
|
||||
protected:
|
||||
GlyphID firstGlyph; /* First glyph index included in the trimmed array. */
|
||||
ArrayOf<HBUINT8> classArray; /* The class codes (indexed by glyph index minus
|
||||
ArrayOf<HBUCHAR> classArray; /* The class codes (indexed by glyph index minus
|
||||
* firstGlyph). */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, classArray);
|
||||
@ -655,15 +678,9 @@ struct ObsoleteTypes
|
||||
static const bool extended = false;
|
||||
typedef HBUINT16 HBUINT;
|
||||
typedef HBUINT8 HBUSHORT;
|
||||
struct ClassType : ClassTable
|
||||
{
|
||||
inline unsigned int get_class (hb_codepoint_t glyph_id,
|
||||
unsigned int num_glyphs HB_UNUSED,
|
||||
unsigned int outOfRange) const
|
||||
{
|
||||
return ClassTable::get_class (glyph_id, outOfRange);
|
||||
}
|
||||
};
|
||||
typedef ClassTable<HBUINT8> ClassTypeNarrow;
|
||||
typedef ClassTable<HBUINT16> ClassTypeWide;
|
||||
|
||||
template <typename T>
|
||||
static inline unsigned int offsetToIndex (unsigned int offset,
|
||||
const void *base,
|
||||
@ -672,6 +689,13 @@ struct ObsoleteTypes
|
||||
return (offset - ((const char *) array - (const char *) base)) / sizeof (T);
|
||||
}
|
||||
template <typename T>
|
||||
static inline unsigned int byteOffsetToIndex (unsigned int offset,
|
||||
const void *base,
|
||||
const T *array)
|
||||
{
|
||||
return offsetToIndex (offset, base, array);
|
||||
}
|
||||
template <typename T>
|
||||
static inline unsigned int wordOffsetToIndex (unsigned int offset,
|
||||
const void *base,
|
||||
const T *array)
|
||||
@ -684,16 +708,9 @@ struct ExtendedTypes
|
||||
static const bool extended = true;
|
||||
typedef HBUINT32 HBUINT;
|
||||
typedef HBUINT16 HBUSHORT;
|
||||
struct ClassType : Lookup<HBUINT16>
|
||||
{
|
||||
inline unsigned int get_class (hb_codepoint_t glyph_id,
|
||||
unsigned int num_glyphs,
|
||||
unsigned int outOfRange) const
|
||||
{
|
||||
const HBUINT16 *v = get_value (glyph_id, num_glyphs);
|
||||
return v ? *v : outOfRange;
|
||||
}
|
||||
};
|
||||
typedef Lookup<HBUINT16> ClassTypeNarrow;
|
||||
typedef Lookup<HBUINT16> ClassTypeWide;
|
||||
|
||||
template <typename T>
|
||||
static inline unsigned int offsetToIndex (unsigned int offset,
|
||||
const void *base,
|
||||
@ -702,6 +719,13 @@ struct ExtendedTypes
|
||||
return offset;
|
||||
}
|
||||
template <typename T>
|
||||
static inline unsigned int byteOffsetToIndex (unsigned int offset,
|
||||
const void *base,
|
||||
const T *array)
|
||||
{
|
||||
return offset / 2;
|
||||
}
|
||||
template <typename T>
|
||||
static inline unsigned int wordOffsetToIndex (unsigned int offset,
|
||||
const void *base,
|
||||
const T *array)
|
||||
|
@ -39,6 +39,27 @@ namespace AAT {
|
||||
|
||||
struct SettingName
|
||||
{
|
||||
friend struct FeatureName;
|
||||
|
||||
int cmp (hb_aat_layout_feature_selector_t key) const
|
||||
{ return (int) key - (int) setting; }
|
||||
|
||||
inline hb_aat_layout_feature_selector_t get_selector (void) const
|
||||
{ return (hb_aat_layout_feature_selector_t) (unsigned) setting; }
|
||||
|
||||
inline void get_info (hb_aat_layout_feature_selector_info_t *s,
|
||||
hb_aat_layout_feature_selector_t default_selector) const
|
||||
{
|
||||
s->name_id = nameIndex;
|
||||
|
||||
s->enable = (hb_aat_layout_feature_selector_t) (unsigned int) setting;
|
||||
s->disable = default_selector == HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID ?
|
||||
(hb_aat_layout_feature_selector_t) (s->enable + 1) :
|
||||
default_selector;
|
||||
|
||||
s->reserved = 0;
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -51,35 +72,76 @@ struct SettingName
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
DECLARE_NULL_NAMESPACE_BYTES (AAT, SettingName);
|
||||
|
||||
struct feat;
|
||||
|
||||
struct FeatureName
|
||||
{
|
||||
int cmp (hb_aat_layout_feature_type_t key) const
|
||||
{ return (int) key - (int) feature; }
|
||||
|
||||
enum {
|
||||
Exclusive = 0x8000, /* If set, the feature settings are mutually exclusive. */
|
||||
NotDefault = 0x4000, /* If clear, then the setting with an index of 0 in
|
||||
Exclusive = 0x8000, /* If set, the feature settings are mutually exclusive. */
|
||||
NotDefault = 0x4000, /* If clear, then the setting with an index of 0 in
|
||||
* the setting name array for this feature should
|
||||
* be taken as the default for the feature
|
||||
* (if one is required). If set, then bits 0-15 of this
|
||||
* featureFlags field contain the index of the setting
|
||||
* which is to be taken as the default. */
|
||||
IndexMask = 0x00FF /* If bits 30 and 31 are set, then these sixteen bits
|
||||
IndexMask = 0x00FF /* If bits 30 and 31 are set, then these sixteen bits
|
||||
* indicate the index of the setting in the setting name
|
||||
* array for this feature which should be taken
|
||||
* as the default. */
|
||||
};
|
||||
|
||||
inline unsigned int get_selector_infos (unsigned int start_offset,
|
||||
unsigned int *selectors_count, /* IN/OUT. May be NULL. */
|
||||
hb_aat_layout_feature_selector_info_t *selectors, /* OUT. May be NULL. */
|
||||
unsigned int *pdefault_index, /* OUT. May be NULL. */
|
||||
const void *base) const
|
||||
{
|
||||
hb_array_t< const SettingName> settings_table = (base+settingTableZ).as_array (nSettings);
|
||||
|
||||
static_assert (Index::NOT_FOUND_INDEX == HB_AAT_LAYOUT_NO_SELECTOR_INDEX, "");
|
||||
|
||||
hb_aat_layout_feature_selector_t default_selector = HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID;
|
||||
unsigned int default_index = Index::NOT_FOUND_INDEX;
|
||||
if (featureFlags & Exclusive)
|
||||
{
|
||||
default_index = (featureFlags & NotDefault) ? featureFlags & IndexMask : 0;
|
||||
default_selector = settings_table[default_index].get_selector ();
|
||||
}
|
||||
if (pdefault_index)
|
||||
*pdefault_index = default_index;
|
||||
|
||||
if (selectors_count)
|
||||
{
|
||||
hb_array_t<const SettingName> arr = settings_table.sub_array (start_offset, selectors_count);
|
||||
unsigned int count = arr.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
settings_table[start_offset + i].get_info (&selectors[i], default_selector);
|
||||
}
|
||||
return settings_table.len;
|
||||
}
|
||||
|
||||
inline hb_aat_layout_feature_type_t get_feature_type () const
|
||||
{ return (hb_aat_layout_feature_type_t) (unsigned int) feature; }
|
||||
|
||||
inline hb_ot_name_id_t get_feature_name_id () const { return nameIndex; }
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
(base+settingTable).sanitize (c, nSettings)));
|
||||
(base+settingTableZ).sanitize (c, nSettings)));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 feature; /* Feature type. */
|
||||
HBUINT16 nSettings; /* The number of records in the setting name array. */
|
||||
LOffsetTo<UnsizedArrayOf<SettingName>, false>
|
||||
settingTable; /* Offset in bytes from the beginning of this table to
|
||||
settingTableZ; /* Offset in bytes from the beginning of this table to
|
||||
* this feature's setting name array. The actual type of
|
||||
* record this offset refers to will depend on the
|
||||
* exclusivity value, as described below. */
|
||||
@ -95,11 +157,47 @@ struct feat
|
||||
{
|
||||
static const hb_tag_t tableTag = HB_AAT_TAG_feat;
|
||||
|
||||
inline bool has_data (void) const { return version.to_int (); }
|
||||
|
||||
inline unsigned int get_feature_types (unsigned int start_offset,
|
||||
unsigned int *count,
|
||||
hb_aat_layout_feature_type_t *features) const
|
||||
{
|
||||
unsigned int feature_count = featureNameCount;
|
||||
if (count && *count)
|
||||
{
|
||||
unsigned int len = MIN (feature_count - start_offset, *count);
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
features[i] = namesZ[i + start_offset].get_feature_type ();
|
||||
*count = len;
|
||||
}
|
||||
return featureNameCount;
|
||||
}
|
||||
|
||||
inline const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
|
||||
{
|
||||
return namesZ.bsearch (featureNameCount, feature_type);
|
||||
}
|
||||
|
||||
inline hb_ot_name_id_t get_feature_name_id (hb_aat_layout_feature_type_t feature) const
|
||||
{ return get_feature (feature).get_feature_name_id (); }
|
||||
|
||||
inline unsigned int get_selector_infos (hb_aat_layout_feature_type_t feature_type,
|
||||
unsigned int start_offset,
|
||||
unsigned int *selectors_count, /* IN/OUT. May be NULL. */
|
||||
hb_aat_layout_feature_selector_info_t *selectors, /* OUT. May be NULL. */
|
||||
unsigned int *default_index /* OUT. May be NULL. */) const
|
||||
{
|
||||
return get_feature (feature_type).get_selector_infos (start_offset, selectors_count, selectors,
|
||||
default_index, this);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
names.sanitize (c, featureNameCount, this)));
|
||||
version.major == 1 &&
|
||||
namesZ.sanitize (c, featureNameCount, this)));
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -109,8 +207,8 @@ struct feat
|
||||
/* The number of entries in the feature name array. */
|
||||
HBUINT16 reserved1; /* Reserved (set to zero). */
|
||||
HBUINT32 reserved2; /* Reserved (set to zero). */
|
||||
UnsizedArrayOf<FeatureName>
|
||||
names; /* The feature name array. */
|
||||
SortedUnsizedArrayOf<FeatureName>
|
||||
namesZ; /* The feature name array. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (24);
|
||||
};
|
||||
|
@ -49,7 +49,7 @@ kerxTupleKern (int value,
|
||||
const void *base,
|
||||
hb_aat_apply_context_t *c)
|
||||
{
|
||||
if (likely (!tupleCount)) return value;
|
||||
if (likely (!tupleCount || !c)) return value;
|
||||
|
||||
unsigned int offset = value;
|
||||
const FWORD *pv = &StructAtOffset<FWORD> (base, offset);
|
||||
@ -93,21 +93,11 @@ struct KernPair
|
||||
template <typename KernSubTableHeader>
|
||||
struct KerxSubTableFormat0
|
||||
{
|
||||
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
|
||||
{
|
||||
hb_glyph_pair_t pair = {left, right};
|
||||
int i = pairs.bsearch (pair);
|
||||
if (i == -1) return 0;
|
||||
return pairs[i].get_kerning ();
|
||||
}
|
||||
|
||||
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
|
||||
hb_aat_apply_context_t *c) const
|
||||
hb_aat_apply_context_t *c = nullptr) const
|
||||
{
|
||||
hb_glyph_pair_t pair = {left, right};
|
||||
int i = pairs.bsearch (pair);
|
||||
if (i == -1) return 0;
|
||||
int v = pairs[i].get_kerning ();
|
||||
int v = pairs.bsearch (pair).get_kerning ();
|
||||
return kerxTupleKern (v, header.tuple_count (), this, c);
|
||||
}
|
||||
|
||||
@ -265,7 +255,7 @@ struct KerxSubTableFormat1
|
||||
unsigned int tuple_count = MAX (1u, table->header.tuple_count ());
|
||||
|
||||
unsigned int kern_idx = Format1EntryT::kernActionIndex (entry);
|
||||
kern_idx = Types::offsetToIndex (kern_idx, &table->machine, kernAction.arrayZ);
|
||||
kern_idx = Types::byteOffsetToIndex (kern_idx, &table->machine, kernAction.arrayZ);
|
||||
const FWORD *actions = &kernAction[kern_idx];
|
||||
if (!c->sanitizer.check_array (actions, depth, tuple_count))
|
||||
{
|
||||
@ -402,9 +392,13 @@ struct KerxSubTableFormat2
|
||||
unsigned int num_glyphs = c->sanitizer.get_num_glyphs ();
|
||||
unsigned int l = (this+leftClassTable).get_class (left, num_glyphs, 0);
|
||||
unsigned int r = (this+rightClassTable).get_class (right, num_glyphs, 0);
|
||||
unsigned int offset = l + r;
|
||||
const FWORD *v = &StructAtOffset<FWORD> (&(this+array), offset);
|
||||
|
||||
const UnsizedArrayOf<FWORD> &arrayZ = this+array;
|
||||
unsigned int kern_idx = l + r;
|
||||
kern_idx = Types::offsetToIndex (kern_idx, this, &arrayZ);
|
||||
const FWORD *v = &arrayZ[kern_idx];
|
||||
if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
|
||||
|
||||
return kerxTupleKern (*v, header.tuple_count (), this, c);
|
||||
}
|
||||
|
||||
@ -447,19 +441,13 @@ struct KerxSubTableFormat2
|
||||
c->check_range (this, array)));
|
||||
}
|
||||
|
||||
/* Note:
|
||||
* OT kern table specifies ClassTable as having 16-bit entries, whereas
|
||||
* AAT kern table specifies them as having 8bit entries.
|
||||
* I've not seen any fonts with this format in kern table.
|
||||
* We follow AAT. */
|
||||
|
||||
protected:
|
||||
KernSubTableHeader header;
|
||||
HBUINT rowWidth; /* The width, in bytes, of a row in the table. */
|
||||
OffsetTo<typename Types::ClassType, HBUINT, false>
|
||||
OffsetTo<typename Types::ClassTypeWide, HBUINT, false>
|
||||
leftClassTable; /* Offset from beginning of this subtable to
|
||||
* left-hand class table. */
|
||||
OffsetTo<typename Types::ClassType, HBUINT, false>
|
||||
OffsetTo<typename Types::ClassTypeWide, HBUINT, false>
|
||||
rightClassTable;/* Offset from beginning of this subtable to
|
||||
* right-hand class table. */
|
||||
OffsetTo<UnsizedArrayOf<FWORD>, HBUINT, false>
|
||||
@ -812,6 +800,7 @@ struct KerxSubTable
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.header.sanitize (c) ||
|
||||
u.header.length <= u.header.static_size ||
|
||||
!c->check_range (this, u.header.length))
|
||||
return_trace (false);
|
||||
|
||||
@ -842,6 +831,21 @@ struct KerxTable
|
||||
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
|
||||
inline const T* thiz (void) const { return static_cast<const T *> (this); }
|
||||
|
||||
inline bool has_state_machine (void) const
|
||||
{
|
||||
typedef typename T::SubTable SubTable;
|
||||
|
||||
const SubTable *st = &thiz()->firstSubTable;
|
||||
unsigned int count = thiz()->tableCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (st->get_type () == 1)
|
||||
return true;
|
||||
st = &StructAfter<SubTable> (*st);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool has_cross_stream (void) const
|
||||
{
|
||||
typedef typename T::SubTable SubTable;
|
||||
@ -920,9 +924,11 @@ struct KerxTable
|
||||
if (reverse)
|
||||
c->buffer->reverse ();
|
||||
|
||||
c->sanitizer.set_object (*st);
|
||||
|
||||
ret |= st->dispatch (c);
|
||||
{
|
||||
/* See comment in sanitize() for conditional here. */
|
||||
hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr);
|
||||
ret |= st->dispatch (c);
|
||||
}
|
||||
|
||||
if (reverse)
|
||||
c->buffer->reverse ();
|
||||
@ -951,8 +957,20 @@ struct KerxTable
|
||||
unsigned int count = thiz()->tableCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (unlikely (!st->u.header.sanitize (c)))
|
||||
return_trace (false);
|
||||
/* OpenType kern table has 2-byte subtable lengths. That's limiting.
|
||||
* MS implementation also only supports one subtable, of format 0,
|
||||
* anyway. Certain versions of some fonts, like Calibry, contain
|
||||
* kern subtable that exceeds 64kb. Looks like, the subtable length
|
||||
* is simply ignored. Which makes sense. It's only needed if you
|
||||
* have multiple subtables. To handle such fonts, we just ignore
|
||||
* the length for the last subtable. */
|
||||
hb_sanitize_with_object_t with (c, i < count - 1 ? st : (const SubTable *) nullptr);
|
||||
|
||||
if (unlikely (!st->sanitize (c)))
|
||||
return_trace (false);
|
||||
|
||||
st = &StructAfter<SubTable> (*st);
|
||||
}
|
||||
|
||||
|
@ -52,10 +52,10 @@ struct lcar
|
||||
const OffsetTo<LigCaretClassEntry>* entry_offset = lookup.get_value (glyph,
|
||||
font->face->get_num_glyphs ());
|
||||
const LigCaretClassEntry& array = entry_offset ? this+*entry_offset : Null (LigCaretClassEntry);
|
||||
if (caret_count && *caret_count)
|
||||
if (caret_count)
|
||||
{
|
||||
const HBINT16 *arr = array.sub_array (start_offset, caret_count);
|
||||
unsigned int count = *caret_count;
|
||||
hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
|
||||
unsigned int count = arr.len;
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
switch (format)
|
||||
{
|
||||
|
@ -911,14 +911,22 @@ struct ChainSubtable
|
||||
}
|
||||
}
|
||||
|
||||
inline bool apply (hb_aat_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_sanitize_with_object_t with (&c->sanitizer, this);
|
||||
return_trace (dispatch (c));
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!length.sanitize (c) ||
|
||||
length < min_size ||
|
||||
length <= min_size ||
|
||||
!c->check_range (this, length))
|
||||
return_trace (false);
|
||||
|
||||
hb_sanitize_with_object_t with (c, this);
|
||||
return_trace (dispatch (c));
|
||||
}
|
||||
|
||||
@ -949,21 +957,21 @@ struct Chain
|
||||
unsigned int count = featureCount;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
const Feature &feature = featureZ[i];
|
||||
uint16_t type = feature.featureType;
|
||||
uint16_t setting = feature.featureSetting;
|
||||
const Feature &feature = featureZ[i];
|
||||
hb_aat_layout_feature_type_t type = (hb_aat_layout_feature_type_t) (unsigned int) feature.featureType;
|
||||
hb_aat_layout_feature_selector_t setting = (hb_aat_layout_feature_selector_t) (unsigned int) feature.featureSetting;
|
||||
retry:
|
||||
const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type);
|
||||
const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch ((uint16_t) type);
|
||||
if (info && info->setting == setting)
|
||||
{
|
||||
flags &= feature.disableFlags;
|
||||
flags |= feature.enableFlags;
|
||||
}
|
||||
else if (type == 3/*kLetterCaseType*/ && setting == 3/*kSmallCapsSelector*/)
|
||||
else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE && setting == HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS)
|
||||
{
|
||||
/* Deprecated. https://github.com/harfbuzz/harfbuzz/issues/1342 */
|
||||
type = 37/*kLowerCaseType*/;
|
||||
setting = 1/*kLowerCaseSmallCapsSelector*/;
|
||||
type = HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE;
|
||||
setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
@ -1026,9 +1034,7 @@ struct Chain
|
||||
if (reverse)
|
||||
c->buffer->reverse ();
|
||||
|
||||
c->sanitizer.set_object (*subtable);
|
||||
|
||||
subtable->dispatch (c);
|
||||
subtable->apply (c);
|
||||
|
||||
if (reverse)
|
||||
c->buffer->reverse ();
|
||||
|
@ -133,7 +133,6 @@ struct TrackData
|
||||
if (!sizes) return 0.;
|
||||
if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
|
||||
|
||||
/* TODO bfind() */
|
||||
hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes);
|
||||
unsigned int size_index;
|
||||
for (size_index = 0; size_index < sizes - 1; size_index++)
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2017 Google, Inc.
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
@ -30,7 +31,7 @@
|
||||
#include "hb-aat-layout.hh"
|
||||
#include "hb-aat-layout-ankr-table.hh"
|
||||
#include "hb-aat-layout-bsln-table.hh" // Just so we compile it; unused otherwise.
|
||||
#include "hb-aat-layout-feat-table.hh" // Just so we compile it; unused otherwise.
|
||||
#include "hb-aat-layout-feat-table.hh"
|
||||
#include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise.
|
||||
#include "hb-aat-layout-kerx-table.hh"
|
||||
#include "hb-aat-layout-morx-table.hh"
|
||||
@ -38,86 +39,96 @@
|
||||
#include "hb-aat-ltag-table.hh"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hb-aat-layout
|
||||
* @title: hb-aat-layout
|
||||
* @short_description: Apple Advanced Typography Layout
|
||||
* @include: hb-aat.h
|
||||
*
|
||||
* Functions for querying OpenType Layout features in the font face.
|
||||
**/
|
||||
|
||||
|
||||
/* Table data courtesy of Apple. Converted from mnemonics to integers
|
||||
* when moving to this file. */
|
||||
static const hb_aat_feature_mapping_t feature_mappings[] =
|
||||
{
|
||||
{HB_TAG ('a','f','r','c'), 11/*kFractionsType*/, 1/*kVerticalFractionsSelector*/, 0/*kNoFractionsSelector*/},
|
||||
{HB_TAG ('c','2','p','c'), 38/*kUpperCaseType*/, 2/*kUpperCasePetiteCapsSelector*/, 0/*kDefaultUpperCaseSelector*/},
|
||||
{HB_TAG ('c','2','s','c'), 38/*kUpperCaseType*/, 1/*kUpperCaseSmallCapsSelector*/, 0/*kDefaultUpperCaseSelector*/},
|
||||
{HB_TAG ('c','a','l','t'), 36/*kContextualAlternatesType*/, 0/*kContextualAlternatesOnSelector*/, 1/*kContextualAlternatesOffSelector*/},
|
||||
{HB_TAG ('c','a','s','e'), 33/*kCaseSensitiveLayoutType*/, 0/*kCaseSensitiveLayoutOnSelector*/, 1/*kCaseSensitiveLayoutOffSelector*/},
|
||||
{HB_TAG ('c','l','i','g'), 1/*kLigaturesType*/, 18/*kContextualLigaturesOnSelector*/, 19/*kContextualLigaturesOffSelector*/},
|
||||
{HB_TAG ('c','p','s','p'), 33/*kCaseSensitiveLayoutType*/, 2/*kCaseSensitiveSpacingOnSelector*/, 3/*kCaseSensitiveSpacingOffSelector*/},
|
||||
{HB_TAG ('c','s','w','h'), 36/*kContextualAlternatesType*/, 4/*kContextualSwashAlternatesOnSelector*/, 5/*kContextualSwashAlternatesOffSelector*/},
|
||||
{HB_TAG ('d','l','i','g'), 1/*kLigaturesType*/, 4/*kRareLigaturesOnSelector*/, 5/*kRareLigaturesOffSelector*/},
|
||||
{HB_TAG ('e','x','p','t'), 20/*kCharacterShapeType*/, 10/*kExpertCharactersSelector*/, 16},
|
||||
{HB_TAG ('f','r','a','c'), 11/*kFractionsType*/, 2/*kDiagonalFractionsSelector*/, 0/*kNoFractionsSelector*/},
|
||||
{HB_TAG ('f','w','i','d'), 22/*kTextSpacingType*/, 1/*kMonospacedTextSelector*/, 7},
|
||||
{HB_TAG ('h','a','l','t'), 22/*kTextSpacingType*/, 6/*kAltHalfWidthTextSelector*/, 7},
|
||||
{HB_TAG ('h','i','s','t'), 1/*kLigaturesType*/, 20/*kHistoricalLigaturesOnSelector*/, 21/*kHistoricalLigaturesOffSelector*/},
|
||||
{HB_TAG ('h','k','n','a'), 34/*kAlternateKanaType*/, 0/*kAlternateHorizKanaOnSelector*/, 1/*kAlternateHorizKanaOffSelector*/, },
|
||||
{HB_TAG ('h','l','i','g'), 1/*kLigaturesType*/, 20/*kHistoricalLigaturesOnSelector*/, 21/*kHistoricalLigaturesOffSelector*/},
|
||||
{HB_TAG ('h','n','g','l'), 23/*kTransliterationType*/, 1/*kHanjaToHangulSelector*/, 0/*kNoTransliterationSelector*/},
|
||||
{HB_TAG ('h','o','j','o'), 20/*kCharacterShapeType*/, 12/*kHojoCharactersSelector*/, 16},
|
||||
{HB_TAG ('h','w','i','d'), 22/*kTextSpacingType*/, 2/*kHalfWidthTextSelector*/, 7},
|
||||
{HB_TAG ('i','t','a','l'), 32/*kItalicCJKRomanType*/, 2/*kCJKItalicRomanOnSelector*/, 3/*kCJKItalicRomanOffSelector*/},
|
||||
{HB_TAG ('j','p','0','4'), 20/*kCharacterShapeType*/, 11/*kJIS2004CharactersSelector*/, 16},
|
||||
{HB_TAG ('j','p','7','8'), 20/*kCharacterShapeType*/, 2/*kJIS1978CharactersSelector*/, 16},
|
||||
{HB_TAG ('j','p','8','3'), 20/*kCharacterShapeType*/, 3/*kJIS1983CharactersSelector*/, 16},
|
||||
{HB_TAG ('j','p','9','0'), 20/*kCharacterShapeType*/, 4/*kJIS1990CharactersSelector*/, 16},
|
||||
{HB_TAG ('l','i','g','a'), 1/*kLigaturesType*/, 2/*kCommonLigaturesOnSelector*/, 3/*kCommonLigaturesOffSelector*/},
|
||||
{HB_TAG ('l','n','u','m'), 21/*kNumberCaseType*/, 1/*kUpperCaseNumbersSelector*/, 2},
|
||||
{HB_TAG ('m','g','r','k'), 15/*kMathematicalExtrasType*/, 10/*kMathematicalGreekOnSelector*/, 11/*kMathematicalGreekOffSelector*/},
|
||||
{HB_TAG ('n','l','c','k'), 20/*kCharacterShapeType*/, 13/*kNLCCharactersSelector*/, 16},
|
||||
{HB_TAG ('o','n','u','m'), 21/*kNumberCaseType*/, 0/*kLowerCaseNumbersSelector*/, 2},
|
||||
{HB_TAG ('o','r','d','n'), 10/*kVerticalPositionType*/, 3/*kOrdinalsSelector*/, 0/*kNormalPositionSelector*/},
|
||||
{HB_TAG ('p','a','l','t'), 22/*kTextSpacingType*/, 5/*kAltProportionalTextSelector*/, 7},
|
||||
{HB_TAG ('p','c','a','p'), 37/*kLowerCaseType*/, 2/*kLowerCasePetiteCapsSelector*/, 0/*kDefaultLowerCaseSelector*/},
|
||||
{HB_TAG ('p','k','n','a'), 22/*kTextSpacingType*/, 0/*kProportionalTextSelector*/, 7},
|
||||
{HB_TAG ('p','n','u','m'), 6/*kNumberSpacingType*/, 1/*kProportionalNumbersSelector*/, 4},
|
||||
{HB_TAG ('p','w','i','d'), 22/*kTextSpacingType*/, 0/*kProportionalTextSelector*/, 7},
|
||||
{HB_TAG ('q','w','i','d'), 22/*kTextSpacingType*/, 4/*kQuarterWidthTextSelector*/, 7},
|
||||
{HB_TAG ('r','u','b','y'), 28/*kRubyKanaType*/, 2/*kRubyKanaOnSelector*/, 3/*kRubyKanaOffSelector*/},
|
||||
{HB_TAG ('s','i','n','f'), 10/*kVerticalPositionType*/, 4/*kScientificInferiorsSelector*/, 0/*kNormalPositionSelector*/},
|
||||
{HB_TAG ('s','m','c','p'), 37/*kLowerCaseType*/, 1/*kLowerCaseSmallCapsSelector*/, 0/*kDefaultLowerCaseSelector*/},
|
||||
{HB_TAG ('s','m','p','l'), 20/*kCharacterShapeType*/, 1/*kSimplifiedCharactersSelector*/, 16},
|
||||
{HB_TAG ('s','s','0','1'), 35/*kStylisticAlternativesType*/, 2/*kStylisticAltOneOnSelector*/, 3/*kStylisticAltOneOffSelector*/},
|
||||
{HB_TAG ('s','s','0','2'), 35/*kStylisticAlternativesType*/, 4/*kStylisticAltTwoOnSelector*/, 5/*kStylisticAltTwoOffSelector*/},
|
||||
{HB_TAG ('s','s','0','3'), 35/*kStylisticAlternativesType*/, 6/*kStylisticAltThreeOnSelector*/, 7/*kStylisticAltThreeOffSelector*/},
|
||||
{HB_TAG ('s','s','0','4'), 35/*kStylisticAlternativesType*/, 8/*kStylisticAltFourOnSelector*/, 9/*kStylisticAltFourOffSelector*/},
|
||||
{HB_TAG ('s','s','0','5'), 35/*kStylisticAlternativesType*/, 10/*kStylisticAltFiveOnSelector*/, 11/*kStylisticAltFiveOffSelector*/},
|
||||
{HB_TAG ('s','s','0','6'), 35/*kStylisticAlternativesType*/, 12/*kStylisticAltSixOnSelector*/, 13/*kStylisticAltSixOffSelector*/},
|
||||
{HB_TAG ('s','s','0','7'), 35/*kStylisticAlternativesType*/, 14/*kStylisticAltSevenOnSelector*/, 15/*kStylisticAltSevenOffSelector*/},
|
||||
{HB_TAG ('s','s','0','8'), 35/*kStylisticAlternativesType*/, 16/*kStylisticAltEightOnSelector*/, 17/*kStylisticAltEightOffSelector*/},
|
||||
{HB_TAG ('s','s','0','9'), 35/*kStylisticAlternativesType*/, 18/*kStylisticAltNineOnSelector*/, 19/*kStylisticAltNineOffSelector*/},
|
||||
{HB_TAG ('s','s','1','0'), 35/*kStylisticAlternativesType*/, 20/*kStylisticAltTenOnSelector*/, 21/*kStylisticAltTenOffSelector*/},
|
||||
{HB_TAG ('s','s','1','1'), 35/*kStylisticAlternativesType*/, 22/*kStylisticAltElevenOnSelector*/, 23/*kStylisticAltElevenOffSelector*/},
|
||||
{HB_TAG ('s','s','1','2'), 35/*kStylisticAlternativesType*/, 24/*kStylisticAltTwelveOnSelector*/, 25/*kStylisticAltTwelveOffSelector*/},
|
||||
{HB_TAG ('s','s','1','3'), 35/*kStylisticAlternativesType*/, 26/*kStylisticAltThirteenOnSelector*/, 27/*kStylisticAltThirteenOffSelector*/},
|
||||
{HB_TAG ('s','s','1','4'), 35/*kStylisticAlternativesType*/, 28/*kStylisticAltFourteenOnSelector*/, 29/*kStylisticAltFourteenOffSelector*/},
|
||||
{HB_TAG ('s','s','1','5'), 35/*kStylisticAlternativesType*/, 30/*kStylisticAltFifteenOnSelector*/, 31/*kStylisticAltFifteenOffSelector*/},
|
||||
{HB_TAG ('s','s','1','6'), 35/*kStylisticAlternativesType*/, 32/*kStylisticAltSixteenOnSelector*/, 33/*kStylisticAltSixteenOffSelector*/},
|
||||
{HB_TAG ('s','s','1','7'), 35/*kStylisticAlternativesType*/, 34/*kStylisticAltSeventeenOnSelector*/, 35/*kStylisticAltSeventeenOffSelector*/},
|
||||
{HB_TAG ('s','s','1','8'), 35/*kStylisticAlternativesType*/, 36/*kStylisticAltEighteenOnSelector*/, 37/*kStylisticAltEighteenOffSelector*/},
|
||||
{HB_TAG ('s','s','1','9'), 35/*kStylisticAlternativesType*/, 38/*kStylisticAltNineteenOnSelector*/, 39/*kStylisticAltNineteenOffSelector*/},
|
||||
{HB_TAG ('s','s','2','0'), 35/*kStylisticAlternativesType*/, 40/*kStylisticAltTwentyOnSelector*/, 41/*kStylisticAltTwentyOffSelector*/},
|
||||
{HB_TAG ('s','u','b','s'), 10/*kVerticalPositionType*/, 2/*kInferiorsSelector*/, 0/*kNormalPositionSelector*/},
|
||||
{HB_TAG ('s','u','p','s'), 10/*kVerticalPositionType*/, 1/*kSuperiorsSelector*/, 0/*kNormalPositionSelector*/},
|
||||
{HB_TAG ('s','w','s','h'), 36/*kContextualAlternatesType*/, 2/*kSwashAlternatesOnSelector*/, 3/*kSwashAlternatesOffSelector*/},
|
||||
{HB_TAG ('t','i','t','l'), 19/*kStyleOptionsType*/, 4/*kTitlingCapsSelector*/, 0/*kNoStyleOptionsSelector*/},
|
||||
{HB_TAG ('t','n','a','m'), 20/*kCharacterShapeType*/, 14/*kTraditionalNamesCharactersSelector*/, 16},
|
||||
{HB_TAG ('t','n','u','m'), 6/*kNumberSpacingType*/, 0/*kMonospacedNumbersSelector*/, 4},
|
||||
{HB_TAG ('t','r','a','d'), 20/*kCharacterShapeType*/, 0/*kTraditionalCharactersSelector*/, 16},
|
||||
{HB_TAG ('t','w','i','d'), 22/*kTextSpacingType*/, 3/*kThirdWidthTextSelector*/, 7},
|
||||
{HB_TAG ('u','n','i','c'), 3/*kLetterCaseType*/, 14, 15},
|
||||
{HB_TAG ('v','a','l','t'), 22/*kTextSpacingType*/, 5/*kAltProportionalTextSelector*/, 7},
|
||||
{HB_TAG ('v','e','r','t'), 4/*kVerticalSubstitutionType*/, 0/*kSubstituteVerticalFormsOnSelector*/, 1/*kSubstituteVerticalFormsOffSelector*/},
|
||||
{HB_TAG ('v','h','a','l'), 22/*kTextSpacingType*/, 6/*kAltHalfWidthTextSelector*/, 7},
|
||||
{HB_TAG ('v','k','n','a'), 34/*kAlternateKanaType*/, 2/*kAlternateVertKanaOnSelector*/, 3/*kAlternateVertKanaOffSelector*/},
|
||||
{HB_TAG ('v','p','a','l'), 22/*kTextSpacingType*/, 5/*kAltProportionalTextSelector*/, 7},
|
||||
{HB_TAG ('v','r','t','2'), 4/*kVerticalSubstitutionType*/, 0/*kSubstituteVerticalFormsOnSelector*/, 1/*kSubstituteVerticalFormsOffSelector*/},
|
||||
{HB_TAG ('z','e','r','o'), 14/*kTypographicExtrasType*/, 4/*kSlashedZeroOnSelector*/, 5/*kSlashedZeroOffSelector*/},
|
||||
{HB_TAG ('a','f','r','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
|
||||
{HB_TAG ('c','2','p','c'), HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE},
|
||||
{HB_TAG ('c','2','s','c'), HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE},
|
||||
{HB_TAG ('c','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF},
|
||||
{HB_TAG ('c','a','s','e'), HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT, HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF},
|
||||
{HB_TAG ('c','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF},
|
||||
{HB_TAG ('c','p','s','p'), HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT, HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF},
|
||||
{HB_TAG ('c','s','w','h'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF},
|
||||
{HB_TAG ('d','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF},
|
||||
{HB_TAG ('e','x','p','t'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS, (hb_aat_layout_feature_selector_t) 16},
|
||||
{HB_TAG ('f','r','a','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
|
||||
{HB_TAG ('f','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('h','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('h','i','s','t'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
|
||||
{HB_TAG ('h','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF},
|
||||
{HB_TAG ('h','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
|
||||
{HB_TAG ('h','n','g','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION, HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION},
|
||||
{HB_TAG ('h','o','j','o'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS, (hb_aat_layout_feature_selector_t) 16},
|
||||
{HB_TAG ('h','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('i','t','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN, HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF},
|
||||
{HB_TAG ('j','p','0','4'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS, (hb_aat_layout_feature_selector_t) 16},
|
||||
{HB_TAG ('j','p','7','8'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS, (hb_aat_layout_feature_selector_t) 16},
|
||||
{HB_TAG ('j','p','8','3'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS, (hb_aat_layout_feature_selector_t) 16},
|
||||
{HB_TAG ('j','p','9','0'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS, (hb_aat_layout_feature_selector_t) 16},
|
||||
{HB_TAG ('l','i','g','a'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF},
|
||||
{HB_TAG ('l','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS, (hb_aat_layout_feature_selector_t) 2},
|
||||
{HB_TAG ('m','g','r','k'), HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS, HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF},
|
||||
{HB_TAG ('n','l','c','k'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS, (hb_aat_layout_feature_selector_t) 16},
|
||||
{HB_TAG ('o','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS, (hb_aat_layout_feature_selector_t) 2},
|
||||
{HB_TAG ('o','r','d','n'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
|
||||
{HB_TAG ('p','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('p','c','a','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
|
||||
{HB_TAG ('p','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('p','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS, (hb_aat_layout_feature_selector_t) 4},
|
||||
{HB_TAG ('p','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('q','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('r','u','b','y'), HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF},
|
||||
{HB_TAG ('s','i','n','f'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
|
||||
{HB_TAG ('s','m','c','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
|
||||
{HB_TAG ('s','m','p','l'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS, (hb_aat_layout_feature_selector_t) 16},
|
||||
{HB_TAG ('s','s','0','1'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF},
|
||||
{HB_TAG ('s','s','0','2'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF},
|
||||
{HB_TAG ('s','s','0','3'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF},
|
||||
{HB_TAG ('s','s','0','4'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF},
|
||||
{HB_TAG ('s','s','0','5'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF},
|
||||
{HB_TAG ('s','s','0','6'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF},
|
||||
{HB_TAG ('s','s','0','7'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF},
|
||||
{HB_TAG ('s','s','0','8'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF},
|
||||
{HB_TAG ('s','s','0','9'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF},
|
||||
{HB_TAG ('s','s','1','0'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF},
|
||||
{HB_TAG ('s','s','1','1'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF},
|
||||
{HB_TAG ('s','s','1','2'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF},
|
||||
{HB_TAG ('s','s','1','3'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF},
|
||||
{HB_TAG ('s','s','1','4'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF},
|
||||
{HB_TAG ('s','s','1','5'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF},
|
||||
{HB_TAG ('s','s','1','6'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF},
|
||||
{HB_TAG ('s','s','1','7'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF},
|
||||
{HB_TAG ('s','s','1','8'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF},
|
||||
{HB_TAG ('s','s','1','9'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF},
|
||||
{HB_TAG ('s','s','2','0'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF},
|
||||
{HB_TAG ('s','u','b','s'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
|
||||
{HB_TAG ('s','u','p','s'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
|
||||
{HB_TAG ('s','w','s','h'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF},
|
||||
{HB_TAG ('t','i','t','l'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS},
|
||||
{HB_TAG ('t','n','a','m'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS, (hb_aat_layout_feature_selector_t) 16},
|
||||
{HB_TAG ('t','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS, (hb_aat_layout_feature_selector_t) 4},
|
||||
{HB_TAG ('t','r','a','d'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS, (hb_aat_layout_feature_selector_t) 16},
|
||||
{HB_TAG ('t','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('u','n','i','c'), HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE, (hb_aat_layout_feature_selector_t) 14, (hb_aat_layout_feature_selector_t) 15},
|
||||
{HB_TAG ('v','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('v','e','r','t'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
|
||||
{HB_TAG ('v','h','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('v','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF},
|
||||
{HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
|
||||
{HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF},
|
||||
};
|
||||
|
||||
const hb_aat_feature_mapping_t *
|
||||
@ -297,3 +308,65 @@ _hb_aat_language_get (hb_face_t *face,
|
||||
{
|
||||
return face->table.ltag->get_language (i);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_aat_layout_get_feature_types:
|
||||
* @face: a face object
|
||||
* @start_offset: iteration's start offset
|
||||
* @feature_count:(inout) (allow-none): buffer size as input, filled size as output
|
||||
* @features: (out caller-allocates) (array length=feature_count): features buffer
|
||||
*
|
||||
* Return value: Number of all available feature types.
|
||||
*
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
unsigned int
|
||||
hb_aat_layout_get_feature_types (hb_face_t *face,
|
||||
unsigned int start_offset,
|
||||
unsigned int *feature_count, /* IN/OUT. May be NULL. */
|
||||
hb_aat_layout_feature_type_t *features /* OUT. May be NULL. */)
|
||||
{
|
||||
return face->table.feat->get_feature_types (start_offset, feature_count, features);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_aat_layout_feature_type_get_name_id:
|
||||
* @face: a face object
|
||||
* @feature_type: feature id
|
||||
*
|
||||
* Return value: Name ID index
|
||||
*
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
hb_ot_name_id_t
|
||||
hb_aat_layout_feature_type_get_name_id (hb_face_t *face,
|
||||
hb_aat_layout_feature_type_t feature_type)
|
||||
{ return face->table.feat->get_feature_name_id (feature_type); }
|
||||
|
||||
/**
|
||||
* hb_aat_layout_feature_type_get_selectors:
|
||||
* @face: a face object
|
||||
* @feature_type: feature id
|
||||
* @start_offset: iteration's start offset
|
||||
* @selector_count: (inout) (allow-none): buffer size as input, filled size as output
|
||||
* @selectors: (out caller-allocates) (array length=selector_count): settings buffer
|
||||
* @default_index: (out) (allow-none): index of default selector if any
|
||||
*
|
||||
* If upon return, @default_index is set to #HB_AAT_LAYOUT_NO_SELECTOR_INDEX, then
|
||||
* the feature type is non-exclusive. Otherwise, @default_index is the index of
|
||||
* the selector that is selected by default.
|
||||
*
|
||||
* Return value: Number of all available feature selectors.
|
||||
*
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
unsigned int
|
||||
hb_aat_layout_feature_type_get_selector_infos (hb_face_t *face,
|
||||
hb_aat_layout_feature_type_t feature_type,
|
||||
unsigned int start_offset,
|
||||
unsigned int *selector_count, /* IN/OUT. May be NULL. */
|
||||
hb_aat_layout_feature_selector_info_t *selectors, /* OUT. May be NULL. */
|
||||
unsigned int *default_index /* OUT. May be NULL. */)
|
||||
{
|
||||
return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index);
|
||||
}
|
||||
|
462
src/hb-aat-layout.h
Normal file
462
src/hb-aat-layout.h
Normal file
@ -0,0 +1,462 @@
|
||||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef HB_AAT_H_IN
|
||||
#error "Include <hb-aat.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef HB_AAT_LAYOUT_H
|
||||
#define HB_AAT_LAYOUT_H
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
#include "hb-ot.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* hb_aat_layout_feature_type_t:
|
||||
*
|
||||
*
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_INVALID = 0xFFFF,
|
||||
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT = 5,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING = 6,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE = 8,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE = 9,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION = 10,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS = 11,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE = 13,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS = 14,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS = 15,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE = 16,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES = 17,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE = 18,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS = 19,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE = 20,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE = 21,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING = 22,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION = 23,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE = 24,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE = 25,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE = 26,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE = 27,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA = 28,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE = 29,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE = 30,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE = 31,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN = 32,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT = 33,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA = 34,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES = 35,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES = 36,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE = 37,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE = 38,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE = 39,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE = 103,
|
||||
|
||||
_HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
|
||||
} hb_aat_layout_feature_type_t;
|
||||
|
||||
/**
|
||||
* hb_aat_layout_feature_selector_t:
|
||||
*
|
||||
*
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID = 0xFFFF,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_OFF = 1,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF = 5,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_ON = 6,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_OFF = 7,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_ON = 8,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_OFF = 9,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_ON = 10,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_OFF = 11,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_ON = 12,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_OFF = 13,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_ON = 14,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_OFF = 15,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_ON = 16,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_OFF = 17,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON = 18,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF = 19,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON = 20,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF = 21,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_UNCONNECTED = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PARTIALLY_CONNECTED = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CURSIVE = 2,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_AND_LOWER_CASE = 0, /* deprecated */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_CAPS = 1, /* deprecated */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_LOWER_CASE = 2, /* deprecated */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS = 3, /* deprecated */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS = 4, /* deprecated */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS_AND_SMALL_CAPS = 5, /* deprecated */
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF = 1,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_OFF = 1,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_NUMBERS = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_NUMBERS = 3,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_OFF = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_ON = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_OFF = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_ON = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_OFF = 5,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_ON = 6,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_OFF = 7,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_ON = 8,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_OFF = 9,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SHOW_DIACRITICS = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HIDE_DIACRITICS = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DECOMPOSE_DIACRITICS = 2,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS = 4,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS = 2,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_OFF = 1,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_OFF = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_ON = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_OFF = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF = 5,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_ON = 6,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_OFF = 7,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_ON = 8,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_OFF = 9,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_ON = 10,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_OFF = 11,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_OFF = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_ON = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_OFF = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_ON = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_OFF = 5,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_ON = 6,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_OFF = 7,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_ON = 8,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_OFF = 9,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON = 10,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF = 11,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ORNAMENTS = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DINGBATS = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PI_CHARACTERS = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_FLEURONS = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DECORATIVE_BORDERS = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_INTERNATIONAL_SYMBOLS = 5,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_MATH_SYMBOLS = 6,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ALTERNATES = 0,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL1 = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL2 = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL3 = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL4 = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL5 = 4,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DISPLAY_TEXT = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ENGRAVED_TEXT = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ILLUMINATED_CAPS = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_TALL_CAPS = 5,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_ONE = 5,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_TWO = 6,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_THREE = 7,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FOUR = 8,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FIVE = 9,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS = 10,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS = 11,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS = 12,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS = 13,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS = 14,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS = 1,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT = 5,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT = 6,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HIRAGANA_TO_KATAKANA = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_KATAKANA_TO_HIRAGANA = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_KANA_TO_ROMANIZATION = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_HIRAGANA = 5,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_KATAKANA = 6,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_ONE = 7,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_TWO = 8,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_THREE = 9,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ANNOTATION = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_BOX_ANNOTATION = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ROUNDED_BOX_ANNOTATION = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CIRCLE_ANNOTATION = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_CIRCLE_ANNOTATION = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PARENTHESIS_ANNOTATION = 5,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIOD_ANNOTATION = 6,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMAN_NUMERAL_ANNOTATION = 7,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAMOND_ANNOTATION = 8,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_BOX_ANNOTATION = 9,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_ROUNDED_BOX_ANNOTATION= 10,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_KANA = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_KANA = 1,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_IDEOGRAPHS = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_IDEOGRAPHS = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_IDEOGRAPHS = 2,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_OFF = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_ON = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_OFF = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_ON = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_OFF = 5,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_RUBY_KANA = 0, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF instead */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA = 1, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON instead */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF = 3,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_SYMBOL_ALTERNATIVES = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_ONE = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_TWO = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_THREE = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FOUR = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FIVE = 5,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_IDEOGRAPHIC_ALTERNATIVES = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_ONE = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_TWO = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_THREE = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FOUR = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FIVE = 5,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_CENTERED = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_HBASELINE = 1,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_ITALIC_ROMAN = 0, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF instead */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN = 1, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON instead */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF = 3,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF = 3,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF = 3,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLISTIC_ALTERNATES = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF = 5,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON = 6,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF = 7,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON = 8,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF = 9,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON = 10,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF = 11,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON = 12,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF = 13,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON = 14,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF = 15,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON = 16,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF = 17,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON = 18,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF = 19,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON = 20,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF = 21,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON = 22,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF = 23,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON = 24,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF = 25,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON = 26,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF = 27,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON = 28,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF = 29,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON = 30,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF = 31,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON = 32,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF = 33,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON = 34,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF = 35,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON = 36,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF = 37,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON = 38,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF = 39,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON = 40,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF = 41,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF = 3,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON = 4,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF= 5,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS = 2,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS = 2,
|
||||
|
||||
/* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE */
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_CJK_ROMAN = 0,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_CJK_ROMAN = 1,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_CJK_ROMAN = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_CJK_ROMAN = 3,
|
||||
|
||||
_HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
|
||||
} hb_aat_layout_feature_selector_t;
|
||||
|
||||
HB_EXTERN unsigned int
|
||||
hb_aat_layout_get_feature_types (hb_face_t *face,
|
||||
unsigned int start_offset,
|
||||
unsigned int *feature_count, /* IN/OUT. May be NULL. */
|
||||
hb_aat_layout_feature_type_t *features /* OUT. May be NULL. */);
|
||||
|
||||
HB_EXTERN hb_ot_name_id_t
|
||||
hb_aat_layout_feature_type_get_name_id (hb_face_t *face,
|
||||
hb_aat_layout_feature_type_t feature_type);
|
||||
|
||||
typedef struct hb_aat_layout_feature_selector_info_t
|
||||
{
|
||||
hb_ot_name_id_t name_id;
|
||||
hb_aat_layout_feature_selector_t enable;
|
||||
hb_aat_layout_feature_selector_t disable;
|
||||
/*< private >*/
|
||||
unsigned int reserved;
|
||||
} hb_aat_layout_feature_selector_info_t;
|
||||
|
||||
#define HB_AAT_LAYOUT_NO_SELECTOR_INDEX 0xFFFFu
|
||||
|
||||
HB_EXTERN unsigned int
|
||||
hb_aat_layout_feature_type_get_selector_infos (hb_face_t *face,
|
||||
hb_aat_layout_feature_type_t feature_type,
|
||||
unsigned int start_offset,
|
||||
unsigned int *selector_count, /* IN/OUT. May be NULL. */
|
||||
hb_aat_layout_feature_selector_info_t *selectors, /* OUT. May be NULL. */
|
||||
unsigned int *default_index /* OUT. May be NULL. */);
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_AAT_LAYOUT_H */
|
@ -35,9 +35,9 @@
|
||||
struct hb_aat_feature_mapping_t
|
||||
{
|
||||
hb_tag_t otFeatureTag;
|
||||
uint16_t aatFeatureType;
|
||||
uint16_t selectorToEnable;
|
||||
uint16_t selectorToDisable;
|
||||
hb_aat_layout_feature_type_t aatFeatureType;
|
||||
hb_aat_layout_feature_selector_t selectorToEnable;
|
||||
hb_aat_layout_feature_selector_t selectorToDisable;
|
||||
|
||||
static inline int cmp (const void *key_, const void *entry_)
|
||||
{
|
||||
|
@ -37,8 +37,8 @@ void hb_aat_map_builder_t::add_feature (hb_tag_t tag,
|
||||
if (tag == HB_TAG ('a','a','l','t'))
|
||||
{
|
||||
feature_info_t *info = features.push();
|
||||
info->type = 17/*kCharacterAlternativesType*/;
|
||||
info->setting = value;
|
||||
info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
|
||||
info->setting = (hb_aat_layout_feature_selector_t) value;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -65,8 +65,8 @@ struct hb_aat_map_builder_t
|
||||
public:
|
||||
struct feature_info_t
|
||||
{
|
||||
uint16_t type;
|
||||
uint16_t setting;
|
||||
hb_aat_layout_feature_type_t type;
|
||||
hb_aat_layout_feature_selector_t setting;
|
||||
unsigned seq; /* For stable sorting only. */
|
||||
|
||||
static int cmp (const void *pa, const void *pb)
|
||||
@ -77,9 +77,9 @@ struct hb_aat_map_builder_t
|
||||
(a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
|
||||
}
|
||||
|
||||
int cmp (const short unsigned int *ty) const
|
||||
int cmp (unsigned int ty) const
|
||||
{
|
||||
return (type != *ty) ? (type < *ty ? -1 : 1) : 0;
|
||||
return (type != ty) ? (type < ty ? -1 : 1) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
38
src/hb-aat.h
Normal file
38
src/hb-aat.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef HB_AAT_H
|
||||
#define HB_AAT_H
|
||||
#define HB_AAT_H_IN
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
#include "hb-aat-layout.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#undef HB_AAT_H_IN
|
||||
#endif /* HB_AAT_H */
|
@ -282,7 +282,7 @@ struct hb_atomic_int_t
|
||||
template <typename P>
|
||||
struct hb_atomic_ptr_t
|
||||
{
|
||||
typedef typename hb_remove_pointer<P>::value T;
|
||||
typedef typename hb_remove_pointer (P) T;
|
||||
|
||||
inline void init (T* v_ = nullptr) { set_relaxed (v_); }
|
||||
inline void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
|
||||
|
@ -60,7 +60,7 @@ struct hb_blob_t
|
||||
template <typename Type>
|
||||
inline const Type* as (void) const
|
||||
{
|
||||
return length < Type::min_size ? &Null(Type) : reinterpret_cast<const Type *> (data);
|
||||
return length < hb_null_size (Type) ? &Null(Type) : reinterpret_cast<const Type *> (data);
|
||||
}
|
||||
inline hb_bytes_t as_bytes (void) const
|
||||
{
|
||||
@ -86,7 +86,7 @@ struct hb_blob_t
|
||||
template <typename P>
|
||||
struct hb_blob_ptr_t
|
||||
{
|
||||
typedef typename hb_remove_pointer<P>::value T;
|
||||
typedef typename hb_remove_pointer (P) T;
|
||||
|
||||
inline hb_blob_ptr_t (hb_blob_t *b_ = nullptr) : b (b_) {}
|
||||
inline hb_blob_t * operator = (hb_blob_t *b_) { return b = b_; }
|
||||
|
@ -204,7 +204,7 @@ static const char canon_map[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0,
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0,
|
||||
'-', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, '-',
|
||||
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0
|
||||
@ -276,7 +276,7 @@ struct hb_language_item_t {
|
||||
|
||||
static hb_atomic_ptr_t <hb_language_item_t> langs;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static void
|
||||
free_langs (void)
|
||||
{
|
||||
@ -323,7 +323,7 @@ retry:
|
||||
goto retry;
|
||||
}
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
if (!first_lang)
|
||||
atexit (free_langs); /* First person registers atexit() callback. */
|
||||
#endif
|
||||
@ -780,18 +780,18 @@ parse_uint32 (const char **pp, const char *end, uint32_t *pv)
|
||||
|
||||
#ifdef USE_XLOCALE
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_C_locale (void);
|
||||
#endif
|
||||
|
||||
static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<HB_LOCALE_T>::value,
|
||||
static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (HB_LOCALE_T),
|
||||
hb_C_locale_lazy_loader_t>
|
||||
{
|
||||
static inline HB_LOCALE_T create (void)
|
||||
{
|
||||
HB_LOCALE_T C_locale = HB_CREATE_LOCALE ("C");
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_C_locale);
|
||||
#endif
|
||||
|
||||
@ -807,7 +807,7 @@ static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<HB_
|
||||
}
|
||||
} static_C_locale;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_C_locale (void)
|
||||
{
|
||||
|
@ -293,14 +293,16 @@ struct hb_auto_trace_t
|
||||
if (plevel) --*plevel;
|
||||
}
|
||||
|
||||
inline ret_t ret (ret_t v, unsigned int line = 0)
|
||||
inline ret_t ret (ret_t v,
|
||||
const char *func = "",
|
||||
unsigned int line = 0)
|
||||
{
|
||||
if (unlikely (returned)) {
|
||||
fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n");
|
||||
return v;
|
||||
}
|
||||
|
||||
_hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1,
|
||||
_hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
|
||||
"return %s (line %d)",
|
||||
hb_printer_t<ret_t>().print (v), line);
|
||||
if (plevel) --*plevel;
|
||||
@ -325,17 +327,21 @@ struct hb_auto_trace_t<0, ret_t>
|
||||
const char *message,
|
||||
...) HB_PRINTF_FUNC(6, 7) {}
|
||||
|
||||
inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
|
||||
inline ret_t ret (ret_t v,
|
||||
const char *func HB_UNUSED = 0,
|
||||
unsigned int line HB_UNUSED = 0) { return v; }
|
||||
};
|
||||
|
||||
/* For disabled tracing; optimize out everything.
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/605 */
|
||||
template <typename ret_t>
|
||||
struct hb_no_trace_t {
|
||||
inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
|
||||
inline ret_t ret (ret_t v,
|
||||
const char *func HB_UNUSED = "",
|
||||
unsigned int line HB_UNUSED = 0) { return v; }
|
||||
};
|
||||
|
||||
#define return_trace(RET) return trace.ret (RET, __LINE__)
|
||||
#define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
|
||||
|
||||
|
||||
/*
|
||||
|
@ -241,6 +241,43 @@ HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) hb_tag_t
|
||||
hb_ot_tag_from_language (hb_language_t language);
|
||||
|
||||
|
||||
typedef unsigned int hb_ot_name_id_t; /* Since is in hb-ot.h */
|
||||
|
||||
/**
|
||||
* HB_OT_VAR_NO_AXIS_INDEX:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
* Deprecated: REPLACEME
|
||||
*/
|
||||
#define HB_OT_VAR_NO_AXIS_INDEX 0xFFFFFFFFu
|
||||
|
||||
/**
|
||||
* hb_ot_var_axis_t:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
* Deprecated: REPLACEME
|
||||
*/
|
||||
typedef struct hb_ot_var_axis_t
|
||||
{
|
||||
hb_tag_t tag;
|
||||
hb_ot_name_id_t name_id;
|
||||
float min_value;
|
||||
float default_value;
|
||||
float max_value;
|
||||
} hb_ot_var_axis_t;
|
||||
|
||||
HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_get_axis_infos) unsigned int
|
||||
hb_ot_var_get_axes (hb_face_t *face,
|
||||
unsigned int start_offset,
|
||||
unsigned int *axes_count /* IN/OUT */,
|
||||
hb_ot_var_axis_t *axes_array /* OUT */);
|
||||
|
||||
HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_find_axis_info) hb_bool_t
|
||||
hb_ot_var_find_axis (hb_face_t *face,
|
||||
hb_tag_t axis_tag,
|
||||
unsigned int *axis_index,
|
||||
hb_ot_var_axis_t *axis_info);
|
||||
|
||||
#endif
|
||||
|
||||
HB_END_DECLS
|
||||
|
149
src/hb-dsalgs.hh
149
src/hb-dsalgs.hh
@ -559,10 +559,16 @@ struct hb_bytes_t
|
||||
unsigned int len;
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct hb_sorted_array_t;
|
||||
|
||||
template <typename Type>
|
||||
struct hb_array_t
|
||||
{
|
||||
static_assert ((bool) (unsigned) hb_static_size (Type), "");
|
||||
|
||||
inline hb_array_t (void) : arrayZ (nullptr), len (0) {}
|
||||
inline hb_array_t (const hb_array_t &o) : arrayZ (o.arrayZ), len (o.len) {}
|
||||
inline hb_array_t (Type *array_, unsigned int len_) : arrayZ (array_), len (len_) {}
|
||||
|
||||
inline Type& operator [] (unsigned int i) const
|
||||
@ -571,39 +577,160 @@ struct hb_array_t
|
||||
return arrayZ[i];
|
||||
}
|
||||
|
||||
inline unsigned int get_size (void) const { return len * sizeof (Type); }
|
||||
|
||||
template <typename hb_sanitize_context_t>
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{ return c->check_array (arrayZ, len); }
|
||||
|
||||
template <typename T> inline operator T * (void) const { return arrayZ; }
|
||||
|
||||
inline Type * operator & (void) const { return arrayZ; }
|
||||
|
||||
inline hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
|
||||
inline unsigned int get_size (void) const { return len * sizeof (Type); }
|
||||
|
||||
inline hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
|
||||
{
|
||||
if (!seg_count) return hb_array_t<Type> ();
|
||||
|
||||
unsigned int count = len;
|
||||
if (unlikely (start_offset > count))
|
||||
count = 0;
|
||||
else
|
||||
count -= start_offset;
|
||||
count = MIN (count, seg_count);
|
||||
count = *seg_count = MIN (count, *seg_count);
|
||||
return hb_array_t<Type> (arrayZ + start_offset, count);
|
||||
}
|
||||
inline hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
|
||||
{ return sub_array (start_offset, &seg_count); }
|
||||
|
||||
inline hb_bytes_t as_bytes (void) const
|
||||
{ return hb_bytes_t (arrayZ, len * sizeof (Type)); }
|
||||
|
||||
template <typename T>
|
||||
inline Type *lsearch (const T &x,
|
||||
Type *not_found = nullptr)
|
||||
{
|
||||
return hb_bytes_t (arrayZ, len * sizeof (Type));
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!this->arrayZ[i].cmp (x))
|
||||
return &this->arrayZ[i];
|
||||
return not_found;
|
||||
}
|
||||
template <typename T>
|
||||
inline const Type *lsearch (const T &x,
|
||||
const Type *not_found = nullptr) const
|
||||
{
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!this->arrayZ[i].cmp (x))
|
||||
return &this->arrayZ[i];
|
||||
return not_found;
|
||||
}
|
||||
|
||||
inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; }
|
||||
inline hb_sorted_array_t<Type> qsort (int (*cmp)(const void*, const void*))
|
||||
{
|
||||
::qsort (arrayZ, len, sizeof (Type), cmp);
|
||||
return hb_sorted_array_t<Type> (*this);
|
||||
}
|
||||
inline hb_sorted_array_t<Type> qsort (void)
|
||||
{
|
||||
::qsort (arrayZ, len, sizeof (Type), Type::cmp);
|
||||
return hb_sorted_array_t<Type> (*this);
|
||||
}
|
||||
inline void qsort (unsigned int start, unsigned int end)
|
||||
{
|
||||
end = MIN (end, len);
|
||||
assert (start <= end);
|
||||
::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
|
||||
}
|
||||
|
||||
inline void free (void)
|
||||
{ ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; }
|
||||
|
||||
template <typename hb_sanitize_context_t>
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{ return c->check_array (arrayZ, len); }
|
||||
|
||||
public:
|
||||
Type *arrayZ;
|
||||
unsigned int len;
|
||||
};
|
||||
template <typename T>
|
||||
inline hb_array_t<T> hb_array (T *array, unsigned int len) { return hb_array_t<T> (array, len); }
|
||||
inline hb_array_t<T> hb_array (T *array, unsigned int len)
|
||||
{ return hb_array_t<T> (array, len); }
|
||||
|
||||
enum hb_bfind_not_found_t
|
||||
{
|
||||
HB_BFIND_NOT_FOUND_DONT_STORE,
|
||||
HB_BFIND_NOT_FOUND_STORE,
|
||||
HB_BFIND_NOT_FOUND_STORE_CLOSEST,
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct hb_sorted_array_t : hb_array_t<Type>
|
||||
{
|
||||
inline hb_sorted_array_t (void) : hb_array_t<Type> () {}
|
||||
inline hb_sorted_array_t (const hb_array_t<Type> &o) : hb_array_t<Type> (o) {}
|
||||
inline hb_sorted_array_t (Type *array_, unsigned int len_) : hb_array_t<Type> (array_, len_) {}
|
||||
|
||||
inline hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
|
||||
{ return hb_sorted_array_t<Type> (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
|
||||
inline hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
|
||||
{ return sub_array (start_offset, &seg_count); }
|
||||
|
||||
template <typename T>
|
||||
inline Type *bsearch (const T &x, Type *not_found = nullptr)
|
||||
{
|
||||
unsigned int i;
|
||||
return bfind (x, &i) ? &this->arrayZ[i] : not_found;
|
||||
}
|
||||
template <typename T>
|
||||
inline const Type *bsearch (const T &x, const Type *not_found = nullptr) const
|
||||
{
|
||||
unsigned int i;
|
||||
return bfind (x, &i) ? &this->arrayZ[i] : not_found;
|
||||
}
|
||||
template <typename T>
|
||||
inline bool bfind (const T &x, unsigned int *i = nullptr,
|
||||
hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{
|
||||
int min = 0, max = (int) this->len - 1;
|
||||
const Type *array = this->arrayZ;
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = ((unsigned int) min + (unsigned int) max) / 2;
|
||||
int c = array[mid].cmp (x);
|
||||
if (c < 0)
|
||||
max = mid - 1;
|
||||
else if (c > 0)
|
||||
min = mid + 1;
|
||||
else
|
||||
{
|
||||
if (i)
|
||||
*i = mid;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (i)
|
||||
{
|
||||
switch (not_found)
|
||||
{
|
||||
case HB_BFIND_NOT_FOUND_DONT_STORE:
|
||||
break;
|
||||
|
||||
case HB_BFIND_NOT_FOUND_STORE:
|
||||
*i = to_store;
|
||||
break;
|
||||
|
||||
case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
|
||||
if (max < 0 || (max < (int) this->len && array[max].cmp (x) > 0))
|
||||
max++;
|
||||
*i = max;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
inline hb_sorted_array_t<T> hb_sorted_array (T *array, unsigned int len)
|
||||
{ return hb_sorted_array_t<T> (array, len); }
|
||||
|
||||
|
||||
struct HbOpOr
|
||||
|
@ -588,10 +588,10 @@ struct hb_face_builder_data_t
|
||||
{
|
||||
struct table_entry_t
|
||||
{
|
||||
inline int cmp (const hb_tag_t *t) const
|
||||
inline int cmp (hb_tag_t t) const
|
||||
{
|
||||
if (*t < tag) return -1;
|
||||
if (*t > tag) return -1;
|
||||
if (t < tag) return -1;
|
||||
if (t > tag) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
14
src/hb-ft.cc
14
src/hb-ft.cc
@ -478,7 +478,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_ft_funcs (void);
|
||||
#endif
|
||||
|
||||
@ -504,7 +504,7 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
|
||||
|
||||
hb_font_funcs_make_immutable (funcs);
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_ft_funcs);
|
||||
#endif
|
||||
|
||||
@ -512,7 +512,7 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
|
||||
}
|
||||
} static_ft_funcs;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_ft_funcs (void)
|
||||
{
|
||||
@ -744,11 +744,11 @@ hb_ft_font_create_referenced (FT_Face ft_face)
|
||||
return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
|
||||
}
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_ft_library (void);
|
||||
#endif
|
||||
|
||||
static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<FT_Library>::value,
|
||||
static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (FT_Library),
|
||||
hb_ft_library_lazy_loader_t>
|
||||
{
|
||||
static inline FT_Library create (void)
|
||||
@ -757,7 +757,7 @@ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<F
|
||||
if (FT_Init_FreeType (&l))
|
||||
return nullptr;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_ft_library);
|
||||
#endif
|
||||
|
||||
@ -773,7 +773,7 @@ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<F
|
||||
}
|
||||
} static_ft_library;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_ft_library (void)
|
||||
{
|
||||
|
@ -336,7 +336,7 @@ hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_glib_funcs (void);
|
||||
#endif
|
||||
|
||||
@ -355,7 +355,7 @@ static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader
|
||||
|
||||
hb_unicode_funcs_make_immutable (funcs);
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_glib_funcs);
|
||||
#endif
|
||||
|
||||
@ -363,7 +363,7 @@ static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader
|
||||
}
|
||||
} static_glib_funcs;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_glib_funcs (void)
|
||||
{
|
||||
|
@ -300,7 +300,7 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_icu_funcs (void);
|
||||
#endif
|
||||
|
||||
@ -326,7 +326,7 @@ static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_
|
||||
|
||||
hb_unicode_funcs_make_immutable (funcs);
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_icu_funcs);
|
||||
#endif
|
||||
|
||||
@ -334,7 +334,7 @@ static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_
|
||||
}
|
||||
} static_icu_funcs;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_icu_funcs (void)
|
||||
{
|
||||
|
@ -82,8 +82,7 @@ static inline Type& StructAfter(TObject &X)
|
||||
/* Check _assertion in a method environment */
|
||||
#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
|
||||
inline void _instance_assertion_on_line_##_line (void) const \
|
||||
{ static_assert ((_assertion), ""); } \
|
||||
static_assert (true, "") /* So we require semicolon here. */
|
||||
{ static_assert ((_assertion), ""); }
|
||||
# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
|
||||
# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
|
||||
|
||||
@ -96,32 +95,36 @@ static inline Type& StructAfter(TObject &X)
|
||||
|
||||
|
||||
#define DEFINE_SIZE_STATIC(size) \
|
||||
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
|
||||
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)) \
|
||||
inline unsigned int get_size (void) const { return (size); } \
|
||||
enum { static_size = (size) }; \
|
||||
enum { min_size = (size) }
|
||||
enum { null_size = (size) }; \
|
||||
enum { min_size = (size) }; \
|
||||
enum { static_size = (size) }
|
||||
|
||||
#define DEFINE_SIZE_UNION(size, _member) \
|
||||
DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
|
||||
static const unsigned int min_size = (size)
|
||||
DEFINE_COMPILES_ASSERTION ((void) this->u._member.static_size) \
|
||||
DEFINE_INSTANCE_ASSERTION (sizeof(this->u._member) == (size)) \
|
||||
enum { null_size = (size) }; \
|
||||
enum { min_size = (size) }
|
||||
|
||||
#define DEFINE_SIZE_MIN(size) \
|
||||
DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
|
||||
static const unsigned int min_size = (size)
|
||||
DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)) \
|
||||
enum { null_size = (size) }; \
|
||||
enum { min_size = (size) }
|
||||
|
||||
#define DEFINE_SIZE_UNBOUNDED(size) \
|
||||
DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)) \
|
||||
enum { min_size = (size) }
|
||||
|
||||
#define DEFINE_SIZE_ARRAY(size, array) \
|
||||
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof ((array)[0])); \
|
||||
DEFINE_COMPILES_ASSERTION ((void) (array)[0].static_size) \
|
||||
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof ((array)[0])) \
|
||||
enum { null_size = (size) }; \
|
||||
enum { min_size = (size) }
|
||||
|
||||
#define DEFINE_SIZE_ARRAY_SIZED(size, array) \
|
||||
inline unsigned int get_size (void) const { return (size - (array).min_size + (array).get_size ()); } \
|
||||
DEFINE_SIZE_ARRAY(size, array)
|
||||
|
||||
#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
|
||||
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
|
||||
DEFINE_COMPILES_ASSERTION ((void) (array1)[0].static_size; (void) (array2)[0].static_size) \
|
||||
static const unsigned int min_size = (size)
|
||||
inline unsigned int get_size (void) const { return (size - (array).min_size + (array).get_size ()); } \
|
||||
DEFINE_SIZE_ARRAY(size, array)
|
||||
|
||||
|
||||
/*
|
||||
@ -256,26 +259,36 @@ struct hb_sanitize_context_t :
|
||||
|
||||
inline void set_max_ops (int max_ops_) { max_ops = max_ops_; }
|
||||
|
||||
/* TODO
|
||||
* This set_object() thing is to use sanitize at runtime lookup
|
||||
* application time. This is very distinct from the regular
|
||||
* sanitizer operation, so, eventually, separate into another
|
||||
* type and make hb_aat_apply_context_t use that one instead
|
||||
* of abusing this one.
|
||||
*/
|
||||
template <typename T>
|
||||
inline void set_object (const T& obj)
|
||||
inline void set_object (const T *obj)
|
||||
{
|
||||
this->start = (const char *) &obj;
|
||||
this->end = (const char *) &obj + obj.get_size ();
|
||||
reset_object ();
|
||||
|
||||
if (!obj) return;
|
||||
|
||||
const char *obj_start = (const char *) obj;
|
||||
const char *obj_end = (const char *) obj + obj->get_size ();
|
||||
assert (obj_start <= obj_end); /* Must not overflow. */
|
||||
|
||||
if (unlikely (obj_end < this->start || this->end < obj_start))
|
||||
this->start = this->end = nullptr;
|
||||
else
|
||||
{
|
||||
this->start = MAX (this->start, obj_start);
|
||||
this->end = MIN (this->end , obj_end );
|
||||
}
|
||||
}
|
||||
|
||||
inline void reset_object (void)
|
||||
{
|
||||
this->start = this->blob->data;
|
||||
this->end = this->start + this->blob->length;
|
||||
assert (this->start <= this->end); /* Must not overflow. */
|
||||
}
|
||||
|
||||
inline void start_processing (void)
|
||||
{
|
||||
this->start = this->blob->data;
|
||||
this->end = this->start + this->blob->length;
|
||||
assert (this->start <= this->end); /* Must not overflow. */
|
||||
reset_object ();
|
||||
this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
|
||||
(unsigned) HB_SANITIZE_MAX_OPS_MIN);
|
||||
this->edit_count = 0;
|
||||
@ -469,6 +482,23 @@ struct hb_sanitize_context_t :
|
||||
bool num_glyphs_set;
|
||||
};
|
||||
|
||||
struct hb_sanitize_with_object_t
|
||||
{
|
||||
template <typename T>
|
||||
inline hb_sanitize_with_object_t (hb_sanitize_context_t *c,
|
||||
const T& obj) : c (c)
|
||||
{
|
||||
c->set_object (obj);
|
||||
}
|
||||
inline ~hb_sanitize_with_object_t (void)
|
||||
{
|
||||
c->reset_object ();
|
||||
}
|
||||
|
||||
private:
|
||||
hb_sanitize_context_t *c;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Serialize
|
||||
@ -691,6 +721,12 @@ struct BEInt<Type, 2>
|
||||
}
|
||||
inline operator Type (void) const
|
||||
{
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
/* Spoon-feed the compiler a big-endian integer with alignment 1.
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
|
||||
struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
|
||||
return __builtin_bswap16 (((packed_uint16_t *) this)->v);
|
||||
#endif
|
||||
return (v[0] << 8)
|
||||
+ (v[1] );
|
||||
}
|
||||
|
@ -38,21 +38,60 @@
|
||||
|
||||
#define HB_NULL_POOL_SIZE 9880
|
||||
|
||||
/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size,
|
||||
* otherwise return sizeof(T). */
|
||||
|
||||
/* The hard way...
|
||||
* https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
|
||||
*/
|
||||
|
||||
template<bool> struct _hb_bool_type {};
|
||||
|
||||
template <typename T, typename B>
|
||||
struct _hb_null_size
|
||||
{ enum { value = sizeof (T) }; };
|
||||
template <typename T>
|
||||
struct _hb_null_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
|
||||
{ enum { value = T::null_size }; };
|
||||
|
||||
template <typename T>
|
||||
struct hb_null_size
|
||||
{ enum { value = _hb_null_size<T, _hb_bool_type<true> >::value }; };
|
||||
#define hb_null_size(T) hb_null_size<T>::value
|
||||
|
||||
/* This doesn't belong here, but since is copy/paste from above, put it here. */
|
||||
|
||||
template <typename T, typename B>
|
||||
struct _hb_static_size
|
||||
{ enum { value = sizeof (T) }; };
|
||||
template <typename T>
|
||||
struct _hb_static_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
|
||||
{ enum { value = T::static_size }; };
|
||||
|
||||
template <typename T>
|
||||
struct hb_static_size
|
||||
{ enum { value = _hb_static_size<T, _hb_bool_type<true> >::value }; };
|
||||
#define hb_static_size(T) hb_static_size<T>::value
|
||||
|
||||
|
||||
/*
|
||||
* Null()
|
||||
*/
|
||||
extern HB_INTERNAL
|
||||
hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
|
||||
|
||||
/* Generic nul-content Null objects. */
|
||||
template <typename Type>
|
||||
static inline Type const & Null (void) {
|
||||
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
|
||||
static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
|
||||
return *reinterpret_cast<Type const *> (_hb_NullPool);
|
||||
}
|
||||
#define Null(Type) Null<typename hb_remove_const<typename hb_remove_reference<Type>::value>::value>()
|
||||
#define Null(Type) Null<typename hb_remove_const (typename hb_remove_reference (Type))> ()
|
||||
|
||||
/* Specializations for arbitrary-content Null objects expressed in bytes. */
|
||||
#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
|
||||
} /* Close namespace. */ \
|
||||
extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]; \
|
||||
extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]; \
|
||||
template <> \
|
||||
/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
|
||||
return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
|
||||
@ -60,7 +99,7 @@ static inline Type const & Null (void) {
|
||||
namespace Namespace { \
|
||||
static_assert (true, "Just so we take semicolon after.")
|
||||
#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
|
||||
const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]
|
||||
const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]
|
||||
|
||||
/* Specializations for arbitrary-content Null objects expressed as struct initializer. */
|
||||
#define DECLARE_NULL_INSTANCE(Type) \
|
||||
@ -85,12 +124,12 @@ extern HB_INTERNAL
|
||||
/* CRAP pool: Common Region for Access Protection. */
|
||||
template <typename Type>
|
||||
static inline Type& Crap (void) {
|
||||
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
|
||||
static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
|
||||
Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
|
||||
memcpy (obj, &Null(Type), sizeof (*obj));
|
||||
return *obj;
|
||||
}
|
||||
#define Crap(Type) Crap<typename hb_remove_const<typename hb_remove_reference<Type>::value>::value>()
|
||||
#define Crap(Type) Crap<typename hb_remove_const (typename hb_remove_reference (Type))> ()
|
||||
|
||||
template <typename Type>
|
||||
struct CrapOrNull {
|
||||
@ -110,7 +149,7 @@ struct CrapOrNull<const Type> {
|
||||
template <typename P>
|
||||
struct hb_nonnull_ptr_t
|
||||
{
|
||||
typedef typename hb_remove_pointer<P>::value T;
|
||||
typedef typename hb_remove_pointer (P) T;
|
||||
|
||||
inline hb_nonnull_ptr_t (T *v_ = nullptr) : v (v_) {}
|
||||
inline T * operator = (T *v_) { return v = v_; }
|
||||
|
@ -111,12 +111,7 @@ typedef struct OffsetTable
|
||||
{
|
||||
Tag t;
|
||||
t.set (tag);
|
||||
/* Linear-search for small tables to work around fonts with unsorted
|
||||
* table list. */
|
||||
int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t);
|
||||
if (table_index)
|
||||
*table_index = i == -1 ? (unsigned) Index::NOT_FOUND_INDEX : (unsigned) i;
|
||||
return i != -1;
|
||||
return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
}
|
||||
inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
|
||||
{
|
||||
|
@ -231,22 +231,31 @@ struct FixedVersion
|
||||
* Use: (base+offset)
|
||||
*/
|
||||
|
||||
template <typename Type, bool has_null_> struct assert_has_min_size { static_assert (Type::min_size > 0, ""); };
|
||||
template <typename Type> struct assert_has_min_size<Type, false> {};
|
||||
template <typename Type, bool has_null>
|
||||
struct _hb_has_null
|
||||
{
|
||||
static inline const Type *get_null (void) { return nullptr; }
|
||||
static inline Type *get_crap (void) { return nullptr; }
|
||||
};
|
||||
template <typename Type>
|
||||
struct _hb_has_null<Type, true>
|
||||
{
|
||||
static inline const Type *get_null (void) { return &Null(Type); }
|
||||
static inline Type *get_crap (void) { return &Crap(Type); }
|
||||
};
|
||||
|
||||
template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
|
||||
struct OffsetTo : Offset<OffsetType, has_null>
|
||||
{
|
||||
static_assert (sizeof (assert_has_min_size<Type, has_null>) || true, "");
|
||||
|
||||
inline const Type& operator () (const void *base) const
|
||||
{
|
||||
if (unlikely (this->is_null ())) return Null (Type);
|
||||
if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_null ();
|
||||
return StructAtOffset<const Type> (base, *this);
|
||||
}
|
||||
inline Type& operator () (void *base) const
|
||||
{
|
||||
if (unlikely (this->is_null ())) return Crap (Type);
|
||||
if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_crap ();
|
||||
return StructAtOffset<Type> (base, *this);
|
||||
}
|
||||
|
||||
@ -322,6 +331,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
||||
DEFINE_SIZE_STATIC (sizeof (OffsetType));
|
||||
};
|
||||
template <typename Type, bool has_null=true> struct LOffsetTo : OffsetTo<Type, HBUINT32, has_null> {};
|
||||
|
||||
template <typename Base, typename OffsetType, bool has_null, typename Type>
|
||||
static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
|
||||
template <typename Base, typename OffsetType, bool has_null, typename Type>
|
||||
@ -335,6 +345,8 @@ static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null>
|
||||
template <typename Type>
|
||||
struct UnsizedArrayOf
|
||||
{
|
||||
static_assert ((bool) (unsigned) hb_static_size (Type), "");
|
||||
|
||||
enum { item_size = Type::static_size };
|
||||
|
||||
HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type);
|
||||
@ -358,8 +370,20 @@ struct UnsizedArrayOf
|
||||
inline unsigned int get_size (unsigned int len) const
|
||||
{ return len * Type::static_size; }
|
||||
|
||||
inline hb_array_t<Type> as_array (unsigned int len) { return hb_array_t<Type> (arrayZ, len); }
|
||||
inline hb_array_t<const Type> as_array (unsigned int len) const { return hb_array_t<const Type> (arrayZ, len); }
|
||||
inline hb_array_t<Type> as_array (unsigned int len)
|
||||
{ return hb_array (arrayZ, len); }
|
||||
inline hb_array_t<const Type> as_array (unsigned int len) const
|
||||
{ return hb_array (arrayZ, len); }
|
||||
|
||||
template <typename T>
|
||||
inline Type &lsearch (unsigned int len, const T &x, Type ¬_found = Crap (Type))
|
||||
{ return *as_array (len).lsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
inline const Type &lsearch (unsigned int len, const T &x, const Type ¬_found = Null (Type)) const
|
||||
{ return *as_array (len).lsearch (x, ¬_found); }
|
||||
|
||||
inline void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
|
||||
{ as_array (len).qsort (start, end); }
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
|
||||
{
|
||||
@ -406,7 +430,7 @@ struct UnsizedArrayOf
|
||||
public:
|
||||
Type arrayZ[VAR];
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (0, arrayZ);
|
||||
DEFINE_SIZE_UNBOUNDED (0);
|
||||
};
|
||||
|
||||
/* Unsized array of offset's */
|
||||
@ -419,8 +443,17 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
|
||||
{
|
||||
inline const Type& operator [] (unsigned int i) const
|
||||
{
|
||||
return this+this->arrayZ[i];
|
||||
const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
|
||||
if (unlikely (p < this->arrayZ)) return Null (Type); /* Overflowed. */
|
||||
return this+*p;
|
||||
}
|
||||
inline Type& operator [] (unsigned int i)
|
||||
{
|
||||
const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
|
||||
if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */
|
||||
return this+*p;
|
||||
}
|
||||
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
|
||||
{
|
||||
@ -435,26 +468,39 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
|
||||
}
|
||||
};
|
||||
|
||||
/* An array with sorted elements. Supports binary searching. */
|
||||
template <typename Type>
|
||||
struct SortedUnsizedArrayOf : UnsizedArrayOf<Type>
|
||||
{
|
||||
inline hb_sorted_array_t<Type> as_array (unsigned int len)
|
||||
{ return hb_sorted_array (this->arrayZ, len); }
|
||||
inline hb_sorted_array_t<const Type> as_array (unsigned int len) const
|
||||
{ return hb_sorted_array (this->arrayZ, len); }
|
||||
|
||||
template <typename T>
|
||||
inline Type &bsearch (unsigned int len, const T &x, Type ¬_found = Crap (Type))
|
||||
{ return *as_array (len).bsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
inline const Type &bsearch (unsigned int len, const T &x, const Type ¬_found = Null (Type)) const
|
||||
{ return *as_array (len).bsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
inline bool bfind (unsigned int len, const T &x, unsigned int *i = nullptr,
|
||||
hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{ return as_array (len).bfind (x, i, not_found, to_store); }
|
||||
};
|
||||
|
||||
|
||||
/* An array with a number of elements. */
|
||||
template <typename Type, typename LenType=HBUINT16>
|
||||
struct ArrayOf
|
||||
{
|
||||
static_assert ((bool) (unsigned) hb_static_size (Type), "");
|
||||
|
||||
enum { item_size = Type::static_size };
|
||||
|
||||
HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOf, Type, LenType);
|
||||
|
||||
inline const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
|
||||
{
|
||||
unsigned int count = len;
|
||||
if (unlikely (start_offset > count))
|
||||
count = 0;
|
||||
else
|
||||
count -= start_offset;
|
||||
count = MIN (count, *pcount);
|
||||
*pcount = count;
|
||||
return arrayZ + start_offset;
|
||||
}
|
||||
|
||||
inline const Type& operator [] (unsigned int i) const
|
||||
{
|
||||
if (unlikely (i >= len)) return Null (Type);
|
||||
@ -469,6 +515,20 @@ struct ArrayOf
|
||||
inline unsigned int get_size (void) const
|
||||
{ return len.static_size + len * Type::static_size; }
|
||||
|
||||
inline hb_array_t<Type> as_array (void)
|
||||
{ return hb_array (arrayZ, len); }
|
||||
inline hb_array_t<const Type> as_array (void) const
|
||||
{ return hb_array (arrayZ, len); }
|
||||
|
||||
inline hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
inline hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count /* IN/OUT */) const
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
inline hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
inline hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count /* IN/OUT */)
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
|
||||
inline bool serialize (hb_serialize_context_t *c,
|
||||
unsigned int items_len)
|
||||
{
|
||||
@ -528,20 +588,15 @@ struct ArrayOf
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
template <typename SearchType>
|
||||
inline int lsearch (const SearchType &x) const
|
||||
{
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!this->arrayZ[i].cmp (x))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
template <typename T>
|
||||
inline Type &lsearch (const T &x, Type ¬_found = Crap (Type))
|
||||
{ return *as_array ().lsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
inline const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const
|
||||
{ return *as_array ().lsearch (x, ¬_found); }
|
||||
|
||||
inline void qsort (void)
|
||||
{
|
||||
::qsort (arrayZ, len, sizeof (Type), Type::cmp);
|
||||
}
|
||||
inline void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
|
||||
{ as_array ().qsort (start, end); }
|
||||
|
||||
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
|
||||
{
|
||||
@ -723,22 +778,31 @@ struct ArrayOfM1
|
||||
template <typename Type, typename LenType=HBUINT16>
|
||||
struct SortedArrayOf : ArrayOf<Type, LenType>
|
||||
{
|
||||
template <typename SearchType>
|
||||
inline int bsearch (const SearchType &x) const
|
||||
{
|
||||
/* Hand-coded bsearch here since this is in the hot inner loop. */
|
||||
const Type *arr = this->arrayZ;
|
||||
int min = 0, max = (int) this->len - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = ((unsigned int) min + (unsigned int) max) / 2;
|
||||
int c = arr[mid].cmp (x);
|
||||
if (c < 0) max = mid - 1;
|
||||
else if (c > 0) min = mid + 1;
|
||||
else return mid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
inline hb_sorted_array_t<Type> as_array (void)
|
||||
{ return hb_sorted_array (this->arrayZ, this->len); }
|
||||
inline hb_sorted_array_t<const Type> as_array (void) const
|
||||
{ return hb_sorted_array (this->arrayZ, this->len); }
|
||||
|
||||
inline hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
inline hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count /* IN/OUT */) const
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
inline hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
inline hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count /* IN/OUT */)
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
|
||||
template <typename T>
|
||||
inline Type &bsearch (const T &x, Type ¬_found = Crap (Type))
|
||||
{ return *as_array ().bsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
inline const Type &bsearch (const T &x, const Type ¬_found = Null (Type)) const
|
||||
{ return *as_array ().bsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
inline bool bfind (const T &x, unsigned int *i = nullptr,
|
||||
hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{ return as_array ().bfind (x, i, not_found, to_store); }
|
||||
};
|
||||
|
||||
/*
|
||||
@ -810,15 +874,36 @@ struct VarSizedBinSearchArrayOf
|
||||
|
||||
HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type);
|
||||
|
||||
inline bool last_is_terminator (void) const
|
||||
{
|
||||
if (unlikely (!header.nUnits)) return false;
|
||||
|
||||
/* Gah.
|
||||
*
|
||||
* "The number of termination values that need to be included is table-specific.
|
||||
* The value that indicates binary search termination is 0xFFFF." */
|
||||
const HBUINT16 *words = &StructAtOffset<HBUINT16> (&bytesZ, (header.nUnits - 1) * header.unitSize);
|
||||
unsigned int count = Type::TerminationWordCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (words[i] != 0xFFFFu)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline const Type& operator [] (unsigned int i) const
|
||||
{
|
||||
if (unlikely (i >= header.nUnits)) return Null (Type);
|
||||
if (unlikely (i >= get_length ())) return Null (Type);
|
||||
return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
|
||||
}
|
||||
inline Type& operator [] (unsigned int i)
|
||||
{
|
||||
if (unlikely (i >= get_length ())) return Crap (Type);
|
||||
return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
|
||||
}
|
||||
inline unsigned int get_length (void) const
|
||||
{
|
||||
return header.nUnits - last_is_terminator ();
|
||||
}
|
||||
inline unsigned int get_size (void) const
|
||||
{ return header.static_size + header.nUnits * header.unitSize; }
|
||||
|
||||
@ -842,7 +927,7 @@ struct VarSizedBinSearchArrayOf
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!sanitize_shallow (c))) return_trace (false);
|
||||
unsigned int count = header.nUnits;
|
||||
unsigned int count = get_length ();
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!(*this)[i].sanitize (c, base)))
|
||||
return_trace (false);
|
||||
@ -853,7 +938,7 @@ struct VarSizedBinSearchArrayOf
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!sanitize_shallow (c))) return_trace (false);
|
||||
unsigned int count = header.nUnits;
|
||||
unsigned int count = get_length ();
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!(*this)[i].sanitize (c, base, user_data)))
|
||||
return_trace (false);
|
||||
@ -864,7 +949,7 @@ struct VarSizedBinSearchArrayOf
|
||||
inline const Type *bsearch (const T &key) const
|
||||
{
|
||||
unsigned int size = header.unitSize;
|
||||
int min = 0, max = (int) header.nUnits - 1;
|
||||
int min = 0, max = (int) get_length () - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = ((unsigned int) min + (unsigned int) max) / 2;
|
||||
|
@ -417,6 +417,7 @@ struct CmapSubtableLongGroup
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
};
|
||||
DECLARE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup);
|
||||
|
||||
template <typename UINT>
|
||||
struct CmapSubtableTrimmed
|
||||
@ -467,10 +468,7 @@ struct CmapSubtableLongSegmented
|
||||
|
||||
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
|
||||
{
|
||||
int i = groups.bsearch (codepoint);
|
||||
if (i == -1)
|
||||
return false;
|
||||
hb_codepoint_t gid = T::group_get_glyph (groups[i], codepoint);
|
||||
hb_codepoint_t gid = T::group_get_glyph (groups.bsearch (codepoint), codepoint);
|
||||
if (!gid)
|
||||
return false;
|
||||
*glyph = gid;
|
||||
@ -517,7 +515,8 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
|
||||
{
|
||||
static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
|
||||
hb_codepoint_t u)
|
||||
{ return group.glyphID + (u - group.startCharCode); }
|
||||
{ return likely (group.startCharCode <= group.endCharCode) ?
|
||||
group.glyphID + (u - group.startCharCode) : 0; }
|
||||
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
@ -673,16 +672,12 @@ struct VariationSelectorRecord
|
||||
hb_codepoint_t *glyph,
|
||||
const void *base) const
|
||||
{
|
||||
int i;
|
||||
const DefaultUVS &defaults = base+defaultUVS;
|
||||
i = defaults.bsearch (codepoint);
|
||||
if (i != -1)
|
||||
if ((base+defaultUVS).bfind (codepoint))
|
||||
return GLYPH_VARIANT_USE_DEFAULT;
|
||||
const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
|
||||
i = nonDefaults.bsearch (codepoint);
|
||||
if (i != -1 && nonDefaults[i].glyphID)
|
||||
const UVSMapping &nonDefault = (base+nonDefaultUVS).bsearch (codepoint);
|
||||
if (nonDefault.glyphID)
|
||||
{
|
||||
*glyph = nonDefaults[i].glyphID;
|
||||
*glyph = nonDefault.glyphID;
|
||||
return GLYPH_VARIANT_FOUND;
|
||||
}
|
||||
return GLYPH_VARIANT_NOT_FOUND;
|
||||
@ -722,7 +717,7 @@ struct CmapSubtableFormat14
|
||||
hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph) const
|
||||
{
|
||||
return record[record.bsearch (variation_selector)].get_glyph (codepoint, glyph, this);
|
||||
return record.bsearch (variation_selector).get_glyph (codepoint, glyph, this);
|
||||
}
|
||||
|
||||
inline void collect_variation_selectors (hb_set_t *out) const
|
||||
@ -734,7 +729,7 @@ struct CmapSubtableFormat14
|
||||
inline void collect_variation_unicodes (hb_codepoint_t variation_selector,
|
||||
hb_set_t *out) const
|
||||
{
|
||||
record[record.bsearch (variation_selector)].collect_unicodes (out, this);
|
||||
record.bsearch (variation_selector).collect_unicodes (out, this);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
@ -863,14 +858,6 @@ struct cmap
|
||||
hb_vector_t<CmapSubtableLongGroup> format12_groups;
|
||||
};
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
likely (version == 0) &&
|
||||
encodingRecord.sanitize (c, this));
|
||||
}
|
||||
|
||||
inline bool _create_plan (const hb_subset_plan_t *plan,
|
||||
subset_plan *cmap_plan) const
|
||||
{
|
||||
@ -1164,11 +1151,21 @@ struct cmap
|
||||
key.platformID.set (platform_id);
|
||||
key.encodingID.set (encoding_id);
|
||||
|
||||
int result = encodingRecord.bsearch (key);
|
||||
if (result == -1 || !encodingRecord[result].subtable)
|
||||
const EncodingRecord &result = encodingRecord.bsearch (key);
|
||||
if (!result.subtable)
|
||||
return nullptr;
|
||||
|
||||
return &(this+encodingRecord[result].subtable);
|
||||
return &(this+result.subtable);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
likely (version == 0) &&
|
||||
encodingRecord.sanitize (c, this));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -66,13 +66,6 @@ struct BaseGlyphRecord
|
||||
inline int cmp (hb_codepoint_t g) const
|
||||
{ return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
|
||||
|
||||
static int cmp (const void *pa, const void *pb)
|
||||
{
|
||||
const hb_codepoint_t *a = (const hb_codepoint_t *) pa;
|
||||
const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb;
|
||||
return b->cmp (*a);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -103,12 +96,7 @@ struct COLR
|
||||
unsigned int *count, /* IN/OUT. May be NULL. */
|
||||
hb_ot_color_layer_t *layers /* OUT. May be NULL. */) const
|
||||
{
|
||||
const BaseGlyphRecord *rec = (BaseGlyphRecord *) bsearch (&glyph,
|
||||
&(this+baseGlyphsZ),
|
||||
numBaseGlyphs,
|
||||
sizeof (BaseGlyphRecord),
|
||||
BaseGlyphRecord::cmp);
|
||||
const BaseGlyphRecord &record = rec ? *rec : Null (BaseGlyphRecord);
|
||||
const BaseGlyphRecord &record = (this+baseGlyphsZ).bsearch (numBaseGlyphs, glyph);
|
||||
|
||||
hb_array_t<const LayerRecord> all_layers ((this+layersZ).arrayZ, numLayers);
|
||||
hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx,
|
||||
@ -137,7 +125,7 @@ struct COLR
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number (starts at 0). */
|
||||
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */
|
||||
LOffsetTo<UnsizedArrayOf<BaseGlyphRecord>, false>
|
||||
LOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord>, false>
|
||||
baseGlyphsZ; /* Offset to Base Glyph records. */
|
||||
LOffsetTo<UnsizedArrayOf<LayerRecord>, false>
|
||||
layersZ; /* Offset to Layer Records. */
|
||||
|
@ -103,8 +103,7 @@ struct SVG
|
||||
|
||||
inline const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
const SortedArrayOf<SVGDocumentIndexEntry> &docs = this+svgDocEntries;
|
||||
return docs[docs.bsearch (glyph_id)];
|
||||
return (this+svgDocEntries).bsearch (glyph_id);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -67,6 +67,7 @@
|
||||
HB_OT_TABLE(AAT, trak) \
|
||||
HB_OT_TABLE(AAT, lcar) \
|
||||
HB_OT_TABLE(AAT, ltag) \
|
||||
HB_OT_TABLE(AAT, feat) \
|
||||
/* OpenType variations. */ \
|
||||
HB_OT_TABLE(OT, fvar) \
|
||||
HB_OT_TABLE(OT, avar) \
|
||||
|
@ -249,7 +249,7 @@ hb_ot_get_font_v_extents (hb_font_t *font,
|
||||
return vmtx.has_font_extents;
|
||||
}
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_ot_funcs (void);
|
||||
#endif
|
||||
|
||||
@ -275,7 +275,7 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
|
||||
|
||||
hb_font_funcs_make_immutable (funcs);
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_ot_funcs);
|
||||
#endif
|
||||
|
||||
@ -283,7 +283,7 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
|
||||
}
|
||||
} static_ot_funcs;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_ot_funcs (void)
|
||||
{
|
||||
|
@ -56,7 +56,9 @@ struct loca
|
||||
protected:
|
||||
UnsizedArrayOf<HBUINT8> dataZ; /* Location data. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (0, dataZ);
|
||||
DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
|
||||
* check the size externally, allow Null() object of it by
|
||||
* defining it MIN() instead. */
|
||||
};
|
||||
|
||||
|
||||
@ -465,7 +467,9 @@ struct glyf
|
||||
protected:
|
||||
UnsizedArrayOf<HBUINT8> dataZ; /* Glyphs data. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (0, dataZ);
|
||||
DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
|
||||
* check the size externally, allow Null() object of it by
|
||||
* defining it MIN() instead. */
|
||||
};
|
||||
|
||||
struct glyf_accelerator_t : glyf::accelerator_t {};
|
||||
|
@ -154,7 +154,7 @@ struct KernSubTable
|
||||
KernSubTableFormat3<KernSubTableHeader> format3;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_MIN (0);
|
||||
DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
|
||||
};
|
||||
|
||||
|
||||
@ -274,6 +274,15 @@ struct kern
|
||||
inline bool has_data (void) const { return u.version32; }
|
||||
inline unsigned int get_type (void) const { return u.major; }
|
||||
|
||||
inline bool has_state_machine (void) const
|
||||
{
|
||||
switch (get_type ()) {
|
||||
case 0: return u.ot.has_state_machine ();
|
||||
case 1: return u.aat.has_state_machine ();
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool has_cross_stream (void) const
|
||||
{
|
||||
switch (get_type ()) {
|
||||
|
@ -128,15 +128,7 @@ struct RecordArrayOf : SortedArrayOf<Record<Type> >
|
||||
}
|
||||
inline bool find_index (hb_tag_t tag, unsigned int *index) const
|
||||
{
|
||||
/* If we want to allow non-sorted data, we can lsearch(). */
|
||||
int i = this->/*lsearch*/bsearch (tag);
|
||||
if (i != -1) {
|
||||
if (index) *index = i;
|
||||
return true;
|
||||
} else {
|
||||
if (index) *index = Index::NOT_FOUND_INDEX;
|
||||
return false;
|
||||
}
|
||||
return this->bfind (tag, index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
}
|
||||
};
|
||||
|
||||
@ -802,11 +794,11 @@ struct Lookup
|
||||
HBUINT16 lookupFlag; /* Lookup qualifiers */
|
||||
ArrayOf<Offset16>
|
||||
subTable; /* Array of SubTables */
|
||||
HBUINT16 markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets
|
||||
/*HBUINT16 markFilteringSetX[VAR];*//* Index (base 0) into GDEF mark glyph sets
|
||||
* structure. This field is only present if bit
|
||||
* UseMarkFilteringSet of lookup flags is set. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
|
||||
DEFINE_SIZE_ARRAY (6, subTable);
|
||||
};
|
||||
|
||||
typedef OffsetListOf<Lookup> LookupList;
|
||||
@ -823,8 +815,8 @@ struct CoverageFormat1
|
||||
private:
|
||||
inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
int i = glyphArray.bsearch (glyph_id);
|
||||
static_assert ((((unsigned int) -1) == NOT_COVERED), "");
|
||||
unsigned int i;
|
||||
glyphArray.bfind (glyph_id, &i, HB_BFIND_NOT_FOUND_STORE, NOT_COVERED);
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -896,12 +888,10 @@ struct CoverageFormat2
|
||||
private:
|
||||
inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
int i = rangeRecord.bsearch (glyph_id);
|
||||
if (i != -1) {
|
||||
const RangeRecord &range = rangeRecord[i];
|
||||
return (unsigned int) range.value + (glyph_id - range.start);
|
||||
}
|
||||
return NOT_COVERED;
|
||||
const RangeRecord &range = rangeRecord.bsearch (glyph_id);
|
||||
return likely (range.start <= range.end) ?
|
||||
(unsigned int) range.value + (glyph_id - range.start) :
|
||||
NOT_COVERED;
|
||||
}
|
||||
|
||||
inline bool serialize (hb_serialize_context_t *c,
|
||||
@ -1194,10 +1184,7 @@ struct ClassDefFormat1
|
||||
private:
|
||||
inline unsigned int get_class (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
unsigned int i = (unsigned int) (glyph_id - startGlyph);
|
||||
if (unlikely (i < classValue.len))
|
||||
return classValue[i];
|
||||
return 0;
|
||||
return classValue[(unsigned int) (glyph_id - startGlyph)];
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
@ -1265,10 +1252,10 @@ struct ClassDefFormat1
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 classFormat; /* Format identifier--format = 1 */
|
||||
GlyphID startGlyph; /* First GlyphID of the classValueArray */
|
||||
HBUINT16 classFormat; /* Format identifier--format = 1 */
|
||||
GlyphID startGlyph; /* First GlyphID of the classValueArray */
|
||||
ArrayOf<HBUINT16>
|
||||
classValue; /* Array of Class Values--one per GlyphID */
|
||||
classValue; /* Array of Class Values--one per GlyphID */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, classValue);
|
||||
};
|
||||
@ -1280,10 +1267,7 @@ struct ClassDefFormat2
|
||||
private:
|
||||
inline unsigned int get_class (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
int i = rangeRecord.bsearch (glyph_id);
|
||||
if (unlikely (i != -1))
|
||||
return rangeRecord[i].value;
|
||||
return 0;
|
||||
return rangeRecord.bsearch (glyph_id).value;
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
@ -1586,9 +1570,9 @@ struct VarData
|
||||
HBUINT16 itemCount;
|
||||
HBUINT16 shortCount;
|
||||
ArrayOf<HBUINT16> regionIndices;
|
||||
UnsizedArrayOf<HBUINT8>bytesX;
|
||||
/*UnsizedArrayOf<HBUINT8>bytesX;*/
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
|
||||
DEFINE_SIZE_ARRAY (6, regionIndices);
|
||||
};
|
||||
|
||||
struct VariationStore
|
||||
|
@ -61,9 +61,10 @@ struct AttachList
|
||||
|
||||
const AttachPoint &points = this+attachPoint[index];
|
||||
|
||||
if (point_count) {
|
||||
const HBUINT16 *array = points.sub_array (start_offset, point_count);
|
||||
unsigned int count = *point_count;
|
||||
if (point_count)
|
||||
{
|
||||
hb_array_t<const HBUINT16> array = points.sub_array (start_offset, point_count);
|
||||
unsigned int count = array.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
point_array[i] = array[i];
|
||||
}
|
||||
@ -216,9 +217,10 @@ struct LigGlyph
|
||||
unsigned int *caret_count /* IN/OUT */,
|
||||
hb_position_t *caret_array /* OUT */) const
|
||||
{
|
||||
if (caret_count) {
|
||||
const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
|
||||
unsigned int count = *caret_count;
|
||||
if (caret_count)
|
||||
{
|
||||
hb_array_t <const OffsetTo<CaretValue> > array = carets.sub_array (start_offset, caret_count);
|
||||
unsigned int count = array.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store);
|
||||
}
|
||||
@ -406,9 +408,20 @@ struct GDEF
|
||||
}
|
||||
}
|
||||
|
||||
HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const;
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
HB_INTERNAL void init (hb_face_t *face);
|
||||
inline void init (hb_face_t *face)
|
||||
{
|
||||
this->table = hb_sanitize_context_t().reference_table<GDEF> (face);
|
||||
if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
|
||||
{
|
||||
hb_blob_destroy (this->table.get_blob ());
|
||||
this->table = hb_blob_get_empty ();
|
||||
}
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
|
@ -1643,6 +1643,9 @@ struct GPOS : GSUBGPOS
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{ return GSUBGPOS::sanitize<PosLookup> (c); }
|
||||
|
||||
HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const;
|
||||
|
||||
typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
|
||||
};
|
||||
|
||||
|
@ -1449,7 +1449,10 @@ struct SubstLookup : Lookup
|
||||
|
||||
hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
|
||||
|
||||
c->flush ();
|
||||
/* While in theory we should flush here, it will cause timeouts because a recursive
|
||||
* lookup can keep growing the glyph set. Skip, and outer loop will retry up to
|
||||
* HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
|
||||
//c->flush ();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1483,6 +1486,9 @@ struct GSUB : GSUBGPOS
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{ return GSUBGPOS::sanitize<SubstLookup> (c); }
|
||||
|
||||
HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const;
|
||||
|
||||
typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t;
|
||||
};
|
||||
|
||||
|
@ -2753,6 +2753,11 @@ struct GSUBGPOS
|
||||
inline void init (hb_face_t *face)
|
||||
{
|
||||
this->table = hb_sanitize_context_t().reference_table<T> (face);
|
||||
if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
|
||||
{
|
||||
hb_blob_destroy (this->table.get_blob ());
|
||||
this->table = hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
this->lookup_count = table->get_lookup_count ();
|
||||
|
||||
|
@ -34,15 +34,17 @@
|
||||
#include "hb-ot-map.hh"
|
||||
#include "hb-map.hh"
|
||||
|
||||
#include "hb-ot-kern-table.hh"
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
#include "hb-ot-layout-gsub-table.hh"
|
||||
#include "hb-ot-layout-gpos-table.hh"
|
||||
#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise
|
||||
#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise
|
||||
#include "hb-ot-kern-table.hh"
|
||||
#include "hb-ot-name-table.hh"
|
||||
#include "hb-ot-os2-table.hh"
|
||||
|
||||
#include "hb-aat-layout-lcar-table.hh"
|
||||
#include "hb-aat-layout-morx-table.hh"
|
||||
|
||||
|
||||
/**
|
||||
@ -65,6 +67,12 @@ hb_ot_layout_has_kerning (hb_face_t *face)
|
||||
return face->table.kern->has_data ();
|
||||
}
|
||||
|
||||
bool
|
||||
hb_ot_layout_has_machine_kerning (hb_face_t *face)
|
||||
{
|
||||
return face->table.kern->has_state_machine ();
|
||||
}
|
||||
|
||||
bool
|
||||
hb_ot_layout_has_cross_kerning (hb_face_t *face)
|
||||
{
|
||||
@ -89,10 +97,9 @@ hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
|
||||
* GDEF
|
||||
*/
|
||||
|
||||
static bool
|
||||
_hb_ot_blacklist_gdef (unsigned int gdef_len,
|
||||
unsigned int gsub_len,
|
||||
unsigned int gpos_len)
|
||||
bool
|
||||
OT::GDEF::is_blacklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const
|
||||
{
|
||||
/* The ugly business of blacklisting individual fonts' tables happen here!
|
||||
* See this thread for why we finally had to bend in and do this:
|
||||
@ -111,8 +118,10 @@ _hb_ot_blacklist_gdef (unsigned int gdef_len,
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
|
||||
*/
|
||||
#define ENCODE(x,y,z) ((int64_t) (x) << 32 | (int64_t) (y) << 16 | (z))
|
||||
switch ENCODE(gdef_len, gsub_len, gpos_len)
|
||||
#define ENCODE(x,y,z) (((uint64_t) (x) << 48) | ((uint64_t) (y) << 24) | (uint64_t) (z))
|
||||
switch ENCODE(blob->length,
|
||||
face->table.GSUB->table.get_length (),
|
||||
face->table.GPOS->table.get_length ())
|
||||
{
|
||||
/* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
|
||||
case ENCODE (442, 2874, 42038):
|
||||
@ -191,20 +200,6 @@ _hb_ot_blacklist_gdef (unsigned int gdef_len,
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
OT::GDEF::accelerator_t::init (hb_face_t *face)
|
||||
{
|
||||
this->table = hb_sanitize_context_t().reference_table<GDEF> (face);
|
||||
|
||||
if (unlikely (_hb_ot_blacklist_gdef (this->table.get_length (),
|
||||
face->table.GSUB->table.get_length (),
|
||||
face->table.GPOS->table.get_length ())))
|
||||
{
|
||||
hb_blob_destroy (this->table.get_blob ());
|
||||
this->table = hb_blob_get_empty ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_hb_ot_layout_set_glyph_props (hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
@ -291,6 +286,38 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
|
||||
* GSUB/GPOS
|
||||
*/
|
||||
|
||||
bool
|
||||
OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED,
|
||||
hb_face_t *face) const
|
||||
{
|
||||
/* Mac OS X prefers morx over GSUB. It also ships with various Indic fonts,
|
||||
* all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken
|
||||
* GSUB/GPOS tables. Some have GSUB with zero scripts, those are ignored by
|
||||
* our morx/GSUB preference code. But if GSUB has non-zero scripts, we tend
|
||||
* to prefer it over morx because we want to be consistent with other OpenType
|
||||
* shapers.
|
||||
*
|
||||
* To work around broken Indic Mac system fonts, we ignore GSUB table if
|
||||
* OS/2 VendorId is 'MUTF' and font has morx table as well.
|
||||
*
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1410
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1348
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1391
|
||||
*/
|
||||
if (unlikely (face->table.OS2->achVendID == HB_TAG ('M','U','T','F') &&
|
||||
face->table.morx->has_data ()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED,
|
||||
hb_face_t *face HB_UNUSED) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static const OT::GSUBGPOS&
|
||||
get_gsubgpos_table (hb_face_t *face,
|
||||
hb_tag_t table_tag)
|
||||
|
@ -48,6 +48,9 @@ struct hb_ot_shape_plan_t;
|
||||
HB_INTERNAL bool
|
||||
hb_ot_layout_has_kerning (hb_face_t *face);
|
||||
|
||||
HB_INTERNAL bool
|
||||
hb_ot_layout_has_machine_kerning (hb_face_t *face);
|
||||
|
||||
HB_INTERNAL bool
|
||||
hb_ot_layout_has_cross_kerning (hb_face_t *face);
|
||||
|
||||
|
@ -57,8 +57,8 @@ struct hb_ot_map_t
|
||||
unsigned int auto_zwj : 1;
|
||||
unsigned int random : 1;
|
||||
|
||||
inline int cmp (const hb_tag_t *tag_) const
|
||||
{ return *tag_ < tag ? -1 : *tag_ > tag ? 1 : 0; }
|
||||
inline int cmp (const hb_tag_t tag_) const
|
||||
{ return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; }
|
||||
};
|
||||
|
||||
struct lookup_map_t {
|
||||
|
@ -509,9 +509,8 @@ struct MathGlyphAssembly
|
||||
if (parts_count)
|
||||
{
|
||||
int scale = font->dir_scale (direction);
|
||||
const MathGlyphPartRecord *arr =
|
||||
partRecords.sub_array (start_offset, parts_count);
|
||||
unsigned int count = *parts_count;
|
||||
hb_array_t<const MathGlyphPartRecord> arr = partRecords.sub_array (start_offset, parts_count);
|
||||
unsigned int count = arr.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
arr[i].extract (parts[i], scale, font);
|
||||
}
|
||||
@ -556,9 +555,8 @@ struct MathGlyphConstruction
|
||||
if (variants_count)
|
||||
{
|
||||
int scale = font->dir_scale (direction);
|
||||
const MathGlyphVariantRecord *arr =
|
||||
mathGlyphVariantRecord.sub_array (start_offset, variants_count);
|
||||
unsigned int count = *variants_count;
|
||||
hb_array_t<const MathGlyphVariantRecord> arr = mathGlyphVariantRecord.sub_array (start_offset, variants_count);
|
||||
unsigned int count = arr.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
variants[i].glyph = arr[i].variantGlyph;
|
||||
|
@ -61,12 +61,12 @@ struct postV2Tail
|
||||
ArrayOf<HBUINT16> glyphNameIndex; /* This is not an offset, but is the
|
||||
* ordinal number of the glyph in 'post'
|
||||
* string tables. */
|
||||
UnsizedArrayOf<HBUINT8>
|
||||
namesX; /* Glyph names with length bytes [variable]
|
||||
/*UnsizedArrayOf<HBUINT8>
|
||||
namesX;*/ /* Glyph names with length bytes [variable]
|
||||
* (a Pascal string). */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX);
|
||||
DEFINE_SIZE_ARRAY (2, glyphNameIndex);
|
||||
};
|
||||
|
||||
struct post
|
||||
|
@ -391,27 +391,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
|
||||
};
|
||||
|
||||
|
||||
/* Uniscribe seems to have a shaper for 'mymr' that is like the
|
||||
* generic shaper, except that it zeros mark advances GDEF_LATE. */
|
||||
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
|
||||
{
|
||||
nullptr, /* collect_features */
|
||||
nullptr, /* override_features */
|
||||
nullptr, /* data_create */
|
||||
nullptr, /* data_destroy */
|
||||
nullptr, /* preprocess_text */
|
||||
nullptr, /* postprocess_glyphs */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
nullptr, /* decompose */
|
||||
nullptr, /* compose */
|
||||
nullptr, /* setup_masks */
|
||||
HB_TAG_NONE, /* gpos_tag */
|
||||
nullptr, /* reorder_marks */
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
|
||||
true, /* fallback_position */
|
||||
};
|
||||
|
||||
|
||||
/* Ugly Zawgyi encoding.
|
||||
* Disable all auto processing.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1162 */
|
||||
|
@ -544,7 +544,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
|
||||
/* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv,
|
||||
/* 111C0 */ H, B, R, R, O, O, O, O, O, FM, CMBlw, VAbv, VBlw, O, O, O,
|
||||
/* 111C0 */ H, B, R, R, O, O, O, O, GB, FBlw, CMBlw, VAbv, VBlw, O, O, O,
|
||||
/* 111D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
|
||||
|
||||
/* Sinhala Archaic Numbers */
|
||||
|
@ -432,7 +432,8 @@ record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
static inline bool
|
||||
is_halant (const hb_glyph_info_t &info)
|
||||
{
|
||||
return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info);
|
||||
return (info.use_category() == USE_H || info.use_category() == USE_HVM) &&
|
||||
!_hb_glyph_info_ligated (&info);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -449,19 +450,38 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
|
||||
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB))
|
||||
#define POST_BASE_FLAGS64 (FLAG64 (USE_FM) | \
|
||||
FLAG64 (USE_FAbv) | \
|
||||
FLAG64 (USE_FBlw) | \
|
||||
FLAG64 (USE_FPst) | \
|
||||
FLAG64 (USE_MAbv) | \
|
||||
FLAG64 (USE_MBlw) | \
|
||||
FLAG64 (USE_MPst) | \
|
||||
FLAG64 (USE_MPre) | \
|
||||
FLAG64 (USE_VAbv) | \
|
||||
FLAG64 (USE_VBlw) | \
|
||||
FLAG64 (USE_VPst) | \
|
||||
FLAG64 (USE_VPre) | \
|
||||
FLAG64 (USE_VMAbv) | \
|
||||
FLAG64 (USE_VMBlw) | \
|
||||
FLAG64 (USE_VMPst) | \
|
||||
FLAG64 (USE_VMPre))
|
||||
|
||||
/* Move things forward. */
|
||||
if (info[start].use_category() == USE_R && end - start > 1)
|
||||
{
|
||||
/* Got a repha. Reorder it to after first base, before first halant. */
|
||||
/* Got a repha. Reorder it towards the end, but before the first post-base
|
||||
* glyph. */
|
||||
for (unsigned int i = start + 1; i < end; i++)
|
||||
if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i]))
|
||||
{
|
||||
bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) ||
|
||||
is_halant (info[i]);
|
||||
if (is_post_base_glyph || i == end - 1)
|
||||
{
|
||||
/* If we hit a halant, move before it; otherwise it's a base: move to it's
|
||||
* place, and shift things in between backward. */
|
||||
/* If we hit a post-base glyph, move before it; otherwise move to the
|
||||
* end. Shift things in between backward. */
|
||||
|
||||
if (is_halant (info[i]))
|
||||
if (is_post_base_glyph)
|
||||
i--;
|
||||
|
||||
buffer->merge_clusters (start, i + 1);
|
||||
@ -471,21 +491,19 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Move things back. */
|
||||
unsigned int j = end;
|
||||
unsigned int j = start;
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
uint32_t flag = FLAG_UNSAFE (info[i].use_category());
|
||||
if ((flag & (BASE_FLAGS)) || is_halant (info[i]))
|
||||
if (is_halant (info[i]))
|
||||
{
|
||||
/* If we hit a halant, move after it; otherwise it's a base: move to it's
|
||||
* place, and shift things in between backward. */
|
||||
if (is_halant (info[i]))
|
||||
j = i + 1;
|
||||
else
|
||||
j = i;
|
||||
/* If we hit a halant, move after it; otherwise move to the beginning, and
|
||||
* shift things in between forward. */
|
||||
j = i + 1;
|
||||
}
|
||||
else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) &&
|
||||
/* Only move the first component of a MultipleSubst. */
|
||||
|
@ -57,7 +57,6 @@ enum hb_ot_shape_zero_width_marks_type_t {
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_old) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_zawgyi) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (use) \
|
||||
@ -269,12 +268,25 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
|
||||
return &_hb_ot_complex_shaper_khmer;
|
||||
|
||||
case HB_SCRIPT_MYANMAR:
|
||||
if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))
|
||||
return &_hb_ot_complex_shaper_myanmar;
|
||||
else if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
|
||||
return &_hb_ot_complex_shaper_myanmar_old;
|
||||
else
|
||||
/* If the designer designed the font for the 'DFLT' script,
|
||||
* (or we ended up arbitrarily pick 'latn'), use the default shaper.
|
||||
* Otherwise, use the specific shaper.
|
||||
*
|
||||
* If designer designed for 'mymr' tag, also send to default
|
||||
* shaper. That's tag used from before Myanmar shaping spec
|
||||
* was developed. The shaping spec uses 'mym2' tag. */
|
||||
if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
|
||||
planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') ||
|
||||
planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
|
||||
return &_hb_ot_complex_shaper_default;
|
||||
else
|
||||
return &_hb_ot_complex_shaper_myanmar;
|
||||
|
||||
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/1162 */
|
||||
case HB_SCRIPT_MYANMAR_ZAWGYI:
|
||||
|
||||
return &_hb_ot_complex_shaper_myanmar_zawgyi;
|
||||
|
||||
|
||||
/* Unicode-2.0 additions */
|
||||
@ -375,10 +387,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
|
||||
return &_hb_ot_complex_shaper_default;
|
||||
else
|
||||
return &_hb_ot_complex_shaper_use;
|
||||
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/1162 */
|
||||
case HB_SCRIPT_MYANMAR_ZAWGYI:
|
||||
return &_hb_ot_complex_shaper_myanmar_zawgyi;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,10 +76,16 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac
|
||||
props (*props),
|
||||
map (face, props),
|
||||
aat_map (face, props),
|
||||
apply_morx (_hb_apply_morx (face)),
|
||||
shaper (apply_morx ?
|
||||
&_hb_ot_complex_shaper_default :
|
||||
hb_ot_shape_complex_categorize (this)) {}
|
||||
apply_morx (_hb_apply_morx (face))
|
||||
{
|
||||
shaper = hb_ot_shape_complex_categorize (this);
|
||||
|
||||
script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
|
||||
script_fallback_mark_positioning = shaper->fallback_position;
|
||||
|
||||
if (apply_morx)
|
||||
shaper = &_hb_ot_complex_shaper_default;
|
||||
}
|
||||
|
||||
void
|
||||
hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
||||
@ -140,10 +146,17 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
||||
plan.apply_kern = true;
|
||||
}
|
||||
|
||||
bool has_kern_mark = plan.apply_kern && hb_ot_layout_has_cross_kerning (face);
|
||||
plan.zero_marks = !plan.apply_morx && !plan.apply_kerx && !has_kern_mark;
|
||||
plan.zero_marks = script_zero_marks &&
|
||||
!plan.apply_kerx &&
|
||||
(!plan.apply_kern || !hb_ot_layout_has_machine_kerning (face));
|
||||
plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
|
||||
plan.fallback_mark_positioning = !plan.apply_gpos && plan.zero_marks;
|
||||
|
||||
plan.adjust_mark_positioning_when_zeroing = !plan.apply_gpos &&
|
||||
!plan.apply_kerx &&
|
||||
(!plan.apply_kern || !hb_ot_layout_has_cross_kerning (face));
|
||||
|
||||
plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
|
||||
script_fallback_mark_positioning;
|
||||
|
||||
/* Currently we always apply trak. */
|
||||
plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
|
||||
@ -158,6 +171,7 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face,
|
||||
|
||||
hb_ot_shape_planner_t planner (face,
|
||||
&key->props);
|
||||
|
||||
hb_ot_shape_collect_features (&planner,
|
||||
key->user_features,
|
||||
key->num_user_features);
|
||||
@ -811,17 +825,16 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c)
|
||||
hb_glyph_info_t *info = c->buffer->info;
|
||||
hb_glyph_position_t *pos = c->buffer->pos;
|
||||
|
||||
/* If the font has no GPOS, AND, no fallback positioning will
|
||||
* happen, AND, direction is forward, then when zeroing mark
|
||||
* widths, we shift the mark with it, such that the mark
|
||||
* is positioned hanging over the previous glyph. When
|
||||
/* If the font has no GPOS and direction is forward, then when
|
||||
* zeroing mark widths, we shift the mark with it, such that the
|
||||
* mark is positioned hanging over the previous glyph. When
|
||||
* direction is backward we don't shift and it will end up
|
||||
* hanging over the next glyph after the final reordering.
|
||||
* If fallback positinoing happens or GPOS is present, we don't
|
||||
* care.
|
||||
*
|
||||
* Note: If fallback positinoing happens, we don't care about
|
||||
* this as it will be overriden.
|
||||
*/
|
||||
bool adjust_offsets_when_zeroing = c->plan->fallback_mark_positioning &&
|
||||
!c->plan->shaper->fallback_position &&
|
||||
bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
|
||||
HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
|
||||
|
||||
/* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
|
||||
@ -877,7 +890,7 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c)
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
|
||||
if (c->plan->fallback_mark_positioning && c->plan->shaper->fallback_position)
|
||||
if (c->plan->fallback_mark_positioning)
|
||||
_hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer);
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,7 @@ struct hb_ot_shape_plan_t
|
||||
bool zero_marks : 1;
|
||||
bool fallback_glyph_classes : 1;
|
||||
bool fallback_mark_positioning : 1;
|
||||
bool adjust_mark_positioning_when_zeroing : 1;
|
||||
|
||||
bool apply_gpos : 1;
|
||||
bool apply_kerx : 1;
|
||||
@ -113,6 +114,8 @@ struct hb_ot_shape_planner_t
|
||||
hb_ot_map_builder_t map;
|
||||
hb_aat_map_builder_t aat_map;
|
||||
bool apply_morx : 1;
|
||||
bool script_zero_marks : 1;
|
||||
bool script_fallback_mark_positioning : 1;
|
||||
const struct hb_ot_complex_shaper_t *shaper;
|
||||
|
||||
HB_INTERNAL hb_ot_shape_planner_t (hb_face_t *face,
|
||||
|
@ -65,7 +65,7 @@ struct InstanceRecord
|
||||
// * instance. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, coordinatesZ);
|
||||
DEFINE_SIZE_UNBOUNDED (4);
|
||||
};
|
||||
|
||||
struct AxisRecord
|
||||
@ -109,40 +109,46 @@ struct fvar
|
||||
axisSize == 20 && /* Assumed in our code. */
|
||||
instanceSize >= axisCount * 4 + 4 &&
|
||||
get_axes ().sanitize (c) &&
|
||||
c->check_range (&get_instance (0), instanceCount, instanceSize));
|
||||
c->check_range (get_instance (0), instanceCount, instanceSize));
|
||||
}
|
||||
|
||||
inline unsigned int get_axis_count (void) const
|
||||
{ return axisCount; }
|
||||
|
||||
inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const
|
||||
inline void get_axis_deprecated (unsigned int axis_index,
|
||||
hb_ot_var_axis_t *info) const
|
||||
{
|
||||
if (info)
|
||||
{
|
||||
const AxisRecord &axis = get_axes ()[index];
|
||||
info->tag = axis.axisTag;
|
||||
info->name_id = axis.axisNameID;
|
||||
info->default_value = axis.defaultValue / 65536.;
|
||||
/* Ensure order, to simplify client math. */
|
||||
info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
|
||||
info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
|
||||
}
|
||||
|
||||
return true;
|
||||
const AxisRecord &axis = get_axes ()[axis_index];
|
||||
info->tag = axis.axisTag;
|
||||
info->name_id = axis.axisNameID;
|
||||
info->default_value = axis.defaultValue / 65536.;
|
||||
/* Ensure order, to simplify client math. */
|
||||
info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
|
||||
info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
|
||||
}
|
||||
|
||||
inline hb_ot_var_axis_flags_t get_axis_flags (unsigned int index) const
|
||||
inline void get_axis_info (unsigned int axis_index,
|
||||
hb_ot_var_axis_info_t *info) const
|
||||
{
|
||||
const AxisRecord &axis = get_axes ()[index];
|
||||
return (hb_ot_var_axis_flags_t) (unsigned int) axis.flags;
|
||||
const AxisRecord &axis = get_axes ()[axis_index];
|
||||
info->axis_index = axis_index;
|
||||
info->tag = axis.axisTag;
|
||||
info->name_id = axis.axisNameID;
|
||||
info->flags = (hb_ot_var_axis_flags_t) (unsigned int) axis.flags;
|
||||
info->default_value = axis.defaultValue / 65536.;
|
||||
/* Ensure order, to simplify client math. */
|
||||
info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
|
||||
info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
|
||||
info->reserved = 0;
|
||||
}
|
||||
|
||||
inline unsigned int get_axis_infos (unsigned int start_offset,
|
||||
unsigned int *axes_count /* IN/OUT */,
|
||||
hb_ot_var_axis_t *axes_array /* OUT */) const
|
||||
inline unsigned int get_axes_deprecated (unsigned int start_offset,
|
||||
unsigned int *axes_count /* IN/OUT */,
|
||||
hb_ot_var_axis_t *axes_array /* OUT */) const
|
||||
{
|
||||
if (axes_count)
|
||||
{
|
||||
/* TODO Rewrite as hb_array_t<>::sub-array() */
|
||||
unsigned int count = axisCount;
|
||||
start_offset = MIN (start_offset, count);
|
||||
|
||||
@ -153,32 +159,70 @@ struct fvar
|
||||
*axes_count = count;
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
get_axis (start_offset + i, axes_array + i);
|
||||
get_axis_deprecated (start_offset + i, axes_array + i);
|
||||
}
|
||||
return axisCount;
|
||||
}
|
||||
|
||||
inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const
|
||||
inline unsigned int get_axis_infos (unsigned int start_offset,
|
||||
unsigned int *axes_count /* IN/OUT */,
|
||||
hb_ot_var_axis_info_t *axes_array /* OUT */) const
|
||||
{
|
||||
if (axes_count)
|
||||
{
|
||||
/* TODO Rewrite as hb_array_t<>::sub-array() */
|
||||
unsigned int count = axisCount;
|
||||
start_offset = MIN (start_offset, count);
|
||||
|
||||
count -= start_offset;
|
||||
axes_array += start_offset;
|
||||
|
||||
count = MIN (count, *axes_count);
|
||||
*axes_count = count;
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
get_axis_info (start_offset + i, axes_array + i);
|
||||
}
|
||||
return axisCount;
|
||||
}
|
||||
|
||||
inline bool find_axis_deprecated (hb_tag_t tag,
|
||||
unsigned int *axis_index,
|
||||
hb_ot_var_axis_t *info) const
|
||||
{
|
||||
const AxisRecord *axes = get_axes ();
|
||||
unsigned int count = get_axis_count ();
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (axes[i].axisTag == tag)
|
||||
{
|
||||
if (index)
|
||||
*index = i;
|
||||
return get_axis (i, info);
|
||||
if (axis_index)
|
||||
*axis_index = i;
|
||||
get_axis_deprecated (i, info);
|
||||
return true;
|
||||
}
|
||||
if (axis_index)
|
||||
*axis_index = HB_OT_VAR_NO_AXIS_INDEX;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool find_axis_info (hb_tag_t tag,
|
||||
hb_ot_var_axis_info_t *info) const
|
||||
{
|
||||
const AxisRecord *axes = get_axes ();
|
||||
unsigned int count = get_axis_count ();
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (axes[i].axisTag == tag)
|
||||
{
|
||||
get_axis_info (i, info);
|
||||
return true;
|
||||
}
|
||||
if (index)
|
||||
*index = HB_OT_VAR_NO_AXIS_INDEX;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline int normalize_axis_value (unsigned int axis_index, float v) const
|
||||
{
|
||||
hb_ot_var_axis_t axis;
|
||||
if (!get_axis (axis_index, &axis))
|
||||
return 0;
|
||||
hb_ot_var_axis_info_t axis;
|
||||
get_axis_info (axis_index, &axis);
|
||||
|
||||
v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */
|
||||
|
||||
@ -194,25 +238,28 @@ struct fvar
|
||||
inline unsigned int get_instance_count (void) const
|
||||
{ return instanceCount; }
|
||||
|
||||
inline hb_ot_name_id_t get_instance_subfamily_name_id (unsigned int index) const
|
||||
inline hb_ot_name_id_t get_instance_subfamily_name_id (unsigned int instance_index) const
|
||||
{
|
||||
const InstanceRecord &instance = get_instance (index);
|
||||
return instance.subfamilyNameID;
|
||||
const InstanceRecord *instance = get_instance (instance_index);
|
||||
if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
|
||||
return instance->subfamilyNameID;
|
||||
}
|
||||
|
||||
inline hb_ot_name_id_t get_instance_postscript_name_id (unsigned int index) const
|
||||
inline hb_ot_name_id_t get_instance_postscript_name_id (unsigned int instance_index) const
|
||||
{
|
||||
const InstanceRecord &instance = get_instance (index);
|
||||
const InstanceRecord *instance = get_instance (instance_index);
|
||||
if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
|
||||
if (instanceSize >= axisCount * 4 + 6)
|
||||
return StructAfter<NameID> (instance.get_coordinates (axisCount));
|
||||
return StructAfter<NameID> (instance->get_coordinates (axisCount));
|
||||
return HB_OT_NAME_ID_INVALID;
|
||||
}
|
||||
|
||||
inline unsigned int get_instance_coords (unsigned int index,
|
||||
inline unsigned int get_instance_coords (unsigned int instance_index,
|
||||
unsigned int *coords_length, /* IN/OUT */
|
||||
float *coords /* OUT */) const
|
||||
{
|
||||
if (unlikely (index >= instanceCount))
|
||||
const InstanceRecord *instance = get_instance (instance_index);
|
||||
if (unlikely (!instance))
|
||||
{
|
||||
if (coords_length)
|
||||
*coords_length = 0;
|
||||
@ -221,9 +268,8 @@ struct fvar
|
||||
|
||||
if (coords_length && *coords_length)
|
||||
{
|
||||
const InstanceRecord &instance = get_instance (index);
|
||||
hb_array_t<const Fixed> instanceCoords = instance.get_coordinates (axisCount)
|
||||
.sub_array (0, *coords_length);
|
||||
hb_array_t<const Fixed> instanceCoords = instance->get_coordinates (axisCount)
|
||||
.sub_array (0, *coords_length);
|
||||
for (unsigned int i = 0; i < instanceCoords.len; i++)
|
||||
coords[i] = instanceCoords.arrayZ[i].to_float ();
|
||||
}
|
||||
@ -234,12 +280,11 @@ struct fvar
|
||||
inline hb_array_t<const AxisRecord> get_axes (void) const
|
||||
{ return hb_array (&(this+firstAxis), axisCount); }
|
||||
|
||||
inline const InstanceRecord &get_instance (unsigned int i) const
|
||||
inline const InstanceRecord *get_instance (unsigned int i) const
|
||||
{
|
||||
if (unlikely (i >= instanceCount)) return Null (InstanceRecord);
|
||||
|
||||
return StructAtOffset<InstanceRecord> (&StructAfter<InstanceRecord> (get_axes ()),
|
||||
i * instanceSize);
|
||||
if (unlikely (i >= instanceCount)) return nullptr;
|
||||
return &StructAtOffset<InstanceRecord> (&StructAfter<InstanceRecord> (get_axes ()),
|
||||
i * instanceSize);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -53,7 +53,6 @@
|
||||
* @face: #hb_face_t to test
|
||||
*
|
||||
* This function allows to verify the presence of OpenType variation data on the face.
|
||||
* Alternatively, use hb_ot_var_get_axis_count().
|
||||
*
|
||||
* Return value: true if face has a `fvar' table and false otherwise
|
||||
*
|
||||
@ -80,6 +79,7 @@ hb_ot_var_get_axis_count (hb_face_t *face)
|
||||
* hb_ot_var_get_axes:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
* Deprecated: REPLACEME
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_var_get_axes (hb_face_t *face,
|
||||
@ -87,13 +87,14 @@ hb_ot_var_get_axes (hb_face_t *face,
|
||||
unsigned int *axes_count /* IN/OUT */,
|
||||
hb_ot_var_axis_t *axes_array /* OUT */)
|
||||
{
|
||||
return face->table.fvar->get_axis_infos (start_offset, axes_count, axes_array);
|
||||
return face->table.fvar->get_axes_deprecated (start_offset, axes_count, axes_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_var_find_axis:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
* Deprecated: REPLACEME
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_ot_var_find_axis (hb_face_t *face,
|
||||
@ -101,21 +102,37 @@ hb_ot_var_find_axis (hb_face_t *face,
|
||||
unsigned int *axis_index,
|
||||
hb_ot_var_axis_t *axis_info)
|
||||
{
|
||||
return face->table.fvar->find_axis (axis_tag, axis_index, axis_info);
|
||||
return face->table.fvar->find_axis_deprecated (axis_tag, axis_index, axis_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_var_axis_get_flags:
|
||||
* hb_ot_var_get_axis_infos:
|
||||
*
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
hb_ot_var_axis_flags_t
|
||||
hb_ot_var_axis_get_flags (hb_face_t *face,
|
||||
unsigned int axis_index)
|
||||
HB_EXTERN unsigned int
|
||||
hb_ot_var_get_axis_infos (hb_face_t *face,
|
||||
unsigned int start_offset,
|
||||
unsigned int *axes_count /* IN/OUT */,
|
||||
hb_ot_var_axis_info_t *axes_array /* OUT */)
|
||||
{
|
||||
return face->table.fvar->get_axis_flags (axis_index);
|
||||
return face->table.fvar->get_axis_infos (start_offset, axes_count, axes_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_var_find_axis_info:
|
||||
*
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_ot_var_find_axis_info (hb_face_t *face,
|
||||
hb_tag_t axis_tag,
|
||||
hb_ot_var_axis_info_t *axis_info)
|
||||
{
|
||||
return face->table.fvar->find_axis_info (axis_tag, axis_info);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Named instances.
|
||||
*/
|
||||
@ -168,10 +185,10 @@ hb_ot_var_normalize_variations (hb_face_t *face,
|
||||
const OT::fvar &fvar = *face->table.fvar;
|
||||
for (unsigned int i = 0; i < variations_length; i++)
|
||||
{
|
||||
unsigned int axis_index;
|
||||
if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, nullptr) &&
|
||||
axis_index < coords_length)
|
||||
coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value);
|
||||
hb_ot_var_axis_info_t info;
|
||||
if (hb_ot_var_find_axis_info (face, variations[i].tag, &info) &&
|
||||
info.axis_index < coords_length)
|
||||
coords[info.axis_index] = fvar.normalize_axis_value (info.axis_index, variations[i].value);
|
||||
}
|
||||
|
||||
face->table.avar->map_coords (coords, coords_length);
|
||||
|
@ -47,19 +47,6 @@ HB_BEGIN_DECLS
|
||||
* fvar / avar
|
||||
*/
|
||||
|
||||
/**
|
||||
* hb_ot_var_axis_t:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
typedef struct hb_ot_var_axis_t {
|
||||
hb_tag_t tag;
|
||||
hb_ot_name_id_t name_id;
|
||||
float min_value;
|
||||
float default_value;
|
||||
float max_value;
|
||||
} hb_ot_var_axis_t;
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_ot_var_has_data (hb_face_t *face);
|
||||
|
||||
@ -68,28 +55,10 @@ hb_ot_var_has_data (hb_face_t *face);
|
||||
* Variation axes.
|
||||
*/
|
||||
|
||||
/**
|
||||
* HB_OT_VAR_NO_AXIS_INDEX:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
#define HB_OT_VAR_NO_AXIS_INDEX 0xFFFFFFFFu
|
||||
|
||||
HB_EXTERN unsigned int
|
||||
hb_ot_var_get_axis_count (hb_face_t *face);
|
||||
|
||||
HB_EXTERN unsigned int
|
||||
hb_ot_var_get_axes (hb_face_t *face,
|
||||
unsigned int start_offset,
|
||||
unsigned int *axes_count /* IN/OUT */,
|
||||
hb_ot_var_axis_t *axes_array /* OUT */);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_ot_var_find_axis (hb_face_t *face,
|
||||
hb_tag_t axis_tag,
|
||||
unsigned int *axis_index,
|
||||
hb_ot_var_axis_t *axis_info);
|
||||
|
||||
/**
|
||||
* hb_ot_var_axis_flags_t:
|
||||
* @HB_OT_VAR_AXIS_FLAG_HIDDEN: The axis should not be exposed directly in user interfaces.
|
||||
@ -97,12 +66,39 @@ hb_ot_var_find_axis (hb_face_t *face,
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
typedef enum { /*< flags >*/
|
||||
HB_OT_VAR_AXIS_FLAG_HIDDEN = 0x0001u,
|
||||
HB_OT_VAR_AXIS_FLAG_HIDDEN = 0x00000001u,
|
||||
|
||||
_HB_OT_VAR_AXIS_FLAG_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
|
||||
} hb_ot_var_axis_flags_t;
|
||||
|
||||
HB_EXTERN hb_ot_var_axis_flags_t
|
||||
hb_ot_var_axis_get_flags (hb_face_t *face,
|
||||
unsigned int axis_index);
|
||||
/**
|
||||
* hb_ot_var_axis_info_t:
|
||||
*
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
typedef struct hb_ot_var_axis_info_t
|
||||
{
|
||||
unsigned int axis_index;
|
||||
hb_tag_t tag;
|
||||
hb_ot_name_id_t name_id;
|
||||
hb_ot_var_axis_flags_t flags;
|
||||
float min_value;
|
||||
float default_value;
|
||||
float max_value;
|
||||
/*< private >*/
|
||||
unsigned int reserved;
|
||||
} hb_ot_var_axis_info_t;
|
||||
|
||||
HB_EXTERN unsigned int
|
||||
hb_ot_var_get_axis_infos (hb_face_t *face,
|
||||
unsigned int start_offset,
|
||||
unsigned int *axes_count /* IN/OUT */,
|
||||
hb_ot_var_axis_info_t *axes_array /* OUT */);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_ot_var_find_axis_info (hb_face_t *face,
|
||||
hb_tag_t axis_tag,
|
||||
hb_ot_var_axis_info_t *axis_info);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -63,11 +63,10 @@ struct VORG
|
||||
|
||||
inline int get_y_origin (hb_codepoint_t glyph) const
|
||||
{
|
||||
int i = vertYOrigins.bsearch (glyph);
|
||||
if (i != -1)
|
||||
return vertYOrigins[i].vertOriginY;
|
||||
|
||||
return defaultVertOriginY;
|
||||
unsigned int i;
|
||||
if (!vertYOrigins.bfind (glyph, &i))
|
||||
return defaultVertOriginY;
|
||||
return vertYOrigins[i].vertOriginY;
|
||||
}
|
||||
|
||||
inline bool _subset (const hb_subset_plan_t *plan HB_UNUSED,
|
||||
|
@ -45,7 +45,7 @@ struct hb_set_t
|
||||
|
||||
struct page_map_t
|
||||
{
|
||||
inline int cmp (const page_map_t *o) const { return (int) o->major - (int) major; }
|
||||
inline int cmp (const page_map_t &o) const { return (int) o.major - (int) major; }
|
||||
|
||||
uint32_t major;
|
||||
uint32_t index;
|
||||
@ -341,11 +341,11 @@ struct hb_set_t
|
||||
{
|
||||
/* TODO perform op even if !successful. */
|
||||
if (unlikely (!successful)) return;
|
||||
page_t *p = page_for (g);
|
||||
if (!p)
|
||||
page_t *page = page_for (g);
|
||||
if (!page)
|
||||
return;
|
||||
dirty ();
|
||||
p->del (g);
|
||||
page->del (g);
|
||||
}
|
||||
inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
@ -357,10 +357,10 @@ struct hb_set_t
|
||||
}
|
||||
inline bool has (hb_codepoint_t g) const
|
||||
{
|
||||
const page_t *p = page_for (g);
|
||||
if (!p)
|
||||
const page_t *page = page_for (g);
|
||||
if (!page)
|
||||
return false;
|
||||
return p->has (g);
|
||||
return page->has (g);
|
||||
}
|
||||
inline bool intersects (hb_codepoint_t first,
|
||||
hb_codepoint_t last) const
|
||||
@ -544,7 +544,7 @@ struct hb_set_t
|
||||
|
||||
page_map_t map = {get_major (*codepoint), 0};
|
||||
unsigned int i;
|
||||
page_map.bfind (map, &i);
|
||||
page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
|
||||
if (i < page_map.len && page_map[i].major == map.major)
|
||||
{
|
||||
if (pages[page_map[i].index].next (codepoint))
|
||||
@ -575,7 +575,7 @@ struct hb_set_t
|
||||
|
||||
page_map_t map = {get_major (*codepoint), 0};
|
||||
unsigned int i;
|
||||
page_map.bfind (map, &i);
|
||||
page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
|
||||
if (i < page_map.len && page_map[i].major == map.major)
|
||||
{
|
||||
if (pages[page_map[i].index].previous (codepoint))
|
||||
@ -670,7 +670,7 @@ struct hb_set_t
|
||||
{
|
||||
page_map_t map = {get_major (g), pages.len};
|
||||
unsigned int i;
|
||||
if (!page_map.bfind (map, &i))
|
||||
if (!page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST))
|
||||
{
|
||||
if (!resize (pages.len + 1))
|
||||
return nullptr;
|
||||
|
@ -48,7 +48,7 @@
|
||||
**/
|
||||
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_shaper_list (void);
|
||||
#endif
|
||||
|
||||
@ -69,7 +69,7 @@ static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
|
||||
shaper_list[i] = shapers[i].name;
|
||||
shaper_list[i] = nullptr;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_shaper_list);
|
||||
#endif
|
||||
|
||||
@ -85,7 +85,7 @@ static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
|
||||
}
|
||||
} static_shaper_list;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_shaper_list (void)
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ static const hb_shaper_entry_t all_shapers[] = {
|
||||
#undef HB_SHAPER_IMPLEMENT
|
||||
};
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_shapers (void);
|
||||
#endif
|
||||
|
||||
@ -80,7 +80,7 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
|
||||
p = end + 1;
|
||||
}
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_shapers);
|
||||
#endif
|
||||
|
||||
@ -96,7 +96,7 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
|
||||
}
|
||||
} static_shapers;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_shapers (void)
|
||||
{
|
||||
|
@ -27,10 +27,12 @@
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-layout-common.hh"
|
||||
#include "hb-aat-layout-common.hh"
|
||||
|
||||
#include "hb-face.hh"
|
||||
|
||||
#include "hb-aat-layout-common.hh"
|
||||
#include "hb-aat-layout-feat-table.hh"
|
||||
#include "hb-ot-layout-common.hh"
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
#include "hb-ot-head-table.hh"
|
||||
#include "hb-ot-maxp-table.hh"
|
||||
|
||||
@ -42,6 +44,8 @@ hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_
|
||||
DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF};
|
||||
DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
|
||||
DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
|
||||
DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};
|
||||
DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
|
||||
/* Hand-coded because Lookup is a template. Sad. */
|
||||
const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
|
||||
|
||||
|
@ -222,7 +222,7 @@ hb_ucdn_decompose(hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_ucdn_funcs (void);
|
||||
#endif
|
||||
|
||||
@ -241,7 +241,7 @@ static struct hb_ucdn_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader
|
||||
|
||||
hb_unicode_funcs_make_immutable (funcs);
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_ucdn_funcs);
|
||||
#endif
|
||||
|
||||
@ -249,7 +249,7 @@ static struct hb_ucdn_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader
|
||||
}
|
||||
} static_ucdn_funcs;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_ucdn_funcs (void)
|
||||
{
|
||||
|
@ -245,7 +245,7 @@ static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t<hb_unis
|
||||
|
||||
funcs->init ();
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_uniscribe_shaper_funcs);
|
||||
#endif
|
||||
|
||||
@ -261,7 +261,7 @@ static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t<hb_unis
|
||||
}
|
||||
} static_uniscribe_shaper_funcs;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_uniscribe_shaper_funcs (void)
|
||||
{
|
||||
|
@ -31,13 +31,15 @@
|
||||
#include "hb.hh"
|
||||
|
||||
|
||||
template <typename Type, unsigned int StaticSize=8>
|
||||
template <typename Type, unsigned int PreallocedCount=8>
|
||||
struct hb_vector_t
|
||||
{
|
||||
static_assert ((bool) (unsigned) hb_static_size (Type), "");
|
||||
|
||||
typedef Type ItemType;
|
||||
enum { item_size = sizeof (Type) };
|
||||
|
||||
HB_NO_COPY_ASSIGN_TEMPLATE2 (hb_vector_t, Type, StaticSize);
|
||||
HB_NO_COPY_ASSIGN_TEMPLATE2 (hb_vector_t, Type, PreallocedCount);
|
||||
inline hb_vector_t (void) { init (); }
|
||||
inline ~hb_vector_t (void) { fini (); }
|
||||
|
||||
@ -45,7 +47,7 @@ struct hb_vector_t
|
||||
private:
|
||||
unsigned int allocated; /* == 0 means allocation failed. */
|
||||
Type *arrayZ_;
|
||||
Type static_array[StaticSize];
|
||||
Type static_array[PreallocedCount];
|
||||
public:
|
||||
|
||||
void init (void)
|
||||
@ -89,6 +91,16 @@ struct hb_vector_t
|
||||
return arrayZ()[i];
|
||||
}
|
||||
|
||||
inline hb_array_t<Type> as_array (void)
|
||||
{ return hb_array (arrayZ(), len); }
|
||||
inline hb_array_t<const Type> as_array (void) const
|
||||
{ return hb_array (arrayZ(), len); }
|
||||
|
||||
inline hb_sorted_array_t<Type> as_sorted_array (void)
|
||||
{ return hb_sorted_array (arrayZ(), len); }
|
||||
inline hb_sorted_array_t<const Type> as_sorted_array (void) const
|
||||
{ return hb_sorted_array (arrayZ(), len); }
|
||||
|
||||
template <typename T> inline operator T * (void) { return arrayZ(); }
|
||||
template <typename T> inline operator const T * (void) const { return arrayZ(); }
|
||||
|
||||
@ -209,75 +221,28 @@ struct hb_vector_t
|
||||
}
|
||||
|
||||
inline void qsort (int (*cmp)(const void*, const void*))
|
||||
{
|
||||
::qsort (arrayZ(), len, sizeof (Type), cmp);
|
||||
}
|
||||
|
||||
inline void qsort (void)
|
||||
{
|
||||
::qsort (arrayZ(), len, sizeof (Type), Type::cmp);
|
||||
}
|
||||
|
||||
inline void qsort (unsigned int start, unsigned int end)
|
||||
{
|
||||
::qsort (arrayZ() + start, end - start, sizeof (Type), Type::cmp);
|
||||
}
|
||||
{ as_array ().qsort (cmp); }
|
||||
inline void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
|
||||
{ as_array ().qsort (start, end); }
|
||||
|
||||
template <typename T>
|
||||
inline Type *lsearch (const T &x)
|
||||
{
|
||||
Type *array = arrayZ();
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
if (0 == array[i].cmp (&x))
|
||||
return &array[i];
|
||||
return nullptr;
|
||||
}
|
||||
inline Type *lsearch (const T &x, Type *not_found = nullptr)
|
||||
{ return as_array ().lsearch (x, not_found); }
|
||||
template <typename T>
|
||||
inline const Type *lsearch (const T &x) const
|
||||
{
|
||||
const Type *array = arrayZ();
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
if (0 == array[i].cmp (&x))
|
||||
return &array[i];
|
||||
return nullptr;
|
||||
}
|
||||
inline const Type *lsearch (const T &x, const Type *not_found = nullptr) const
|
||||
{ return as_array ().lsearch (x, not_found); }
|
||||
|
||||
template <typename T>
|
||||
inline Type *bsearch (const T &x)
|
||||
{
|
||||
unsigned int i;
|
||||
return bfind (x, &i) ? &arrayZ()[i] : nullptr;
|
||||
}
|
||||
inline Type *bsearch (const T &x, Type *not_found = nullptr)
|
||||
{ return as_sorted_array ().bsearch (x, not_found); }
|
||||
template <typename T>
|
||||
inline const Type *bsearch (const T &x) const
|
||||
{
|
||||
unsigned int i;
|
||||
return bfind (x, &i) ? &arrayZ()[i] : nullptr;
|
||||
}
|
||||
inline const Type *bsearch (const T &x, const Type *not_found = nullptr) const
|
||||
{ return as_sorted_array ().bsearch (x, not_found); }
|
||||
template <typename T>
|
||||
inline bool bfind (const T &x, unsigned int *i) const
|
||||
{
|
||||
int min = 0, max = (int) this->len - 1;
|
||||
const Type *array = this->arrayZ();
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = ((unsigned int) min + (unsigned int) max) / 2;
|
||||
int c = array[mid].cmp (&x);
|
||||
if (c < 0)
|
||||
max = mid - 1;
|
||||
else if (c > 0)
|
||||
min = mid + 1;
|
||||
else
|
||||
{
|
||||
*i = mid;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (max < 0 || (max < (int) this->len && array[max].cmp (&x) > 0))
|
||||
max++;
|
||||
*i = max;
|
||||
return false;
|
||||
}
|
||||
inline bool bfind (const T &x, unsigned int *i = nullptr,
|
||||
hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{ return as_sorted_array ().bfind (x, i, not_found, to_store); }
|
||||
};
|
||||
|
||||
|
||||
|
18
src/hb.hh
18
src/hb.hh
@ -47,6 +47,10 @@
|
||||
#define HB_H_IN
|
||||
#include "hb-ot.h"
|
||||
#define HB_OT_H_IN
|
||||
#include "hb-aat.h"
|
||||
#define HB_AAT_H_IN
|
||||
|
||||
#include "hb-aat.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
@ -281,7 +285,7 @@ static int errno = 0; /* Use something better? */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if HAVE_ATEXIT
|
||||
#if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT)
|
||||
/* atexit() is only safe to be called from shared libraries on certain
|
||||
* platforms. Whitelist.
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
|
||||
@ -313,6 +317,9 @@ static int errno = 0; /* Use something better? */
|
||||
#ifdef HB_NO_ATEXIT
|
||||
# undef HB_USE_ATEXIT
|
||||
#endif
|
||||
#ifndef HB_USE_ATEXIT
|
||||
# define HB_USE_ATEXIT 0
|
||||
#endif
|
||||
|
||||
#define HB_STMT_START do
|
||||
#define HB_STMT_END while (0)
|
||||
@ -443,9 +450,11 @@ typedef uint64_t hb_vector_size_impl_t;
|
||||
* For example, for testing "x ∈ {x1, x2, x3}" use:
|
||||
* (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
|
||||
*/
|
||||
#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned int)(x) < 32) + (1U << (unsigned int)(x)))
|
||||
#define FLAG_UNSAFE(x) ((unsigned int)(x) < 32 ? (1U << (unsigned int)(x)) : 0)
|
||||
#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
|
||||
#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
|
||||
#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
|
||||
#define FLAG64(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
|
||||
#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
|
||||
|
||||
|
||||
/* Size signifying variable-sized array */
|
||||
@ -503,10 +512,13 @@ _hb_memalign(void **memptr, size_t alignment, size_t size)
|
||||
/* Some really basic things everyone wants. */
|
||||
template <typename T> struct hb_remove_const { typedef T value; };
|
||||
template <typename T> struct hb_remove_const<const T> { typedef T value; };
|
||||
#define hb_remove_const(T) hb_remove_const<T>::value
|
||||
template <typename T> struct hb_remove_reference { typedef T value; };
|
||||
template <typename T> struct hb_remove_reference<T &> { typedef T value; };
|
||||
#define hb_remove_reference(T) hb_remove_reference<T>::value
|
||||
template <typename T> struct hb_remove_pointer { typedef T value; };
|
||||
template <typename T> struct hb_remove_pointer<T *> { typedef T value; };
|
||||
#define hb_remove_pointer(T) hb_remove_pointer<T>::value
|
||||
|
||||
|
||||
/* Headers we include for everyone. Keep sorted. They express dependency amongst
|
||||
|
@ -28,6 +28,7 @@ check_PROGRAMS = $(TEST_PROGS)
|
||||
noinst_PROGRAMS = $(TEST_PROGS)
|
||||
|
||||
TEST_PROGS = \
|
||||
test-aat-layout \
|
||||
test-baseline \
|
||||
test-blob \
|
||||
test-buffer \
|
||||
|
BIN
test/api/fonts/aat-feat.ttf
Normal file
BIN
test/api/fonts/aat-feat.ttf
Normal file
Binary file not shown.
118
test/api/test-aat-layout.c
Normal file
118
test/api/test-aat-layout.c
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright © 2018 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#include "hb-test.h"
|
||||
|
||||
#include <hb.h>
|
||||
#include <hb-ot.h>
|
||||
#include <hb-aat.h>
|
||||
|
||||
/* Unit tests for hb-aat.h */
|
||||
|
||||
static hb_face_t *face;
|
||||
static hb_face_t *sbix;
|
||||
|
||||
static void
|
||||
test_aat_get_feature_types (void)
|
||||
{
|
||||
hb_aat_layout_feature_type_t features[3];
|
||||
unsigned int count = 3;
|
||||
g_assert_cmpuint (11, ==, hb_aat_layout_get_feature_types (face, 0, &count, features));
|
||||
|
||||
g_assert_cmpuint (1, ==, features[0]);
|
||||
g_assert_cmpuint (3, ==, features[1]);
|
||||
g_assert_cmpuint (6, ==, features[2]);
|
||||
|
||||
g_assert_cmpuint (258, ==, hb_aat_layout_feature_type_get_name_id (face, features[0]));
|
||||
g_assert_cmpuint (261, ==, hb_aat_layout_feature_type_get_name_id (face, features[1]));
|
||||
g_assert_cmpuint (265, ==, hb_aat_layout_feature_type_get_name_id (face, features[2]));
|
||||
}
|
||||
|
||||
static void
|
||||
test_aat_get_feature_selectors (void)
|
||||
{
|
||||
unsigned int default_index;
|
||||
hb_aat_layout_feature_selector_info_t settings[3];
|
||||
unsigned int count = 3;
|
||||
|
||||
g_assert_cmpuint (4, ==, hb_aat_layout_feature_type_get_selector_infos (face,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE,
|
||||
0, &count, settings,
|
||||
&default_index));
|
||||
g_assert_cmpuint (3, ==, count);
|
||||
g_assert_cmpuint (0, ==, default_index);
|
||||
|
||||
g_assert_cmpuint (0, ==, settings[0].enable);
|
||||
g_assert_cmpuint (294, ==, settings[0].name_id);
|
||||
|
||||
g_assert_cmpuint (1, ==, settings[1].enable);
|
||||
g_assert_cmpuint (295, ==, settings[1].name_id);
|
||||
|
||||
g_assert_cmpuint (2, ==, settings[2].enable);
|
||||
g_assert_cmpuint (296, ==, settings[2].name_id);
|
||||
|
||||
count = 3;
|
||||
g_assert_cmpuint (4, ==, hb_aat_layout_feature_type_get_selector_infos (face,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE,
|
||||
3, &count, settings,
|
||||
&default_index));
|
||||
g_assert_cmpuint (1, ==, count);
|
||||
g_assert_cmpuint (0, ==, default_index);
|
||||
|
||||
g_assert_cmpuint (3, ==, settings[0].enable);
|
||||
g_assert_cmpuint (297, ==, settings[0].name_id);
|
||||
|
||||
count = 1;
|
||||
g_assert_cmpuint (1, ==, hb_aat_layout_feature_type_get_selector_infos (face,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS,
|
||||
0, &count, settings,
|
||||
&default_index));
|
||||
g_assert_cmpuint (1, ==, count);
|
||||
g_assert_cmpuint (HB_AAT_LAYOUT_NO_SELECTOR_INDEX, ==, default_index);
|
||||
|
||||
g_assert_cmpuint (8, ==, settings[0].enable);
|
||||
g_assert_cmpuint (308, ==, settings[0].name_id);
|
||||
|
||||
count = 100;
|
||||
g_assert_cmpuint (0, ==, hb_aat_layout_feature_type_get_selector_infos (face, HB_AAT_LAYOUT_FEATURE_TYPE_INVALID,
|
||||
0, &count, settings,
|
||||
NULL));
|
||||
g_assert_cmpuint (0, ==, count);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
hb_test_init (&argc, &argv);
|
||||
|
||||
hb_test_add (test_aat_get_feature_types);
|
||||
hb_test_add (test_aat_get_feature_selectors);
|
||||
|
||||
face = hb_test_open_font_file ("fonts/aat-feat.ttf");
|
||||
sbix = hb_test_open_font_file ("fonts/chromacheck-sbix.ttf");
|
||||
unsigned int status = hb_test_run ();
|
||||
hb_face_destroy (sbix);
|
||||
hb_face_destroy (face);
|
||||
return status;
|
||||
}
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <hb.h>
|
||||
#include <hb-ot.h>
|
||||
#include <hb-aat.h>
|
||||
|
||||
#ifdef HAVE_GLIB
|
||||
#include <hb-glib.h>
|
||||
|
@ -93,7 +93,7 @@ test_face (hb_face_t *face,
|
||||
hb_ot_name_get_utf32 (face, cp, NULL, NULL, NULL);
|
||||
|
||||
hb_ot_var_get_axis_count (face);
|
||||
hb_ot_var_get_axes (face, 0, NULL, NULL);
|
||||
hb_ot_var_get_axis_infos (face, 0, NULL, NULL);
|
||||
hb_ot_var_normalize_variations (face, NULL, 0, NULL, 0);
|
||||
hb_ot_var_normalize_coords (face, 0, NULL, NULL);
|
||||
|
||||
|
@ -449,6 +449,9 @@ test_ot_tag_language (void)
|
||||
|
||||
/* A UN M.49 region code, not an extended language subtag */
|
||||
test_tag_from_language ("ARA", "ar-001");
|
||||
|
||||
/* An invalid tag */
|
||||
test_tag_from_language ("TRK", "tr@foo=bar");
|
||||
}
|
||||
|
||||
static void
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -5,6 +5,16 @@ if (HB_BUILD_UTILS)
|
||||
add_test (NAME ${test}
|
||||
COMMAND "${PYTHON_EXECUTABLE}" run-tests.py $<TARGET_FILE:hb-shape> "data/in-house/${test}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set_property (TEST ${test} PROPERTY SKIP_RETURN_CODE 77)
|
||||
endforeach ()
|
||||
|
||||
file (READ "${CMAKE_CURRENT_SOURCE_DIR}/data/aots/Makefile.sources" INHOUSE)
|
||||
extract_make_variable (TESTS ${INHOUSE})
|
||||
foreach (test IN ITEMS ${TESTS})
|
||||
add_test (NAME ${test}
|
||||
COMMAND "${PYTHON_EXECUTABLE}" run-tests.py $<TARGET_FILE:hb-shape> "data/aots/${test}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set_property (TEST ${test} PROPERTY SKIP_RETURN_CODE 77)
|
||||
endforeach ()
|
||||
|
||||
file (READ "${CMAKE_CURRENT_SOURCE_DIR}/data/text-rendering-tests/Makefile.sources" TEXTRENDERING)
|
||||
@ -13,5 +23,6 @@ if (HB_BUILD_UTILS)
|
||||
add_test (NAME ${test}
|
||||
COMMAND "${PYTHON_EXECUTABLE}" run-tests.py $<TARGET_FILE:hb-shape> "data/text-rendering-tests/${test}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set_property (TEST ${test} PROPERTY SKIP_RETURN_CODE 77)
|
||||
endforeach ()
|
||||
endif ()
|
||||
|
@ -4,6 +4,7 @@ NULL =
|
||||
SUBDIRS = \
|
||||
in-house \
|
||||
text-rendering-tests \
|
||||
aots \
|
||||
$(NULL)
|
||||
|
||||
# Convenience targets:
|
||||
|
13
test/shaping/data/aots/COPYING
Normal file
13
test/shaping/data/aots/COPYING
Normal file
@ -0,0 +1,13 @@
|
||||
Copyright 2000-2016 Adobe Systems Incorporated. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use these files except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
37
test/shaping/data/aots/Makefile.am
Normal file
37
test/shaping/data/aots/Makefile.am
Normal file
@ -0,0 +1,37 @@
|
||||
# Process this file with automake to produce Makefile.in
|
||||
|
||||
NULL =
|
||||
|
||||
# Convenience targets:
|
||||
lib:
|
||||
@$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
|
||||
|
||||
EXTRA_DIST = \
|
||||
COPYING \
|
||||
fonts \
|
||||
$(TESTS) \
|
||||
$(NULL)
|
||||
|
||||
TEST_EXTENSIONS = .tests
|
||||
TESTS_LOG_COMPILER = $(srcdir)/../../run-tests.py $(top_builddir)/util/hb-shape$(EXEEXT)
|
||||
|
||||
init-aots:
|
||||
git clone https://github.com/adobe-type-tools/aots $(srcdir)/aots
|
||||
make -C$(srcdir)/aots
|
||||
make -C$(srcdir)/aots/harfbuzz
|
||||
touch $(srcdir)/init-aots
|
||||
|
||||
update-tests: init-aots lib
|
||||
cp $(srcdir)/hb-aots-tester.cpp $(srcdir)/aots/harfbuzz/hb-aots-tester.cpp
|
||||
$(CXX) -Wno-narrowing $(srcdir)/aots/harfbuzz/hb-aots-tester.cpp \
|
||||
-I$(top_srcdir)/src/ -o $(srcdir)/aots/harfbuzz/aots \
|
||||
-L$(top_builddir)/src/.libs -lharfbuzz
|
||||
rm -rf $(srcdir)/tests/
|
||||
mkdir $(srcdir)/tests/
|
||||
export LD_LIBRARY_PATH=$(realpath $(top_builddir)/src/.libs); cd $(srcdir)/aots/harfbuzz; ./aots
|
||||
|
||||
.PHONY: update-tests
|
||||
|
||||
include Makefile.sources
|
||||
|
||||
-include $(top_srcdir)/git.mk
|
126
test/shaping/data/aots/Makefile.sources
Normal file
126
test/shaping/data/aots/Makefile.sources
Normal file
@ -0,0 +1,126 @@
|
||||
TESTS = \
|
||||
tests/classdef1_empty.tests \
|
||||
tests/classdef1_multiple.tests \
|
||||
tests/classdef1_single.tests \
|
||||
tests/classdef1.tests \
|
||||
tests/classdef2_empty.tests \
|
||||
tests/classdef2_multiple.tests \
|
||||
tests/classdef2_single.tests \
|
||||
tests/classdef2.tests \
|
||||
tests/gpos_chaining1_boundary.tests \
|
||||
tests/gpos_chaining1_lookupflag.tests \
|
||||
tests/gpos_chaining1_multiple_subrules.tests \
|
||||
tests/gpos_chaining1_next_glyph.tests \
|
||||
tests/gpos_chaining1_simple.tests \
|
||||
tests/gpos_chaining1_successive.tests \
|
||||
tests/gpos_chaining2_boundary.tests \
|
||||
tests/gpos_chaining2_lookupflag.tests \
|
||||
tests/gpos_chaining2_multiple_subrules.tests \
|
||||
tests/gpos_chaining2_next_glyph.tests \
|
||||
tests/gpos_chaining2_simple.tests \
|
||||
tests/gpos_chaining2_successive.tests \
|
||||
tests/gpos_chaining3_boundary.tests \
|
||||
tests/gpos_chaining3_lookupflag.tests \
|
||||
tests/gpos_chaining3_next_glyph.tests \
|
||||
tests/gpos_chaining3_simple.tests \
|
||||
tests/gpos_chaining3_successive.tests \
|
||||
tests/gpos_context1_boundary.tests \
|
||||
tests/gpos_context1_expansion.tests \
|
||||
tests/gpos_context1_lookupflag.tests \
|
||||
tests/gpos_context1_multiple_subrules.tests \
|
||||
tests/gpos_context1_next_glyph.tests \
|
||||
tests/gpos_context1_simple.tests \
|
||||
tests/gpos_context1_successive.tests \
|
||||
tests/gpos_context2_boundary.tests \
|
||||
tests/gpos_context2_classes.tests \
|
||||
tests/gpos_context2_expansion.tests \
|
||||
tests/gpos_context2_lookupflag.tests \
|
||||
tests/gpos_context2_multiple_subrules.tests \
|
||||
tests/gpos_context2_next_glyph.tests \
|
||||
tests/gpos_context2_simple.tests \
|
||||
tests/gpos_context2_successive.tests \
|
||||
tests/gpos_context3_boundary.tests \
|
||||
tests/gpos_context3_lookupflag.tests \
|
||||
tests/gpos_context3_next_glyph.tests \
|
||||
tests/gpos_context3_simple.tests \
|
||||
tests/gpos_context3_successive.tests \
|
||||
tests/gpos1_1_lookupflag.tests \
|
||||
tests/gpos1_1_simple.tests \
|
||||
tests/gpos1_2_lookupflag.tests \
|
||||
tests/gpos1_2.tests \
|
||||
tests/gpos2_1_lookupflag.tests \
|
||||
tests/gpos2_1_next_glyph.tests \
|
||||
tests/gpos2_1_simple.tests \
|
||||
tests/gpos2_1.tests \
|
||||
tests/gpos2_2.tests \
|
||||
tests/gpos3_lookupflag.tests \
|
||||
tests/gpos3.tests \
|
||||
tests/gpos4_lookupflag.tests \
|
||||
tests/gpos4_multiple_anchors.tests \
|
||||
tests/gpos4_simple.tests \
|
||||
tests/gpos5.tests \
|
||||
tests/gpos6.tests \
|
||||
tests/gpos7_1.tests \
|
||||
tests/gpos9.tests \
|
||||
tests/gsub_chaining1_boundary.tests \
|
||||
tests/gsub_chaining1_lookupflag.tests \
|
||||
tests/gsub_chaining1_multiple_subrules.tests \
|
||||
tests/gsub_chaining1_next_glyph.tests \
|
||||
tests/gsub_chaining1_simple.tests \
|
||||
tests/gsub_chaining1_successive.tests \
|
||||
tests/gsub_chaining2_boundary.tests \
|
||||
tests/gsub_chaining2_lookupflag.tests \
|
||||
tests/gsub_chaining2_multiple_subrules.tests \
|
||||
tests/gsub_chaining2_next_glyph.tests \
|
||||
tests/gsub_chaining2_simple.tests \
|
||||
tests/gsub_chaining2_successive.tests \
|
||||
tests/gsub_chaining3_boundary.tests \
|
||||
tests/gsub_chaining3_lookupflag.tests \
|
||||
tests/gsub_chaining3_next_glyph.tests \
|
||||
tests/gsub_chaining3_simple.tests \
|
||||
tests/gsub_chaining3_successive.tests \
|
||||
tests/gsub_context1_boundary.tests \
|
||||
tests/gsub_context1_expansion.tests \
|
||||
tests/gsub_context1_lookupflag.tests \
|
||||
tests/gsub_context1_multiple_subrules.tests \
|
||||
tests/gsub_context1_next_glyph.tests \
|
||||
tests/gsub_context1_simple.tests \
|
||||
tests/gsub_context1_successive.tests \
|
||||
tests/gsub_context2_boundary.tests \
|
||||
tests/gsub_context2_classes.tests \
|
||||
tests/gsub_context2_expansion.tests \
|
||||
tests/gsub_context2_lookupflag.tests \
|
||||
tests/gsub_context2_multiple_subrules.tests \
|
||||
tests/gsub_context2_next_glyph.tests \
|
||||
tests/gsub_context2_simple.tests \
|
||||
tests/gsub_context2_successive.tests \
|
||||
tests/gsub_context3_boundary.tests \
|
||||
tests/gsub_context3_lookupflag.tests \
|
||||
tests/gsub_context3_next_glyph.tests \
|
||||
tests/gsub_context3_simple.tests \
|
||||
tests/gsub_context3_successive.tests \
|
||||
tests/gsub1_1_lookupflag.tests \
|
||||
tests/gsub1_1_modulo.tests \
|
||||
tests/gsub1_1_simple.tests \
|
||||
tests/gsub1_2_lookupflag.tests \
|
||||
tests/gsub1_2_simple.tests \
|
||||
tests/gsub2_1_lookupflag.tests \
|
||||
tests/gsub2_1_multiple_sequences.tests \
|
||||
tests/gsub2_1_simple.tests \
|
||||
tests/gsub3_1_lookupflag.tests \
|
||||
tests/gsub3_1_multiple.tests \
|
||||
tests/gsub3_1_simple.tests \
|
||||
tests/gsub4_1_lookupflag.tests \
|
||||
tests/gsub4_1_multiple_ligatures.tests \
|
||||
tests/gsub4_1_multiple_ligsets.tests \
|
||||
tests/gsub4_1_simple.tests \
|
||||
tests/gsub7.tests \
|
||||
tests/lookupflag_ignore_attach.tests \
|
||||
tests/lookupflag_ignore_base.tests \
|
||||
tests/lookupflag_ignore_combination.tests \
|
||||
tests/lookupflag_ignore_ligatures.tests \
|
||||
tests/lookupflag_ignore_marks.tests \
|
||||
$(NULL)
|
||||
|
||||
DISABLED_TESTS = \
|
||||
$(NULL)
|
BIN
test/shaping/data/aots/fonts/classdef1_font1.otf
Normal file
BIN
test/shaping/data/aots/fonts/classdef1_font1.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/classdef1_font2.otf
Normal file
BIN
test/shaping/data/aots/fonts/classdef1_font2.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/classdef1_font3.otf
Normal file
BIN
test/shaping/data/aots/fonts/classdef1_font3.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/classdef1_font4.otf
Normal file
BIN
test/shaping/data/aots/fonts/classdef1_font4.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/classdef2_font1.otf
Normal file
BIN
test/shaping/data/aots/fonts/classdef2_font1.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/classdef2_font2.otf
Normal file
BIN
test/shaping/data/aots/fonts/classdef2_font2.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/classdef2_font3.otf
Normal file
BIN
test/shaping/data/aots/fonts/classdef2_font3.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/classdef2_font4.otf
Normal file
BIN
test/shaping/data/aots/fonts/classdef2_font4.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/cmap0_font1.otf
Normal file
BIN
test/shaping/data/aots/fonts/cmap0_font1.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/cmap10_font1.otf
Normal file
BIN
test/shaping/data/aots/fonts/cmap10_font1.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/cmap10_font2.otf
Normal file
BIN
test/shaping/data/aots/fonts/cmap10_font2.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/cmap12_font1.otf
Normal file
BIN
test/shaping/data/aots/fonts/cmap12_font1.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/cmap14_font1.otf
Normal file
BIN
test/shaping/data/aots/fonts/cmap14_font1.otf
Normal file
Binary file not shown.
BIN
test/shaping/data/aots/fonts/cmap2_font1.otf
Normal file
BIN
test/shaping/data/aots/fonts/cmap2_font1.otf
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user